Note 1 Word2Vec
Note 1 Word2Vec
词语表示
早期的词语表示方法
-
WordNet 一种list, 包含同义词和上位词(A是B的关系)
问题:不够精准;词义不够全面;主观性强;人力操作复杂繁琐;无法精准计算词之间的相似性。
-
one-hot vectors (独热向量) 每一个向量只有一个1,剩下的都是0
motel = [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0]
问题:由于每个词向量彼此正交,因此无法表示不同词之间的关系。
词向量表示
- 中心思想为分布式语义(Distributional Semantics) :用不同语境中该词附近的文本来表示词的含义
词向量也叫做词嵌入/neural word representations 是一种分布式的词表示方法
Word2vec
Word2vec是一种学习词向量的框架,思想如下:
- 把每个词初始化为一个向量(必须是随机的,如果全部初始化为0向量,那么学习将无法进行),遍历文本的每一个位置,定义中心词c和上下文词o
- 用词向量间的相似度计算P(o|c) :在中心词为c的前提下计算上下文词为o的概率
- 不断调整词向量使得P(o|c)达到最大值
如何实现(数学语言)
对于文本中的每一个位置t = 1,2,…,T,在中心词为 wt 预测固定长度为m的上下文,采用极大似然估计的方法:
\(\theta\) 是所有模型参数构成的长向量
定义目标函数 \(J (\theta)=-\frac{1}{T}logL(\theta)\)
我们需要使目标函数最小,从而求出此时的\(\theta\)
-
但是我们首先应该解决的是如何计算\(P(w_{t+j}|w_t;\theta)\)
- 记词w对应的词向量为:vw (w为中心词),uw (w为上下文词)
- 用uoTvc表示中心词与上下文词的相似度,并取指数放大(把负数变正并放大差异)
- 归一化,即除以各相似度的和
这样我们就得到了:
\[P(o|c)=\frac{exp(u_{o}^{T}v_{o})}{\sum_{w\in V}exp(u_{w}^{T}v_{c})} \]这是softmax函数(归一化指数函数)\(\mathbb{R}^{n}→(0,1)^{n}\)
- "soft"是指概率较小的值依旧对P有贡献
- "max"是指它通过exp放大了较大的值的贡献程度
- 在深度学习中很常用
-
接下来,调整参数\(\theta\) 使得\(J(\theta)\)的值最小
-
在我们的情境下,总共有V个词,每一个词拥有两个词向量(vw, uw),每一个词向量是d维的
于是,\(\theta \in \mathbb{R}^{2dV}\)
-
梯度下降法(Gradient Descent)是来最小化\(J(\theta)\)的算法
对于\(\theta\)当前的值,计算\(\nabla J(\theta)\), 取小步长沿着\(-\nabla J(\theta)\)方向更新\(\theta\) 的值,反复进行上述操作
-
\(\theta^{new}=\theta^{old}-\alpha\nabla_{\theta}J(\theta)\)(矩阵形式)
注:\(\alpha\) 称为步长/学习率,一般很小,取103~105
-
\(\theta^{new}_j=\theta^{old}_{j}-\alpha \frac{\partial}{\partial\theta^{old}_{j}}J(\theta)\)
-
算法
while Ture: theta_grad =evaluate_gradient(J,corpus,theta) theta = theta - alpha * theta_grad -
但是由于语料库一般都很庞大,因此计算\(\nabla_{\theta}J(\theta)\)需要花费很多费 时费钱的,因此我们引入
Stochastic gradient descent (SGD)随机梯度下降
这种取小的子集作为样本的训练方法也叫做Mini Batch Gradient Descent(小批量梯度下降)
实际上,采用小批量样本计算得出的估计值是不够精准的,但是在神经网络中,引入这种不精准往往会产生更好的效果。
While True: window = sample_window(corpus) theta_grad =evaluate_gradient(J,window,theta) theta = theta - alpha * theta_grade
-
-
-
总结:Word2vec模型参数只有中心词和上下文词的词向量,我们用中心词和上下文词词向量的点集来表示相似程度,用softmax归一化指数函数来得到概率分布(模型认为不同外部词的可能性有多大)用计算结果和实际中出现的词进行比较,得到误差来源。
-
这在NLP中被称为词袋模型,因为它并不理解句子的含义,只是单纯根据词出现的位置和频率来做出预测,并且在每一个位置进行相同的预测
-
问题:之前提到的Word2vec是把每一个词用一个向量进行表示,但是在前面的操作中,我们对于每一个词用两个词向量(uw和vw)来表示。
实际上,这两个向量是相当接近的,因为我们对于每一个位置的处理方式是相同的,实际情况中我们可以取平均值作为该词的词向量
用两个向量来表示让数学计算更简单一些。
Word2vec的具体模型变体
- Skip-grams(SG/跳字模型):根据中心词预测上下文词
- Continuous Bag of Words(CBOW/连续词袋模型):根据上下文词预测中心词
这里我们主要展示Skip-gram model
-
训练时的损失函数(Loss functions)
- Naive softmax 也就是上面展示的部分
- More optimized variants like hierachical softmax(层次化softmax):通过构建以词频为权重的哈夫曼树来代替传统softmax的多分类器,使得常见词路径更短,减少训练模型时的计算复杂度
- Negative sampling(负采样)
-
跳字模型与负采样 (The skip-gram model with negative sampling)
-
传统的归一化项(normalization term,下式分母)在计算上是昂贵的:
\[P(o|c)=\frac{exp(u_o^Tv_c)}{\sum_{w\in V}exp(u_w^Tv_c)} \]它需要遍历语料库的每一个词,计算量太大了,因此,标准的Word2vec采用负采样的跳字模型
主要思想:训练二分类逻辑回归(binary logistic regressions)来区分真实的词对(中心词和文本窗中的上下文词)以及“噪声词对”(中心词和随机词)
做法:
-
对于每一个正样本取k个负样本(噪声/随机词)按照词频抽取
-
最大化真实词出现的概率,最小化随机词出现的概率
-
于是,我们在负样本词向量点积前加符号,这样我们需要最小化:
\[J_{neg-sample}(u_o,v_c,U)=-log\sigma (u_o^Tv_c)-\sum_{k\in{K \ sampled \ indices}}log\sigma(-u_k^Tv_c) \]这里我们用了sigmoid函数(也叫logistic函数)
\[\sigma(x)=\frac{1}{1+e^{-x}} \] -
在进行采样时,我们在加权的时候按P(w)=U(w)3/4/Z,这里的3/4次方起到了适当降低高频词权重和增加低频词权重的作用
-
-
随机梯度与负采样(Stochastic gradients with negative sampling)
- 我们对于每一个文本窗分别取梯度
- 在每一个窗口中,我们只有2m+1个词和2km个负采样得到的词,因此\(\nabla_{\theta}J_t({\theta})\)相当稀疏
- 我们只需要更新出现的词的词向量:要么只更新特定的行或者为词向量创建哈希表储存
共现矩阵(Co-occurrence Matrix)
-
既然Word2vec要遍历整个预料库,那为什么不直接统计不同词临近出现的次数?基于这个想法,我们尝试构建共现矩阵
-
我们面对两个选择,是像word2vec一样对每一个词用文本窗的方式分别记录还是将全部词悉数记录
-
这里以文本窗为例,我们展示Window based co-occurrence matrix
- 文本窗长度(一般是5-10个词)
- 同样具有对称性,与词出现在中心词左/右无关
共现数组同样有两条路线
- 简单的计数:随着体量的增大,数组维度会非常庞大,并且鲁棒性降低。
- 低维数组:将最重要的信息存储在固定尺寸的低维数组当中,一般是25-1000维。
-
显然,我们采用后者,这又引出一个问题:如何降维?
-
经典方法:奇异值分解Singular Value Decomposition(SVD )
将矩阵分解成X=U\(\Sigma\)VT,其中U与V标准正交
只保留最大的k个奇异值以便泛化,数学上这是对原矩阵的最佳低秩近似(最小二乘意义下)
但是计算复杂度太高了
-
直接在原始数据下跑SVD效果惨不忍睹!
function word 像(he,,the,has)出现频率太高了,有许多fixes:
对频率取对数,将频率限制在1-100,忽略这些功能词
针对方法本身还有如下fixes:
衰减窗口:离中心词越近权重越大
用相关性代替计数,把负值设置为0
-
GloVe
-
核心思想:将共现概率的比率转化为向量空间中的**线性关系 **(能够实现语义加减法)
-
对数双线性模型(Log-bilinear model):\(w_i·w_j=logP(i|j)\)
所以\(w_x·(w_a-w_b)=log\frac{P(x|a)}{P(x|b)}\)
-
损失函数
\[J=\sum_{i,j=1}^{V}f(X_{ij})(w_i^T\tilde{w_j}+b_i+\tilde{b_j}-logX_{ij})^2 \]这个损失函数本质上是平方误差(MSE)
\[J=\sum_{i,j=1}^{V}(w_i^T\tilde{w_j}-logP(i|j))^2\\ P(i|j)=\frac{X_{ij}}{X_j}\\ logP(i|j)=logX_{ij}-logX_j\\ \]bi和\(\tilde b_j\)是偏移值,用来处理共现矩阵的方向性(\(P(i|j)\neq P(j|i)\)d但是点乘得到的结果是对称的)以及提升模型自由度
对于固定的j来说Xj是常数,在训练模型是,我们把-logXj存入\(\tilde b_j\)中
引入权重函数f(Xij)
- 当Xij=0时,f(Xij)=0:忽略没有出现的词
- Xij很小时,f(Xij)逐渐增大
- Xij很大时,f(XIj)=1:避免频次很高的词权重爆炸
如何评估词向量
在NLP当中我们有两种评估:内在评估(intrinsic)外在评估(extrinsic)
-
内在评估
- 评估一个具体的子任务过程中的效果
- 速度快、帮助我们理解系统
- 对于下游任务的效果是不清楚的
-
外在评估
- 在实际问题当中进行的评估
- 花费时间长、如果你想知道某一个子部件的改善是否有益,需要运行整个系统并且计算下游准确度
-
内在的词向量评估
-
词向量类比
a:b ::c:?
\[d=\arg\max_i\frac{(x_b-x_a+x_c)^Tx_i}{||x_b-x_a+x_c||} \]因为 d=b-a+c,我们用b-a+c归一化后与词表里所有词点乘,将最大的结果作为答案
需要排除输入词
这里我们假设语义关系在向量空间中是线性可加的,但如果不是线性的该怎么办?
-
语义相似度
将词向量之间的距离与人类评判的打分进行比较
这里我们有一个人工标注的数据集WordSim353,对每一对词打一个0-10的相似度评分
-
-
外在的词向量评估
- 把词向量应用到真实的下游任务,看任务指标进行评估
词多义和词义模糊
对于每一个词都用一个词向量进行表示,但是很多次都有多个意思,一个词向量可以抓住所有的意思吗?
有两种思路处理这个问题:
-
多原型:把所有包含该词的上下文收集起来,重新训练将不同词义区分开,like bank1、bank2……
-
线性叠加:在训练得到的词向量本身就是不同词词义的线性叠加
\(v_{pike}=\alpha _{1}v_{pike_{1}}+\alpha _{2}v_{pike_{2}}+\alpha _{3}v_{pike_{3}}\)
\(\alpha_1=\frac{f_1}{f_1+f_2+f_3}\)
我们可以通过稀疏编码(sparse coding)把不同的意思区分开

浙公网安备 33010602011771号