前言
词向量技术将自然语言中的词转化为稠密的向量,相似的词会有相似的向量表示,这样的转化方便挖掘文字中词语和句子之间的特征。生成词向量的方法从一开始基于统计学的方法(共现矩阵、SVD分解)到基于不同结构的神经网络的语言模型方法。这里总结一下比较经典的语言模型方法:word2vec、glove、ELMo、BERT。
其中BERT是最新Google发表的模型,在11个经典的NLP任务中全面超越最佳模型,并且为下游任务设计了简单至极的接口,改变了之前花销的Attention、Stack等盖楼似的堆叠结构的玩法,应该属于NLP领域里程碑式的贡献。
word2vec
word2vec来源于2013年的论文《Efficient Estimation of Word Representation in Vector Space》,它的核心思想是通过词的上下文得到词的向量化表示,有两种方法:CBOW(通过附近词预测中心词)、Skip-gram(通过中心词预测附近的词):
CBOW :
通过目标词的上下文的词预测目标词,图中就是取大小为2的窗口,通过目标词前后两个词预测目标词。具体的做法是,设定词向量的维度d,对所有的词随机初始化为一个d维的向量,然后要对上下文所有的词向量编码得到一个隐藏层的向量,通过这个隐藏层的向量预测目标词,CBOW中的做法是简单的相加,然后做一个softmax的分类,例如词汇表中一个有V个不同的词,就是隐藏层d维的向量乘以一个W矩阵( R d × V \mathbb{R}^{d \times V} Rd×V)转化为一个V维的向量,然后做一个softmax的分类。由于V词汇的数量一般是很大的,每次训练都要更新整个W矩阵计算量会很大,同时这是一个样本不均衡的问题,不同的词的出现次数会有很大的差异,所以论文中采用了两种不同的优化方法多层Softmax和负采样。
Skip-gram :
跟CBOW的原理相似,它的输入是目标词,先是将目标词映射为一个隐藏层向量,根据这个向量预测目标词上下文两个词,因为词汇表大和样本不均衡,同样也会采用多层softmax或负采样优化。
多层softmax :
由于单词出现的频率是不一样的,所以用哈夫曼编码构建一个二叉树,出现频率高的词放在前面可以减少计算量,用哈夫曼编码记录路径,例如图中单词2( w 2 w_2 w2,规定左边走是1,右边走是0)的哈夫曼编码就是1110,在路径上每到一个节点就是一个sigmoid的二分类,所以叫多层softmax。具体来说每个节点处会有一个d维的向量参数 θ \theta θ,每个单词也是d维的向量 x w x_w xw,一个sigmoid的方程决定向左或者右走的概率,往左走的概率是:
P ( + ) = σ ( x w T θ ) = 1 1 + e − x w T θ P(+) = \sigma(x_w^T\theta) = \frac{1}{1+e^{-x_w^T\theta}} P(+)=σ(xwTθ)=1+e−xwTθ1
将路径上的概率连乘,极大化这个概率值,就是模型的训练目标,每次用一个样本更新梯度,使用对数似然函数:
L = ∑ j = 2 l w ( 1 − d j w ) l o g [ s i g m a ( x w T θ j − 1 w ) ] + d j w l o g [ 1 − s i g m a ( x w T θ j − 1 w ) ] L = \sum^{l_w}_{j=2}(1 - d_j^w)log[sigma(x_w^T\theta^w_{j-1})] + d_j^wlog[1 - sigma(x_w^T\theta^w_{j-1})] L=j=2∑lw(1−djw)log[sigma(xwTθj−1w)]+djwlog[1−sigma(xwTθj−1w)]
其中 l w l_w lw代表目标词在哈夫曼树中的深度, d j w d_j^w djw代表在j层中目标词根据哈夫曼编码的路径应该向左还是向右走,左是1右是0,可以看到整个目标函数跟逻辑回归是基本相似的,梯度的计算也跟逻辑回归基本一样。
对于CBOW,多层softmax是将窗口内的2c个词求平均得到 x w x_w xw,放入哈夫曼树的网络中,每一层得到的梯度更新哈夫曼树中的参数,同时梯度同步更新到2c个单词的向量中。
对于Skip-gram,多层softmax是用目标词的词向量为 x w x_w xw,然后遍历窗口内的2c个词,一个进行2c次的训练,每次将 x w x_w xw放进哈夫曼树中,更新 x w x_w xw和树中的参数。
负采样 :
负采样也是把模型变为二元的逻辑回归,每个词对应一个词向量 x w x_w xw和词的网络参数 θ w \theta_w θw,每个词附近有2c个词,通过负采样,随机采样neg个反例,让正例词对目标词的词向量和窗口内词的网络参数的乘积尽可能的大,反例的尽可能小,是模型的训练目标。例如在skip-gram中目标词A的词向量是 x A x_A x