三、Word2Vec
3.1 CBOW 模型
CBOW
模型(continuous bag-of-word
):根据上下文来预测下一个单词。
3.1.1 一个单词上下文
在一个单词上下文的
CBOW
模型中:输入是前一个单词,输出是后一个单词,输入为输出的上下文。由于只有一个单词作为输入,因此称作一个单词的上下文。
一个单词上下文的
CBOW
模型如下:其中:
为隐层的大小,即隐向量 。
网络输入 ,它是输入单词(即上下文单词)的
one-hote
编码,其中只有一位为 1,其他位都为 0 。网络输出 ,它是输出单词为词汇表各单词的概率。
相邻层之间为全连接:
- 输入层和隐层之间的权重矩阵为
- 隐层和输出层之间的权重矩阵为
假设没有激活函数,没有偏置项。给定输入 ,则其对应的隐向量 为: 。
令:
由于 是个
one-hot
编码,假设它为词表 中第 个单词 ,即:则有:。
即: 的第 行 就是词表 中第 个单词 的表达,称作单词 的输入向量。
给定隐向量 ,其对应的输出向量 为: 。令:
则有: 。
- 表示词表 中,第 个单词 的得分。
- 为矩阵 的第 列,称作单词 的输出向量。
之后接入一层
softmax
层,则有:即 表示词汇表 中第 个单词 为真实输出单词的概率。
假设输入单词为 (它称作上下文) ,观测到它的下一个单词为 。令输入单词的对应的网络输入为 ,其隐向量为 ,输入输出单词对应的输出单元为 ,则采用交叉熵的损失函数为:
考虑语料库 中所有的样本,则整体经验损失函数为:
则网络的优化目标为:
设张量 为某个网络参数,则有:
则该参数的单次更新 ,可以表示为单个样本的多次更新:
因此本节的参数更新推导是关于单个样本的更新: 。
3.1.2 参数更新
定义 ,即第 个输出单元对应于真实的输出单词 时,它为1;否则为0。定义:
它刻画了每个输出单元的预测误差:
- 当 时: ,它刻画了输出概率 () 与真实概率 之间的差距。小于 0 表示预测不足。
- 当 时:,它刻画了输出概率 () 与真实概率 之间的差距。大于 0 表示预测过量。
根据: ,则有:
则 更新规则为:
其物理意义为:
- 当估计过量 () 时, 会减去一定比例的 。 这发生在第 个输出单元不对应于真实的输出单词时。
- 当估计不足 () 时, 会加上一定比例的 。这发生在第 个输出单元刚好对应于真实的输出单词时。
- 当 时,更新的幅度将非常微小。
定义:
根据: ,则有: 。
的物理意义为:词汇表 中所有单词的输出向量的加权和,其权重为 。
考虑到 ,则有:
写成矩阵的形式为: ,其中 为克罗内克积。
由于 是
one-hote
编码,所以它只有一个分量非零,因此 只有一行非零,且该非零行就等于 。因此得到更新方程:其中 为 非零分量对应的 中的行,而 的其它行在本次更新中都保持不变。
考虑更新 第 行的第 列,则:
- 当 时, 趋近于 0 ,则更新的幅度将非常微小。
- 当 与 差距越大, 绝对值越大, 则更新的幅度越大。
当给定许多训练样本(每个样本由两个单词组成),上述更新不断进行,更新的效果在不断积累。
根据单词的共现结果,输出向量与输入向量相互作用并达到平衡。
输出向量 的更新依赖于输入向量 : 。
这里隐向量 等于输入向量 。
输入向量 的更新依赖于输出向量 : 。
这里 为词汇表 中所有单词的输出向量的加权和,其权重为 。
平衡的速度与效果取决于单词的共现分布,以及学习率。
3.1.3 多个单词上下文
考虑输入为目标单词前后的多个单词(这些单词作为输出的上下文),输入为 个单词: 。对于每个输入单词,其权重矩阵都为 ,这称作权重共享。这里的权重共享隐含着:每个单词的表达是固定的、唯一的,与它的上下文无关。
隐向量为所有输入单词映射结果的均值:
其中: 表示第 个输入单词在词汇表 中的编号, 为矩阵 的第 行,它是对应输入单词的输入向量。
假设给定一个单词序列 (它称作上下文),观测到它的下一个单词为 。 对应的网络输出编号为 。
定义损失函数为交叉熵:
它的形式与
一个单词上下文
中推导的完全相同,除了这里的 不同。考虑语料库 中所有的样本,则整体经验损失函数为:
则网络的优化目标为:
.
与
一个单词上下文
中推导的结果相同,这里给出参数更新规则:更新 :
其中 。
更新 :
其中 :
- ,它是词汇表 中所有单词的输出向量的加权和,其权重为 。
- 为第 个输入单词在词表 中的编号。
在更新 时,如果有相同的输入单词(如: ),则在参数更新时认为它们是不同的。最终的效果就是在 中多次减去同一个增量 。
你也可以直接减去 , 其中 为词汇表中单词 在输入中出现的次数。
3.2 Skip-Gram
Skip-Gram
模型是根据一个单词来预测其前后附近的几个单词(即:上下文)。
3.2.1 网络结构
Skip-Gram
网络模型如下。其中:网络输入 ,它是输入单词的
one-hote
编码,其中只有一位为 1,其他位都为 0 。网络输出 ,其中 是第 个输出单词为词汇表各单词的概率。
对于网络的每个输出 ,其权重矩阵都相同,为 。这称作权重共享。
这里的权重共享隐含着:每个单词的输出向量是固定的、唯一的,与其他单词的输出无关。
Skip-Gram
网络模型中,设网络第 个输出的第 个分量为 ,则有:表示第 个输出中,词汇表 中第 个单词 为真实输出单词的概率。
因为 在多个单元之间共享,所以对于网络每个输出,其得分的分布 是相同的。但是这并不意味着网络的每个输出都是同一个单词。
并不是网络每个输出中,得分最高的单词为预测单词。因为每个输出中,概率分布都相同,即: 。
Skip-Gram
网络的目标是:网络的多个输出之间的联合概率最大。假设输入为单词 ,输出单词序列为 。定义损失函数为:
其中 为输出单词序列对应于词典 中的下标序列。
由于网络每个输出的得分的分布都相同,令 ,则上式化简为:
.
3.1.2 参数更新
定义 ,即网络第 个输出的第 个分量对应于第 个真实的输出单词 时,它为 1;否则为0。
定义:
它刻画了网络第 个输出的第 个分量的误差:
- 当 时: ,它刻画了输出概率 与真实概率 之间的差距。小于 0 表示预测不足。
- 当 时:,它刻画了输出概率 与真实概率 之间的差距。大于 0 表示预测过量。
根据: ,则有:
定义 ,它为网络每个输出的第 个分量的误差之和。于是有:
则有更新方程:
定义:
根据:
则有:
的物理意义为:词汇表 中所有单词的输出向量的加权和,其权重为 。
考虑到 ,则有:
写成矩阵的形式为: ,其中 为克罗内克积。
由于 是
one-hote
编码,所以它只有一个分量非零,因此 只有一行非零,且该非零行就等于 。因此得到更新方程:其中 为 非零分量对应的 中的行,而 的其它行在本次更新中都保持不变。
3.3 优化
原始的
CBOW
模型和Skip-Gram
模型的计算量太大,非常难以计算。模型在计算网络输出的时候,需要计算误差 。对于
CBOW
模型,需要计算 个误差(词汇表的大小),对于Skip-Gram
模型,需要计算 个误差。另外,每个误差的计算需要用到
softmax
函数,该softmax
函数涉及到 复杂度的运算: 。每次梯度更新都需要计算网络输出。
如果词汇表有
100万
单词,模型迭代100
次,则计算量超过 1 亿次。虽然输入向量的维度也很高,但是由于输入向量只有一位为 1,其它位均为 0,因此输入的总体计算复杂度较小。
word2vec
优化的主要思想是:限制输出单元的数量。事实上在上百万的输出单元中,仅有少量的输出单元对于参数更新比较重要,大部分的输出单元对于参数更新没有贡献。
有两种优化策略:
- 通过分层
softmax
来高效计算softmax
函数。 - 通过负采样来缩减输出单元的数量。
- 通过分层
3.3.1 分层 softmax
分层
softmax
是一种高效计算softmax
函数的算法。经过分层
softmax
之后,计算softmax
函数的算法复杂度从 降低到 ,但是仍然要计算 个内部节点的向量表达 。
a) 网络结构
在分层
softmax
中,字典 中的 个单词被组织成二叉树。叶子结点值为某个具体单词的概率(如下图中的白色结点)
中间节点值也代表一个概率(如下图中的灰色结点)。它的值等于直系子节点的值之和,也等于后继的叶子结点值之和,也等于从根节点到当前节点的路径的权重的乘积。
之所以有这些性质,是由于结点值、权重都是概率,满足和为1的性质
根据定义,根节点的值等于所有叶子结点的值之和,即为 1.0
二叉树的每条边代表分裂:
- 向左的边:表示选择左子节点,边的权重为选择左子节点的概率
- 向右的边:表示选择右子节点,边的权重为选择右子节点的概率
对于任意一个中间节点 , 假设其向量表达为 ,它是待求的参数。
选择左子节点的概率为:
选择右子节点的概率为 :
如果求得所有中间节点的向量表达,则根据每个中间节点的分裂概率,可以很容易的求得每个叶节点的值。
在分层
softmax
中,算法并不直接求解输出向量 ,而是求解二叉树的 个中间节点的向量表达 。当需要计算某个单词的概率时,只需要记录从根节点到该单词叶子结点的路径。给定单词 :
- 定义 为从根节点到单词 的路径的第 个节点(从 1 计数)。
- 定义 为从根节点到单词 的路径的长度。
- 定义 表示节点 的左子节点。
输出为单词 的概率为:
其中:
表示:从根节点到单词 的路径上,第 个节点是第 个节点的左子节点。
是一个函数。当 是个事实时,其值为 1;当 不成立时,其值为 -1。
表示:从根节点到单词 的路径上:
- 当第 个节点是第 个节点的左子节点时,函数值为 1
- 当第 个节点是第 个节点的右子节点时,函数值为 -1
表示:从根节点到单词 的路径上,第 个节点的向量表达
对于从根节点到单词 的路径上,从第 个节点到第 个节点的概率为:
因此 刻画了:从根节点到单词 的路径上,每条边的权重(也就是分裂概率)的乘积。
对于所有的叶子节点,有 。
利用数学归纳法,可以证明:
左子节点的值+右子节点的值=父节点的值
。上式最终证明等于根节点的值,也就是 1.0 。
b) 参数更新
为了便于讨论,这里使用
CBOW
的一个单词上下文
模型。记 为 , 定义损失函数对数似然:
则有:
其中:
定义:
为预测选择 的左子节点的概率。
的物理意义为:从根节点到单词 的路径上,第 个节点的选择误差:
- 如果下一个节点选择第 个节点的左子节点,则 , 此时 表示预测的不足。
- 如果下一个节点选择第 个节点的右子节点,则 , 此时 表示预测的过量。
考虑内部节点 ,其向量表达为 。则有:
得到向量表达为 的更新方程:
对于每个单词 ,由于它是叶节点,因此可以更新 个内部节点的向量表达。
当模型的预测概率较准确,即 时,则 接近0 。此时梯度非常小, 的更新幅度也会非常小。
当模型的预测概率较不准,则 较大。此时梯度会较大, 的更新幅度也会较大。
对于内部结点的向量表达 的更新方程适用于
CBOW
模型和Skip-Gram
模型。但是在Skip-Gram
模型中,需要对 个输出的每一个单词进行更新。CBOW
输入参数更新:对于CBOW
模型,定义:的物理意义为:二叉树中所有内部节点向量表达的加权和,其权重为 。
考虑到 ,则有:
写成矩阵的形式为: ,其中 为克罗内克积。
将 的更新分解为 次,每次对应于一个输入 。因此得到 的更新方程:
其中 为第 个输入单词在词表 中的编号。
Skip-Gram
输入参数更新:对于Skip-Gram
模型,定义:其中: 表示网络第 个输出的输出单词。
注意:由于引入分层
softmax
,导致更新路径因为输出单词的不同而不同。因此 会因为 的不同而不同。与
Skip-Gram
中推导相同, 的更新方程为:其中 为 非零分量对应的 中的行,而 的其它行在本次更新中都保持不变。
3.3.2 负采样
a) 原理
在网络的输出层,真实的输出单词对应的输出单元作为正向单元,其它所有单词对应的输出单元为负向单元。
正向单元的数量为 1,毋庸置疑,正向单元必须输出。
负向单元的数量为 ,其中 为词表的大小,通常为上万甚至百万级别。如果计算所有负向单元的输出概率,则计算量非常庞大。
可以从所有负向单元中随机采样一批负向单元,仅仅利用这批负向单元来更新。这称作负采样。
负采样的核心思想是:利用负采样后的输出分布来模拟真实的输出分布。
对于真实的输出分布,有:
对于负采样后的输出分布,假设真实输出单词 对应于输出单元 ,负采样的 个单词对应的输出单元 ,则有:
在参数的每一轮更新中,负采样实际上只需要用到一部分单词的输出概率。
对于未被采样到的负向单元 ,其输出单元的预测误差 , 则 不会被更新。
中仅有负采样的单元 起作用,因此 的更新仅仅依赖于正向单元和负采样的单元。
随着训练的推进,概率分布 逐渐接近于真实的分布 (第 位为 1),其绝大部分概率接近 0 、 接近 1 。
而概率分布 也有类似的性质,因此用概率分布 去模拟概率分布 效果较好。
负采样时,每个负向单元是保留还是丢弃是随机的。负向单元采样的概率分布称作
noise
分布,记做 。可以为任意的概率分布(通常需要根据经验来选择)。谷歌给出的建议是挑选 5~10 个负向单元,根据下面公式来采样:
其中: 为单词在语料库中出现的概率,分母仅考虑负向单元(不考虑正向单元)。
的物理意义为:单词在语料库中出现的概率越大,则越可能被挑中。
b) 参数更新
假设输出的单词分类两类:
- 正类:只有一个,即真实的输出单词
- 负类:从 采样得到的 个单词
论文
word2vec Explained: Deriving Mikolov et al.’s Negative-Sampling Word-Embedding Method
的作者指出:下面的训练目标能够得到更好的结果:其中:
- 为真实的输出单词对应的输出向量, 为负采样的单词得到的输出向量。
- :在单词 上输出为正类的概率; :在单词 上输出为负类的概率。
该目标函数是一个经验公式,而不是采用理论上的交叉熵 。其物理意义为:在正类单词上取正类的概率尽可能大,在负类单词上取负类的概率尽可能大。
它是从另一个角度考虑:输出为正向单元的概率 * 输出为负向单元的概率。
其负的对数似然为:
仅仅考虑负采样,则可得到: 。
根据 的定义,有:
其中 标记了单词 的标签:
令 ,它刻画了网络在正类单词和负类单词上的预测误差。
- 当 时, 表示对正类单词预测概率的不足。
- 当 时, 表示对负类单词预测概率的过量。
根据:
则有输出向量的更新方程:
给定一个样本,在更新输出向量时,只有 个输出向量( 1 个输出单词 、 个负采样单词对应的输出向量)得到更新,其中 通常数量很小。其它所有单词对应的输出向量未能得到更新。
相比较而言:
- 原始算法中,给定一个样本在更新输出向量时,所有输出向量(一共 个)都得到更新
- 分层
softmax
算法中,给定一个样本在更新输出向量时, 个内部节点的向量表达得到更新。
输出向量的更新方程可以用于
CBOW
模型和Skip-Gram
模型。若用于
Skip-Gram
模型,则对每个输出依次执行输出向量的更新。CBOW
输入向量参数更新:对于CBOW
模型,定义:的物理意义为:负采样单词、输出单词对应输出向量的加权和,其权重为 。
与
分层softmax: CBOW 输入向量参数更新
中的推导相同, 的更新方程为:其中 为第 个输入单词在词表 中的编号。
Skip-Gram
输入向量参数更新:对于Skip-Gram
模型,定义:其中: 表示网络第 个输出的输出单词, 表示网络第 个输出的负采样单词集。
注意:由于引入负采样,导致网络每个输出中,对应的输出单词有所不同,负采样单词也有所不同。因此 会因为 的不同而不同。
与
Skip-Gram
中推导相同, 的更新方程为:其中 为 非零分量对应的 中的行,而 的其它行在本次更新中都保持不变。
3.3.3 降采样
对于一些常见单词,比如
the
,我们可以在语料库中随机删除它。这有两个原因(假设使用CBOW
):- 当
the
出现在上下文时,该单词并不会为目标词提供多少语义上的信息。 - 当
the
作为目标词时,该单词从语义上本身并没有多大意义,因此没必要频繁更新。
降采样过程中,单词 被保留的概率为:
其中 为单词 在语料库中出现的概率, 为降采样率(默认为
0.001
)。可以看到:随着单词在语料库中出现的词频越来越大,该单词保留的概率越来越低。
- 当
3.4 subword embedding
论文
《Enriching Word Vectors with Subword Information》
中,作者提出通过增加字符级信息来训练词向量。下图给出了该方法在维基百科上训练的词向量在相似度计算任务上的表现(由人工评估模型召回的结果)。
sisg-
和sisg
模型均采用了subword embedding
,区别是:对于未登录词,sisg-
采用零向量来填充,而sisg
采用character n-gram embedding
来填充。单词拆分:每个单词表示为一组
character n-gram
字符(不考虑顺序),以单词where
、n=3
为例:- 首先增加特殊的边界字符
<
(单词的左边界)和>
(单词的右边界)。 - 然后拆分出一组
character n-gram
字符:<wh, whe,her,ere,re>
。 - 最后增加单词本身:
<where>
。
为了尽可能得到多样性的
character n-gram
字符,作者抽取了所有3<= n <= 6
的character n-gram
。以单词mistake
为例:<mi,mis,ist,sta,tak,ake,ke>, // n = 3
<mis,mist,ista,stak,take,ake>, // n = 4
<mist,mista,istak,stake,take>, // n = 5
<mista,mistak,istake,stake>, // n = 6
<mistake> // 单词本身
注意:这里的
take
和<take>
不同。前者是某个character n-gram
,后者是一个单词。- 首先增加特殊的边界字符
一旦拆分出单词,则:
- 词典 扩充为包含所有单词和
N-gram
字符。 - 网络输入包含单词本身以及该单词的所有
character n-gram
,网络输出仍然保持为单词本身。
模型采用
word2vec
,训练得到每个character n-gram embedding
。最终单词的词向量是其所有character n-gram embedding
包括其本身embedding
的和(或者均值)。如:单词
where
的词向量来自于下面embedding
之和:- 单词
<where>
本身的词向量。 - 一组
character n-gram
字符<wh, whe,her,ere,re>
的词向量。
- 词典 扩充为包含所有单词和
利用字符级信息训练词向量有两个优势:
有利于低频词的训练。
低频词因为词频较低,所以训练不充分。但是低频词包含的
character n-gram
可能包含某些特殊含义并且得到了充分的训练,因此有助于提升低频词的词向量的表达能力。有利于获取
OOV
单词(未登录词:不在词汇表中的单词)的词向量。对于不在词汇表中的单词,可以利用其
character n-gram
的embedding
来获取词向量。
3.5 应用
模型、语料库、超参数这三个方面都会影响词向量的训练,其中语料库对训练结果的好坏影响最大。
根据论文
How to Generate a Good Word Embedding?
,作者给出以下建议:模型选择:所有的词向量都是基于分布式分布假说:拥有相似上下文的单词,其词义相似。根据目标词和上下文的关系,模型可以分为两类:
- 通过上下文来预测目标词。这类模型更能够捕获单词之间的可替代关系。
- 通过目标词来预测上下文。
通过实验发现:简单的模型(
Skip-Gram
) 在小语料库下表现较好。复杂的模型在大语料库下略有优势。语料库:实际上语料库并不是越大越好,语料库的领域更重要。
- 选择了合适的领域,可能只需要
1/10
甚至1/100
的语料就能够得到一个大的、泛领域语料库的效果。 - 如果选择不合适的领域,甚至会导致负面效果,比随机词向量效果还差。
- 选择了合适的领域,可能只需要
超参数:
词向量的维度:
- 做词向量语义分析任务时,一般维度越大,效果越好。
- 做具体
NLP
任务时(用作输入特征、或者网络初始化),50
维之后效果提升就比较少了。
迭代次数:由于训练词向量的目标是尽可能精确地预测目标词,这个优化目标和实际任务并不一致。因此最好的做法是:直接用实际任务的验证集来挑选迭代次数。
如果实际任务非常耗时,则可以随机挑选某个简单任务(如:情感分类)及其验证集来挑选迭代次数。
word2vec
还有一些重要的超参数:- 窗口大小:该超参数通常和语料库中句子长度有关,可以统计句子长度分布来设置。
min-count
:最小词频训练阈值,词频低于该阈值的词被过滤。- 降采样率
subsampling_rate
:降采样率越低,高频词保留的越少低频词保留的越多。
word2vec
结果评估:- 通过
kmeans
聚类,查看聚类的簇分布。 - 通过词向量计算单词之间的相似度,查看相似词。
- 通过类比来查看类比词:
a
之于b
,等价于c
之于d
。 - 使用
tsne
降维可视化查看词的分布。
- 通过
在
word2vec
中实际上存在两种类型的embedding
向量: 的第 行 称作单词 的输入向量, 的第 列 称作单词 的输出向量。大多数论文中都采用输入向量 作为单词 的表达,而论文
Using the Output Embedding to Improve Language Models
综合了输入向量和输出向量。在该论文中,作者得出结论:- 在
skip-gram
模型中,在常见的衡量词向量的指标上,输出向量略微弱于输入向量。 - 在基于
RNN
的语言模型中,输出向量反而强于输入向量。 - 通过强制要求 ,这可以使得输入向量等于输出向量。这种方式得到的词向量能够提升语言模型的困惑度
perplexity
。
- 在
word2vec
可以用于计算句子相似度。博客Comparing Sentence Similarity Methods
总结了 6 种计算句子相似度的方法:无监督方法:
对句子中所有的词的词向量求平均,获得
sentence embedding
。对句子中所有的词的词向量加权平均,每个词的权重为
tf-idf
,获得sentence embedding
。对句子中所有的词的词向量加权平均,每个词的权重为
smooth inverse frequency:SIF
;然后考虑所有的句子,并执行主成分分析;最后对每个句子的词向量加权平均减去first principal componet
,获得sentence embedding
。SIF
定义为: ,其中 是一个超参数(通常取值为 0.001), 为数据集中单词 的词频。通过
Word Mover's Distance:WMD
,直接度量句子之间的相似度。WMD
使用两个句子中单词的词向量来衡量一个句子中的单词需要在语义空间中移动
到另一个句子中的单词的最小距离。
有监督方法:
通过分类任务来训练一个文本分类器,取最后一个
hidden layer
的输出作为sentence embedding
。其实这就是使用文本分类器的前几层作为
encoder
。直接训练一对句子的相似性,其优点是可以直接得到
sentence embeding
。
最终结论是:简单加权的词向量平均已经可以作为一个较好的
baseline
。