在《(一)理解word2vec:原理篇》中,我已经介绍了word2vec的相关应用和原理。在这篇博客中,我主要介绍word2vec的实践。

本篇博客的基础实践代码仍然参考刘新建老师的博客,在他文章的基础上,我又扩展了一些功能。

我用的实现word2vec的包是gensim(官方github)。gensim是一款开源的第三方Python工具包,用于从原始的非结构化的文本中,无监督地学习到文本隐层的主题向量表达。它支持包括TF-IDF,LSA,LDA,和word2vec在内的多种主题模型算法,支持流式训练,并提供了诸如相似度计算,信息检索等一些常用任务的API接口。

目录

一、gensim word2vec API概述

二、对原始语料分词

三、利用gensim实现word2vec

四、关于实践word2vec的一些问题

4.1 word2vec是word embedding 最好的工具吗?

4.2 word2vec 训练结果的差异主要来自什么因素?

4.2.1 语料影响最大

4.2.2 算法参数的影响

4.3 word2vec 影响速度的因素有哪些?

4.3.1 语言模型:cbow 比skip-gram 更快

4.3.2 迭代次数

4.3.3 线程数

4.3.4 其他参数

4.4 怎样评估word2vec训练的好坏?

4.4.1 词聚类

4.4.2 词cos 相关性

4.4.3 Analogy对比

4.4.4 使用tnse,pca等降维可视化展示

参考文献


一、gensim word2vec API概述

在gensim中,word2vec 相关的API都在包gensim.models.word2vec中。和算法有关的参数都在类gensim.models.word2vec.Word2Vec中。相关主页:word2vec,keyedvectors

算法需要注意的参数有:

1) sentences: 我们要分析的语料,可以是一个列表,或者从文件中遍历读出。后面我们会有从文件读出的例子。

2) size: 词向量的维度,默认值是100。这个维度的取值一般与我们的语料的大小相关,如果是不大的语料,比如小于100M的文本语料,则使用默认值一般就可以了。如果是超大的语料,建议增大维度

3) window:即词向量上下文最大距离,这个参数在我们的算法原理篇中标记为cc,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,则算法中的xwxw为上下文的词向量之和,为1则为上下文的词向量的平均值。在我们的原理篇中,是按照词向量的平均值来描述的。在原理篇中,我们用平均值来表示x_w,默认值也是1,不推荐修改默认值。

8) min_count:需要计算词向量的最小词频。这个值可以去掉一些很生僻的低频词,默认是5。如果是小语料,可以调低这个值。

9) iter: 随机梯度下降法中迭代的最大次数,默认是5。对于大语料,可以增大这个值。

10) alpha: 在随机梯度下降法中迭代的初始步长。算法原理篇中标记为\eta,默认是0.025。

11) min_alpha: 由于算法支持在迭代的过程中逐渐减小步长,min_alpha给出了最小的迭代步长值。随机梯度下降中每轮的迭代步长可以由iter,alpha, min_alpha一起得出。这部分由于不是word2vec算法的核心内容,因此在原理篇我们没有提到。对于大语料,需要对alpha, min_alpha,iter一起调参,来选择合适的三个值。

以上就是gensim word2vec的主要的参数,下面我们用一个实际的例子来学习word2vec。

二、对原始语料分词

 刘新建老师选择《人民的名义》的小说原文作为语料,语料原文在这里。在这里,我也用这个语料。由于这个原始语料就是小说,因此,我们应该先分词。采用jieba。

代码如下:

import jieba
import jieba.analysejieba.suggest_freq('沙瑞金', True) # 加入一些词,使得jieba分词准确率更高
jieba.suggest_freq('田国富', True)
jieba.suggest_freq('高育良', True)
jieba.suggest_freq('侯亮平', True)
jieba.suggest_freq('钟小艾', True)
jieba.suggest_freq('陈岩石', True)
jieba.suggest_freq('欧阳菁', True)
jieba.suggest_freq('易学习', True)
jieba.suggest_freq('王大路', True)
jieba.suggest_freq('蔡成功', True)
jieba.suggest_freq('孙连城', True)
jieba.suggest_freq('季昌明', True)
jieba.suggest_freq('丁义珍', True)
jieba.suggest_freq('郑西坡', True)
jieba.suggest_freq('赵东来', True)
jieba.suggest_freq('高小琴', True)
jieba.suggest_freq('赵瑞龙', True)
jieba.suggest_freq('林华华', True)
jieba.suggest_freq('陆亦可', True)
jieba.suggest_freq('刘新建', True)
jieba.suggest_freq('刘庆祝', True)
jieba.suggest_freq('赵德汉', True)with open('in_the_name_of_people.txt', 'rb') as f:document = f.read()     document_cut = jieba.cut(document)result = ' '.join(document_cut)result = result.encode('utf-8')with open('in_the_name_of_people_segment.txt', 'wb') as f2:f2.write(result)
f.close()
f2.close()

