阅读笔记 - word2vec Parameter Learning Explained

论文内容

原文地址

感想

在上完CS224N头三节课后,我对word2vec没有产生很好的理解,于是在网上搜寻资料,无意间看到有人推荐这篇论文,于是立刻找来拜读,但第一次读是云里雾里的,于是在积攒了一些读论文的经验后,重看了一遍,觉得舒坦多了,特此记录一下。

连续词袋模型(CBOW)

这是Word2Vec原论文中提出的第一个训练任务,使用连续的上下文向量(context vector)来预测中心向量。
结构如下:
在这里插入图片描述
首先指定一些符号表示:
V V V:代表词表的大小,即总共有多少个词
N N N:隐藏层的单元数
W I W_I WI:从输入层到隐藏层的权重矩阵,形状为 V × N V\times N V×N
W O W_O WO:从隐藏层到输出层的权重矩阵,形状为 N × V N\times V N×V
w t w_t wt:代表输入的上下文词汇,其中 t ∈ V t\in V tV
w o w_o wo:代表预测的中心词
h h h:代表隐藏层
v ′ v^{'} v:代表 W O W_O WO中的列向量
v v v:代表 W I W_I WI中的行向量
这篇博客按照该论文的思路来叙述模型,所以先从最简单的情况入手,我们假设每一次仅通过一个上下文向量来预测中心词向量,于是,现在模型输入情况如下:
在这里插入图片描述
输入是one-hot形式的词向量,经过矩阵 W I W_I WI映射至中间的隐藏层,由于输入是one-hot形式,因此实际上这个操作相当于按该单词在词典中的位置从矩阵 W I W_I WI取出对应行向量。这个行向量也就是我们最后希望得到的词向量。然后经过第二个矩阵 W O W_O WO,来到输出层,注意隐藏层没有使用非线性的激活函数,而是直接将多项式送到输出层,最后用softmax得到单词的概率分布。
这里,输入只有一个上下文向量,因此,我们的目标是最大化条件概率 p ( w o ∣ w t ) p(w_o\vert w_t) p(wowt),即给定输入上下文向量,预测正确中心词的概率。而最大化概率,又等效于最小化概率的负对数。因此优化目标为最小化负对数似然 − log ⁡ ( p ( w o ∣ w t ) ) -\log\left(p(w_o\vert w_t)\right) log(p(wowt)),其中,条件概率的计算由下式得出:

p ( w o ∣ w ) = e x p ( v j ′ T h ) ∑ j = 1 V e x p ( v j ′ T h ) p(w_o\vert w)=\frac{exp(v_j^{'T}h)}{{\displaystyle\sum_{j=1}^V}exp(v_j^{'T}h)} p(wow)=j=1Vexp(vjTh)exp(vjTh)

于是,负对数似然 E E E又可以表示为:

− log ⁡ ( p ( w o ∣ w t ) ) = − ( v j ′ T h    −    log ⁡ ( ∑ j = 1 V e x p ( v j ′ T h ) ) ) -\log\left(p(w_o\vert w_t)\right) = -(v_j^{'T}h\;-\;\log\left(\sum_{j=1}^Vexp(v_j^{'T}h)\right)) log(p(wowt))=(vjThlog(j=1Vexp(vjTh)))

这就是训练时我们的目标函数。其中 v j T h v_j^Th vjTh实际上是最后输出层上每个单元的输出值,相当于是每个位置的一个分数。以下用 u j u_j uj代表每个位置的分数。
然后来观察一下参数是如何更新的:
模型中我们有两套矩阵需要更新参数,首先来看输出层到隐藏层的矩阵 W O W_O WO,对其中每个元素,梯度通过以下过程求得:
首先得到 E E E对每个输出单元分数 u j u_j uj的导数

∂ E ∂ u j    =    y j    −    t = e j \frac{\partial E}{\partial u_j}\;=\;y_j\;-\;t = e_j ujE=yjt=ej

其中, y j y_j yj表示每个输出单元经过softmax后输出的概率, t t t y j y_j yj表示正确中心词时为1,其余为0。我们把这步产生的结果视作每个输出单元与真实分布的误差 e j e_j ej
对于输出矩阵 W O W_O WO中的每个参数 w i j w_{ij} wij我们都有:

u j    =    ∑ i ∈ ∣ h ∣ w i j h i u_j\;=\;\sum_{i\in\left|h\right|}w_{ij}h_i uj=ihwijhi

于是由链式求导法则,得到下式:

