NLP学习笔记(一)

在传统监督学习(supervised learning)中,词元的特征是手动添加的。手动添加的特征往往太过具体、不够全面、耗时长且表现一般。

例如:“good"这个单词,我们可能主观认为与其相似的单词有"fine”,“expert”,"beneficial"等,但是这会造成一些问题:

(1)在同义词层面上,会遗漏细微差别(不够全面);

(2)在同义词词集里面添加单词是非常主观的选择(太过具体);

(3)打标签费时费力(耗时长)。

于是有了自监督学习,也称为无监督学习(unsupervised learning)。

无监督学习常常用于解决聚类、主成分分析、因果关系、概率图、生成对抗网络等问题。

而我们接下来要讲的word2vec模型,它所要解决的就属于聚类问题。

我们逐步了解这个模型,分为三个部分:词义、word2vec原理、训练word2vec。

(一)词义

词义是人类判断词相似性的依据,对于word2vec同样如此。

我们采用词向量来表示词元的特征,具体来讲就是:

给定这样一句话"Today is a fine day.",我们可以句子做如下的编码:

today	->	 0
is		->	 1
a 		->	 2
fine 	->	 3
day 	->	 4

然后采用独热编码去生成"fine"的词向量[0, 0, 0, 1, 0]

这是一个长度为 5 5 5的张量(tensor),独热编码长度由词元种类数量决定;除了一个位置是 1 1 1之外,其余为 0 0 0,故得名独热编码。

从以上这个简单例子中,我们会发现独热编码的几个问题

(1)独热编码可能会很长

对于一个庞大的数据集来说,其中词元的种类可能多达十万个,那么此时独热编码生成的词向量长度会很长。

(2)独热编码没有保留词元间的相似性

对于上面的句子来说,我们知道"today"和"day"的意义是相似的,但是二者的词向量点积(常常用于衡量相关性和相似性)是 0 0 0

显然二者没有任何相关性,这并不是我们希望看到的结果。

那么如何解决独热编码词向量的问题

对于问题(1)有一个简单的解决方案就是去掉出现频率过低的词元,同时改变句子编码策略,将"today"拆开为"to"和"day"后分别编码。

而对于问题(2),解决方案就是word2vec模型

(二)word2vec原理

我们应该早就已经见过这个模型,只不过一直以来它都是以黑盒的形式出现在代码之中:

self.embedding = nn.Embedding(vocab_size, embed_size)

对的,这就是嵌入层

word2vec,顾名思义,就是将词元转化为向量(word to vector)。

这也就是模型的目标:学习每个词元的词向量表示

将词元转化为向量的过程被称为词嵌入,这就是嵌入层得名的原因。

接下来我们去了解一下黑盒是如何把词元转化为词向量的。

1.理论

词嵌入技术有一个核心的理论支撑,分布相似性理论

直观来讲,就是一句话中的每个单词,都具有一定的上下文,也就是说我们可以通过一个单词去推断其上下文出现的概率。

根据分布相似性理论,我们可以学习词元的分布式表示

有这样一句话评价词元分布式表示的价值:

词汇的分布式表示非常有价值,可以预测上下文,只要得到好的分布式表示,甚至不需要构建可以预测的概率语言模型,只需要找到一种学习单词表示的方法。

2.算法

这里给出两种学习词元分布式表示的算法:

(1)跳元模型(SG,Skip-Gram)

(2)连续词袋模型(CBOW,Continuous Bag Of Words)


(1)跳元模型(SG,Skip-Gram)

跳元模型条件概率公式 w t w_t wt出现的前提下,上下文出现的条件概率):
P ( c o n t e x t ∣ w t ) = . . . P(context|w_t)=... P(contextwt)=...
在之前的例子中,条件概率公式表现为 P ( T o d a y ,   i s ,   f i n e ,   d a y   ∣   a ) P(Today,\ is,\ fine,\ day\ |\ a) P(Today, is, fine, day  a)

在这个模型中,每个词元都有两个 d d d维向量表示,用于计算条件概率。

具体的说,对于词表中索引为 i i i的任何词 w i w_i wi,有两个向量表示 v i v_i vi u i u_i ui,其中 v i v_i vi代表着中心词, u i u_i ui代表着上下文词。

为什么要用两个向量而不是一个向量表示?

因为这样,同一个词元的两个分布式表示是相互独立的,在优化的时候不会互相耦合。