三、利用gensim实现word2vec

拿到了分词后的文件,在一般的NLP处理中,会需要去停用词。由于word2vec的算法依赖于上下文,而上下文有可能就是停词。因此对于word2vec,我们可以不用去停词。

现在我们可以直接读分词后的文件到内存。这里使用了word2vec提供的LineSentence类来读文件,然后套用word2vec的模型。在实际应用中,可以调参提高词的embedding的效果。

① 训练模型

# import modules & set up logging
import logging
from gensim.models import word2veclogging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
sentences = word2vec.LineSentence('in_the_name_of_people_segment.txt') model = word2vec.Word2Vec(sentences, hs=1, min_count=10, window=3, size=100)

② 选出最相似的5个词

# 选出最相似的5个词,方法一
for e in model.wv.similar_by_word('沙瑞金', topn =5):print (e[0], e[1])
'''
高育良 0.9234411716461182
田国富 0.8858301043510437
亮 0.8368291854858398
李达康 0.822664737701416
指示 0.8102874755859375
'''print ('*'*50)      # 选出最相似的5个词,方法二
for e in model.wv.most_similar(positive=['沙瑞金'], topn=5):print(e[0], e[1])
'''
高育良 0.9234411716461182
田国富 0.8858301043510437
亮 0.8368291854858398
李达康 0.822664737701416
指示 0.8102874755859375
'''   

2个方法的结果一样,可以看到能找到几个相关的词,但是也有噪音

③ 选出词汇相对于另一组词汇的对应词

# 选出词汇相对于另一组词汇的对应词
model.wv.most_similar(positive=['李达康', '欧阳菁'], negative=['侯亮平'])
'''
[('一个', 0.8564327359199524),('为', 0.8563842177391052),('老婆', 0.8343011140823364),('中国', 0.8328956961631775),('问题', 0.8306251764297485),('班子', 0.8267861604690552),('发展', 0.8258910179138184),('干部', 0.8231020569801331),('思路', 0.8212059140205383),('重要', 0.8195070028305054)]
'''

第3个是老婆,看来还是能get到欧阳菁是李达康的老婆。但是却找不到侯亮平的老婆?

④ 计算两个词的相似度

# 计算两个词的相似度
print(model.wv.similarity('沙瑞金', '季昌明'))
print(model.wv.similarity('沙瑞金', '田国富'))
'''
0.69518
0.88583
'''

沙瑞金和田国富都是书记,而季昌明是检察长,因此沙瑞金和田国富更相关。

⑤ 计算两个集合的相似度

# 计算两个集合的相似度
list1 = ['李达康', '欧阳菁']
list2 = ['侯亮平', '钟小艾']
print(model.wv.n_similarity(list1, list2))
'''
0.811746
'''

⑥ 选出集合中不同类的词语

# 选出集合中不同类的词语
list3 = ['沙瑞金', '李达康', '季昌明', '刘新建']
print(model.wv.doesnt_match(list3))
'''
刘新建
'''

刘新建明显跟他们3个不是一类的。

⑦ 查看词的向量值

# 查看词的向量值
print(model.wv.__getitem__(['沙瑞金']))  # 输出 一行100列的向量

⑧ 保存并读出训练好的模型

# 保存训练好的模型
model.save('model.bin')
# 读出训练好的模型
new_model =  word2vec.Word2Vec.load('model.bin')

在这篇文章里有更多模型保存和读入的例子。

上面实现了一个很简单的例子,在实际应用中,我们可以对word2vec进行调参提高embedding的准确性。有时间,自己会整理一个调参的代码。这里有一个调参的参考。

四、关于实践word2vec的一些问题

4.1 word2vec是word embedding 最好的工具吗?

word2vec并非是效果最好的word embedding 工具。最容易看出的就是word2vec没有考虑语序,这里会有训练效果损失

由于 word2vec训练速度快 ,易用,google出品 等,使得word2vec使用的人多。

