终于弄明白了gensim.word2vec怎么玩,说到底word2vec就是用共现矩阵来判断两个词语是不是相关,从而得出两个词语相似度高不高,这话听起来有问题~
但事实就是这样的,不管我们认为这两个词是不是近义词,只要放在一起,这两个词在窗口内经常一起出现,那它就是近义词,于是我用网上最著名的例子《人民的名义》做了实验:
需要的库有 gensim,jieba 使用pip安装即可。
人民的名义下载地址:http://files.cnblogs.com/files/pinard/in_the_name_of_people.zip
#-*-coding:utf-8 -*-
''' jieba分词 '''
import jieba.analyse
import jieba
from gensim.models import word2vec
jieba.suggest_freq('沙瑞金',True)
jieba.suggest_freq('田国富',True)
jieba.suggest_freq('高育良',True)
jieba.suggest_freq('侯亮平',True)
jieba.suggest_freq('钟小艾', True)
jieba.suggest_freq('陈岩石', True)
jieba.suggest_freq('欧阳菁', True)
jieba.suggest_freq('易学习', True)
jieba.suggest_freq('王大路', True)
jieba.suggest_freq('蔡成功', True)
jieba.suggest_freq('孙连城', True)
jieba.suggest_freq('季昌明', True)
jieba.suggest_freq('丁义珍', True)
jieba.suggest_freq('郑西坡', True)
jieba.suggest_freq('赵东来', True)
jieba.suggest_freq('高小琴', True)
jieba.suggest_freq('赵瑞龙', True)
jieba.suggest_freq('林华华', True)
jieba.suggest_freq('陆亦可', True)
jieba.suggest_freq('刘新建', True)
jieba.suggest_freq('刘庆祝', True)
jieba.suggest_freq('京州市', True)
jieba.suggest_freq('副市长', True)
jieba.suggest_freq('赵德汉',True)
with open('人民的名义.txt','rb') as f:
document=f.read()
document_cut=jieba.cut(document,cut_all=False)
result=' '.join(document_cut)
result=result.encode('utf-8')
with open('分词后的人民的名义.txt','wb+') as f1:
f1.write(result)
f.close()
f1.close()
因为人名我们不希望分割嘛,加进去。
就拿沙瑞金做实验吧。
沙瑞金这个人名后面不可能跟着饮料的名字,也就是说这“可乐”和“沙瑞金”怎么也不能被人类是作为同义词。
全局搜索沙瑞金然后替换一下。
do = "train"
if(do=="train"):
#加载此分类后的文本,使用的是Ttext2Corpus类
sentences=word2vec.Text8Corpus(r'分词后的人民的名义.txt')
#训练模型,部分参数如下
model=word2vec.Word2Vec(sentences,size=100,sg=1,hs=0,min_count=1,window=5)#,iter=10
model.save(u'人民的名义.model')#保留模型.方便重用
else:
#读取模型
model = word2vec.Word2Vec.load(u"人民的名义.model")
其中关于这个函数的参数解释:
在gensim中,word2vec 相关的API都在包gensim.models.word2vec中。和算法有关的参数都在类gensim.models.word2vec.Word2Vec
中。算法需要注意的参数有:
1) sentences: 我们要分析的语料,可以是一个列表,或者从文件中遍历读出。后面我们会有从文件读出的例子。
2) size: 词向量的维度,默认值是100。这个维度的取值一般与我们的语料的大小相关,如果是不大的语料,比如小于100M的文本语料,则使用默认值一般就可以了。如果是超大的语料,建议增大维度。
3) window:即词向量上下文最大距离,这个参数在我们的算法原理篇中标记为cc,window越大,则和某一词较远的词也会产生上下文关系。默认值为5。在实际使用中,可以根据实际的需求来动态调整这个window的大小。如果是小语料则这个值可以设的更小。对于一般的语料这个值推荐在[5,10]之间。
4) sg: 即我们的word2vec两个模型的选择了。如果是0, 则是CBOW模型,是1则是Skip-Gram模型,默认是0即CBOW模型。
5) hs: 即我们的word2vec两个解法的选择了,如果是0, 则是Negative Sampling,是1的话并且负采样个数negative大于0, 则是Hierarchical Softmax。默认是0即Negative Sampling。
6) negative:即使用Negative Sampling时负采样的个数,默认是5。推荐在[3,10]之间。这个参数在我们的算法原理篇中标记为neg。
7) cbow_mean: 仅用于CBOW在做投影的时候,为0,则算法中的xwxw为上下文的词向量之和,为1则为上下文的词向量的平均值。在我们的原理篇中,是按照词向量的平均值来描述的。个人比较喜欢用平均值来表示xwxw,默认值也是1,不推荐修改默认值。
8) min_count:需要计算词向量的最小词频。这个值可以去掉一些很生僻的低频词,默认是5。如果是小语料,可以调低这个值。
9) iter: 随机梯度下降法中迭代的最大次数,默认是5。对于大语料,可以增大这个值。
10) alpha: 在随机梯度下降法中迭代的初始步长。算法原理篇中标记为ηη,默认是0.025。
11) min_alpha: 由于算法支持在迭代的过程中逐渐减小步长,min_alpha给出了最小的迭代步长值。随机梯度下降中每轮的迭代步长可以由iter,alpha, min_alpha一起得出。这部分由于不是word2vec算法的核心内容,因此在原理篇我们没有提到。对于大语料,需要对alpha, min_alpha,iter一起调参,来选择合适的三个值。
#计算两个词向量的相似度
try:
sim1=model.similarity(u'沙瑞金',u'可乐')
except KeyError:
sim1=0
print(u'沙瑞金 和 可乐 的相似度为',sim1)
运行结果:
沙瑞金 和 可乐 的相似度为 0.9885233
啊哈,就应该是这样的。
再上一些其他代码把
print(u'与 沙瑞金 最相近的3个字的词')
req_count=5 #求出5个词
for key in model.similar_by_word(u'沙瑞金',topn=100):
if (len(key[0])>1): #字符长度1个字以上
req_count-=1
print(key[0],key[1]) #某一个词,某一个词出现的概率
if req_count==0:
break;
# #找出不同类的词
sim4=model.doesnt_match(u'沙瑞金 高育良 李达康 刘庆祝'.split())
print(u'这类人物中不同类的人名',sim4)