练习-word2vec

练习-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: PyCharm
from __future__ import print_function

import logging
import os.path
import six
import sys

from gensim.corpora import WikiCorpus

if __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') + '\n')
        # ###another method###
        #    output.write(
        #            space.join(map(lambda x:x.decode("utf-8"), text)) + '\n')
        else:
            output.write(space.join(text) + "\n")
        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)+'\n'
            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 sim2
print sim3
print sim4

结果:

0.853490406767
0.731875922105
0.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_sim1
list_sim2 = model.n_similarity(list1, list3)
print list_sim2

结果:

0.320081918524
0.679899988956

选出集合中不同类型的词语:

list = [u'纽约', u'北京', u'美国', u'西安']
print model.doesnt_match(list)
list = [u'纽约', u'北京', u'华盛顿', u'女神']
print model.doesnt_match(list)

结果

美国
女神


到这里打住吧,我是觉得这是一件很神奇的事情,冥冥之中感觉word2vec发现了语言的某种特征,是人类语言学家没有发现的,研究的角度不一样,果然出来的结果也不一样,是不是说,从NLP这条路,可以解除我英语不及格的魔咒。。。。。。哎,还是不要多想,老老实实码字吧。

今天就先到这里,晚安。

编辑于 2017-09-09

文章被以下专栏收录