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) :用不同语境中该词附近的文本来表示词的含义

\[banking =\begin{pmatrix} 0.286\\ 0.792\\ -0.177\\ ...\\ 0.271 \end{pmatrix} \]

​ 词向量也叫做词嵌入/neural word representations 是一种分布式的词表示方法

Word2vec

​ Word2vec是一种学习词向量的框架,思想如下:

  • 把每个词初始化为一个向量(必须是随机的,如果全部初始化为0向量,那么学习将无法进行),遍历文本的每一个位置,定义中心词c上下文词o
  • 用词向量间的相似度计算P(o|c) :在中心词为c的前提下计算上下文词为o的概率
  • 不断调整词向量使得P(o|c)达到最大值

​ 如何实现(数学语言)

对于文本中的每一个位置t = 1,2,…,T,在中心词为 wt 预测固定长度为m的上下文,采用极大似然估计的方法:

\[L(\theta)=\prod_{t=1}^{T}\prod_{\substack{-m \leq j \leq m \\ j\neq0}}P(w_{t+j}|w_{t};\theta) \]

\(\theta\) 是所有模型参数构成的长向量

定义目标函数 \(J (\theta)=-\frac{1}{T}logL(\theta)\)

\[J(\theta)=-\frac{1}{T}\sum_{t=1}^{T}\sum_{\substack{-m\leq j\leq m\\j\neq 0}}logP(w_{t+j}|w_t;\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的相似度评分

  • 外在的词向量评估

    • 把词向量应用到真实的下游任务,看任务指标进行评估

词多义和词义模糊

对于每一个词都用一个词向量进行表示,但是很多次都有多个意思,一个词向量可以抓住所有的意思吗?

有两种思路处理这个问题:

  1. 多原型:把所有包含该词的上下文收集起来,重新训练将不同词义区分开,like bank1、bank2……

  2. 线性叠加:在训练得到的词向量本身就是不同词词义的线性叠加

    \(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)把不同的意思区分开

posted @ 2026-09-13 10:56  ZomBie_J  阅读(4)  评论(0)    收藏  举报