训练快是因为word2vec只有输入层和输出层,砍去了神经网络中,隐藏层的耗时计算(所以word2vec并不算是一个深度学习算法)。另外,阅读word2vec的google的源码,会发现里面有一些提速的trick。如 sigmod函数,采用一次计算,以后查表,减去了大量的重复计算。如词典hash存储, 层次softmax等。

易用是因为word2vec公布了word2vec的代码。在tensorflow,gensim,spark mllib包中都有集成,使用方便。

4.2 word2vec 训练结果的差异主要来自什么因素?

4.2.1 语料影响最大

语料的场景,比如微博的语料和新闻语料训练的结果差别很大。因为微博属于个人发帖,比较随意。而新闻比较官方正式,另外新闻句式相对复杂。经过训练对比:微博这种短文,训练的相似词更多是同级别的相关词。比如 深圳 相关的是 广州 。而用新闻语料,训练得到 深圳 相关的词 更多是与 深圳 有关联的词,比如 深圳大学。

4.2.2 算法参数的影响

算法参数对总体效果影响不大。相对来说,比较重要的参数有以下:

① 子采样(subsampling)

子采样越低,对高频词越不利,对低频词有利。可以这么理解,本来高频词被迭代50次,低频词迭代10次,如果采样频率降低一半,高频词失去了25次迭代,而低频词只失去了5次。一般设置成le-5。个人觉得,降采样有类似tf-idf的功能,降低高频词对上下文影响的权重。

② 语言模型

skip-gram 和cbow,之前有对比,切词效果偏重各不相同。

从效果来看,感觉cbow对词频低的词更有利。这是因为cbow是基于周围词来预测某个词,虽然这个词词频低,但是它是基于周围词训练的基础上,通过算法来得到这个词的向量。通过周围词的影响,周围词训练的充分,这个词就会收益。

③ 窗口大小

窗口大小影响词和前后多少个词的关系,和语料中语句长度有关,建议可以统计一下语料中,句子长度的分布,再来设置window大小。

④ min-count

最小词频训练阀值,这个根据训练语料大小设置,只有词频超过这个阀值的词才能被训练。

根据经验,如果切词效果不好,会切错一些词,比如 “在深圳”,毕竟切错的是少数情况,使得这种错词词频不高,可以通过设置相对大一点的 min-count 过滤掉切错的词。

⑤ 向量维度

如果词量大,训练得到的词向量还要做语义层面的叠加,比如句子的向量表示用词的向量叠加,为了有区分度,语义空间应该要设置大一些,所以维度要偏大。一般情况下200维够用。

⑥ 其他参数

比如学习率,可以根据需要调。

4.3 word2vec 影响速度的因素有哪些?

4.3.1 语言模型:cbow 比skip-gram 更快

为什么 cbow更快,很重要的一个原因,cbow是基于周围词来预测这个单词本身 。而skip-gram是基于本身词去预测周围词。 那么,cbow只要 把窗口内的其他词相加一次作为输入来预测 一个单词。不管窗口多大,只需要一次运算。而skip-gram直接受窗口影响,窗口越大,需要预测的周围词越多。在训练中,通过调整窗口大小明显感觉到训练速度受到很大影响。

4.3.2 迭代次数

影响训练次数,语料不够的情况下,可以调大迭代次数。

4.3.3 线程数

单机版(google word2vec)可以通过设置多线程跑,集群版(spark mllib)可以设置多个partitions。但是从经验来看,在集群上设置partitions 过多,会影响训练的效果。

4.3.4 其他参数

采样频率 影响词的训练频率
min-count 最小词频 影响 训练词的数量
向量维度 维度决定了训练过程中计算的维度

4.4 怎样评估word2vec训练的好坏?

该篇论文介绍了word embedding 的评估方法。

4.4.1 词聚类

可以采用 kmeans 聚类,看聚类簇的分布

4.4.2 词cos 相关性

查找cos相近的词

4.4.3 Analogy对比

a:b 与 c:d的cos距离 (man-king woman-queen )

4.4.4 使用tnse,pca等降维可视化展示

在参考文献【3】中有用pca展示的代码。

参考文献

【1】15分钟入门Gensim

【2】python︱gensim训练word2vec及相关函数与功能理解

【3】How to Develop Word Embeddings in Python with Gensim

【4】关于word2vec,我有话要说

