腾讯公开了训练好的语料库 语料地址,我决定拿来用用; 介绍上显示还是很强大的,下载下来解压16G,txt 格式。直觉告诉我这是好东西,然后……没有然后了,不知道该怎么用,忙工作去。
3天后…… 发现关键词 Word2vec,Gensim,一番搜索后,把环境配了一下 ubuntu 下 python3,pip3,gensim,Word2vec
sudo apt install -y python3-pip
sudo pip3 install --upgrade pip
sudo pip3 install gensim
sudo pip3 install jieba
注意 python 版本问题
测试代码
from gensim.models import KeyedVectors
model = KeyedVectors.load_word2vec_format(r'./model/Tencent_AILab_ChineseEmbedding.txt', binary=False,limit=50000)
print(model.most_similar(positive=['刘德华'], topn=10))
测试
python3 using_txt.py
输出结果:
[('周润发', 0.889106273651123), ('梁朝伟', 0.8705732226371765), ('张学友', 0.8653705716133118), ('古天乐', 0.8521826267242432), ('张国荣', 0.8434552550315857), ('成龙', 0.8371275663375854), ('周星驰', 0.8290221691131592), ('郭富城', 0.8202318549156189), ('李连杰', 0.8052970170974731), ('梅艳芳', 0.8025732040405273)]
到这里我们似乎已经成功了,其实还有几个疑点没有得到解决
1.速度有点慢,大概10秒才返回
2.可能出现目标词不在范围的问题
3.目前只加载了50000个热门词
4.如何训练自己的模型
5.如何在当前基础上继续增量训练
6.除了相似性还能干些什么
前三个问题,速度慢主要是因为加载模型慢,模型太大,目前没找到好办法,期待大佬指点;如果完整加载,应该不会出现不在范围的问题了。
后三个问题,让我们重头开始,做一下实践吧!
选择大家耳熟能详的《人民的名义》
建议去掉里面的标点符号并替换为空格,各种缩进,空行,最好也能替换成空格 我比较懒,直接去除中文以外的所有字符,然后一行一行的读入数据处理
google 了一个现成的代码
import jieba
import re
class MySentence(object):
def __init__(self,filename):
self.filename = filename
def __iter__(self):
lines = open(self.filename,'r',encoding='utf-8').readlines()
for line in lines:
#用正则剔除了除中文以外的所有字符
ChineseSentence = ''.join(re.findall(r'[\u4e00-\u9fa5]', line))
#jieba.cut生成的是生成器,这里要转换为列表
wordlist = list(jieba.cut(ChineseSentence))
yield wordlist
MySentences = MySentence(filename=r'./人民的名义.txt')
#训练模型
model = Word2Vec(sentences=MySentences,
size=200,
window=10,
min_count=10,
workers=4)
#保存模型
model.wv.save_word2vec_format(fname=r'./model/renmin_word2vec_binary.bin',binary=True)
然后你会看到这样的结果,表示训练成功
chris@xxx-s1:~$ python3 generate_model.py
Building prefix dict from the default dictionary ...
Loading model from cache /tmp/jieba.cache
Loading model cost 1.102 seconds.
Prefix dict has been built succesfully.
16.410267114639282
基本操作了,代码如下
from gensim.models import KeyedVectors
#导入模型
model = KeyedVectors.load_word2vec_format(r'./model/santi_word2vec_binary.bin', binary=True)
print(model.most_similar(positive=['高育良'], topn=10))
神马,返回结果说这个词都不在范围!!应该是人名识别有问题,决定使用jieba.add_word处理
搜集人名如下
侯亮平
陆亦可
沙瑞金
李达康
祁同伟
高育良
高小琴
吴惠芬
刘新建
陈岩石
季昌明
赵瑞龙
郑西坡
钟小艾
赵东来
蔡成功
欧阳菁
田国富
丁义珍
赵徳汉
易学习
王馥真
梁璐
程度
陈海
孙连城
郑胜利
林华华
周正
张宝宝
陈群芳
吴心仪
肖钢玉
王大路
吕梁
王国风
陈清泉
王文革
重新训练,测试 得到如下结果
[('沙瑞金', 0.9998887777328491), ('学生', 0.9998694062232971), ('向', 0.9998139142990112), ('祁同伟', 0.9998072385787964), ('汇报', 0.9998005628585815), ('看', 0.999794602394104), ('李达康', 0.999789297580719), ('易学习', 0.9997716546058655), ('意见', 0.9997698068618774), ('苦笑', 0.9997631311416626)]
[('你', -0.9805782437324524), ('我', -0.9833072423934937), ('大风', -0.9913561344146729), ('厂', -0.9914196729660034), ('的', -0.9919933080673218), ('山水', -0.9923231601715088), ('集团', -0.9933937788009644), ('说', -0.9943312406539917), ('持股', -0.9952439665794373), ('啊', -0.9957468509674072)]
看起来还是比较靠谱的,原来育良书记最亲近的是沙瑞金,最爱说汇报,经常苦笑,学生是祁同伟,经常提大风厂,山水集团,还有可能在其中持股
接下来看一下常规操作都有哪些。
1.语料中的词语数
print(len(model.vocab))
1637
2.计算两个词语的相似性,共现性,出现在一起的概率
print(model.similarity('李达康','欧阳菁')) print(model.similarity('高育良','欧阳菁'))
0.99961865 0.99909705
3.查找不合群的词
print(model.doesnt_match(['沙瑞金','李达康','侯亮平','高育良','王文革']))
王文革
4.近义词
print(model.most_similar(positive=['侯亮平','陆亦可'], topn=10))
[('赵东来', 0.9999196529388428), ('审讯', 0.9998973608016968), ('拿', 0.9998887777328491), ('面前', 0.9998874664306641), ('打开', 0.9998865127563477), ('走', 0.9998860955238342), ('张', 0.9998802542686462), ('及时', 0.9998802542686462), ('出', 0.9998796582221985), ('办公室', 0.9998794198036194)]
5.反义词
print(model.most_similar(negative=['高育良','赵瑞龙'], topn=10))
[('你', -0.9885416030883789), ('我', -0.990293562412262), ('说', -0.995975911617279), ('的', -0.9965078830718994), ('拘', -0.9965690970420837), ('哼', -0.9967851042747498), ('吗', -0.9971542954444885), ('高', -0.9972282648086548), ('在', -0.9972807168960571), ('您', -0.9973388314247131), ('同伟', -0.9975545406341553), ('吧', -0.9976481199264526), ('母亲', -0.9976506233215332), ('啊', -0.9977402687072754), ('一笑', -0.997803807258606), ('书记', -0.9978573322296143), ('啥', -0.997896671295166), ('持股', -0.9979396462440491), ('老师', -0.9980702996253967), ('众人', -0.9980815649032593)]
//todo::很烦,有许多干扰词
6.近义反义一起
print(model.most_similar(positive=['侯亮平','陆亦可'],negative=['祁同伟','丁义珍'], topn=10))
[('在', 0.028748536482453346), ('的', 0.024609221145510674), ('着', 0.02243509702384472), ('蔡成功', 0.02002798393368721), ('到', 0.019254302605986595), ('上', 0.01914154924452305), ('身后', 0.019096005707979202), ('走', 0.018249182030558586), ('屏幕', 0.018027106299996376), ('他', 0.01739991083741188)]
在gensim中,word2vec 相关的API都在包gensim.models.word2vec中。和算法有关的参数都在类gensim.models.word2vec.Word2Vec中。算法需要注意的参数有:
1) sentences: 我们要分析的语料,可以是一个列表,或者从文件中遍历读出。后面我们会有从文件读出的例子。
2) size: 词向量的维度,默认值是100。这个维度的取值一般与我们的语料的大小相关,如果是不大的语料,比如小于100M的文本语料,则使用默认值一般就可以了。如果是超大的语料,建议增大维度。
3) window:即词向量上下文最大距离,这个参数在我们的算法原理篇中标记为c,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,则算法中的xw为上下文的词向量之和,为1则为上下文的词向量的平均值。在我们的原理篇中,是按照词向量的平均值来描述的。个人比较喜欢用平均值来表示xw,默认值也是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一起调参,来选择合适的三个值。
gensim是一款强大的自然语言处理工具,里面包括N多常见模型:
基本的语料处理工具 LSI LDA HDP DTM DIM TF-IDF word2vec、paragraph2vec