[書蘊筆記-1]word2vec模型訓練

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,不得不說的確效率而且快速,直接就可以使用。

正式使用

各種使用姿勢我參考了很多,我特別懶,不細說怎麼訓練了,直接放鏈接。
如果是新手,建議按照從上到下的順序食用,不推薦一次性看完,如果只是想使用的話,看到參數和官方文檔就足夠了。

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條其實相對來說是個不錯的水準了,當然還是更希望語料庫更大,這樣相關性就更明確了。

總結

先寫到這裏吧,關於模型訓練這邊,後期很多參數肯定要微調,找到一個相對合理的效果。關於效果的測量,其實也是有待斟酌,還是那句話,先儘快做出一個原型吧。

以上。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章