筆者透過以 jieba 與 gensim 探索文本主題:五月天人生無限公司歌詞分析 文章教學
用相同架構進行洗錢名單掃描之功能,主要使用Jieba、gensim 建構模型
本實驗目的是希望透過文字自動化掃描,能更準確判斷可能洗錢名單
安裝套件
pip install jieba
pip install gensim
pip intsall wordcloud
一開始先準備好目標詞庫,這裡黑名單就是筆者的資料庫
訓練好的模型就是要準備給接下來隨意輸入一個名字,找出相似黑名單人員或是就是黑名單一員
首先先來了解一下這份黑名單常見內容為何?
在建構模型前,先了解資料,這裡共有115,263筆黑名單並且有不同的語言文字,每一列都是一筆姓名
因為名單裡會有英文、中文、拉丁文等等,這份txt會是一個utf-8編碼的.txt檔
而為了便利測試,就用jieba內建的語料庫斷詞
import jieba.analyse
from wordcloud import WordCloud
import matplotlib.pyplot as plt
#載入語料庫
jieba.set_dictionary("dict.txt.big")
value=""
#黑名單文字檔
content = open('aml_2.txt', 'rb').read()
#斷詞,選出100個主題
tags = jieba.analyse.extract_tags(content,topK=100,withWeight=True)
for tag, weight in tags:
if value=="":
value=tag
else :
value=value+" "+tag
接著是停用詞的應用,但因為是姓名的掃「毒」
筆者認為停用詞的部分應該不會存在於姓名之中,反而是文章、句子、語音的判斷比較會與停用詞直接的關係
這裡就不設定停用詞
直接就呼叫WordCloud,並因為姓名有中文的可能,而用一個支援中文的字型
這裡就需要事先下載好.otf
wc = WordCloud(font_path="NotoSansCJKtc-Black.otf",
#設置字體
background_color="white", #背景顏色
max_words = 2000 #文字雲顯示最大詞數
)
wc.generate(value)
#詞雲轉為圖片存檔
wc.to_file("sys_wordcloud.jpg")
wc.to_file(filename)會自動將產生的圖片存檔成jpg
如果要在console上看到這張圖,可以利用matplotlib.pyplot 進行顯示
#顯示詞雲
plt.imshow(wc)
plt.axis("off")
plt.figure(figsize=(10,6), dpi = 100)
plt.show()
文字雲中,字越大的就是出現越多次的內容
以下圖為例,最常出現就是名字含Jo、de字眼,而其次叫Martin的出現次數也很多
像是亞洲人會出現的姓式,在Lu 跟Chen也佔了不少比例
而因為黑名單包含公司名稱,變的也有「Company」字眼現身
未來要取名字就可以盡量避免這些「菜市場名」(誤
姓名搜尋建模
了解完資料,接下來可以開始來做姓名搜尋,首先前面提到要建模
第一步把剛斷詞的結果存成一個.dataset檔案,以利後續可以使用
wf=open("cut.dataset", mode="w",encoding="utf8")
#取得斷詞結果
with open("aml_2.txt", "r",encoding="utf8") as f:
for line in f:
words = jieba.cut(line)
wf.write(" ".join(words))
wf.close()
從斷詞>同義字取代>停用詞過濾>建立自定義詞庫 是一連串建模前的資料準備
因用簡單的名單過濾,這裡跳過同意字取代、停用詞過濾,直接做自定議詞庫建立
而black_list.dict就是黑名單資料庫分析後的結果
import os
from gensim import corpora, models, similarities
stop_word_content = " ".join(stopword_set)
dictionary = corpora.Dictionary(document.split() for document in open("cut.dataset",encoding="utf8"))
stoplist = set(stop_word_content.split())
stop_ids = [dictionary.token2id[stopword] for stopword in stoplist
if stopword in dictionary.token2id] #dictionary.token2id: 代表什麼字詞對應到什麼id,有幾個id就代表有幾維向量空間
dictionary.compactify()
dictionary.save("black_list.dict")
建好詞庫後,先來看一下詞庫裡長什麼樣子
if (os.path.exists("black_list.dict")):
dictionary = corpora.Dictionary.load("black_list.dict")
#查看字典裡的資料
for word,index in dictionary.token2id.items():
print(word +" id:"+ str(index))
else:
print("語料庫不存在")
上圖可見,每一個斷詞後的結果就會給一個唯一碼
可以幫助後續利用tf-idf的方法建立模型,利用gensim 的元件包設計好的TfidfModel
載入語料庫建模時,也是要走同義字取代>停用詞過濾二個動作,在將結果做序列化
本例一樣是略過這二步,直接將語料庫做序列化
而在載入時,一定要將encoding設在utf8,才不會有日文、中文、韓文等變亂碼的問題
# 載入語料庫(save 辭庫會有亂碼的問題)
if (os.path.exists("black_list.dict")):
dictionary = corpora.Dictionary.load("black_list.dict")
#打開詞庫
texts = [[word for word in document.split() ]
for document in open("cut.dataset",encoding="utf8")]
#將 corpus 序列化
corpus = [dictionary.doc2bow(text) for text in texts]
corpora.MmCorpus.serialize("black_list.mm", corpus) # Corpus in Matrix Market format
print("載入語料庫完成")
else:
print("語料庫不存在")
#建立 tfidf model
tfidf = models.TfidfModel(corpus)
# 轉為向量表示
corpus_tfidf = tfidf[corpus]
#保存tf-idf
tfidf.save(u'sys_tf.tfidf')
# 建立 LSI model
lsi = models.LsiModel(corpus_tfidf, id2word=dictionary, num_topics=100)#num_topics
corpus_lsi = lsi[corpus_tfidf] # LSI潛在語義索引
lsi.save('black_list.lsi') #保存模型
corpora.MmCorpus.serialize('black_list.mm', corpus_lsi)
前面提到,筆者斷詞時給定了一個topK=100,代表會有100個主題
在建模時,透過gensim元件包的LsiModel function 參數num_topics 給定特徵參數數量
當給定100,即是模型的自變數會有100個並透過模型建立與訓練給定權重值
筆者認知,這二件事應該是相同之意
如果模型能抓到越多的特徵,判斷可以更加準確,但也有失真的風險
以上的動作就是把一個模型建立完成並存在black_list.mm 檔案裡
由此開始,就要把剛剛的.mm模型進行測試
# 載入語料庫(save 辭庫會有亂碼的問題)
if (os.path.exists(u"black_list.dict")):
dictionary = corpora.Dictionary.load(u"black_list.dict")
corpus = corpora.MmCorpus(u"black_list.mm")
print("載入語料庫完成")
else:
print("語料庫不存在")
#復原模型
# 建立 tfidf model
tfidf = models.TfidfModel.load(u'sys_tf.tfidf')
lsi = models.LsiModel.load(u'black_list.lsi') # load model
輸入一個名字>名字斷詞>模型判定>回傳相似度前五名高的名字
#相似度計算
#隨便輸入一串字並經過斷詞
doc="北川謙次"
words_new = jieba.cut(doc)
vec_bow = dictionary.doc2bow(words_new) # 斷詞轉換成陣列
#開始計算相似度
vec_lsi = lsi[vec_bow] # 使用建立的模型進行計算
# 建立索引
index = similarities.MatrixSimilarity(lsi[corpus])
index.save("black_list.index")
# 列出相似度前五名
sims = index[vec_lsi]
sims = sorted(enumerate(sims), key=lambda item: -item[1])
print(sims[:5])
#對應自建語料庫,把完整的相似名字列出
array_1= [];
fp = open("cut.dataset",encoding="utf8")
for i, line in enumerate(fp):
array_1.append(line)
fp.close()
for item in sims[:5]:
print("\n相似名字:", array_1[item [0]])
print("相似度分數:", array_1[1])
最後,依輸入的名字,模型列出了五個分數比較高的名子出來
這可以幫助我們判斷,跟這個名子相似的(不一定長的一樣,也許是部分相似)
是否也屬於問題相關之一,而這樣的應用還可以擴充在智慧應答等
筆者最後在git上放了一段使用一百條問答庫,進行模型建置
以相同的式建立出聊天機器人的效果
參考資訊