DL4NLP——词表示模型(三)word2vec(CBOW/Skip-gram)的加速:Hierarchical Softmax与Negative Sampling
上篇博文提到,原始的CBOW / Skip-gram模型虽然去掉了NPLM中的隐藏层从而减少了耗时,但由于输出层仍然是softmax(),所以实际上依然“impractical”。所以接下来就介绍一下如何对训练过程进行加速。
paper中提出了两种方法,一种是Hierarchical Softmax,另一种是Negative Sampling。
本文简述了以下内容:
CBOW / Skip-gram模型的加速策略(一):Hierarchical Softmax
CBOW / Skip-gram模型的加速策略(二):Negative Sampling
CBOW / Skip-gram模型的加速策略(一):Hierarchical Softmax
拿原始模型来说,计算 \hat{\boldsymbol y} 的一个分量 \hat{y_{\underline i}}=P(w_{\underline i}|w_{t-m},...,w_{t-1},w_{t+1},...,w_{t+m})=\text{softmax}(z_{\underline i}) 时,由于使用的是softmax()函数,时间复杂度为 O(|\mathbb V|) ,因此计算代价很大,对大规模的训练语料来说,非常impractical。
Hierarchical Softmax是一种对输出层进行优化的策略,输出层从原始模型的利用softmax计算概率值改为了利用Huffman树计算概率值。
以词表中的全部词作为叶子节点,词频作为节点的权,构建Huffman树,作为输出。Huffman树是二叉树,在叶子节点及叶子节点的权给定的情况下,该树的带权路径长度最短(一个节点的带权路径长度指根节点到该节点的路径长度乘以该节点的权,树的带权路径长度指全部叶子节点的带权路径长度之和)。直观上可以看出,叶子节点的权越大,则该叶子节点就应该离根节点越近。因此对于模型来说就是,词频越高的词,距离根节点就越近。
从根节点出发,到达指定叶子节点的路径是唯一的。Hierarchical Softmax正是利用这条路径来计算指定词的概率,而非用softmax来计算。
图片来源:[2],记号改成和本文一致
上图是一个已根据词频构建好的Huffman树,各叶子节点代表词表中的各个词,非叶子节点共 |\mathbb V|-1 个。以词 w_{\underline 2} 为例,从根节点到该叶子节点的路径长度 L(w_{\underline 2})=4 ,各个节点依次被记为 n(w_{\underline 2},1) 、n(w_{\underline 2},2) 、n(w_{\underline 2},3) 和 n(w_{\underline 2},L(w_{\underline 2})) 。对于每个非叶子节点 n(w,j) ,虽然不是词表中的词,但也引入所谓的“输出词向量” \boldsymbol u_{n(w,j)} ,是需要学习的参数,为什么要引入它?下面讲述。
从根节点出发,走到指定叶子节点 w 的过程,就是一个进行 L(w)-1 次二分类的过程:路径上的每个非叶子节点都拥有两个孩子节点,从当前节点 n(w,j) 向下走时共有两种选择,走到左孩子节点 \text{ch}(n(w,j)) 就定义为分类到了正类,走到右孩子节点就定义为分类到了负类。
以CBOW模型为例,即输入层是 \hat{\boldsymbol v}_t 。用二项Logistic回归模型对每一次分类过程建模:从当前节点 n(w,j) 走到下一节点,那么走到左孩子节点的概率为
\sigma(\boldsymbol u_{n(w,j)}^\top \hat{\boldsymbol v}_t)
走到右孩子节点的概率为
1-\sigma(\boldsymbol u_{n(w,j)}^\top \hat{\boldsymbol v}_t)=\sigma(-\boldsymbol u_{n(w,j)}^\top \hat{\boldsymbol v}_t)
将上面两个式子统一起来,那就是
(双线括号的意思是,当括号内为真则输出1,为假则输出-1。因为这个符号渲染不出来,就用截图代替了)
现在计算输出词为 w 的概率:这对应于一条从根节点 n(w,1) 走到叶子节点 n(w,L(w)) 的路径,概率计算式为下式:
平均时间复杂度为 O(\log |\mathbb V|) ,相比于使用softmax()函数有很大提高。
对于Skip-gram模型,表达式类似:
可以证明,这样计算的结果满足概率和为1:
\sum_{i=1}^{|\mathbb V|}P(w_{\underline i}|w_{t-m},...,w_{t-1},w_{t+1},...,w_{t+m})=1
模型对语料中的全部词串计算概率值做连乘得到似然函数,再取对数得到对数似然 \mathcal L ,进而用极大似然估计来求取参数。使用SGD更新参数(求取梯度时,由于是SGD,所以 \mathcal L 的求和号可以去掉)。易知在Hierarchical Softmax的情况下每个词只会得到一个词表示(输入词向量)。梯度求取比较简单,[3] 写的非常详细并给出了参数更新过程的伪代码(Skip-gram部分写反了,应改为“各个周围词预测中心词再做连乘”,而非“中心词预测各个周围词再做连乘”)。
CBOW / Skip-gram模型的加速策略(二):Negative Sampling
第二种加速策略是Negative Sampling(简写NEG,负采样),这是Noise-Contrastive Estimation(简写NCE,噪声对比估计)的简化版本:把语料中的一个词串的中心词替换为别的词,构造语料 \mathbb D 中不存在的词串作为负样本。因此在这种策略下,优化目标变为了:最大化正样本的概率,同时最小化负样本的概率。对于一个词串 (w,c) ( c 表示 w 的上下文),用二项Logistic回归模型对其是正样本的概率建模:
P(\mathbb D=1|w,c)=\sigma(\boldsymbol u_{(w)}^\top \boldsymbol v_{(c)})
所以全部正样本的似然函数为
\prod_{(w,c)\in\mathbb D}P(\mathbb D=1|w,c)
同理,全部负样本的似然函数为
\prod_{(w,c)\notin\mathbb D}P(\mathbb D=1|w,c)
需要最大化前者同时最小化后者,也就是最大化下式:
\prod_{(w,c)\in\mathbb D}P(\mathbb D=1|w,c)\prod_{(w,c)\notin\mathbb D}(1-P(\mathbb D=1|w,c))
取对数得到对数似然:
\begin{aligned}\mathcal L=&\log\Biggr (\prod_{(w,c)\in\mathbb D}P(\mathbb D=1|w,c)\prod_{(w,c)\notin\mathbb D}(1-P(\mathbb D=1|w,c))\Biggr )\\=&\log\Biggr (\prod_{(w,c)\in\mathbb D}\sigma(\boldsymbol u_{(w)}^\top \boldsymbol v_{(c)})\prod_{(w,c)\notin\mathbb D}\sigma(-\boldsymbol u_{(w)}^\top \boldsymbol v_{(c)})\Biggr )\\=&\sum_{(w,c)\in\mathbb D}\log\sigma(\boldsymbol u_{(w)}^\top \boldsymbol v_{(c)})+\sum_{(w,c)\notin\mathbb D}\log\sigma(-\boldsymbol u_{(w)}^\top \boldsymbol v_{(c)})\end{aligned}
由于使用SGD,所以只需要知道对一个正样本 (w,c) 的目标函数。式中 NEG(w) 指 (w,c) 的负样本的中心词集合:
L=\log\sigma(\boldsymbol u_{(w)}^\top \boldsymbol v_{(c)})+\sum_{w_-\in NEG(w)}\log\sigma(-\boldsymbol u_{(w_-)}^\top \boldsymbol v_{(c)})
求梯度的过程依旧可以参照 [3]。
行文仓促,后面有机会再修正。
参考资料:
[1] Distributed Representations of Words and Phrases and their Compositionality, NIPS2013
[2] word2vec Parameter Learning Explained
[3] word2vec中的数学原理 - peghoty
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步