∂ E ∂ w i j = ∂ E ∂ u j × ∂ u j ∂ w i j    =    e j h i \frac{\partial E}{\partial w_{ij}} = \frac{\partial E}{\partial u_j}\times\frac{\partial u_j}{\partial w_{ij}}\;=\;e_jh_i wijE=ujE×wijuj=ejhi

对应参数使用梯度下降更新( α \alpha α代表学习率):

w i j n e w    =    w i j o l d    −    α e j h i w_{ij}^{new}\;=\;w_{ij}^{old}\;-\;\alpha e_jh_i wijnew=wijoldαejhi

也可以用向量形式表示为:

v j ′ n e w    =    v j ′ o l d    −    α e j h v_j^{'new}\;=\;v_j^{'old}\;-\;\alpha e_jh vjnew=vjoldαejh

实际上,从公式中也可以看出,每一次更新,我们都会将输出中心词与词典中每一个词作比较,如果输出词的预测概率大于其真实概率(1或者0),即该词被错误预测,那么此时误差会大于0,更新时 W O W_O WO对应的词向量 v j ′ v_j^{'} vj会减去这部分信息,相反,若该词是正确的预测,误差会小于0,此时 v j ′ v_j^{'} vj会加上这部分的信息。同时,作为系数的一部分,误差 e j e_j ej也会随着预测概率与真实概率之间的接近程度而变化,从而影响信息的传递。
此外,虽然 W I W_I WI/ W O W_O WO中的行/列向量均可以视为词向量,但我们一般使用的是 W I W_I WI中的行向量。
接下来,梯度信号由隐藏层传至输出层,此时对 W I W_I WI进行参数更新,同理,我们由链式法则得到:

∂ E ∂ h i    =    ∑ j ∈ ∣ V ∣ ∂ E ∂ u j × ∂ u j ∂ h i = ∑ j ∈ ∣ V ∣ w i j e j \frac{\partial E}{\partial h_i}\;=\;\sum_{j\in\left|V\right|}\frac{\partial E}{\partial u_j}\times\frac{\partial u_j}{\partial h_i} = \sum_{j\in\left|V\right|}w_{ij}e_j hiE=jVujE×hiuj=jVwijej

∂ h i ∂ w j i    =    x j \frac{\partial h_i}{\partial w_{ji}}\;=\;x_j wjihi=xj

两式相乘,就得到了更新值。注意到此处的 x j x_j xj这代表输出层的第 j j j个单元,但由于输入是one-hot形式的编码。因此上式实际上只会对输入的词汇对应的权重进行更新,也就是说,仅有输入词对应的词向量会得到更新。
于是,两套矩阵就在不断的迭代中更新。在更新过程中,可以发现, W O W_O WO中的词向量基于中心词而不断被更新,而 W I W_I WI中则只有输入词的向量在被更新。

v j n e w    =    v j o l d    −    α E T v_j^{new}\;=\;v_j^{old}\;-\;\alpha E^T vjnew=vjoldαET

向量E中的每个元素都是对应隐单元对输入词向量位置的导数。
有了单个词的经验,CBOW中的更新就比较好理解了,由于使用词袋模型,此时输入变成:
在这里插入图片描述
对于 C C C个输入向量,我们取其向量之和 ∑ C x j \sum_Cx_j Cxj作为模型输入,此时隐藏层得到 C C C个词向量的均值。
从输出层到隐藏层到更新与单个上下文词汇的情况是完全一致的。唯一的区别在于隐藏层到输入层到更新。由于我们使用了 C C C个向量,因此在更新时需要对这 C C C个词向量进行更新。此时更新由下式完成:

v j , c n e w    =    v j , c o l d    −    1 C α E T v_{j,c}^{new}\;=\;v_{j,c}^{old}\;-\;\frac1C\alpha E^T vj,cnew=vj,coldC1αET

滑动词块模型(skip-gram)

这个翻译是我瞎整的,不知道中文应该怎么翻译,skip-gram模型与CBOW相反,其任务是用给定中心词预测上下文向量,模型结构与CBOW一样,都是一个三层前馈网络。

在这里插入图片描述
预测单个上下文向量的情形与CBOW中单个词的情形是完全等价的。就不再多写了。
当我们要预测c个上下文向量时,情况会有所不同。在CBOW中,我们通过最终预测与单个真实中心向量的误差来更新梯度。skip-gram中,我们有多个上下文向量。因此梯度更新时需要利用多个上下文向量的误差叠加。
此时,最小化目标变为以下对数似然:

