[NLP复习笔记] Word2Vec: 基于负采样的 Skip-gram 及其 SGD 训练

1. one-hot 向量

我们先了解一下 one-hot 向量。one-hot 编码是表示分类变量的常见方法,尤其在数据预处理和机器学习的特征工程中。一个 one-hot 向量是一个其中只有一个元素是 1,其余为 0 的向量。

假设存在一个单词集合:{marisa, reimu, renko, hearn},可以将这些单词进行索引映射:

marisa0reimu1renko2hearn3

那么,这些单词经过 one-hot 编码的向量如下:

marisa:[1,0,0,0]reimu:[0,1,0,0]renko:[0,0,1,0]hearn:[0,0,0,1]

显然,每个位置被看作一个特征,这个特征只能是 1(存在)或者 0(不存在)。

但是,对于包含大量唯一词汇的大型语料库而言, one-hot 编码会产生 极大的稀疏矩阵,每一个单词对应的词向量都是 |V| 维的,使得 维度很高,导致计算效率低下。

而且 one-hot 编码的词向量之间都是等距的,每个词语的向量与其他词语的向量都是正交的关系,这意味着它们 不携带任何词语间的相似性信息

one-hot 编码现在依然有比较广泛的应用,但在一些自然语言处理问题中,为了避免上述的限制,会采用更加高级的技术,就比如 Word2Vec




2. Word2Vec

2.1 Word2Vec 介绍

Word2Vec 模型通过训练神经网络,为每个单词构建一个密集且连续的向量。这些向量被称为 词嵌入word embeddings),它们捕捉大量关于单词的语义和句法信息。每个单词在多维空间中被表示为一个向量,向量中的每个维度代表词义的不同方面,具体每个维度代表什么并不是人为定义的,而是通过 模型学习得到 的。

例如,经过训练后,单词 marisa 最终对应的词向量是 一个 d 维的向量,有可能是如下的形式:

vecmarisa=[0.11.50.7]

vec 就是 目标单词的词向量。这里的维度 d人为设定的一个超参数,表示我们需要将单词映射到一个 d 维的向量空间,决定了 词向量的特征数量,也就是我们想要 得到的词向量的大小

通过 Word2Vec 得到的词向量 拥有相似上下文的词在空间中的位置,能够捕捉单词之间的语义关系。

从维度上,提取的 d 个维度特征,可以一定程度上避免维度过高的情况;从语义上,携带上下文信息,可以表示出近义词的相似性。

2.2 Skip-gram 与 CBOW

Word2Vec 模型包括输入层、隐藏层和输出层。模型框架根据输入输出的不同,主要包括 Skip-gramCBOW 两种模型。

Skip-gram 模型: 用一个词语作为输入,来预测其上下文。模型的目标是 最大化在给定目标单词的情况下上下文单词出现的概率,也就是 计算其他单词出现在目标单词周围的概率

CBOW 模型: 用一个词语的上下文作为输入,来预测这个词语。模型的目标是最大化上下文单词出现时目标单词的条件概率。

本篇文章将会介绍基于 Negative SamplingSkip-gram 模型。Negative Sampling 也就是 负采样,是 Word2Vec 模型训练的加速策略之一)




3. 基于 Negative Sampling 的 Skip-gram

3.1 Skip-gram 模型

Skip-gram 模型输入层 x 只有一个单词,输出层 y 为多个单词,其基本结构如下:

下面的 d 对应图中的 N

  • 输入层 x:一个 1×Vone-hot 向量,V 为词汇表大小。表示一个单词,也是我们的 目标词

  • W 矩阵:输入层到隐藏层之间 V×d 的参数矩阵,包含了模型使用的所有词向量,目的是为了将输入层的 one-hot 向量映射到嵌入向量空间,也就是 d 维空间。

  • 隐藏层 h:一个 1×d 的特征向量,其实也就是当前的 目标词对应的词向量

  • W 矩阵:隐藏层到输出层之间的 d×V 的参数矩阵,用来将隐藏层的表示转换到输出空间。也表示了所有单词的词向量,将于 目标词词向量做内积

  • 输出层 o:一个 1×V 的向量。经过 h×W 后(做内积之后)产生一个相似度向量,向量中 每个元素 表示词汇表 每个单词在目标词上下文出现原始概率。最后要经过一个 激活层 得到 真实概率。对于 多分类 问题,常常采用 softmax 函数;对于 二分类 问题,则一般采用 sigmoid 函数。(注意,这里的输出层并非图中最终的输出,只是一个概率的分布)

    PS: 在后面的问题中,将会采用 sigmoid 函数。

  • 输出单词 yC 个单词的 one-hot 向量,其中 C 表示采用的 上下文窗口的大小。根据输出层 o 的概率分布,选取 C 大概率 的单词作为最终预测的 目标词 x 的上下文单词 y

    下图是一个上下文窗口典型示例:


3.2 Negative Sampling

传统的神经语言模型需要在每一步对全词汇表进行运算,而 Negative Sampling(负采样)只在更新权重时考虑一个小的负样本集合,也就是随机选择一个负单词集合(也就是若干非上下文的单词组成的一个子集)。这样,目标就转化为 最大化正样本的概率,同时最小化负样本的概率。

由此我们可以得到如下定义:

  • 样本概率

    P(+|w,c)=σ(cw)

    其中 w 表示 目标词对应的词向量c 表示 目标词的上下文对应的词向量

    σ 表示 sigmoid 函数,cw 是两个词向量的内积。

  • 正样本似然函数

    P(+|w,cpos)

  • 负样本似然函数

    P(|w,cneg)