(二)理解word2vec:实践篇相关推荐

  1. 如何通俗理解Word2Vec

    如何通俗理解Word2Vec 看本文之前,建议先看此文:<BERT通俗笔记:从Word2Vec/Transformer逐步理解到BERT> 前言 今年上半年,我在我的上一篇LSTM博客中写 ...

  2. (一)理解word2vec:原理篇

    为什么想起来学习word2vec呢?其实之前自己根本没有接触过NLP的知识和任务,只是最近尝试使用了embedding的方法去处理类别特征和用embedding去做推荐,发现有不错的效果.同时,自己也 ...

  3. 让电脑读懂你的语言——如何理解 Word2Vec

    让电脑读懂你的语言--如何理解 Word2Vec 将单词向量化在 NLP 领域,是非常常见的一个技术.这篇文章介绍一下 Word2Vec 这个算法的具体思想.如果有什么理解不到位的地方也欢迎各位指正. ...

  4. 理解Word2vec

    理解Word2vec 一,词向量 首先需要理解词向量. 比如有一个城市的词汇表(北京,上海,宁夏,纽约,巴黎,,,,,南京)One-Hot Encoder按照如下方式: 杭州 [0,0,0,0,0,0 ...

  5. 理解 Word2Vec 之 Skip-Gram 模型

    20211003 NLP系列:Word2Vec原始论文:Efficient Estimation of Word Representations in Vector Space - 简书 原始论文翻译 ...

  6. word2vec原理_深入理解Word2Vec底层原理

    本文主要三个部分: (1)DNN如何计算字词的语义特征表示 (2)word2vec如何计算字词的语义特征表示 (3)霍夫曼对于word2vec的意义 词嵌入,就是将文本的单词嵌入数学空间中. 不同于o ...

  7. 【转】java提高篇(二)-----理解java的三大特性之继承

    [转]java提高篇(二)-----理解java的三大特性之继承 原文地址:http://www.cnblogs.com/chenssy/p/3354884.html 在<Think in ja ...

  8. word2vec预训练词向量+通俗理解word2vec+CountVectorizer+TfidfVectorizer+tf-idf公式及sklearn中TfidfVectorizer

    文章目录 文分类实(一) word2vec预训练词向量 2 数据集 3 数据预处理 4 预训练word2vec模型 canci 通俗理解word2vec 独热编码 word2vec (Continuo ...

  9. NLP自然语言处理学习笔记(二)Word2Vec

    NLP自然语言处理学习笔记(二)Word2Vec 一.Word2Vec 二.负采样 本文是根据吴恩达教授的教学视频来整理的学习笔记,部分图片来源于视频的截图.原教学视频连接 https://mooc. ...

最新文章

  1. POJ - 3660 Cow Contest(flod)
  2. POJ 2356 Find a multiple (抽屉原理)
  3. mapreduce编程实例python-Python模拟MapReduce的流程
  4. 提示You don't have permission to access /index.php on this server.
  5. C语言分区排序partition sort 算法(附完整源码)
  6. 不能将参数转化为lparam_反渗透纯水机是将自来水直接转化为超纯水的装置
  7. 字节跳动 java面经_字节跳动Java面经(已offer)
  8. IPv6实验1_IPv6地址配置
  9. 单纯形法求最小值的检验数_【运筹学】单纯形法(笔记和思考)
  10. 公众号 -「前端攻略 开光篇」
  11. buck电路 dac stm32_STM32定时器学习---基本定时器
  12. 列表[1,2,3,4,5],请使用map()函数输出[1,4,9,16,25],并使用列表推导式提取出大于10的数,最终输出[16,25]
  13. [转载] 机器学习模型的保存和调用
  14. 深度学习自学(六):Android人脸检测环境配置等相关问题
  15. 2017年前端该学些什么(译)
  16. 数字证书理解(CA证书签名原理)
  17. DataSource
  18. 【雷达原理】FMCW雷达简介
  19. 速营社团队分享互联网发展过程那些疯狂的时代
  20. 带有功利性的做一件事 ?

热门文章

  1. 跨境电商 阿里巴巴外贸 之 为什么我要做外贸!
  2. 大厂php笔试题,【大厂必备】2020超经典PHP面试题
  3. 如何将视频中的水印去掉,视频去水印哪个好
  4. 静电浪涌防护:TVS
  5. php realpath()
  6. EMC(1)——外设接口ESD防护电路设计
  7. i5四核八线程怎么样_四核八线程和六核六线程cpu相比哪个好?
  8. 天创速盈带您速读:怎么提升拼多多关键词综合排名?方案如下
  9. Ubuntu apt卸载
  10. ArcGIS如何将Excel表格转换为SHP格式