1. 程式人生 > >windows環境下使用wiki中文百科及gensim工具庫訓練詞向量

windows環境下使用wiki中文百科及gensim工具庫訓練詞向量

       以前做影象演算法,面對的都是一幅影象、m*n個畫素點,對於詞向量完全沒有概念,在接觸自然語言處理一些演算法後,才知道這個概念,想必做自然語言處理的同學都訓練過詞向量。訓練詞向量的相關文章已經很多,不過由於大家使用的作業系統不同, 每個人的做法可能都不一樣,沒有標準做法,大家使用的工具庫可能有些也是不同的,相信每個人都在尋找最佳的訓練方法。本文主要介紹windows環境下使用python語言,呼叫gensim工具庫訓練詞向量的過程。說了這麼多,那到底什麼是詞向量呢,為啥要訓練這個東東? 自然語言處理的都是文字,比如要對100個文字的小段文字做分析,而演算法運算需要的輸入是數字,比如y=w*x +b,不管你是中文漢字還是英文字母,都需要將文字對映成數字才行,對映後的結果就是詞向量了。比如:
【蘋果】這個詞,訓練後的詞向量為: (-0.289151 0.025888 0.135030 0.075366 0.099814 -0.001124 0.162626 0.090600 -0.350755 0.250274),        一般詞向量都是高維向量,比如我在工作中訓練的詞向量是200維,這裡僅僅以10維向量為例。有了這個詞向量後,就可以將其作為神經網路模型的輸入,用於訓練文字分類模型等,還可以用於計算詞和詞之間的相似性,在詞向量空間,蘋果和桔子兩個詞是很接近的,同樣麻辣燙和酸辣粉是很接近的。訓練詞向量,首先要有語料庫,語料庫就是分好詞的、每個文字佔據一行的大集合,製作語料庫是一個繁瑣的事情,原材料選擇上一般大家會選擇wiki中文百科,下載地址:
https://dumps.wikimedia.org/zhwiki/
,不過一般下載比較慢,推薦找一些映象網站下載,比如:
http://dumps.wikimedia.your.org/zhwiki/latest/zhwiki-latest-pages-articles.xml.bz2 下載稍微快一些。如果使用程式下載可參考下面python程式碼:
size = 0
chunk_size = 1024*1000
req = requests.get("http://dumps.wikimedia.your.org/zhwiki/latest/zhwiki-latest-pages-articles.xml.bz2", stream=True)
fwiki = open("wiki_download/zhwiki-latest-pages-articles.xml.bz2", "wb")
for chunk in req.iter_content(chunk_size=1024):
    if chunk:
        fwiki.write(chunk)
        size += 1024
        if ((size % chunk_size) == 0):
            print("download finished: " + str(size/1000000) + "M")

fwiki.flush()
fwiki.close()
       下載完成後就自動將該壓縮包儲存至wiki_download資料夾內。下載完成後,下一步就是解壓縮並提取文字,可以使用開源工具wiki extractor(https://github.com/attardi/wikiextractor)完成。這一步比較簡單,只需要將該檔案儲存到自己工程目錄下,然後執行命令:
cmd = "python wiki_extractor.py -b 1200M -o wiki_download/extracted wiki_download/zhwiki-latest-pages-articles.xml.bz2"
subprocess.call(cmd, shell=True)
       -b 1200M表示以 1200M 為單位切分檔案,-o 後面接出入檔案,最後是輸入檔案,這個抽取過程還是比較漫長的。上面是寫程式碼、程式化的方式,如果在控制檯敲命令也可以,但是如果將整個過程程式化的一鍵自動完成,那麼簡單寫下上面程式碼就可以了。抽取後的文字是一個巨大的檔案,大概長這樣:        
       下一步就是分詞前的資料預處理工作,通過上面圖也可以看到,文本里麵包含了很多wiki文件特有的標記及特殊字元,比如<doc>、“”、《》等等,需要依次剔除,當然還有很多繁體字,需要統一轉成簡體字。這裡簡單說一下繁簡轉換,本來打算用opencc,但是發現在純python環境下無法使用,opencc需要依賴一個.so庫。只好用其他庫了,後來我選擇的是hanziconv,效果也不錯的。簡單示例程式碼如下:
line = HanziConv.toSimplified(line)
       資料預處理完成後就可以進行分詞了,示例程式碼如下:
seg_list = jieba.cut(line, HMM=True)
       由於是python環境,我這裡用的是jieba分詞,在java環境下我也用過HanLP分詞工具庫,真心佩服這些開源庫的作者,程式碼質量都蠻高的。這兩個分詞庫各有千秋,HanLP庫執行速度更快,而對於淘寶體文字,比如:【透氣拖鞋夏季一字拖男女士韓版學生簡約魔術貼沙灘鞋帆布防滑涼拖 結巴分詞結果:透氣 拖鞋 夏季 一字 拖 男 女士 韓版 學生 簡約 魔術 貼 沙灘鞋 帆布 防滑 涼 拖 HanLP分詞結果:透氣 拖鞋 夏季一 字 拖 男 女士 韓版 學生 簡約 魔術 貼 沙灘 鞋 帆布 防滑 涼 拖 個人感覺jieba分詞在淘寶體上效果更準一些。        分完詞後,wiki相關檔案就可以刪除了,檔案很大,比較佔用空間,示例程式碼如下:
os.remove("wiki_download/extracted/AA/wiki_00")
os.remove("wiki_download/zhwiki-latest-pages-articles.xml.bz2")
       至此,語料庫就生成好了,大概長這個樣子(這是我某個版本的語料庫,裡面有些字元沒有剔除):           
       下面就可以使用gensim工具庫訓練詞向量了,相比較訓練過程反而簡單了,程式碼量很少,這也得益於gensim工具庫的強大。示例程式碼如下:
logging.basicConfig(format='%(asctime)s: %(levelname)s: %(message)s')
logging.root.setLevel(level=logging.INFO)
logging.info("running %s" % ' '.join(sys.argv))

model = Word2Vec(LineSentence("corpus/corpus_results.txt"), size=200, window=10, min_count=15, workers=4)
model.save("model/model_gram.bin")
model.wv.save_word2vec_format("model/model_vec.bin", binary=True)
       上面的size=200,就是要訓練的詞向量維度;window=10,為視窗大小,也就是訓練時計算當前詞和周圍多少個詞,這個概念有點像卷積核的長度;min_count=5,最小閾值,對於出現次數少於該值的詞,會被拋棄掉;workers=4,為訓練時開啟的執行緒數量。其他還有很多引數,這裡就不一一列舉了。訓練好詞向量後,驗證過程也比較簡單,示例程式碼如下:
model = Word2Vec.load('model/model_gram.bin')
result = model.most_similar("麻辣燙")
for word in result:
    print(word.__str__())
       由於我在實際訓練時還使用了其他語料,所以是下面這樣的結果:           
       整個訓練過程需要用到多個工具庫,每個工具庫安裝及使用都會頗費一些周折,不過按照流程動手做一次,回頭再看就很簡單了。至於詞向量的理論相關知識本文就不做過多介紹了,碼字可以,編輯公式有時感覺好繁瑣。文章最後還是想吐槽csdn,這次改版真彆扭,是為了方便移動端閱讀嗎?可是大家多數都是在工作時,pc端瀏覽csdn的,可能是我的猜測過於武斷。