使用gensim训练word2vec
# 安装
使用pip安装gensim
# 训练
# 导包
from gensim.models.keyedvectors import KeyedVectors
from gensim.models import word2vec
# 使用一个很小的英文语料
# 下载地址 http://mattmahoney.net/dc/text8.zip
sentences = word2vec.Text8Corpus('text8')
model = word2vec.Word2Vec(sentences, size=200, window=5, min_count=5)
# 设置向量为200维,窗口大小为5,忽略掉词频低于5的词
# 经过一段时间的等待,就训练完成了。
2
3
4
5
6
7
8
9
10
11
# 保存和载入
# 将训练好的模型保存到硬盘,文件名随意
model.save('text8.w2v.model')
# 将硬盘中的模型载入
model = KeyedVectors.load('text8.w2v.model')
2
3
4
5
6
# 体验
# 查看词向量
model = KeyedVectors.load('text8.w2v.model')
# 如果词不存在的话,会抛异常
# 计算两个词的相似度
model.similarity('boy', 'man')
# 寻找和某个词最相似的词(会输出词和相似度打分,本以为这个如果自己实现的话会很复杂,竟然在包里就提供了相关方法)
model.most_similar('good', topn=20)
# 寻找对应关系
model.most_similar('good', topn=20)
# 输出
[('mother', 0.7575523853302002),
('grandmother', 0.725717306137085),
('wife', 0.7087926268577576)]
# 识别不合群的词
model.doesnt_match('breakfast cereal dinner lunch'.split())
# 输出
'cereal'
# 获得词典中的词
model.wv.vocab.keys()
# 加一个len,查看长度,这里训练得到的是71290个词
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
啊,word2vec的使用体验真棒啊!
# ref
https://blog.csdn.net/liuyanfeier/article/details/76994489
下载了一些中文语料,并且拿来训练了多个不同的word2vec模型。针对不同应用领域,使用相应语料训练的word2vec应该会具有更好的性质。
# 使用中文维基百科语料训练word2vec
这部分内容主要参考了 AimeeLee77 (opens new window) 的教程,针对python3做了一丢丢小修改。
# 语料获取
下载地址 https://dumps.wikimedia.org/zhwiki/latest/zhwiki-latest-pages-articles.xml.bz2
这个地址速度很慢,可以用迅雷加速,或者用百度网盘先离线到网盘中,再从网盘下载。
# 预处理
文本提取
这份语料是xml格式,各篇文章放在同一个xml中,各篇文章中也包含了很多信息,因此需要先从xml中提取出文本。
xml的基本格式是前面先有个siteinfo,后面就是各个文章的page,page里面包含id、title、text等信息。
文本提取用gensim自带的针对维基百科语料的处理工具就行。
见github代码 /wiki/1-extract-text.py
# 使用gensim自带工具,将xml格式的wiki语料数据转换为text格式
# 每篇文章转换为1行文本,并去掉标点符号
import logging
import os.path
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))
if len(sys.argv) < 3:
print(globals()['__doc__'] % locals())
sys.exit(1)
inp, outp = sys.argv[1:3]
space = " "
i = 0
output = open(outp, 'w')
wiki =WikiCorpus(inp, lemmatize=False, dictionary=[])#gensim里的维基百科处理类WikiCorpus
for text in wiki.get_texts():#通过get_texts将维基里的每篇文章转换位1行text文本,并且去掉了标点符号等内容
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.")
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
繁体转简体
维基百科好多内容是繁体。使用opencc的包,编译好的程序直接拿过来用就行,一行命令搞定。 https://bintray.com/package/files/byvoid/opencc/OpenCC
opencc -i wiki.zh.txt -o wiki.zh.simp.txt -c t2s.json
这部分处理速度很快。
中文分词 仍然是每行一篇文章,但进行了分词,词语之间用空格隔开。
代码见 /wiki/2-jieba-cut.py
# 逐行读取文件数据进行jieba分词
import jieba
import jieba.analyse
import jieba.posseg as pseg #引入词性标注接口
import codecs,sys
if __name__ == '__main__':
f = codecs.open('/mnt/hgfs/shared/zhwiki-simp.txt', 'r', encoding='utf8')
target = codecs.open('/mnt/hgfs/shared/zhwiki-simp-seg.txt', 'w', encoding='utf8')
print('open files.')
lineNum = 1
line = f.readline()
while line:
if lineNum % 10000 == 0:
print('---processing ',lineNum,' article---')
seg_list = jieba.cut(line,cut_all=False)
line_seg = ' '.join(seg_list)
target.writelines(line_seg)
lineNum = lineNum + 1
line = f.readline()
print('well done.')
f.close()
target.close()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
原作者写的每切一行输出一次命令行,过多的输出会拖慢速度,所以改成10000行输出一次提示。
# 模型训练
模型训练就是用gensim自带的Word2Vec训练一下就行,可以指定skipgram还是cbow,可以指定词向量的维度大小,以及窗口大小等。训练之后将模型和词向量都保存到文件中。
代码见 /wiki/3-train-word2vec.py
#使用gensim word2vec训练脚本获取词向量
import warnings
warnings.filterwarnings(action='ignore', category=UserWarning, module='gensim')# 忽略警告
import logging
import os.path
import sys
import multiprocessing
from gensim.corpora import WikiCorpus
from gensim.models import Word2Vec
from gensim.models.word2vec import LineSentence
if __name__ == '__main__':
program = os.path.basename(sys.argv[0])
logger = logging.getLogger(program)
logging.basicConfig(format='%(asctime)s: %(levelname)s: %(message)s',level=logging.INFO)
logger.info("running %s" % ' '.join(sys.argv))
# inp为输入语料, outp1 为输出模型, outp2为原始c版本word2vec的vector格式的模型
fdir = '/mnt/hgfs/shared/'
inp = fdir + 'zhwiki-cn-simp-seg.txt'
outp1 = fdir + 'wiki.zh.text.model'
outp2 = fdir + 'wiki.zh.text.vector'
# 训练skip-gram模型
model = Word2Vec(LineSentence(inp), size=400, window=5, min_count=5,
workers=multiprocessing.cpu_count())
# 保存模型
model.save(outp1)
model.wv.save_word2vec_format(outp2, binary=False)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
训练过程中会输出提示信息,速度跟电脑有关,总的来说还比较快的。
使用模型 用的时候加载一下就可以了。(发现加载模型真的很吃内存啊,本想做个公网上线能用的,2G小水管云服务器根本带不起来这种大模型啊)
model = gensim.models.Word2Vec.load(fdir + 'wiki.zh.text.model')
#测试训练好的模型
import warnings
warnings.filterwarnings(action='ignore', category=UserWarning, module='gensim')# 忽略警告
import sys
import gensim
if __name__ == '__main__':
fdir = '/mnt/hgfs/shared/'
model = gensim.models.Word2Vec.load(fdir + 'wiki.zh.text.model')
word = model.most_similar(u"足球")
for t in word:
print t[0],t[1]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 500W微博语料
# 语料获取
http://www.nlpir.org/?action-viewnews-itemid-299