一、word2vec的原理就不介绍
原理可以参考码农场介绍:http://www.hankcs.com/nlp/word-vector-representations-word2vec.html
二、 gensim的介绍与使用
1. gensim安装
gensim是一个很好用的Python NLP的包,不光可以用于使用word2vec,还有很多其他的API可以用。
安装gensim是很容易的,使用"pip install gensim"即可。但是需要注意的是gensim对【numpy】和【scipy】的版本有要求,所会先要求你先升级numpy和scipy版本。同时需要注意pip的版本也需要升级对应版本。
安装成功的标志是你可以在代码里做下面的import而不出错:
在gensim中,word2vec 相关的参数都在包gensim.models.word2vec中。完整函数如下:
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=
1) sentences: 我们要分析的语料,可以是一个列表,或者从文件中遍历读出。对于大语料集,建议使用BrownCorpus,Text8Corpus或lineSentence构建。
2) size: 词向量的维度,默认值是100。这个维度的取值一般与我们的语料的大小相关,视语料库的大小而定。
3) alpha: 是初始的学习速率,在训练过程中会线性地递减到min_alpha。
4) window:即词向量上下文最大距离,skip-gram和cbow算法是基于滑动窗口来做预测。默认值为5。在实际使用中,可以根据实际的需求来动态调整这个window的大小。对于一般的语料这个值推荐在[5,10]之间。
5) min_count::可以对字典做截断. 词频少于min_count次数的单词会被丢弃掉, 默认值为5。
6) max_vocab_size: 设置词向量构建期间的RAM限制,设置成None则没有限制。
7) sample: 高频词汇的随机降采样的配置阈值,默认为1e-3,范围是(0,1e-5)。
8) seed:用于随机数发生器。与初始化词向量有关。
9) workers:用于控制训练的并行数。
10) min_alpha: 由于算法支持在迭代的过程中逐渐减小步长,min_alpha给出了最小的迭代步长值。随机梯度下降中每 轮的迭代步长可以由iter,alpha, min_alpha一起得出。对于大语料,需要对alpha, min_alpha,iter一起调参,来选 择合适的三个值。
11) sg: 即我们的word2vec两个模型的选择了。如果是0, 则是CBOW模型,是1则是Skip-Gram模型,默认是0即CBOW模型。
12)hs: 即我们的word2vec两个解法的选择了,如果是0, 则是Negative Sampling,是1的话并且负采样个数negative大于0, 则是Hierarchical Softmax。默认是0即Negative Sampling。
13) negative:如果大于零,则会采用negativesampling,用于设置多少个noise words(一般是5-20)。
14) cbow_mean: 仅用于CBOW在做投影的时候,为0,则采用上下文的词向量之和,为1则为上下文的词向量的平均值。默认值也是1,不推荐修改默认值。
15) hashfxn: hash函数来初始化权重,默认使用python的hash函数。
16) iter: 随机梯度下降法中迭代的最大次数,默认是5。对于大语料,可以增大这个值。
17) trim_rule: 用于设置词汇表的整理规则,指定那些单词要留下,哪些要被删除。可以设置为None(min_count会被使用)。
18) sorted_vocab: 如果为1(默认),则在分配word index 的时候会先对单词基于频率降序排序。
19) batch_words:每一批的传递给线程的单词的数量,默认为10000。
以上就是gensim word2vec的全部参数,下面我们用一个实际的例子来学习word2vec。
3. gensim word2vec应用
文本数据:搜狗实验室新闻作为训练语料 搜狗实验室:http://www.sogou.com/labs/resource/ca.php
说明:原搜狗新闻语料较大,预处理方面在此就不累述。参考:https://blog.csdn.net/u010122972/article/details/79543061
由于目前只是为了练习使用gensim,使用的其中部分数据集,分词后大概有8M。
拿到了原文,我们首先进行分词,这里使用jieba分词完成。分词的结果,我们放到另一个文件中。代码如下, 加入下面的一串专有名词是为了结巴分词能更准确的把专有名词分出来,最后将分词后的结果保存在文件中。注意其中的编码的问题,读取方式是‘rb’。也可以添加字典,增加分词效果。
# -*-coding:utf-8 -*-
import jieba.analyse
import jieba
import os
#添加专有名词,增加分词力度
jieba.suggest_freq('中国社科院研究生院', True)
jieba.suggest_freq('德国ZF集团', True)
jieba.suggest_freq('技术换市场', True)
jieba.suggest_freq('中央企业', True)
jieba.suggest_freq('工作会议', True)
jieba.suggest_freq('国资委主任', True)
raw_data_path = 'F:/sougou_data/'
cut_data_path = 'F:/sougou_cutdata/'
stop_word_path = 'F:/sougou_cutdata/stopwords.txt'
def stopwordslist(filepath):
stopwords = [line.strip() for line in open(filepath, 'rb').readlines()]
return stopwords
def cut_word(raw_data_path, cut_data_path ):
data_file_list = os.listdir(raw_data_path)
corpus = ''
temp = 0
for file in data_file_list:
with open(raw_data_path + file,'rb') as f:
print(temp+1)
temp +=1
document = f.read()
document_cut = jieba.cut(document, cut_all=False)
# print('/'.join(document_cut))
result = ' '.join(document_cut)
corpus += result
# print(result)
with open(cut_data_path + 'corpus.txt', 'w+', encoding='utf-8') as f:
f.write(corpus) # 读取的方式和写入的方式要一致
stopwords = stopwordslist(stop_word_path) # 这里加载停用词的路径
with open(cut_data_path + 'corpus.txt', 'r', encoding='utf-8') as f:
document_cut = f.read()
outstr = ''
for word in document_cut:
if word not in stopwords:
if word != '\t':
outstr += word
outstr += " "
with open(cut_data_path + 'corpus1.txt', 'w+', encoding='utf-8') as f:
f.write(outstr) # 读取的方式和写入的方式要一致
if __name__ == "__main__":
cut_word(raw_data_path, cut_data_path )
分词之后的部分截图,词与词之间用空格间隔开
接下来,使用分词后的文本训练word2vec模型
直接就贴上相应的代码
# -*- coding: utf-8 -*-
from gensim.models import word2vec
import logging
##训练word2vec模型
# 获取日志信息
logging.basicConfig(format='%(asctime)s:%(levelname)s:%(message)s', level=logging.INFO)
# 加载分词后的文本,使用的是Text8Corpus类
sentences = word2vec.Text8Corpus(r'F:\sougou_cutdata\corpus.txt')
# 训练模型,部分参数如下
model = word2vec.Word2Vec(sentences, size=100, hs=1, min_count=1, window=3)
# 模型的预测
print('-----------------分割线----------------------------')
# 计算两个词向量的相似度
try:
sim1 = model.similarity(u'中央企业', u'事业单位')
sim2 = model.similarity(u'教育网', u'新闻网')
except KeyError:
sim1 = 0
sim2 = 0
print(u'中央企业 和 事业单位 的相似度为 ', sim1)
print(u'人民教育网 和 新闻网 的相似度为 ', sim2)
print('-----------------分割线---------------------------')
# 与某个词(李达康)最相近的3个字的词
print(u'与国资委最相近的3个字的词')
req_count = 5
for key in model.similar_by_word(u'国资委', topn=100):
if len(key[0]) == 3:
req_count -= 1
print(key[0], key[1])
if req_count == 0:
break
print('-----------------分割线---------------------------')
# 计算某个词(侯亮平)的相关列表
try:
sim3 = model.most_similar(u'新华社', topn=20)
print(u'和 新华社 与相关的词有:\n')
for key in sim3:
print(key[0], key[1])
except:
print(' error')
print('-----------------分割线---------------------------')
# 找出不同类的词
sim4 = model.doesnt_match(u'新华社 人民教育出版社 人民邮电出版社 国务院'.split())
print(u'新华社 人民教育出版社 人民邮电出版社 国务院')
print(u'上述中不同类的名词', sim4)
print('-----------------分割线---------------------------')
# 保留模型,方便重用
model.save(u'搜狗新闻.model')
# 对应的加载方式
# model2 = word2vec.Word2Vec.load('搜狗新闻.model')
# 以一种c语言可以解析的形式存储词向量
# model.save_word2vec_format(u"书评.model.bin", binary=True)
# 对应的加载方式
# model_3 =word2vec.Word2Vec.load_word2vec_format("text8.model.bin",binary=True)
程序运行的结果如下:
这就是大概word2vec对于中文基本使用,希望有点收获。训练的语料库还是较小,所以会有效果不太好的情况。
参考资料:
gensim函数库的Word2Vec的参数说明
gensim官网文档
用gensim学习word2vec(刘建平Pinard)
python结巴分词、jieba加载停用词表