練習-word2vec

上一篇我們學習了word2vec,這一節我們來練習下,對於word2vec,我們已經知道了原理,怎麼用代碼實現,我們就不要再去琢磨了吧,以後有機會,我們可以看看如何用tensorflow實現word2vec,這節,我們就用被人做好到輪子吧,gensim包裡面有word2vec模型,我們就用它吧。

安裝gensim。

sudo pip install gensim

要訓練模型,我們需要數據,自己去爬數據當然也是可以,不過今天數據也用被人到,維基百科的中文語料庫:

dumps.wikimedia.org/enw

下載下來,大小在1.47G左右,數據是xml格式的,我們需要轉換成text格式,新建.py文件process_wiki.py,內容如下:

# -*- coding: utf-8 -*-# @Time : 2017/9/9 下午2:03# @Author : 修為# @Site : # @File : process_wiki.py.py# @Software: PyCharmfrom __future__ import print_functionimport loggingimport os.pathimport siximport sysfrom gensim.corpora import WikiCorpusif __name__ == "__main__": program = os.path.basename(sys.argv[0]) logger = logging.getLogger(program) logging.basicConfig(format="%(asctime)s: %(levelname)s: %(message)s") logging.root.setLevel(level=logging.INFO) logger.info("running %s" % " ".join(sys.argv)) # check and process input arguments if len(sys.argv) != 3: print("Using: python process_wiki.py enwiki.xxx.xml.bz2 wiki.en.text") sys.exit(1) inp, outp = sys.argv[1:3] space = " " i = 0 output = open(outp, "w") wiki = WikiCorpus(inp, lemmatize=False, dictionary={}) for text in wiki.get_texts(): if six.PY3: output.write(b" ".join(text).decode("utf-8") + "
") # ###another method### # output.write( # space.join(map(lambda x:x.decode("utf-8"), text)) + "
")
else: output.write(space.join(text) + "
") i = i + 1 if (i % 10000 == 0): logger.info("Saved " + str(i) + " articles") output.close() logger.info("Finished Saved " + str(i) + " articles")

創建完成之後,運行以下指令:

python process_wiki.py enwiki-latest-pages-articles.xml.bz2 wiki.en.text

這樣我們就得到了text格式的語料庫,但是還有一個問題,

語料庫中有很多繁體字,想辦法解決才行,別急,肯定有輪子的,有個叫opencc的輪子,裝上走了。

安裝opencc:

brew install opencc

調用opencc把繁體中文轉化為簡體中文:

opencc -i wiki.zh.text -o wiki.zh.text.jian -c t2s.json

那麼我們得到了簡體的中文了,再打開看看確認一遍。

我去,有英文啊,麻煩果然一波一波的啊,想辦法去掉英文:

好了,準備好乾凈的中文語料庫了,現在我們需要分詞,語料庫中的中文,都是一個一個的句子,要使用word2vec模型,我們還需要分詞,對,我們就用之前說的jieba中文分詞去分詞。

現在我們來看,gensim的word2vec模型怎麼用,包中有個LineSentence方法,我們只要把語料庫中的中文按以下規則存放:

以每一行對應一個句子(已經分詞,以空格隔開)。

就能直接調用LineSentence,把語料塞入模型。那我們現在來看看如何整理語料庫:

f=codecs.open("lastread.txt", "a+","utf-8")for line in open("wiki.zh.text.jian"): for i in re.sub("[a-zA-Z0-9]","",line).split(" "): if i!="": data=list(jieba.cut(i,cut_all=False)) readline=" ".join(data)+"
" f.write(readline)f.close()

通過以上代碼,新的文件lastread.txt就是煮好了的語料,就可以喂word2vec模型了,這個語料庫太大,跑完需要很久,到一半左右,我就強制結束了,得到的lastread.txt文件大小在860M左右,對於我們實驗來說足夠了。

接下來我們就廢話少說,來訓練word2vec模型吧:

inp="lastread.txt"outp1 = "wiki.zh.text.model"outp2 = "wiki.zh.text.vector"model = Word2Vec(LineSentence(inp), size=400, window=5, min_count=5, workers=4)model.save(outp1)model.save_word2vec_format(outp2, binary=False)

模型跑了一個多小時之後,終於結束了,我們看看,訓練出來多模型是什麼樣子的:

詞向量是什麼樣子的:

print type(model[u"數學模型"])print len(model[u"數學模型"])

結果:

<type "numpy.ndarray">400

詞向量為400維的向量。

找近似值:

result = model.most_similar(u"遠方")for each in result: print each[0] , each[1]

結果:

遠處 0.66281914711遙遠 0.579495191574天上 0.565921902657大海 0.545112609863另一邊 0.544482350349彼方 0.541613221169何方 0.541087567806高處 0.539955258369何處 0.53577029705那邊 0.532495379448

計算兩個詞之間的餘弦相似度:

sim1 = model.similarity(u"男朋友", u"女朋友")sim2 = model.similarity(u"學弟", u"學長")sim3 = model.similarity(u"美國", u"中國")sim4 = model.similarity(u"計算機", u"老太太")print sim1 print sim2print sim3print sim4

結果:

0.8534904067670.7318759221050.56048267699-0.202670932376

集合之間的相似度

list1 = [u"我", u"今天", u"很", u"傷心"]list2 = [u"中國",u"是", u"新", u"市場"]list3 = [u"心情", u"不好", u"想", u"打", u"人"]list_sim1 = model.n_similarity(list1, list2)print list_sim1list_sim2 = model.n_similarity(list1, list3)print list_sim2

結果:

0.3200819185240.679899988956

選出集合中不同類型的詞語:

list = [u"紐約", u"北京", u"美國", u"西安"]print model.doesnt_match(list)list = [u"紐約", u"北京", u"華盛頓", u"女神"]print model.doesnt_match(list)

結果

美國女神

到這裡打住吧,我是覺得這是一件很神奇的事情,冥冥之中感覺word2vec發現了語言的某種特徵,是人類語言學家沒有發現的,研究的角度不一樣,果然出來的結果也不一樣,是不是說,從NLP這條路,可以解除我英語不及格的魔咒。。。。。。哎,還是不要多想,老老實實碼字吧。

今天就先到這裡,晚安。


推薦閱讀:

自然語言處理和UI界面的全自動生成
寫了一篇識別文本情感的論文,用樸素貝葉斯方法;期刊回復沒有創新,拒錄。求建議?
有沒有好的中文髒話識別的解決方案?
小猿搜題用到了哪些牛逼技術?
廣告ctr預估有什麼值得推薦的論文?

TAG:自然语言处理 |