之前用word2vector模型,上网找原理,出现各种CSDN上的解答。看了一下,都是copy某个人写的东西,而且什么CBOW,什么Skip-Gram,什么哈夫曼树,层次softmax,概念很多,绕都给绕晕了。
看了很多遍,只知道个大概,具体还是没看懂。今天重新整理关于word2vector的原理。以一个好的脉络把这个模型理清楚。
原型:NNLM(Neural Network Language Model)
大家看原理一定看过下面这张图
这个模型其实就是一个结构简单的神经网络,MLP模型。输入层,隐藏层(也许有两层,看个人设计),接softmax输出。它的作用是通过前 N-1 个词,推测出第 N 个词是什么。
举个栗子,有一句话 “我今天中午吃的涮羊肉”。这个词要输出模型的话得把它先分词,分词成
”我“, ”今天“,”中午“,”吃的“,”涮羊肉“。要做的事情就是通过”我“, ”今天“,”中午“,”吃的“这四个词,来推测”涮羊肉“这个词。
怎么把这个场景建立模型呢。
输入层
首先建立一个词典,假设有30000个词,那么把”我“, ”今天“,”中午“,”吃的“用one-hot表示的话,每个词向量为 300001。那个图片里面的C是什么呢,这里叫做投影矩阵,投影到词空间的矩阵*。
到这里很多人就搞不清楚这个到底是个啥了。
换个方式理解,我们用word2vec的时候,最后每一个词是不是都会用一个向量表示,而表示方法是
[0.31343242, 0.65464122, 0.12343425, ..., -1.324344]
如果一个词是这样表示,那么整个词典是什么样的,是不是一个矩阵?这个矩阵就是投影矩阵训练完成,迭代得到的最后结果。
如果我们设定的矩阵维度D(超参数),那个这个投影矩阵的维度就是 D * V, C * 词向量(one-hot表示既在投影矩阵中取第n列来表示对应的词),维度表示是 D * V * V * 1 = D * 1
隐藏层
假设只有一个隐藏层,把 上一层中的词向量乘投影矩阵输入到这一层中,就是有一个权重矩阵H,(BP过程需要更新投影矩阵C和投影矩阵H),在通过tanh激活输出到下一层中。
输出层
这里接的是一个softmax,有多少个类呢,30000个。从词典中预测出现"涮羊肉"的概率。这就导致了一个问题,如果词典特别大,那么这一层的参数直接爆炸。2003年只有CPU用,这导致了模型效果并不好。巨神Bengio也在论文里说了这个模型要从最后一层进行改进。具体流程和计算公式可以看论文原文。
训练过程
这里我用的一句话, “我今天中午吃的涮羊肉”,去前4个词推第5个词。如果我取3个词,推第4个词,那么就是用”我“, ”今天“,”中午“,推"吃的", ”今天“,”中午“,”吃的“,推“涮羊肉”。相当于有一个滑动窗口不断在移动,逐渐训练模型的参数。
word2vecor
时间到了2013年,google另一位巨神Mikolov掏出了word2vector。而我们知道的CBOW(Continuous Bag-of-Words Model)和Skip-gram (Continuous Skip-gram Model),是word2vec的两种训练模式。
而负采样(Negative Sample)和层次softmax(Hierarchical Softmax)则是两种加速训练的方法。
CBOW / Skip-gram
CBOW的意思就是用上下文来预测当前词,如下图所示:
而Skip-gram就是用当前词来预测上下文,如下图所示:
两种形式大体上其实差不多,这里讲一下CBOW。
还是刚才那个句子,“我今天中午吃的涮羊肉”,而现在我需要用”我“, ”今天“,”吃的“,”涮羊肉“,来推出“中午”这个词。为什么要这样做呢,因为之前那个模型只考虑了前文,并没有后文的信息加入到预测中,word2vec把前后文信息也加入了。
这里的输入层处理方式和NNLM里是一样的,也是乘一个投影矩阵,最后我们需要的也是那个投影矩阵。
需要说一下的是隐藏层处理。这4个词得到4个词向量,在CBOW里,我们需要的是将这4个词向量做一个SUM操作,成为一个向量。
然后接一个softmax输出,还是类别数还是词典的大小。
结构如下图所示:
具体例子可以看对CBOW具体理解 这篇博客。
而Skip-gram就是从一个词推多个词,结构类似。具体可以看对Skip-gram的举例理解 这篇博客。
那么到这里,模型解决了,但是还是面临着softmax有太多参数,所以需要优化,加速训练。这里采用层次softmax和负采样的办法。
层次softmax
Hierarchical Softmax,层次softmax是一种加速训练的技巧,要解决的问题是原来softmax的参数太多的问题,所以不管是层次softmax也好,还是负采样也好,都是对最后的softmax做一个处理。
层次softmax的核心内容是哈夫曼树(Huffman Tree),树的核心概念是 出现概率越高的符号使用较短的编码(层次越浅),出现概率低的符号则使用较长的编码(层次越深)。
比如说一个二叉树结构,“我”肯定是第一层叶子节点,“涮羊肉”肯定是在最后一层的叶子节点。如下图:如果把哈夫曼结构替换掉之前的softmax,是不是在做一层层的二分类,最后分类需要的参数也会减少非常多。
这里可以看基于层次softmax的CBOW。
负采样
这里还有一种解决问题的思路,我们最后的softmax分出来的类是整个词袋的大小,那么是不是可以把词袋大小减小,因为有些出现概率低的词我们根本可以不考虑。这就是负采样的核心思想。
那么怎么选取频率较高的词,构成最后softmax要分的类呢。可以看这篇负采样具体做法。 (实在不想复制粘贴)
以上就是word2vector的全部内容。现在除了word2vector,还有GloVe做embedding,最后的结果类似。
word2vector存在的问题是,因为只考虑同时出现的概率,没有考虑到语意,所以对于多义词来说,word2vector就不好处理了。当然也有相关的改进,比如说加入人工标注等等。
推荐一个博客,讲的很透彻负采样
今天就到这,下次进行RNN/LSTM。