word2vec模型訓練
前言
整體索引在此
書蘊——基於書評的人工智能推薦系統
上次把文本進行了預處理,主要是使用正則去除標籤以及對文本去除停用詞以及結巴分詞。
後續還會加入tf-idf來動態選取停用詞。
word2vec模型訓練
word2vec簡介
關於word2vec到底是什麼,推薦一個鏈接:DL4J,有對理解幫助很大的圖文
雖然鏈接裏的word2vec是java寫的,和我們用的python word2vec不太一致,但思想上是一致的,而且文章具有深度的科研性以及廣度的科普性,值得一看。
gensim
gensim是python的一個包,包含word2vec。不過安裝起來相對麻煩,需要scipy和numpy依賴,最簡單的安裝方案是去anaconda下載python3,自帶這些包。
我是先手動去找的依賴,然後一個小細節上的問題是:numpy不能直接安裝,要去下載官網上寫了+mkl的版本(比如我的是1.13.1+mkl)不知道後續的版本有沒有更新解決問題。其餘的還算順利。
當時也很着急,就先下了anaconda,不得不說的確效率而且快速,直接就可以使用。
正式使用
各種使用姿勢我參考了很多,我特別懶,不細說怎麼訓練了,直接放鏈接。
如果是新手,建議按照從上到下的順序食用,不推薦一次性看完,如果只是想使用的話,看到參數和官方文檔就足夠了。
- 這個鏈接是我17年暑假的啓蒙,幫助很多
- 處理中文維基百科的步驟,我訓練的中文維基百科的語料庫就是跟着這個來的
- 原理上的理解word2vec以及參數使用
- 官方英文文檔
- 十分細節的理解word2vec
- 聲稱是看了此文還不懂word2vec,就說明是博主太笨的文章
talk is cheap, show me the code
import time
import gensim
import multiprocessing
import logging
import os
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s',
level=logging.INFO)
def train_book(book_base, book_name, outfile_base):
infile = book_base + book_name
outfile = "model_" + book_name.replace('.txt', '')
model = gensim.models.Word2Vec(gensim.models.word2vec.LineSentence(infile),
size=100, min_count=5, sg=1,
workers=multiprocessing.cpu_count())
model.save(outfile_base + "model\\" + outfile)
model.wv.save_word2vec_format(
outfile_base + "vector\\" + "vector_" + outfile,
outfile_base + "vocabulary\\" + "vocabulary_" + outfile,
binary=False)
if __name__ == '__main__':
indir = "書評\\seg\\"
books = os.listdir(indir)
begin = time.time()
for book in books:
train_book(indir, book, "書評\\word2vec\\")
# train_book(indir, "seg_追風箏的人.txt", "書評\\word2vec\\")
total_end = time.time()
print("Total procesing time: %d seconds" % (total_end - begin))
日常不寫註釋,反正我看得懂代碼,不不不以後還是把註釋補上吧。= =
大致解釋一下,就是從已經分好詞的目錄中把所有文本文件逐個訓練出模型,模型分別爲model、vector和vocabulary(分別是可供使用的二進制文件、向量表和詞彙表)詞彙表包含詞頻,對於人工篩選停用詞幫助挺大的。
根據官方文檔,模型訓練會掃描兩遍文本內容,一遍是統計詞頻,第二遍纔是建立樹模型等等(這裏描述可能不夠精確)
使用
訓練的結果往往和語料庫關係很大。怎麼使用word2vec我就不多說了,這裏直接引用下:
model.most_similar(positive=['woman', 'king'], negative=['man'])
#輸出[('queen', 0.50882536), ...]
model.doesnt_match("breakfast cereal dinner lunch".split())
#輸出'cereal'
model.similarity('woman', 'man')
#輸出0.73723527
model['computer'] # raw numpy vector of a word
#輸出array([-0.00449447, -0.00310097, 0.02421786, ...], dtype=float32)
具體的例子我建議看看 這篇blog,一目瞭然
效果
因爲一開始語料庫實在太小,拿《追風箏的人》這本書的書評舉例,一開始只有60條長評,相對而言內容太少。效果很差
根據vocabulary,阿富汗和風箏這兩個詞是文本中出現頻率較多的內容,而與其關聯的詞,第一個竟然是“中”?當然這個其實主要是停用詞沒選好的問題。整體其實還不算差,畢竟風箏能和孩子、追、阿米爾這些詞關聯度較爲靠近,算不錯的了。
然後再看看餘弦值,這就很過分了,全是0.999+就太接近了,這個時候語料庫不夠大的問題才充分得以暴露。詞和詞之間距離過近,那麼潛在噪音帶來的影響就不可估量了。比如中這個字,在大一些的語料庫中是很難排在這麼前面的(參考維基百科語料庫訓練的結果,我訓練了一次,連停用詞都沒去。以後有空填坑寫博客)
所以找到小夥伴,強烈要求評論給多一些,冬瑜也是很給力,直接來了一份1000條長評的追風箏的人(之前是60條)
訓練之後的結果如下:
效果拔羣!
明顯詞與詞直接距離拉開了,也沒看見什麼“中”了,嗯1000條其實相對來說是個不錯的水準了,當然還是更希望語料庫更大,這樣相關性就更明確了。
總結
先寫到這裏吧,關於模型訓練這邊,後期很多參數肯定要微調,找到一個相對合理的效果。關於效果的測量,其實也是有待斟酌,還是那句話,先儘快做出一個原型吧。
以上。