word2vec负采样中softmax的应用

word2vec可以说是整个embedding理论的基础,几乎所有的embedding方法,最终都会把序列用skip-gram或者是CBOW训练一把得到embedding。

word2vec的原理并不复杂,精妙的思想在于如何减少输出层softmax的计算量,相关的基础文章王喆大神都列出来了,最近在阅读,经常会有一些让人眼前一亮的点,做一个简单的记录。

word2vec理论提出的文章中,Mikolov et al,写得并不是很好懂,好在有几篇explained,比如这篇:word2vec Explained: Deriving Mikolov et al.’s Negative-Sampling Word-Embedding Method,另外一篇更详细一些,JinRong教授写的。

在计算输出矩阵时,激活函数是这样的:
p(c|w;\theta)=\frac {e^{v_c ·v_w}} {\sum_{c' \in C} e^{v_{c'} ·v_w}} (1)

进一步可以写成对数形式:
log(p(c|w;\theta))= v_c · v_w - log\sum_{c' \in C} e^{v_{c'} ·v_w} (2)

这里就有一个很尴尬的问题,当C,也就是我们的字典(vocabulary)的size很大的时候,这个softmax算的就会非常慢。

解决这个问题官方是有两种方案,1)层次softmax;2)负采样。
关于这两种方法刘建平大神以及其他各种ml博主都有写,我也写不了他们那么好,就不用多说了。但是为了说下面的东西,简单说一说负采样。

其实负采样一言以蔽之,就是把公式(1)中分母的C干掉。引入了这样的思想:只考察两个词wc,怎么能描述他们的关系呢?还是用上面的余弦距离。当我们认为w的embedding,也就是v_w是直接从输入矩阵中拿到的,这时候要学习的就是c的表示v_c,这时候论文中直接给出了一个softmax的表达:
p=\frac 1 {1+e^{-v_c·v_w}} (3)

光从这个公式上理解,还是可以接受的,当两个embedding接近的时候,余弦距离大,p \to 1,反之p \to 0

这里就有两个问题,感觉如果搞清楚这两点,负采样基本上就捋顺了:

  1. 理解上好像公式(1)和公式(3)表达的是一个意思,但是他们真正是等价的吗,有没有严格的推导过程?
  2. 公式(3)明明是个sigmoid函数啊,为什么说这是一个softmax呢?(这进一步引出,为什么好多人都说sigmoid跟softmax是一回事呢?)

首先说第一个问题,比较好的解释就是:使用了不同的目标函数,但是可以达到一样的效果,我可以通过一个多项分布概率(多分类,也就是softmax)来描述一件事情的概率,当然也可以用一个二分类(发生与否,也就是logistic regression)来描述它。这里使用的有点类似这个,请注意是类似,具体的区别在第二个问题里面会大概提一下。
举一个极端一些的栗子,在batch梯度下降的时候,每个batch只有一个样本v_w那么对于输出矩阵中的正样本的embedding肯定是学成v_c=v_w,对应的负样本一定是学成了v_c'=-v_w,如果是这样的话,softmax就基本上变成了如下,其中n就是字典vocabulary的大小:
p(c|w;\theta)=\frac 1 {1+e^{-n·v_c·v_w}}
这么一看,跟二分类没啥区别了就。

对于第二个问题,看上去这确实是一个sigmoid函数,但是为什么说它是个softmax呢,\frac 1 {1+e^{-wx}}在这个函数中,x是确定的值,w是需要训练的参数,但是在\frac 1 {1+e^{-v_wv_c}}中,v_wv_c是协同训练的两组参数(joint learned),所以确实不能称之为sigmoid。
事实上,在论文里面也提到,如果固定c训练w,或者反过来固定w训练c那这都会退化成为一个逻辑回归问题。
明白了这一点,为什么称之为softmax就稍微好解释一些了,下面是我自己的解释,softmax定义的是若干件事情发生的概率。对于两个出现在样本中的word也就是wc,根据内积输出v_w·v_c,对于未出现的pair,可以用两种方法来定义输出1)直接输出一个常数:对于所有负样本统一输出一个确定的值,优化会使得正样本输出更大;2)输出正样本的负值,也就是-v_w·v_c,表达的意思也类似,即尽量让负样本小。
这两种方法都可以构造出一个二分类的softmax,分别是\frac 1 {1+a·e^{-v_c·v_w}}\frac 1 {1+e^{-2·v_c·v_w}},其实优化起来跟公式(3)是完全一回事儿。

回答了这两个问题,其实接下去的事情就比较简单,或者说通畅。我们直接把公式(3)的softmax激活写成一个通用的激活形式\sigma(v_w·v_c),最后的损失函数就可以写成:

Loss=\sum_{c \in C_p}log(\sigma(v_w·v_c)) - \sum_{c' \in C_n}log(\sigma(v_w·v_c'))

题外话可以说说softmax和lr的关系,设想这样的一个简单的逻辑回归问题,用线性函数拟合对数几率的废话不多说,公式如下:
p(y=1)=\frac 1 {1+e^{-wx}} (4)

但是当我们把它当成是一个多分类问题的时候,写成softmax的样子,可以有:
p(y=0)=\frac {e^{w_0x}}{e^{w_0x}+e^{w_1x} }
p(y=1)=\frac {e^{w_1x}}{e^{w_0x}+e^{w_1x} }
把下面的公式稍微变化一下就写成:
p(y=1)=\frac 1 {1+e^{-(w_1-w_0)x}}

也就是说,当softmax是一个二分类问题的时候,其实没有必要训练两组参数,本质上就是一个逻辑回归问题,优化过程中,我们只关注w_1-w_0而不是这两组参数分别是多少。事实上,我们确实也无法求出他们准确的值来,或者说他们可以任意的数,因为在求偏导的时候\frac {\partial p} {\partial w_0}=\frac {\partial p} {\partial w_1}恒成立,迭代中只会优化它俩的差值。

问题:

  1. 关于目标函数的变换是我自己猜的,我也不知道有没有推导
  2. softmax那个,构造成一个二分类的事情,也是我猜的,没看到有人这么说
  3. 这个过程整体上是个协同训练,上面举的个随机梯度下降的例子也不知道是不是很合适

推荐阅读更多精彩内容