我们将跳元模型条件概率公式拆解:
P ( c o n t e x t ∣ w t ) = ∏ − m ≤ j ≤ m , j ≠ 0 P ( w t + j ∣ w t ) P(context|w_t)={\prod_{-m\le j\le m, j\ne 0}{P(w_{t+j}|w_t)}} P(contextwt)=mjm,j=0P(wt+jwt)
其中 T T T代表着文本序列长度, m m m是窗口长度,二者均为超参数;

P ( w t + j ∣ w t ) P(w_{t+j}|w_t) P(wt+jwt)代表在 w t + j w_{t+j} wt+j出现的前提下 w t w_t wt出现的概率:
P ( w o ∣ w c ) = e x p ( u o T v c ) ∑ i ∈ V e x p ( u i T v c ) P(w_o|w_c)=\frac{exp(u_o^Tv_c)}{\sum_{i\in V}exp(u_i^Tv_c)} P(wowc)=iVexp(uiTvc)exp(uoTvc)
其中 u o u_o uo为上下文词向量, v c v_c vc为中心词向量, V = { 0 , 1 , . . . , ∣ V ∣ − 1 } V=\{0,1,...,|V|-1\} V={0,1,...,V1}为词表索引集。

这里的条件概率采用了softmax处理。

注意softmax处理后的概率分布与原来的分布不同。我们都知道什么是指数爆炸,所以很自然的,softmax会放大最大值所占的比重,这也是为什么它的名字中有"max"。

接下来我们尝试将文本序列中的每一个词作为中心词,进行累乘操作:
∏ t = 1 T P ( c o n t e x t ∣ w t ) = ∏ t = 1 T ∏ − m ≤ j ≤ m , j ≠ 0 P ( w t + j ∣ w t ) \prod_{t=1}^TP(context|w_t)=\prod_{t=1}^T{\prod_{-m\le j\le m, j\ne 0}{P(w_{t+j}|w_t)}} t=1TP(contextwt)=t=1Tmjm,j=0P(wt+jwt)

我们的目标是让这个公式的结果尽可能的大。

但是累乘是很麻烦的,我们可以取负对数,将其变成累加:

− ∑ t = 1 T ∑ − m ≤ j ≤ m , j ≤ 0 l o g   P ( u t + j ∣ v t ) -\sum_{t=1}^T{\sum_{-m\le j\le m,j\le 0}log\ P(u_{t+j}|v_t)} t=1Tmjm,j0log P(ut+jvt)
现在我们的目标变为使公式的值尽可能的小(因为是对数似然),这个公式就是我们的目标函数

注意,对于每个中心词,其上下文只有一个概率分布,不同的中心词的上下文具有不同的概率分布。也就是说,目标概率分布与上下文和中心词之间的距离无关,所以我们称这个跳元模型算法是位置独立的

(2)连续词袋模型(CBOW,Continuous Bag Of Words)

连续词袋模型的预测方法恰好是跳元模型的逆过程:根据上下文预测中心词元。

连续词袋模型条件概率公式(上下文出现的前提下, w t w_t wt出现的概率):
P ( w t ∣ c o n t e x t ) = . . . P(w_t|context)=... P(wtcontext)=...
在之前的例子中,可以表现为 P ( a   ∣   T o d a y ,   i s ,   f i n e ,   d a y ) P(a\ |\ Today,\ is,\ fine,\ day) P(a  Today, is, fine, day)

在这个模型中,各个符号所代表的意义与跳元模型相同。

与之前不同是,连续词袋模型条件概率公式无法拆解:
P ( w t ∣ c o n t e x t ) = P ( w t ∣ w o 1 , . . . , w o 2 m ) P(w_t|context)=P(w_t|w_{o_1},...,w_{o_{2m}}) P(wtcontext)=P(wtwo1,...,wo2m)
其中 m m m为窗口长度,是超参数。

为了表示方便,我们设 W t = { w t − m , . . . , w t − 1 , w t + 1 , . . . , w t + m } W_t=\{w_{t-m},...,w_{t-1},w_{t+1},...,w_{t+m}\} Wt={wtm,...,wt1,wt+1,...,wt+m}

因为存在多个上下文词,我们需要对 2 m 2m 2m个上下文词取均值。

为了表示方便,设 u ˉ t = 1 2 m ( w t − m , . . . , w t − 1 , w t + 1 , . . . , w t + m ) \bar u_t=\frac{1}{2m}(w_{t-m},...,w_{t-1},w_{t+1},...,w_{t+m}) uˉt=2m1(wtm,...,wt1,wt+1,...,wt+m)

