windows下使用word2vec训练维基百科中文语料全攻略!

浏览: 4039

训练一个聊天机器人的很重要的一步是词向量训练,无论是生成式聊天机器人还是检索式聊天机器人,都需要将文字转化为词向量,时下最火的词向量训练模型是word2vec,所以,今天小编文文带你使用维基百科训练词向量。

1、训练数据下载

我们使用维基百科训练词向量,维基百科数据的下载地址为:https://dumps.wikimedia.org/zhwiki/latest/zhwiki-latest-pages-articles.xml.bz2
下载后无需解压,中文维基百科的数据比较小,整个xml的压缩文件大约才1G

2、安装依赖库

下载数据之后,网上提供了现成的程序对xml进行解压,在网上找到了一个解析xml的py文件,命名为process_wiki.py。不过还需要对其进行修改,
将原有的output = open(outp, 'w'),修改为output = open(outp, 'w',encoding='utf-8')
否则会报下图的错误:

错误提示


在放完整的代码之前,我们需要安装一些依赖库,有numpy、scipy以及gensim,安装gensim依赖于scipy,安装scipy依赖于numpy。我们直接用pip安装numpy,在windows命令行下使用命令:
pip install numpy
成功安装numpy之后安装scipy,仍然使用命令pip install scipy,此时却发现报错了,其实,一般都会报错,正确的打开方式是去网站下载whl,再进行安装,去如下的网址下载scipy包:
http://www.lfd.uci.edu/~gohlke/pythonlibs/
找到相应版本的:

scipy.png


下载好之后使用pip命令安装即可:
pip install scipy-0.19.0-cp35-cp35m-win_amd64.whl
接下来使用命令  pip install gensim 即可。

3、将xml的wiki数据转换为text格式

使用下面的代码对数据进行处理,命名为process_wiki.py,这个代码是python2和python3通用的:

#!/usr/bin/env python
# Author: Pan Yang (panyangnlp@gmail.com)
# Copyrigh 2017

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',encoding='utf-8')
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 zhwiki-latest-pages-articles.xml.bz2 wiki.zh.text
不过发现报错了:

报错


这是因为我们的numpy版本不对,所以我们首先要使用pip卸载掉我们当前的numpy,然后去网站:http://www.lfd.uci.edu/~gohlke/pythonlibs/下载对应的numpy版本并安装即可:

numpy.png


随后使用刚才的命令执行,发现执行成功:

执行成功

4、繁简转换

上一篇中讲到了将文档从xml中抽取出来,下一步是将繁体字转换为简体字,那么我们使用opencc工具进行繁简转换,首先去下载opencc:https://bintray.com/package/files/byvoid/opencc/OpenCC
下载完成之后解压即可,随后使用命令:
opencc -i wiki.zh.text -o wiki.zh.jian.text -c t2s.json进行转换
效果如下:

转换前-繁体

转换后-简体

5、文章分词:

使用jieba分词器对文章及进行分词,代码如下:

import jieba
import jieba.analyse
import jieba.posseg as pseg
import codecs,sys
def cut_words(sentence):
#print sentence
return " ".join(jieba.cut(sentence)).encode('utf-8')
f=codecs.open('wiki.zh.jian.text','r',encoding="utf8")
target = codecs.open("wiki.zh.jian.seg.txt", 'w',encoding="utf8")
print ('open files')
line_num=1
line = f.readline()
while line:
print('---- processing', line_num, 'article----------------')
line_seg = " ".join(jieba.cut(line))
target.writelines(line_seg)
line_num = line_num + 1
line = f.readline()
f.close()
target.close()
exit()
while line:
curr = []
for oneline in line:
#print(oneline)
curr.append(oneline)
after_cut = map(cut_words, curr)
target.writelines(after_cut)
print ('saved',line_num,'articles')
exit()
line = f.readline1()
f.close()
target.close()

6、训练词向量

接下来就可以训练词向量啦,代码如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import logging
import os
import sys
import multiprocessing

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')
logging.root.setLevel(level=logging.INFO)
logger.info("running %s" % ' '.join(sys.argv))

# check and process input arguments
if len(sys.argv) < 4:
print(globals()['__doc__'] % locals())
sys.exit(1)
inp, outp1, outp2 = sys.argv[1:4]

model = Word2Vec(LineSentence(inp), size=400, window=5, min_count=5,
workers=multiprocessing.cpu_count(),iter=100)

# trim unneeded model memory = use(much) less RAM
# model.init_sims(replace=True)
model.save(outp1)
model.wv.save_word2vec_format(outp2, binary=False)

使用命令开始训练
python train_word2vec_model.py wiki.zh.jian.seg.txt wiki.zh.text.model wiki.zh.text.vector
发现训练开始:

模型训练ing

7、参数说明

上一步我们已经开始训练词向量,但是对于模型的参数并没有介绍,我们先来看一下源代码:

class gensim.models.word2vec.Word2Vec(sentences=None,size=100,alpha=0.025,window=5, min_count=5, max_vocab_size=None, sample=0.001,seed=1, workers=3,min_alpha=0.0001, sg=0, hs=0, negative=5, cbow_mean=1, hashfxn=<built-in function hash>,iter=5,null_word=0, trim_rule=None, sorted_vocab=1, batch_words=10000)

参数含义如下(转自http://blog.csdn.net/szlcw1/article/details/52751314):
· sentences:可以是一个·ist,对于大语料集,建议使用BrownCorpus,Text8Corpus或·ineSentence构建。
· sg: 用于设置训练算法,默认为0,对应CBOW算法;sg=1则采用skip-gram算法。
· size:是指特征向量的维度,默认为100。大的size需要更多的训练数据,但是效果会更好. 推荐值为几十到几百。
· window:表示当前词与预测词在一个句子中的最大距离是多少
· alpha: 是学习速率
· seed:用于随机数发生器。与初始化词向量有关。
· min_count: 可以对字典做截断. 词频少于min_count次数的单词会被丢弃掉, 默认值为5
· max_vocab_size: 设置词向量构建期间的RAM限制。如果所有独立单词个数超过这个,则就消除掉其中最不频繁的一个。每一千万个单词需要大约1GB的RAM。设置成None则没有限制。
· sample: 高频词汇的随机降采样的配置阈值,默认为1e-3,范围是(0,1e-5)
· workers参数控制训练的并行数。
· hs: 如果为1则会采用hierarchica·softmax技巧。如果设置为0(defau·t),则negative sampling会被使用。
· negative: 如果>0,则会采用negativesamp·ing,用于设置多少个noise words
· cbow_mean: 如果为0,则采用上下文词向量的和,如果为1(defau·t)则采用均值。只有使用CBOW的时候才起作用。
· hashfxn: hash函数来初始化权重。默认使用python的hash函数
· iter: 迭代次数,默认为5
· trim_rule: 用于设置词汇表的整理规则,指定那些单词要留下,哪些要被删除。可以设置为None(min_count会被使用)或者一个接受()并返回RU·E_DISCARD,uti·s.RU·E_KEEP或者uti·s.RU·E_DEFAU·T的函数。
· sorted_vocab: 如果为1(defau·t),则在分配word index 的时候会先对单词基于频率降序排序。
· batch_words:每一批的传递给线程的单词的数量,默认为10000

8、获取词向量

经过第6步,我们已经成功训练好了模型,并保存,想要测试训练的效果,我们首先要加载模型:

import gensim

model = gensim.models.Word2Vec.load('wiki.zh.text.model')

如何获取某个单词的词向量呢, 很简单,使用类似字典的方式即可:

print (model['计算机'])

由于我们在参数中设置的是将单词表示成500维的特征向量,所以输出是一个500维的向量

[ -5.21776974e-01  -1.24511528e+00   1.72550952e+00  -1.10107374e+00

..............................................
1.48737788e-01 6.13833666e-01 1.45513227e-03 2.48806804e-01]

如果有的单词不存在字典中,会报错

报错


所以在获取单词的词向量前,最好加一个判断:

if '计算机' in model:
print (model['计算机'])
else:
print ('单词不在字典中')

9、单词相似度计算

训练好的模型还可以计算单词之间的相似度,这里的相似度我理解的并不是同义词或者近义词,而是在给定的上下文中,最可能相互替换的词语。使用如下的方法获取一个单词的相似词语:

result = model.most_similar('计算机')
for e in result:
print (e[0], e[1])

结果输出:

休斯敦 0.5665031671524048
休士顿 0.5348116755485535
洛杉矶 0.48812389373779297
圣安东尼奥 0.4772784411907196
杰克逊 0.4631540775299072
奥斯汀 0.45239296555519104
达拉斯 0.4364917278289795
纽约 0.4348965883255005
芝加哥 0.43324437737464905
丹佛 0.43036091327667236

如何计算两个单词的相似度呢,使用如下的方法:

print (model.similarity('计算机','电脑'))

结果输出:

0.648130987661

模型还提供了一个方法,用于寻找离群词:

print (model.doesnt_match(u"早餐 晚餐 午餐 中心".split()))

结果输出

中心

我们还可以根据给定的条件推断相似词,比如下面的代码中,我们找到一个跟篮球最相关,跟计算机很不相关的第一个词:

print (model.most_similar(positive=['篮球'],negative=['计算机'],topn=1))

结果输出

[('棒球', 0.4819049835205078)]

至此,windows下使用word2vec训练维基百科中文语料全系列就到此结束啦,如果你喜欢我写的文章,可以帮忙给小编点个赞或者加个关注,我一定会互粉的!
如果你想与小编交流python的知识,欢迎加我微信(sxw2251):

我的微信

推荐 2
本文由 石晓文 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

0 个评论

要回复文章请先登录注册