Word2Vec
一、为什么需要词向量
- 文本数据需要有结构化的表示。
- 独热编码表示稀疏、且表达能力有限,无法提现词与词之间的相似性。
- 分布式表示较为灵活,表达能力强,避免稀疏性。
二、 如何得到词向量
- 词向量作为给定任务,设计模型的副产物。
- 任务有两种形式:给定句子,用中心词预测周围词、或者周围词预测中心词。
- P ( w ∣ c o n t e x t ( w ) ) o r P ( c o n t e x t ( w ) ∣ w ) P(w|context(w)) \quad or \quad P(context(w)|w) P(w∣context(w))orP(context(w)∣w)
- 很明显对于这两个任务,中心词预测周围词难度较大。
三、模型的学习目标是什么
- 周围词预测中间词、中心词预测周围词。
P ( w ∣ c o n t e x t ( w ) ) o r P ( c o n t e x t ( w ) ∣ w ) P(w|context(w)) \quad or \quad P(context(w)|w) P(w∣context(w))orP(context(w)∣w) - 很明显对于这两个任务,中心词预测周围词难度较大。
- 对于 P ( w ∣ c o n t e x t ( w ) ) P(w|context(w)) P(w∣context(w)),需要将上下文的映射(也就是词向量)拼接,得到 x w x_w xw
- 对于 P ( c o n t e x t ( w ) ∣ w ) P(context(w)|w) P(context(w)∣w), x w x_w xw就是中心词经过W得到的向量(词向量)。
- 接下来的操作就是对 x w x_w xw进行
- 先看一般的做法:
- 这里N是词表的维度。
- 计算损失就是一个交叉熵。如果是预测中心词,每个样本就是计算一次,如果预测周围词,每个样本就需要计算 s i z e ( c o n t e x t ( w ) ) size(context(w)) size(context(w))次交叉熵。
四、模型设定有什么问题?如何解决?
用输出层softmax进行预测,向量的维度是词表的大小,计算代价大。
4.1 层次softmax
构建哈夫曼树
-
权重高的比较短的编码,权重少的用长的编码。——词频越高离根节点越近。
-
所以这样将预测的词编程哈夫曼树,每次走哪边就用二分类器来决定。这样好处在于高频词离根节点近,减小计算。
-
每个二分类器的参数是不一样的。
-
想法:感觉这样的做法只适合训练。因为训练的时候,我是知道正确的词所在的位置,我可以停下来。而如果做预测,不知道何时停止。
-
但没关系,因为这样做的目的是为了提高计算效率,得到训练过程中的权重向量(作为词向量)。
4.2 负采样
将
P
(
w
∣
c
o
n
t
e
x
t
(
w
)
)
P(w|context(w))
P(w∣context(w))定义为是否选择该词(二分类问题)。因此目标是选择该词的概率尽可能大,选择其他词的概率尽可能小。
(
w
,
c
o
n
t
e
x
t
(
w
)
(w,context(w)
(w,context(w)就是正样本,其他词就是负样本。
负样本自然不可能是所有其他词,需要有一定的采样方式。
负采样的方法:
- 思路很简单,根据词频来,高频词更容易被选到,低频词更难。
- 首先将词频映射到一个线段,长度为
l
e
n
(
w
)
len(w)
len(w):
- 显然,所有线段长度之和为1,而且这些线段是不等距的。
- 接着再画一条长度为1的线段,等距切成M份,M远大于线段的个数(也就是词典的词数N)
- 采样的方式就是从 [ 1 , M − 1 ] [1,M-1] [1,M−1]的区间随机取一个整数,看其落在哪个区间。【源码中 M = 1 0 8 M=10^8 M=108】
- 如果正好选到正样本词,跳过去,再选一次。
- 在源码中,
l
e
n
(
w
)
len(w)
len(w)的计算为:
五、 如何做优化
最大化似然概率,就是随机梯度上升。
六、 SkipGram V.S CBOW
一般而言,skipgram效果比CBOW要好。
- 数据量:同样的数据,skip-gram生成的样本比CBOW更多
- 难易度:由中心词预测周围词的任务更难
- 低频词:直观理解:
- 周围词预测中心词,一群学生从一个老师学东西,而且这一群人学的东西还是类似于平均,出现少次数少的学生学到就比较少。
- 中心词预测周围词:一个学生从一群老师学东西,学的肯定更多
- Skip-gram训练速度更慢,CBOW更快。
七、 得到的词向量有什么问题?
- 固定的词向量,无法解决一词多义的问题;
- 静态表示,无法将预训练的模型拼接到下游任务。也就是迁移时,只能将词向量作为特征输入进新的模型。
---------------7.20更新-------------------------
Glove
一、 Glove的思想是什么?
- Glove是为了克服全局矩阵分解和局部上下文窗口的缺陷
- word2vec只用到了局部的上下文信息(滑动窗口内),虽然说负采样也会用到其他词,但真正概率最大的部分还是希望模型学到滑动窗口内的信息。
- Glove根据滑动窗口统计共现信息,得到全局的共现矩阵
- glove可以被看作是更换了目标函数和权重函数的全局word2vec
二、如何构建Glove?
-
根据语料库得到共现矩阵 X X X,其中 X i j X_{ij} Xij表示单词 i i i 和上下文单词 j j j 在特定大小的滑动窗口共现的次数。【一般来说,最小次数是1,但在Glove认为在窗口内距离越远的单词占总计数权重越小,所以有个衰减函数1/d。】
-
设词向量为 ω i \omega_i ωi, ω ^ i \hat \omega_i ω^i,其损失函数为:
- J = ∑ i , j V f ( X i j ) ( ω i T ω ^ j + b i + b j − l o g X i j ) 2 J = \sum_{i,j}^Vf(X_{ij})(\omega_i^T\hat \omega_j + b_i + b_j - logX_{ij})^2 J=∑i,jVf(Xij)(ωiTω^j+bi+bj−logXij)2
- 其中 f ( x ) = { ( x / x m a x ) α x < x m a x 1 o t h e r w i s e f(x)=\left\{ \begin{aligned} &(x/x_{max})^\alpha & x<x_{max}\\ &1 & otherwise \\ \end{aligned} \right. f(x)={(x/xmax)α1x<xmaxotherwise
- α \alpha α也是取0.75效果最好
- 与word2vec想比,这边损失函数带权重的mean loss(word2vec损失函数实质上是带权重的交叉熵,权重固定)
-
虽然语料是没有标注的,但是从优化目标的角度来看。模型的要学习的词向量 ω \omega ω, ω ^ \hat \omega ω^是参数,label是 l o g X i j logX_{ij} logXij。因此,训练的时候还是有监督的。
-
采用Adagrad优化方法,对矩阵 X X X中的所有非零元素进行随机采样,学习曲率为0.05,在vector size小于300的情况下迭代了50次,其他大小的vectors上迭代了100次,直至收敛。
-
学出来的的 ω \omega ω, ω ^ \hat \omega ω^词向量理论上是对称的-可以等价拿来使用,因为 X X X是对称的。但因为初始化的值不一样,所以最终值会有区别。但是为了提高鲁棒性,我们最终会选择两者之和 ω \omega ω+ ω ^ \hat \omega ω^作为最终的vector(两者的初始化不同相当于加了不同的随机噪声,所以能提高鲁棒性)。
三、如何理解损失函数
- 损失函数如何构造核心是:利用共现矩阵 X X X,可以计算单词 j j j 出现在单词 i i i 上下文中的概率 P i j P_{ij} Pij。
- 文章认为,概率的比例 P i k P j k \frac{P_{ik}}{P_{jk}} PjkPik更能反映出单词 k k k与单词 i , j i,j i,j哪个更相关。
- 因此,通过概率的比例而不是概率本身去学习词向量可能是一个更恰当的方法。
- 具体步骤:Glove详解
四、如何衡量词向量的好坏?
五、Glove的应用
现在讨论glove,似乎显得有点过时?当下第二代预训练模型确实很火热,但是在近两年的顶会文章中,依旧有使用词向量作为语义表征。其原因我觉得在一定程度上是想绕开与bert这类预训练模型做比较。不然有可能审稿人觉得模型的效果是来源于Bert而不是你自己设计的模型。