一文弄懂word2vec(从源码解析)

一、简介

Word2Vec并非指一个模型,而是2013年Google开源的一个获取词向量的工具包,由于简单高效,大大降低了词向量在工业界的应用门槛。我们先来看下Word2Vec能够取得的效果:

相似词:通过向量间距离的远近来寻找相似词,如man的相似词woman;
词语线性运算:V(King) - V(man) + V(woman) = V(Queen)

由此可见,Word2Vec可以通过上下文将语义较好的嵌入到向量空间中。由于Word2Vec生成的词向量将自然语言的特征较好地融合进了低维度稠密词向量中,使用词向量进行后续的各种NLP任务便可以取得较好的结果。

要理解Word2Vec,我们主要需要了解其中的四个概念:

  • CBOW
  • Skip-gram
  • Hierarchical softmax
  • Negative Sampling

其中,前两个代表Word2Vec中两种不同的获取词向量的策略,或者说模型结构;后两个则是两种改进softmax计算复杂度过高问题的方法。

需要提到一点的是,这个词向量的维度(与隐含层节点数一致)一般情况下要远远小于词语总数 V 的大小,所以 Word2vec 本质上是一种降维操作——把词语从 one-hot encoder 形式的表示降维到 Word2vec 形式的表示。

作者论文:http://papers.nips.cc/paper/5021-distributed-representations-of-words-and-phrases-and-their-compositionality.pdf
word2vec原理分析:http://www.cnblogs.com/peghoty/p/3857839.html
[NLP] 秒懂词向量Word2vec的本质:https://mp.weixin.qq.com/s/aeoFx6sIX6WNch51XRF5sg

二、两种模型

1、CBOW

CBOW(Continuous Bag-of-Words Model)是一种根据上下文的词语预测当前词语的出现概率的模型。以当前词的周围词语作为输入,当前词作为输出。即上下文预测当前词。
在这里插入图片描述

  • 输入层: 包含当前词w(t)中的2c个词的词向量w(t-2)、w(t-1)、w(t+1)、w(t+2)。
  • 投影层: 将输入层的2c个向量做求和累加(实现代码中往往都是直接使用均值)。
    在这里插入图片描述
  • 输出层: 从投影层到输出层一般使用softmax求概率,其中每个单词对应的多个上下文单词实际上是共享一个权重矩阵 。为了加速训练并且提高词向量的质量,可以采用我们采用Huffman树或负采样(negative sampling)的方法来进行权重更新。如下采用负采样的方式(主要使用tf.nn.nce_loss函数)实现:
    在这里插入图片描述

参考:
使用TENSORFLOW實作WORD2VEC CBOW:https://vinachangblog.wordpress.com/2017/08/13/使用tensorflow實作word2vec-cbow
一种源码实现:https://github.com/edwardbi/DeepLearningModels/blob/master/CBOW/TFCBOW.ipynb

2、Skip-Gram

Skip-gram只是逆转了CBOW的因果关系而已,以当前词作为输入,当前词的周围词作为输出。即当前词预测上下文。
在这里插入图片描述

  • 输入层: 只含有当前样本的中心词w的词向量
  • 投影层: 这是一个恒等投影,把v(w)投影到v(w),某些博文说词向量就是隐层权重矩阵就是源于此,因此,这个投影层其实是多余的,这里之所以保留投影层主要是方便与CBOW模型的网络结构做对比。从输入层到投影层的实现代码(代码见下文链接):
    在这里插入图片描述
    首先,通过tf.random_uniform函数产生字典对应的权重矩阵(其实质就是对应的词向量),输入层到投影层是通过tf.nn.embedding_lookup根据输入数据lookup到对应词向量。
  • 输出层: 从投影层到输出层同CBOW一样。区别在于直接使用每个(input word, output word)训练样本来作为我们的输入。如下采用负采样的方式(主要使用tf.nn.sampled_softmax_loss)实现:
    在这里插入图片描述

