如果在以词为基本单元输入的自然语言处理任务中,都避免不了使用词的表示,词的表示有很多种,这里主要介绍的就是词向量,word2vec是目前比较通用的训练词向量的工具,使用Gensim模块,可以使词向量的训练变的简单,那么我们知道对于word2vec来说,不论的Skip-Gram models还是CBOW models,他们的输入以及输出都是以单词为基本单位的,只是他们对应的输入以及输出不一样:
CBOW models:输入为多个上下文单词,输出目标为一个单词;
Skip-Gram models:输入为单个词,输出目标为多个上下文单词;
我们从上面可以看出,无论是Skip-Gram models还是CBOW models基本的单元都是词,那么我们获取到的语料,必须要经过分词处理以后才能用于词向量的训练语料。
1.数据的处理
这里我选用维基百科作为词向量模型的训练语料,如果还不知道怎么去处理维基百科数据,可以参考下面这篇文章,为了效率,我选择了个小的语料,当然对于词向量的训练,语料越大训练出来的结果越好:
得到的中文语料以后,最重要的就是要进行分词的操作了,这里使用jieba分词工具对语料进行精确模式的分词:
import jieba.analyse
import codecs
#以写的方式打开原始的简体中文语料库
f=codecs.open('zhwiki_jian_zh.txt','r',encoding="utf8")
#将分完词的语料写入到wiki_jian_zh_seg-189.5.txt文件中
target = codecs.open("wiki_jian_zh_seg-189.5.txt", 'w',encoding="utf8")
print('open files')
line_num=1
line = f.readline()
#循环遍历每一行,并对这一行进行分词操作
#如果下一行没有内容的话,就会readline会返回-1,则while -1就会跳出循环
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()
2.训练模型
有了分好词的语料,我们就可以通过Gensim模块中的word2vec函数来训练语料。
import logging
import os.path
import sys
import multiprocessing
from gensim.models import Word2Vec
from gensim.models.word2vec import LineSentence
#程序的入口
#1.如果当前脚本文件做模块供其他程序使用的话,不会执行if __name__ == '__main__':中的内容
#2.如果直接执行当前的额脚本文件的话,执行if __name__ == '__main__':中的内容
if __name__ == '__main__':
#1.os.path.basename('g://tf/code') ==>code
#2.sys.argv[0]获取的是脚本文件的文件名称
program = os.path.basename(sys.argv[0])
#指定name,返回一个名称为name的Logger实例
logger = logging.getLogger(program)
#1.format: 指定输出的格式和内容,format可以输出很多有用信息,
#%(asctime)s: 打印日志的时间
#%(levelname)s: 打印日志级别名称
#%(message)s: 打印日志信息
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:得到的词向量
inp, outp1, outp2 = sys.argv[1:4]
'''
LineSentence(inp):格式简单:一句话=一行; 单词已经过预处理并被空格分隔。
size:是每个词的向量维度;
window:是词向量训练时的上下文扫描窗口大小,窗口为5就是考虑前5个词和后5个词;
min-count:设置最低频率,默认是5,如果一个词语在文档中出现的次数小于5,那么就会丢弃;
workers:是训练的进程数(需要更精准的解释,请指正),默认是当前运行机器的处理器核数。这些参数先记住就可以了。
sg ({0, 1}, optional) – 模型的训练算法: 1: skip-gram; 0: CBOW
alpha (float, optional) – 初始学习率
iter (int, optional) – 迭代次数,默认为5
'''
model = Word2Vec(LineSentence(inp), size=400, window=5, min_count=5, workers=multiprocessing.cpu_count())
model.save(outp1)
#不以C语言可以解析的形式存储词向量
model.wv.save_word2vec_format(outp2, binary=False)
这里有一些训练词向量的调参技巧:
选择的训练word2vec的语料要和要使用词向量的任务相似,并且越大越好,论文中实验说明语料比训练词向量的模型更加的重要,所以要尽量收集大的且与任务相关的语料来训练词向量;语料小(小于一亿词,约 500MB 的文本文件)的时候用 Skip-gram 模型,语料大的时候用 CBOW 模型;设置迭代次数为三五十次,维度至少选 50,常见的词向量的维度为256、512以及处理非常大的词表的时候的1024维;
通过下面命令来执行Python文件:
python word2vec_model.py seg_filename model_name word2vec.vector
word2vec_model.py:存放训练代码的Python文件;seg_filename:分好词的训练语料;model_name:训练好的模型的名称;word2vec.vector:得到的词向量;
对于本例来说:
python word2vec_model.py wiki_jian_zh_seg-189.5.txt wiki_zh_jian_text.model wiki_zh_jian_text.vector
3.测试模型
有了词向量我们就可以使用词向量来做一些自然语言处理的任务了。那在这之前,我们需要测试一个模型是否训练成功。
from gensim.models import Word2Vec
en_wiki_word2vec_model = Word2Vec.load('wiki_zh_jian_text.model')
testwords = ['金融','上','股票','跌','经济']
for i in range(5):
res = en_wiki_word2vec_model.most_similar(testwords[i])
print (testwords[i])
print (res)
'''
result:
金融
[('金融业', 0.7712020874023438), ('房地产', 0.7530461549758911), ('银行业', 0.7478024959564209), ('保险业', 0.7240537405014038), ('金融机构', 0.7114974856376648), ('投资银行', 0.7104595899581909), ('证券', 0.7046274542808533), ('信贷', 0.7021963596343994), ('金融服务', 0.6956385374069214), ('公共事业', 0.6882480382919312)]
上
[('之上', 0.5678470134735107), ('上以', 0.4623713493347168), ('上面', 0.4558977782726288), ('上用', 0.42831096053123474), ('水性', 0.4084252119064331), ('上会', 0.3999699354171753), ('方面', 0.3975197672843933), ('上要', 0.3963406980037689), ('上仅', 0.3950901925563812), ('面上', 0.38935011625289917)]
股票
[('期货', 0.7636638879776001), ('债券', 0.7634198069572449), ('外汇', 0.7477541565895081), ('获利', 0.7359930276870728), ('期权', 0.7332447171211243), ('A股', 0.7319167852401733), ('存款', 0.7306094765663147), ('普通股', 0.7264690399169922), ('不动产', 0.724310040473938), ('证券', 0.7240179777145386)]
跌
[('滑落', 0.70113605260849), ('回落', 0.6962391138076782), ('涨', 0.6842378377914429), ('季尾', 0.6791133284568787), ('攀升', 0.6673789620399475), ('急跌', 0.6652034521102905), ('跌落', 0.6540493965148926), ('飙升', 0.6493663787841797), ('下跌', 0.6452913284301758), ('回升', 0.6349585652351379)]
经济
[('工商业', 0.631495475769043), ('国民经济', 0.6289297342300415), ('农业', 0.6132777333259583), ('生产力', 0.6094485521316528), ('金融', 0.5886996984481812), ('市场经济', 0.5880722403526306), ('旅游业', 0.585972011089325), ('对外贸易', 0.575571596622467), ('经济繁荣', 0.5738641023635864), ('金融业', 0.5717495083808899)]
'''