自然语言处理之语言模型与词向量原理
语言模型
基于语法的语言模型
在研究机器如何“理解”自然语言之前,不妨先看看人们是怎么理解自己的语言的。根据语言学(Linguistics)的课程大纲,我们认为语言包括语音、构词、语法、句法等内容。不妨对语言进行如下建模(个人意见):
语言学的自然语言模型
- 自然语言定义:L=(V,T,S,P)
- 非终结符集V:句子成分如主语、定语、谓语……
- 终结符集T:语言中的所有单词
- 起始符S:句子
- 生成规则集P:所有句法S–>主语+谓语;谓语–>谓语+状语;……
从上文模型可知,我们可以用L=(V,T,S,P)定义世界上每一种语言。凡是符合生成规则的句子,都被认为是语言L中的合法句子。
早期计算机学者从语言学的角度帮助计算机理解语言,在高级编程语言方面,《编译原理》告诉我们高级编程语言均包括词法、句法、终结符、非终结符等,符合L=(V,T,S,P)模型。在自然语言方面,早期计算机学者发明了POS标注和依存句法,从语言规则的角度使计算机能对句子进行解读。
POS标注和依存句法对现行的深度学习主导的NLP研究有意义嘛?答案是有的,研究前沿中EMNLP2019最新论文《Aspect-Level Sentiment Analysis Via Convolution over Dependency Tree》结合依存句法进行细粒度情感分析。个人对这篇论文有分析,见链接。
基于统计的语言模型
为了方便计算机对语言的计算,提出基于统计的语言模型。与语言学定义的,基于语法的语言模型不同,统计语言模型通过单词、句子、段落的概率来解释语言现象。
对于一个自然语言序列(句子),
S
=
w
1
,
w
2
,
.
.
.
,
w
n
S = {w_1,w_2,...,w_n}
S=w1,w2,...,wn 定义这个句子在这一语言模型下出现的概率为:
P
(
S
)
=
P
(
w
1
,
w
2
,
.
.
.
,
w
n
)
=
P
(
w
2
∣
w
1
)
P
(
w
3
∣
w
1
,
w
2
)
.
.
.
P
(
w
n
∣
w
1
,
w
2
,
.
.
.
,
w
n
−
1
)
P(S)=P(w_1,w_2,...,w_n)\\=P(w_2|w_1)P(w_3|w_1,w_2)...P(w_n|w_1,w_2,...,w_{n-1})
P(S)=P(w1,w2,...,wn)=P(w2∣w1)P(w3∣w1,w2)...P(wn∣w1,w2,...,wn−1)
上式描述的语言模型属于一种理想情况,为什么呢?我们看这一项
P
(
w
n
∣
w
1
,
w
2
,
.
.
.
,
w
n
−
1
)
P(w_n|w_1,w_2,...,w_{n-1})
P(wn∣w1,w2,...,wn−1),如果我们想求出
w
n
w_n
wn在
w
1
,
w
2
,
.
.
.
,
w
n
−
1
w_1,w_2,...,w_{n-1}
w1,w2,...,wn−1语境下的概率,就只能去统计给定
w
1
,
w
2
,
.
.
.
,
w
n
−
1
w_1,w_2,...,w_{n-1}
w1,w2,...,wn−1语境后,下一个词出现
w
n
w_n
wn的概率。当n足够大时,我们可能翻遍文本库也找不到几个
w
1
,
w
2
,
.
.
.
,
w
n
−
1
w_1,w_2,...,w_{n-1}
w1,w2,...,wn−1语境,那么统计出来的
w
n
w_n
wn的条件概率就是严重失真的。因此上式描述的语言模型(n元语法模型,n-gram model)是一种理想模型。一般来讲,语言模型只需要考虑
n
=
2
n=2
n=2或
n
=
3
n=3
n=3的情况就已足够使用了(在需要语言模型的场景下),及二元语言模型或三元语言模型。
我们可以通过设计程序去统计每一个词的条件概率。以二元语言模型为例,假设语料库中有1000个不重复单词。步骤如下:
- 初始化一个1000*1000大小的矩阵A,矩阵中的 ( i , j ) (i,j) (i,j)元用于记录 w i w_i wi后出现 w j w_j wj的次数。
- 以大小为2的窗口遍历文本库,将统计数据计入矩阵A。
- 按照如下公式计算每个词的条件概率。
P ( w j ∣ w i ) = A ( i , j ) / ∑ x = 1 n A ( i , x ) P(w_j|w_i)=A(i,j)/\sum\nolimits_{x=1}^{n}{A(i,x}) P(wj∣wi)=A(i,j)/∑x=1nA(i,x)
得到想要的语言模型后,我们最简单的应用(之一),就是用它去生成一段文本,比如给定一个词“中国”,得到后续概率最大的词为“是”,是后边是“一个”,“一个”后边可能是“人”。那么我们就生成了一个二元语言模型下十分合理(概率最高),现实语境下不可理喻的句子。
我认为这就是n元语言模型的两大问题之一,也就是除非n取到无限大,词的概率都无法完整地考虑到语境。而另一大问题是,如果我的文本有1000000个独立单词,那么就需要1000000*1000000大小的矩阵(这仅是二元的情况),可见n元语言模型难以应用到大文本库下。
基于神经网络的语言模型
基于神经网络的语言模型(Neural Network based Language Model)其实和基于统计的语言模型区别不大,但是用 P ( w n ∣ c o n t e x t ) P(w_n|context) P(wn∣context)代替了 P ( w n ∣ w 1 , w 2 , . . . , w n − 1 ) P(w_n|w_1,w_2,...,w_{n-1}) P(wn∣w1,w2,...,wn−1)。由上文可知,在真实场景下,统计得出 P ( w n ∣ w 1 , w 2 , . . . , w n − 1 ) P(w_n|w_1,w_2,...,w_{n-1}) P(wn∣w1,w2,...,wn−1)会失真(一般需要平滑化处理,但是现在已经很少提了)。对于基于神经网络的语言模型来说,词的出现定义为 P ( w n ∣ c o n t e x t ) P(w_n|context) P(wn∣context),假设我们对于任意句子都可以计算出context,那么对于任意context,都能预测出概率最大的词。
例如:“北京是一座()”和“上海是一座()”这两句话,若使用N-gram进行预测,则需要文本库中出现“北京是一座”和“上海是一座”这样的语境,要求较高。而对于基于神经网络的语言模型,我们可以通过计算发现“北京是一座”和“上海是一座”计算出的context向量十分接近,于是哪怕文本库中没有这两句话,也能得出相同的预测。
这时候会有如下疑惑,“北京”和“上海”差那么多,为什么计算出来的context会很接近呢?就要用2013年提出的词向量来解释了。(此处跳过了基于神经网络的语言模型的基本模型,NNLM,感兴趣的朋友需要自行了解,这里就不介绍了。)
词向量
对词的直观表示——独热(One-Hot)向量
怎么去表示一个具有1000个独立单词的文本?最直观的方式是用一个1000维的向量表示每一个词:
v
(
"
d
o
g
"
)
=
(
0
,
0
,
.
.
.
,
1
,
.
.
.
,
0
,
0
)
v("dog")=(0,0,...,1,...,0,0)
v("dog")=(0,0,...,1,...,0,0)
于是我们可以很直观地得到文档和句子的表示(Sentence-level representation & Document-level representation):
v
(
S
)
=
∑
i
=
1
n
v
(
w
i
)
v
(
D
)
=
∑
i
=
1
n
v
(
S
i
)
v(S)=\sum\nolimits_{i=1}^{n}{v(w_i})\\ v(D)=\sum\nolimits_{i=1}^{n}{v(S_i})
v(S)=∑i=1nv(wi)v(D)=∑i=1nv(Si)
我们可以发现独热向量和N-gram(N元语言模型)很配。例如,用v(“dog”)去乘矩阵A,就可以得到一个向量,这个向量告诉我们"dog"后最可能出现的词有哪些。
独热向量自身存在如下问题:
1. 浪费空间
2. 缺乏语义:dog和dogs向量正交,北京和上海正交
文档和句子表示的改进——TF-IDF
很多人把TF-IDF和独热向量、词向量混为一谈,我认为不妥。TF-IDF(term frequency–inverse document frequency)是基于独热向量,对文档和句子表示的改进方法,本质上,是对上述文档和句子的表示进行单词级别的加权。因此,TF-IDF从位格上低于独热向量和词向量(后两者更基础)。
说了半天,TF-IDF是什么呢,TF-IDF是一种统计方法,用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度,通过TF-IDF我们可以计算句子、文档中的每一个词的权重,对句子、文档向量进行加权之后,更能突出句子、文档的特征,从而使分类、回归等任务效果表现更好。其计算公式如下:
t
f
i
,
j
=
n
i
,
j
∑
k
n
k
,
j
tf_{i,j}=\frac{n_{i,j}}{\sum\nolimits_{k}n_{k,j}}
tfi,j=∑knk,jni,j
i
d
f
i
=
l
o
g
D
∣
D
i
∣
+
1
idf_{i}=log\frac{D}{|D_i|+1}
idfi=log∣Di∣+1D
对于单词i,和文档(句子)j,单词i在文档j中的权重为tf*idf。上式
n
i
,
j
n_{i,j}
ni,j为文档j中单词i出现的次数。
n
k
,
j
n_{k,j}
nk,j为文档词的总数。D为文档(句子)总数,
∣
D
i
∣
|D_i|
∣Di∣为包含i词的文档总数。
我们假设一个如下的使用场景:我们有一个情感分类任务,要求分清句子是正面情感还是负面情感。数据集来自手机商城的用户评价。对于一个句子:“这个手机就是垃圾,手机屏幕垃圾,手机电池垃圾,连手机系统都是垃圾。”我们就看手机和垃圾这两个词,在句子中出现次数一样,但是由于文本库中,来自手机商城的用户评价会经常提到手机,所以“手机”的idf极低,导致手机权重低,反之“垃圾”权重高,因此这句话的句子表示向量会突出“垃圾”,从而有利于情感分类。
词向量(word2vec)
如今的自然语言处理已经离不开词向量了,然而词向量是2013年才出现的,在词向量之前,人们仅通过独热编码、tf-idf、pos标注、依存句法、主题模型等方法,完成自然语言处理的任务。而词向量出现之后,上述的众多方法开始退幕,论文向深度学习+词向量靠拢。
词向量要解决的问题完全针对独热向量的弱点。一方面,使用300维到50维的向量表示每一个词,极大节省空间。另一方面,词向量中蕴含了语义信息,dog和dogs余弦距离十分接近,“北京”与“上海”的距离也较为接近。基于词向量,我们的模型就可以更好地解决“北京是一座()”和“上海是一座()”这样的问题了。在2013年词向量(word2vec)提出之后,人们也不断对词向量进行改进,从GloVe到Bert。这一部分将以后在自然语言处理前沿中进行介绍。
CBOW(Continuous Bag-of-Words model)
在2013年word2vec论文中同时提出了CBOW模型和Skip-Gram模型。简单来说,CBOW模型用上下文来预测中心词,Skip-Gram模型是通过当前词预测上下文。显然CBOW模型更符合咱们的思路,因此重点介绍。
由上图可知,CBOW模型和Skip-Gram模型都由单隐层的神经网络组成,其中,CBOW模型输入上下文词的k维独热编码向量,通过隐层权重矩阵
W
k
,
n
h
W^h_{k,n}
Wk,nh,计算出隐层向量(代表上下文),之后通过输出层权重矩阵
W
n
,
k
o
W^o_{n,k}
Wn,ko,计算得到k维中心词预测向量。矩阵
W
k
,
n
h
W^h_{k,n}
Wk,nh的每一行就对应了每一个词的词向量,相当于一个词向量的字典。
词向量的训练
词向量的使用很好理解,但是训练过程相对复杂,这里只介绍原始的思路,在实际的训练中一般使用负采样(negative sampling)方法,在这里不做介绍。首先,设置目标函数如下:
−
L
=
1
T
∑
w
j
∈
C
l
o
g
P
(
w
j
∣
c
o
n
t
e
x
t
)
-L=\frac{1}{T}\sum\nolimits_{w_j \in C}{logP(w_j|context)}
−L=T1∑wj∈ClogP(wj∣context) 其中,
P
(
w
j
∣
c
o
n
t
e
x
t
)
=
y
j
=
e
x
p
(
u
j
)
∑
w
i
∈
C
e
x
p
(
u
i
)
P(w_j|context)=y_j=\frac{exp(u_j)}{\sum\nolimits_{w_i \in C}{exp(u_i)}}
P(wj∣context)=yj=∑wi∈Cexp(ui)exp(uj) 其中
u
j
u_j
uj代表输出层第j维的值,
u
j
u_j
uj同理。
代入上式,则对每一个预测结果j,有:
∂
L
∂
u
j
=
∂
(
u
j
−
l
o
g
∑
w
i
∈
C
e
x
p
(
u
i
)
)
∂
u
j
\frac{\partial L}{\partial u_j}=\frac{\partial (u_j-log\sum\nolimits_{w_i \in C}exp(u_i))}{\partial u_j}
∂uj∂L=∂uj∂(uj−log∑wi∈Cexp(ui))
∂
L
∂
u
j
=
y
j
−
t
j
\frac{\partial L}{\partial u_j}=y_j-t_j
∂uj∂L=yj−tj 其中
y
j
y_j
yj为标注结果,
t
j
t_j
tj除j维是1之外,其余维与
u
j
u_j
uj相同。进而有:
∂
L
∂
W
i
,
j
o
=
∂
L
∂
u
j
∂
u
j
∂
W
i
,
j
o
=
(
y
j
−
t
j
)
h
i
\frac{\partial L}{\partial W^o_{i,j}}=\frac{\partial L}{\partial u_j}\frac{\partial u_j}{\partial W^o_{i,j}}=(y_j-t_j)h_i
∂Wi,jo∂L=∂uj∂L∂Wi,jo∂uj=(yj−tj)hi
∂
L
∂
h
i
=
∑
j
=
1
v
(
y
j
−
t
j
)
w
i
,
j
o
\frac{\partial L}{\partial h_{i}}=\sum \nolimits^v_{j=1}(y_j-t_j)w^o_{i,j}
∂hi∂L=∑j=1v(yj−tj)wi,jo 其中
h
i
h_i
hi为隐层向量。根据所求梯度更新对应的输出层矩阵。之后进一步推导有:
∂
L
∂
W
i
,
j
h
=
∂
L
∂
h
i
∂
h
i
∂
W
i
,
j
h
=
∑
j
=
1
v
(
y
j
−
t
j
)
w
i
,
j
o
x
i
\frac{\partial L}{\partial W^h_{i,j}}=\frac{\partial L}{\partial h_i}\frac{\partial h_i}{\partial W^h_{i,j}}=\sum \nolimits^v_{j=1}(y_j-t_j)w^o_{i,j}x_i
∂Wi,jh∂L=∂hi∂L∂Wi,jh∂hi=∑j=1v(yj−tj)wi,joxi 根据上式所求梯度更新隐层权重矩阵,有:
w
i
,
j
n
e
w
=
w
i
,
j
o
l
d
−
η
∂
L
∂
W
i
,
j
h
w^{new}_{i,j}=w^{old}_{i,j}-\eta\frac{\partial L}{\partial W^h_{i,j}}
wi,jnew=wi,jold−η∂Wi,jh∂L