我们需要最大化正样本的概率,同时最小化负样本的概率,所以,可以转化为最大化下式:

P(+|w,cpos)(1P(|w,cneg))

为了计算方便,我们可以取对数,得到对数似然函数:

L=log(P(+|w,cpos)(1P(|w,cneg)))

为了后续方便训练,我们可以变成最小化如下形式 (在前面加一个负号):

L=log(P(+|w,cpos)(1P(|w,cneg)))

sigmoid 函数 f(x)=11+ex 得:

L=log(σ(cposw)σ(cnegw))=[logσ(cposw)+logσ(cnegw)]

一般情况下使用 SGD随机梯度下降法)来进行学习,故只需要知道对一个正样本 (w,cpos) 的目标函数。假设我们随机选取 k 个负样本单词作为负采样集合,则有如下形式:

L=[logσ(cposw)+i=1klogσ(cnegiw)]

这就是我们最终要 最小化的目标函数 L


3.3 参数求导

我们最终需要得到最优的 cposcneg 以及 w 参数,由 SGD 算法(应该没有人不懂这个算法吧),我们要分别对这些参数求导。

目标函数中有 sigmoid 函数,故在求导之前,我们先看一下 sigmoid 函数的求导,以便后续化简。

sigmoid 函数如下:

σ(x)=11+ex

我们先对其进行变形,得:

σ(x)=11+ex=exex+1=1(ex+1)1

由此可得 sigmoid 的导数如下:

dσdx=(ex+1)2ex=[ex(1+ex)]2ex=(1+ex)2e2xex=(1+ex)1ex1+ex=σ(x)(1σ(x))

我们可以再看下 σ(x) 的导数。显然 sigmoid 函数满足 σ(x)=1σ(x),所以σ(x) 的导数就很简单了,就是 σ(x)(1σ(x))

后面再对各个参数求导就比较清晰易懂了,具体过程如下(对数看作取 ln 函数):

  • cpos 求导

    这里使用了 链式求导法则

    Lcpos=cpos([logσ(cposw)+i=1klogσ(cnegiw)])=Lσ(cposw)σ(cposw)cpos

    其中前半部分为:

    Lσ(cposw)=1σ(cposw)

    后半部分为:

    σ(cposw)cpos=σ(cposw)(1σ(cposw))w

    最后结合起来得到 Lcpos(记得最前面有一个负号) :

    Lcpos=1σ(cposw)σ(cposw)(1σ(cposw))w=[σ(cposw)1]w


  • cneg 求导

    使用 链式求导法则

    Lcneg=cneg([logσ(cposw)+i=1klogσ(cnegiw)])=i=1kLσ(cnegiw)σ(cnegiw)cnegi

    前半部分为:

    Lσ(cnegiw)=1σ(cnegiw)

    后半部分为:

    σ(cnegiw)cnegi=σ(cnegiw)(1σ(cnegiw))w

    由于 σ(x)=1σ(x),我们可以把 (1σ(cnegiw)) 换成 σ(cnegiw) 便于后续化简:

    σ(cnegiw)cnegi=σ(cnegiw)σ(cnegiw)w

    将两个部分结合起来,得到 Lcneg(记得最前面有一个负号):

    Lcneg=i=1k1σ(cnegiw)[σ(cnegiw)σ(cnegiw)w]=i=1k1σ(cnegiw)[σ(cnegiw)σ(cnegiw)w]=i=1kσ(cnegiw)w=[σ(cnegw)]w


  • w 求导

    对前面两个参数进行求导后,对 w 求导就方便多了。

    Lw=[w(logσ(cposw))+w(i=1klogσ(cnegiw))]

    对于前半部分,由

    wσ(cposw)=σ(cposw)(1σ(cposw))cpos

    可得

    w(logσ(cposw))=1σ(cposw)σ(cposw)(1σ(cposw))cpos=[1σ(cposw)]cpos

    对于后半部分,由

    wσ(cnegiw)=σ(cnegiw)(1σ(cnegiw))(cnegi)

    w(logσ(cnegiw))=1σ(cnegiw)σ(cnegiw)(1σ(cnegiw))(cnegi)=[1σ(cnegiw)]cnegi=[σ(cnegiw)]cnegi

    最后结合起来,得到 Lw(记得最前面有一个负号):

    Lw=[σ(cposw)1]cpos+i=1k[σ(cnegiw)]cnegi

以上就是对参数求导的全部推导过程。


3.4 SGD 更新公式

将上面的导数套用到 SGD 更新公式就可以了。最后简单写一下更新公式:

cpost+1=cpostη[σ(cpostwt)1]wt

cnegt+1=cnegtη[σ(cnegtwt)]wt

wt+1=wtη([σ(cposw)1]cpos+i=1k[σ(cnegiw)]cnegi)

经过不断迭代更新后,最后得到最优的 cposcneg 以及 w 参数,也就是最终的 上下文词向量 c目标词对应的词向量 w

最后,通常会将两个词向量进行相加,来表述单词。例如第 i 个单词就可以表示为 wi+ci




参考

【词向量基础】:one-hot

全面理解word2vec

Word2Vec介绍:直观理解skip-gram模型

深入浅出Word2Vec原理解析

[NLP] 秒懂词向量Word2vec的本质

sigmoid函数求导-只要四步

posted @   MarisaMagic  阅读(860)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 提示词工程——AI应用必不可少的技术
· 字符编码:从基础到乱码解决
· 地球OL攻略 —— 某应届生求职总结
点击右上角即可分享
微信分享提示