− ∑ j ∈ ∣ C ∣ u j    +    C log ⁡ ( ∑ j ∈ ∣ V ∣ e x p ( u j ) ) -\sum_{j\in\left|C\right|}u_j\;+\;C\log\left(\sum_{j\in\left|V\right|}exp(u_j)\right) jCuj+Clog(jVexp(uj))

CBOW中,目标函数对每个预测位置的误差 e j e_j ej变成 ∑ ∣ C ∣ e c , j \sum_{\left|C\right|}e_{c,j} Cec,j,即累计 C C C个上下文向量在对应位置的误差,作为最终误差。
因此,由隐藏层到输出层的更新变为:

w i j n e w    =    w i j o l d    −    α h i ∑ ∣ C ∣ e c , j w_{ij}^{new}\;=\;w_{ij}^{old}\;-\;\alpha h_i\sum_{\left|C\right|}e_{c,j} wijnew=wijoldαhiCec,j

隐藏层到输入层到更新沿用前文的形式:

v j n e w    =    v j o l d    −    α E T v_j^{new}\;=\;v_j^{old}\;-\;\alpha E^T vjnew=vjoldαET

但此时,E中的元素变为:

∑ j ∈ ∣ V ∣ E h i w i j \sum_{j\in\left|V\right|}E_{h_i}w_{ij} jVEhiwij

其中

E h i = ∑ ∣ C ∣ e c , j E_{h_i} = \sum_{\left|C\right|}e_{c,j} Ehi=Cec,j

优化技巧(tricks)

从前文中的梯度更新公式可以看出,计算开销最大的部分就是计算softmax时的分母,每一次都是O(V)的操作,而在实践中,词典大小很可能会处于百万级别,这样的话,softmax将是一个开销很大的操作,导致训练速度变慢。
于是,在原文中,作者便提出了两个计算时的优化技巧。

Hierarchical Softmax

层次softmax,这个操作能够将原本O(V)的操作变为O(logV)。在层次softmax中,每一个词汇被预测到的概率由一条路径决定。具体如下:

在这里插入图片描述
如图所示,每个叶节点代表一个词典中的词,每一个内部结点都代表一个向量 w i ′ ( i ∈ L ) w_i^{'} (i\in L) wi(iL)其中 L L L代表树的深度。这些内部节点的向量是我们用来计算得分的向量,设预测词的词向量为 v v v,则每个节点代表的概率用sigmoid函数计算为 σ ( v T w i ′ ) \sigma(v{^T}w_i^{'}) σ(vTwi),其中,每个路径的概率由下式计算:

p ( w O = w I ) = ∏ i    =    1 L σ ( e ′ v T w i ′ ) p(w_O=w_I)=\prod_{i\;=\;1}^L\sigma(e^{'}v^{T}w_i^{'}) p(wO=wI)=i=1Lσ(evTwi)

其中 e ′ e^{'} e在当前节点为父节点的左孩子时取1,右孩子时取-1,这跟sigmoid函数的性质也有关,左右孩子的概率之和为1,且 σ ( − x ) = 1 − σ ( x ) \sigma(-x) = 1 - \sigma(x) σ(x)=1σ(x)
因此,路径上的概率之积就是对应预测词的概率。这里也容易知道所有预测词概率之和为1。
原文中,这棵树被构造为二叉赫夫曼树。这样,我们就将计算复杂度降到O(logV),是一个极大的提升。

Negative Sampling

负采样也是一种降低计算复杂度的技巧,其思想是这样:每一次都要更新 W O W_O WO中的所有向量太耗时了,我们可以考虑用一部分样本的更新来取代整体的更新,感觉跟dropout的想法类似,即每次仅更新一部分权重。
这部分样本就是所谓的负样本,CS224N中这样解释这些负样本:存在一些词,他们同时出现的概率很小,甚至根本不会一同出现,比如"I the a an cold"这样毫无逻辑的序列。因此,我们目标函数就是使这些词同时出现的概率最小化。
因此目标函数变为:

E    =    − log ⁡ ( σ ( v T h ) )      −    ∑ w ∈ w n e g a t i v e log ⁡ ( σ ( − w T h ) ) E\;=\;-\log\left(\sigma(v^Th)\right)\;\;-\;\sum_{w\in w_{negative}}\log\left(\sigma(-w^Th)\right) E=log(σ(vTh))wwnegativelog(σ(wTh))

这样,每一次更新参数仅有负样本对应的向量得到更新,计算速度大大加快。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值