参考:
理解 Word2Vec 之 Skip-Gram 模型:https://zhuanlan.zhihu.com/p/27234078
基于TensorFlow实现Skip-Gram模型:https://zhuanlan.zhihu.com/p/27296712
一种代码实现:https://github.com/NELSONZHAO/zhihu/blob/master/skip_gram/Skip-Gram-Chinese-Corpus.ipynb
tensorflow官网examples的实现:https://github.com/tensorflow/tensorflow/blob/master/tensorflow/examples/tutorials/word2vec/word2vec_basic.py

三、Trick

模型的最后一层softmax层计算非常耗时,为了加速模型训练,使模型能够应用于大规模语料库。可以采用如下方式优化:

1、hierarchical softmax

本质是把 N 分类问题变成 log(N)次二分类

Hierarchical Softmax是一种对输出层进行优化的策略,输出层从原始模型的利用softmax计算概率值改为了利用Huffman树计算概率值。一开始我们可以用以词表中的全部词作为叶子节点,词频作为节点的权,构建Huffman树,作为输出。从根节点出发,到达指定叶子节点的路径是唯一的。Hierarchical Softmax正是利用这条路径来计算指定词的概率,而非用softmax来计算。

2、negative sampling

本质是预测总体类别的一个子集

Negative Sampling(简写NEG,负采样),这是Noise-Contrastive Estimation(简写NCE,噪声对比估计)的简化版本:把语料中的一个词串的中心词替换为别的词,构造语料 D 中不存在的词串作为负样本。在这种策略下,优化目标变为了:最大化正样本的概率,同时最小化负样本的概率。

参考:
word2vec原理(二) 基于Hierarchical Softmax的模型:https://www.cnblogs.com/pinard/p/7243513.html
word2vec原理(三) 基于Negative Sampling的模型:http://www.cnblogs.com/pinard/p/7249903.html

四、比较

根据Word2Vec作者Mikolov的说法,两者的比较如下:

  • Skip-gram: works well with small amount of the training data, represents well even rare words or phrases.(在小数据集和低频词能取得更好的效果。)
  • CBOW: several times faster to train than the skip-gram, slightly better accuracy for the frequent words.(CBOW训练速度更快,在高频词上效果优于Skip-gram。)

关于训练集大小:Skip-gram在数据集较小时能取得更好的效果;原因我认为有两点:1. 数据集较小时,低频词较多,Skip-gram对低频词的表示效果较好;2. 同样的语料库,Skip-gram能产生更多(子)样本。
关于训练速度:CBOW训练速度更快。这是因为,一个batch中,CBOW包含batch_size个中心词样本,Skip-gram包含batch_size/num_skips个中心词样本,同样的batch_size遍历一次样本集,CBOW需要更少的step。

参考:
BERT发展史(三)全方位多角度理解Word2Vec:https://www.jianshu.com/p/18a601ec9103
不懂word2vec,还敢说自己是做NLP?https://www.jianshu.com/p/cede3ae146bb

五、最佳实践

  • 生产环境训练过程一般直接使用基于Gensim的Word2Vec更好(底层还是google的word2vec)
    参考:基于Gensim的Word2Vec实现:https://zhuanlan.zhihu.com/p/24961011
  • word2vec一旦训练完,未登录词将无法取得向量,因此训练时候要求词料库尽量大而全,这个收集数据难度较高,在满足业务的前提下,建议直接用一些开源词向量即可。

开源词向量集:
腾讯AI Lab开源大规模高质量中文词向量数据(800万中文词): https://ai.tencent.com/ailab/nlp/embedding.html
Chinese Word Vectors中文词向量:https://github.com/Embedding/Chinese-Word-Vectors

  • 对一些未登录词,一般自定义向量,例如:
try:
    embedding = word2vec_dict[word]
except Exception:
    embedding = np.random.uniform(low_bound, high_bound, embed_size)
  • word2vec没有考虑语序,这里会有训练效果损失,在需要考虑一些语序的场景使用需注意。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值