word2vec 是 Google 于 2013年开源的一个用于获取词向量的工具包,作者是 Tomas Mikolov,不过现在他已经从 Google Brain 跳槽到了 Facebook Research,后来还参与了 fasttext 项目的研究。下面是我读博客 word2vec 中的数学原理 的一些笔记和总结。
统计语言模型(statistical language model)是自然语言处理里比较常见的一个概念,是建立在一段序列(比如一句话)上联合概率分布。比如 “我/特别/喜欢/跑步”这句话(’/’符号表示分词,假设我们序列的基本单位是词语),其概率可以分解(factorize)成
观察一下条件概率就可以发现,如果尝试对上面的每个概率建立概率分布,词表的大小将会非常大,要拟合的参数也非常大。因此上面只是理论分析,并不是实用,我们可以考虑一些近似的计算。考虑做 N-1 阶马尔可夫假设,即第 N 个词的概率,只依赖于其前面 N-1 个词的概率。这样就得到了 N-gram 模型。写成链式法则(chain rule)就是
如果词汇表的大小是 |V| ,那么 bigram 要学习的参数就是 p(wi|wj) ,共 |V|2 个。具体训练的做法就是,抽取一句话中的单词 w 和其对应的上下文 Context(w) ,最大化对数似然函数(log-likelihood function),即最大化概率 p(w|Context(w)) .
当然,除了 N-gram 模型,还有其他方法来做 language model,比如 Recurrent Neural Network Language Model 这篇论文。没错,作者也是 Tomas Mikolov,这个是他做 word2vec 之前的工作。
词向量的概念由 Bengio 在 2003 年的经典论文《A Neural Probabilistic Language Model》提出。他尝试用神经网络来学一个语言模型。在表示一个词的时候,如果用词典的序号表示,词与词之间的距离是序号之差,这样很没道理;如果用 one-hot 编码,可以保证每个词语之间的距离都是相等的,每个词语的维度都是词典的大小。
但是这篇论文则首次尝试了词嵌入(word embedding)的工作,即用更小的维度来表示一个词语,每个词都是这个连续的空间的一个稠密(dense)向量,这样可以表达更丰富的语义。这种用低维向量表示词的方法叫做词向量的分布式表示(Distributed Representation),因为词的语义被分散地存储在了向量的各个维度中(像分布式系统一样),每个维度都包含部分语义信息。不同词之间的相似度,可以用余弦距离来计算。
论文里的模型(见下图)也很简单,词嵌入使用一个矩阵 C 来表示,大小是词表大小乘以嵌入的维度,而前 n-1 个词在 C 中找到对应的词向量后,直接拼接到一起经过一个隐层神经元,再经过 Softmax 即可得到预测词的概率分布。模型的公式如下,
我们设置一个大小为 t 的窗口,在语料库里随机抽取一个词 wt ,这个核心词的前 c 个和后 c 个单词构成该词的上下文,即
在 word2vec 的第一篇论文《Efficient Estimation of Word Representations in Vector Space, 2013a》中,设计了两个模型来训练词向量,分别是 CBOW(Continuous Bag-of-Words)和 Skip-gram 模型。下图是取窗口大小 c = 2 的例子,
然而这篇论文里没有提到模型具体是怎么构建的,但是在第二篇论文《Distributed Representation of Words and Phrases and their Compositionality, 2013c》中,本来是要讲层次 Softmax 和负采样,顺便提了一下 Skip-gram 模型的公式。
Skip-gram 模型是尝试用 wt 预测 context(w) ,具体是最大化“均值对数似然概率”,
由此可见,这两个模型的原始做法都是做内积,经过 Softmax 后得到概率,因此复杂度很高。【此处该有复杂度分析】所以才有了 2013c 中的两种改进方法,即层次 Softmax 和负采样。
上面的 Softmax 每次和全部的词向量做内积,复杂度是 O(V) , V 是词典大小。如果考虑把每个词都放到哈夫曼树的叶节点上,那么复杂度就可以降为 O(logV) ,即树的高度,因为只需要预测从根节点到相应叶节点的路径即可。哈夫曼树的构造,是根据词的词频,逐渐把小的两个词频合并,从底向上知道合并只剩根节点这样子逐渐构建,然后往右子树的分叉都编号 0,左边都编号 1 得到。最后词频较大的,离根节点也会近,相应的哈夫曼编码也会很短。
如上图所示,是 CBOW + Hierarchical Softmax 组合的模型,如果是要预测这个词,那么要沿着路径(图中红色的线) (root,dw2,dw3,dw4,dw5)=(root,1,0,0,1) 一直走到目标叶节点。优化目标就是让每个非叶节点去预测要选择的路径,即让 σ(w⋅θwi) 趋近 dwi+1 的值。总体的目标函数就是,
哈夫曼树有个性质,叶节点的数量正好比非叶子结点多一个。这里的叶子节点个数就是词典大小,非叶子结点是 Hierarchical Softmax 的训练参数 θ ,因此这里的参数不能当做是词向量。词向量要用前面那套,即图里的 v .
基于负采样的训练方法感觉有点暴力,相当于是直接用多个二分类来做多分类问题。比如 CBOW + Negative Sampling 的模型,是用 xw 预测 w ,直接让 σ(xw⋅w) 预测 1,随机采几个词作为负例 u∈NEG(w) ,让 σ(xw⋅u) 预测 0,写成目标函数就是,
Skip-gram + Negative Sampling 的过程也类似,就不阐述了。
问题 1,介绍一下 word2vec
问题 2,对比 Skip-gram 和 CBOW
问题 3,对比 HS 和 负采样
问题 4,负采样为什么要用词频来做采样概率?
问题 5,为什么训练完有两套词向量,为什么一般只用前一套?
问题 6,对比字向量和词向量
博客参考
论文