词向量
词向量(word embedding)是为了让计算机能够处理的一种词的表示。
自然语言处理(NLP)相关任务中,要将自然语言交给机器学习中的算法来处理,通常需要首先将语言数学化,因为机器不是人,机器只认数学符号。向量是人把自然界的东西抽象出来交给机器处理的东西,基本上可以说向量是人对机器输入的主要方式。
词向量就是用来将语言中的词进行数学化的一种方式,顾名思义,词向量就是把一个词表示成一个向量。
词向量表示的方式主要有两种:
- One-Hot Representation
NLP相关任务中最常见的第一步是创建一个词表库并把每个词顺序编号。这实际就是词表示方法中的One-hot Representation,这种方法把每个词顺序编号,每个词就是一个很长的向量,向量的维度等于词表大小,只有对应位置上的数字为1,其他都为0。当然在实际应用中,一般采用稀疏编码存储,主要采用词的编号。举个例子:
“话筒”表示为 [0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 …]
“麦克”表示为 [0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 …]
这种 One-hotRepresentation 如果采用稀疏方式存储,会非常简洁:也就是给每个词分配一个数字 ID。比如刚才的例子中,话筒记为 3,麦克记为 8(假设从 0 开始记)。如果要编程实现的话,用 Hash 表给每个词分配一个编号就可以了。这么简洁的表示方法配合上最大熵、SVM、CRF 等等算法已经很好地完成了 NLP 领域的各种主流任务。这种表示方法一个最大的问题是无法捕捉词与词之间的相似度,就算是近义词也无法从词向量中看出任何关系。此外这种表示方法还容易发生维数灾难,尤其是在Deep Learning相关的一些应用中。
- Distributed Representation
Distributed representation 最早是 Hinton 在 1986 年的论文《Learning distributed representations of concepts》中提出的。其基本思想是通过训练将每个词映射成K维实数向量(K一般为模型中的超参数),通过词之间的距离(比如cosine相似度、欧氏距离等)来判断它们之间的语义相似度。虽然这篇文章没有说要将词做 Distributed representation,但至少这种先进的思想在那个时候就在人们的心中埋下了火种,到 2000 年之后开始逐渐被人重视。Distributed representation 用来表示词,通常被称为“Word Representation”或“Word Embedding”,中文俗称“词向量”。
Distributed representation 最大的贡献就是让相关或者相似的词,在距离上更接近了。向量的距离可以用最传统的欧氏距离来衡量,也可以用余弦夹角来衡量。用这种方式表示的向量,“麦克”和“话筒”的距离会远远小于“麦克”和“天气”。可能理想情况下“麦克”和“话筒”的表示应该是完全一样的,但是由于有些人会把英文名“迈克”也写成“麦克”,导致“麦克”一词带上了一些人名的语义,因此不会和“话筒”完全一致。word2vec使用的就是这种Distributed representation的词向量表示方式。
word2vec
简介
Word2vec 是 Google 在 2013 年开源的一款将词表征为实数值向量的高效工具,利用深度学习思想,通过训练,把对文本内容的处理简化为 K 维向量空间中的向量运算,而向量空间上的相似度可以用来表示文本语义上的相似度。
Word2vec输出的词向量可以被用来做很多 NLP 相关的工作,比如聚类、找同义词、词性分析等等。如果换个思路,把词当做特征,那么Word2vec就可以把特征映射到 K 维向量空间,可以为文本数据寻求更加深层次的特征表示。
Word2vec 使用的是 Distributed representation 的词向量表示方式。采用一个三层的神经网络“输入层-隐层-输出层”。有个核心的技术是根据词频用Huffman编码,使得所有词频相似的词隐藏层激活的内容基本一致,出现频率越高的词语,他们激活的隐藏层数目越少,这样有效的降低了计算的复杂度。
而Word2vec大受欢迎的一个原因正是其高效性,Mikolov在论文中指出,一个优化的单机版本一天可训练上千亿词。
这个三层神经网络本身是对语言模型进行建模,但也同时获得一种单词在向量空间上的表示,而这个副作用才是Word2vec的真正目标。
建模方式
- Continuous Bag-of-Words Model (CBOW,连续词袋模型)
它的做法是,将一个词所在的上下文中的词作为输入,而那个词本身作为输出,也就是说,看到一个上下文,希望大概能猜出这个词和它的意思。通过在一个大的语料库训练,得到一个从输入层到隐含层的权重模型。例如第l个词的上下文词是i,j,k,那么i,j,k作为输入,它们所在的词汇表中的位置的值置为1。然后,输出是l,把它所在的词汇表中的位置的值置为1。训练完成后,就得到了每个词到隐含层的每个维度的权重,就是每个词的向量。
这是一种与前向NNLM类似的模型,不同点在于CBOW去掉了最耗时的非线性隐层且所有词共享隐层。如上图所示。可以看出,CBOW模型是预测
$P(w(t)|w(t-k),w(t-(k-1))…,w(t-1),w(t+1),w(t+2)…,w(t+k))$
即用上下文来预测目标词。
- Skip-Gram (跳字模型)
它的做法是,将一个词所在的上下文中的词作为输出,而那个词本身作为输入,也就是说,给出一个词,希望预测可能出现的上下文的词。通过在一个大的语料库训练,得到一个从输入层到隐含层的权重模型。例如第l个词的上下文词是i,j,k,那么i,j,k作为输出,它们所在的词汇表中的位置的值置为1。然后,输入是l,把它所在的词汇表中的位置的值置为1。训练完成后,就得到了每个词到隐含层的每个维度的权重,就是每个词的向量。
具体来说,给定一个训练的句子:$w1,w2,w3,…,wt$
$skip-gram$模型的目标是最大化以下极大似然估计:
$$\frac{1}{T} \sum_{t=1}^T \sum_{-c \leq j \leq c,j\neq 0} \log P(w_{t+j}|w_t) $$
其中t表示单词表中的词数。j表示上下文窗口的大小。
如上图所示,输入一个词的向量表示,利用一个隐含层进行抽象,输出层节点数目等于单词表中词的数目。表示预测各词组成输入词上下文的概率,通常选用softmax来表示输出。
损失函数常选以上极大似然估计的相反数。可以选用一些常见的,如随机梯度下降(SGD)来训练模型。
即用一个词来预测一段目标上下文。
实现方式
回想word2vec的目的,是找出一种可以表达词与词之间隐含的相互关联的信息的词表示。那如何捕捉这些信息呢? 有一句话是这么说的:“词是没有意义的,除非它在语境之中。” 也就是说,我们要找出想要的信息,需要从词及其语境信息中得到。从概率的角度,也就是说我们要建模,使:
$$maxP(s(w,context(w_t))) \quad \quad \quad if\quad w==w_t$$
或者
$$max\prod_{t}P(s(w_t,context(w_t))) \quad \quad \quad w_t\in Corpus$$
其中$s(a,b)$表示$a,b$的某个关系函数。
- Hierarchical Softmax (层序softmax)
层序softmax利用了二叉树。树的每个叶子节点代表着词典V中的每个词。每个词$w_i$相应的词向量为$v_i$。以下图为例,来描述层序softmax的工作机制。
假设$l( w )$为从二叉树的根到代表词$w$的叶子节点的路径上的节点数,并设$n(w,i)$为该路径上第$i$个节点,该节点的向量为$\vec u_{n ( w , i )}$。以上图为例,$l(w_3)=4$。那么,跳字模型和连续词袋模型所需要计算的任意词$w_i$生成词$w$的概率为:
我们可以使用随机梯度下降在跳字模型和连续词袋模型中不断迭代计算字典中所有词向量$v$和非叶子节点的向量$u$。每次迭代的计算开销由$O ( | V | )$降为二叉树的高度$O ( \log | V | )$。
- negative sampling (负采样)
以跳字模型为例讨论负采样。
词典$V$大小之所以会在目标函数中出现,是因为中心词$w_c$生成背景词$w_o$的概率$P ( w_o ∣ w_c )$使用了$softmax$,而$softmax$正是考虑了背景词可能是词典中的任一词,并体现在$softmax$的分母上。
我们不妨换个角度,假设中心词$w_c$生成背景词$w_o$由以下相互独立事件联合组成来近似。
中心词 $w_c$ 和背景词$w_o$同时出现在该训练数据窗口
中心词 $w_c$ 和第$1$个噪声词$w_1$不同时出现在该训练数据窗口(噪声词 $w_1$ 按噪声词分布 $P ( w )$ 随机生成,假设一定和$w_c$不同时出现在该训练数据窗口)…
中心词 $w_c$ 和第$k$个噪声词 $w_k$ 不同时出现在该训练数据窗口(噪声词 $w_k$ 按噪声词分布 $P ( w )$ 随机生成,假设一定和 $w_c$ 不同时出现在该训练数据窗口)…
我们可以使用$σ ( x ) = 1 / ( 1 + exp ( − x ) )$函数来表达中心词$w_c$和背景词$w_o$同时出现在该训练 数据窗口的概率:
当我们把$K$取较小值时,每次随机梯度下降的梯度计算开销将由$O(|V|)$降为$O(K)$。
同样地,当我们把$K$取较小值时,每次随机梯度下降的梯度计算开销将由$O(|V|)$降为$O(K)$。