斯坦福深度自然语言处理笔记:深入词向量训练
上次有讲到词向量背后的思想,还有提到用中心词预测周围词的方法来获得好的词向量。
最后有说 Word2vec 学习的几个步骤:
- 用中心词 c 和周围词 o 的向量,计算在o上下文的情况下有多大概率出现 c;
- 通过最大化以上概率,不断调整词向量。
关于调整词向量,最直接方法就是人为一个个看中心词和周围词上下文,然后基于向量计算知识手动调整。当然用屁股想想都知道这样不可能的,太麻烦了,那么大的词表!(其实过去那些编字典词典的就在做类似工作,无外乎一本词典可能就得编一辈子,安利电影《编舟记》。)
不能自己看,那总得从某地方得到如何调整的信息吧。于是就需要目标函数来反馈训练的信息了。
我们的目标是什么:最小化目标函数!
我们想要:通过数据,学习到中心词与正确上下文的关系,抽象点就是获得参数,来最大化正确上下文出现在某词周围的概率。
详细点解释,通过一套参数我们能确定其他词作为当前词上下文出现的概率,最初模型没学习时,模型可能会认为每个词作为上下文出现的概率都一样。而我们需要做的是“实事求是”,最大化现实场景中的上下文出现词的概率。
比如有个词“son”,开始模型没有看过任何数据学习,可能就对“beach”作为上下文,或“bitch”作为上下文出现,哪个概率大,没太多概念。但当看过数据,经过学习,就会知道后者概率大,而且也最符合实际。
于是似然函数(likelihood function)就是,在数据中,中心词对周围词的概率乘积:
我们希望参数 $\theta$ 能够最大化这个概率,使其符合现实数据。为了便于计算和最优化,于是对它加上对数 log,还有负号,就得到了目标函数 $J(\theta)$ :
然后问题就变成了最小化这个目标函数,也就是总说的最小化损失函数。回顾下就是,最小化目标函数 -> 最大化似然函数 -> 最大化预测准确。
啥是 P($w_{t+j}|w_t;\theta$)
好了,大的框架有了。再看看公式里,发现就只剩下一块硬骨头:
表面意思是,参数参数 $\theta$ 的情况下,$w_t$ 预测 $w_{t+j}$ 的概率,$t$ 就是当前词,加个 $j$ 当然就是想表示周围的词,所以$j$ 一般也不会太大。
但问题是,这个方程其实只是表示一个概念,具体怎么计算呢。
按照课程里,可以这样:
- 每个词 w 我们用两个向量 $v$,$u$
- $v$ 是作为中心词的时候
- $u$ 是作为上下文的时候
词 o 出现在中心词 c 上下文的概率就这样计算:
这里直接用最简单的点乘,然后加上个 softmax 来计算。
点乘是比较两个向量的相似性,乘积越大则可能越大;下面是 softmax 的正则化,使得出结果以概率表示(0到1的数)。
题外话,softmax 是相对一般的 hardmax 来说的,也就是一般的 max,取最大值。而 soft 字面意思就是没那么硬,虽然给大的更大的概率,但是小的也会分配些概率,更平滑。
为什么用俩矩阵
看过 word2vec 论文的童鞋,可能觉得为啥要俩向量矩阵啊。明明都一个词表,还特意分为中心词时的词向量表,和周围词的词向量表。
官方给出的解释是,优化起来简单。我猜可能是因为作业里代码都是直接 numpy 实现,也没有到什么框架。所以没麻烦地弄计算图什么的,如果一个矩阵,优化时梯度加和比较麻烦。
那么优化完后,我们用哪个矩阵作为词向量呢?课上说的是把两个平均一下来使用。
其实我感觉平均或用哪个效果可能不会差太多,因为在之后手动计算梯度的时候就会发现,一起出现的词向量会把对方往自己拉。
最后一步:最优化
要最小化上面说的目标函数,就要用到我们的好伙伴最优化理论里的 GD(graduate gradient descent),梯度下降法(还有一个很)。
经典的优化算法分两大类,直接法和迭代法,而 GD 属于迭代法,大概思路是每次找到更新的方向然后对参数进行更新,让每次的目标函数更小,直到最后到达最小值。
而这里的我们需要的方向就是目标函数的梯度,下面最右边那家伙:
这里有个练习,对目标函数分别求中心词向量 $v$ 和周围词向量$u$ 的导:
课程里有推导一个,可以参考自己推导,化简之后会得到很有意思的结论,发现之前想得复杂更新词向量原来干的是这玩意儿。