则上下文出现的前提下, w t w_t wt出现的概率:
P ( w t ∣ W t ) = e x p ( v t T u ˉ t ) ∑ i ∈ V e x p ( v i T u ˉ t ) P(w_t|W_t)=\frac{exp(v_t^T\bar u_t)}{\sum_{i\in V}exp(v_i^T\bar u_t)} P(wtWt)=iVexp(viTuˉt)exp(vtTuˉt)

V = { 0 , 1 , . . . , ∣ V ∣ − 1 } V=\{0,1,...,|V|-1\} V={0,1,...,V1}为词表索引集。

接下来我们尝试预测文本序列中的每一个词,进行累乘操作:
∏ t = 1 T P ( w t ∣ W t ) \prod_{t=1}^{T} P(w_t|W_t) t=1TP(wtWt)
由于累乘过于繁琐,我们取负对数:
− ∑ t = 1 T l o g   P ( w t ∣ W t ) -\sum_{t=1}^{T} log\ P(w_t|W_t) t=1Tlog P(wtWt)
我们的目标就是使上式的值最小,它就是我们的目标函数

(三)训练word2vec

嵌入层的基本训练方式与常规神经网络并无不同:

数据处理、训练数据输入、计算损失、反向传播更新梯度、优化模型。

训练方法有以下两种:

(1)层次softmax(Hierarchical softmax);

(2)负采样(Negative sampling)。

但是这里不介绍这两种方法,因为本文的主要目的是介绍word2vec的基本原理。

这里只说明一个非常简单的训练方法。

1.初始化参数

简单取两个比较小的数值,然后在这个范围内随机取值进行初始化即可。

2.优化模型

优化算法的核心是梯度。(求导过程省略,实际应用时只需要反向传播即可,感兴趣可以自行求导)

(1)跳元模型(SG,Skip-Gram)

根据跳元模型的条件概率公式:
P ( w o ∣ w c ) = e x p ( u o T v c ) ∑ i ∈ V e x p ( u i T v c ) P(w_o|w_c)=\frac{exp(u_o^Tv_c)}{\sum_{i\in V}exp(u_i^Tv_c)} P(wowc)=iVexp(uiTvc)exp(uoTvc)
通过求微分,我们可以获得其对于中心词向量 v c v_c vc的梯度:
∂ l o g   P ( w o ∣ w c ) ∂ v c = u o − ∑ j ∈ V P ( w j ∣ w c ) u j \frac{\partial log\ P(w_o|w_c)}{\partial v_c}=u_o-\sum_{j\in V}P(w_j|w_c)u_j vclog P(wowc)=uojVP(wjwc)uj

(2)连续词袋模型(CBOW,Continuous Bag Of Words)

根据连续词袋模型的条件概率公式:
P ( w t ∣ W t ) = e x p ( v t T u ˉ t ) ∑ i ∈ V e x p ( v i T u ˉ t ) P(w_t|W_t)=\frac{exp(v_t^T\bar u_t)}{\sum_{i\in V}exp(v_i^T\bar u_t)} P(wtWt)=iVexp(viTuˉt)exp(vtTuˉt)
通过求微分,我们可以获得其对于 m m m个上下文词向量的梯度:
∂ P ( w t ∣ W t ) ∂ u i = 1 2 m ( v t − ∑ i ∈ V P ( w i ∣ W t ) v i ) \frac{\partial P(w_t|W_t)}{\partial u_i}=\frac{1}{2m}(v_t-\sum_{i\in V}P(w_i|W_t)v_i) uiP(wtWt)=2m1(vtiVP(wiWt)vi)
因为数据集往往很大,所以计算并存储整个数据集的梯度然后反向传播是不实际的(反向传播本质就是偏导数+存储),而且效果也并不好。

所以我们使用小批量随机梯度下降(SGD,Stochastic Gradient Descent)。

因为是随机取样,所以最终计算得到的梯度很好代表了整个样本的均值,并没有影响模型收敛。

参考:《动手学深度学习 Pytorch版》

【中英字幕】吹爆!最全斯坦福CS224n《深度学习自然语言处理》课程!我愿称之为2022最强NLP课程!超重量级,赶紧收藏!—人工智能/深度学习/机器学习

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WitheredSakura_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值