赞
踩
语言模型本质上是在回答一个问题:出现的语句是否合理。
在历史的发展中,语言模型经历了专家语法规则模型(至80年代),统计语言模型(至00年),神经网络语言模型(到目前)。
专家语法规则模型在计算机初始阶段,随着计算机编程语言的发展,归纳出的针对自然语言的语法规则。但是自然语言本身的多样性、口语化,在时间、空间上的演化,及人本身强大的纠错能力,导致语法规则急剧膨胀,不可持续。
统计语言模型用简单的方式,加上大量的语料,产生了比较好的效果。统计语言模型通过对句子的概率分布进行建模,统计来说,概率高的语句比概率低的语句更为合理。在实现中,通过给定的上文来预测句子的下一个词, 如果预测的词和下一个词是一致(该词在上文的前提下出现的概率比其它词概率要高),那么上文+该词出现的概率就会比上文+其他词词的概率要更大,上文+该词更为合理。
神经网络语言模型在统计语言模型的基础上,通过网络的叠加和特征的逐层提取,可以表征除了词法外,相似性、语法、语义、语用等多方面的表示。
语言模型可以用于多种 NLP 任务,如预测、纠错、推理等。在本文中,主要介绍语言模型在统计及(深度学习)神经网络方面的发展情况。
统计语言模型从统计的角度预测句子的概率分布,通常对数据量有较大要求。对于句子
w
1
,
w
2
,
…
,
w
n
w_1,w_2,\dots,w_n
w1,w2,…,wn,计算其序列概率
P
(
w
1
,
w
2
,
…
,
w
n
)
P(w_1,w_2,\dots,w_n)
P(w1,w2,…,wn),根据链式法则可以求得整个句子的概率:
P
(
w
1
,
w
2
,
…
,
w
n
)
=
P
(
w
1
)
P
(
w
2
∣
w
1
)
…
P
(
w
n
∣
w
1
,
…
,
w
n
−
1
)
P(w_1,w_2,\dots,w_n) = P(w_1)P(w_2|w_1)\dots P(w_n|w_1,\dots,w_{n-1})
P(w1,w2,…,wn)=P(w1)P(w2∣w1)…P(wn∣w1,…,wn−1)
其中,每个词出现的概率通过统计计算得到:
P
(
w
i
∣
w
1
,
…
,
w
i
−
1
)
=
C
(
w
1
,
w
2
,
…
,
w
i
)
∑
w
C
(
w
1
,
w
2
,
…
,
w
i
−
1
)
P(w_i|w_1,\dots,w_{i-1}) = \frac{C(w_1,w_2,\dots,w_i)}{\sum_{w}C(w_1,w_2,\dots,w_{i-1})}
P(wi∣w1,…,wi−1)=∑wC(w1,w2,…,wi−1)C(w1,w2,…,wi)
这种方法有以下问题:
n-gram 是最为普遍的统计语言模型。它的基本思想是将文本里面的内容进行大小为 N N N的滑动窗口操作,形成长度为 N N N 的短语子序列,对所有短语子序列的出现频度进行统计。 直观上理解,n-gram 就是将句子长度缩短为只考虑前 n − 1 n-1 n−1 个词。 值得注意的是:这里 P ( w 1 ) P(w_1) P(w1)的实际含义是句首词概率,实际应用中应加入起始符<s>,如对于 bigram 而言,应为 P ( w 1 ∣ < s > ) P(w_1|<s>) P(w1∣<s>),同理应在句尾加入结束符 </s>,加入起始符和结束符的意义在于对句中任意长度的部分序列均进行建模。这里举一个小数量的例子进行辅助说明:假设我们有一个语料库,如下:
老鼠真讨厌,老鼠真丑,你爱老婆,我讨厌老鼠。
想要预测“我爱老”这一句话的下一个字。我们分别通过 bigram 和 trigram 进行预测。
通过 bigram,便是要对 P ( w ∣ 老 ) P(w | 老) P(w∣老)进行计算,经统计,“老鼠”出现了3次,“老婆”出现了1次,通过最大似然估计可以求得 P ( 鼠 ∣ 老 ) = 0.75 , P ( 婆 ∣ 老 ) = 0.25 P(鼠|老)=0.75,P(婆|老)=0.25 P(鼠∣老)=0.75,P(婆∣老)=0.25, 因此我们通过 bigram 预测出的整句话为: 我爱老鼠。
通过 trigram,便是要对便是要对 P ( w ∣ 爱 老 ) P(w | 爱 老) P(w∣爱老)进行计算,经统计,仅“爱老婆”出现了1次,通过最大似然估计可以求得 P ( 婆 ∣ 爱 老 ) = 1 P(婆|爱 老)=1 P(婆∣爱老)=1,因此我们通过trigram 预测出的整句话为: 我爱老婆。显然这种方式预测出的结果更加合理。
上例证明了,随着 n 的提升,我们拥有了更多的前置信息量,可以更加准确地预测下一个词。但这也带来了一个问题,数据随着 n 的提升变得更加稀疏了,导致很多预测概率结果为0。当遇到零概率问题时,我们可以通过平滑来缓解 n-gram 的稀疏问题。
n-gram 需要平滑的根本原因在于数据的稀疏性,而数据的稀疏性则是由自然语言的本质决定的。当这种稀疏性存在的时候,平滑总能用于缓解问题提升性能。 直观上讲,如果你认为你拥有足够多的数据以至于稀疏性不再是一个问题,我们总是可以使用更加复杂、更多参数的模型来提升效果,如提高 n 的大小。当 n 提高,模型参数空间的指数级增加,稀疏性再度成为了所面临的问题,这时通过合理的平滑手段可以获得更优的性能。
在一个有限的数据集中,高频事件通过统计所求得的概率更加可靠,而出现频次越小的事件所得的概率越不可靠,这种现象在高维空间中表现更加突出。如果将训练集的概率分布直接拿来作为测试集分布,那么训练集中的“未登录词”概率将会是0,这显然与我们的认知是不符合的,因为测试集中是有可能出现未登录词的,没见过的不代表不存在。**平滑解决的问题就是:根据训练集数据的频率分布,估计在测试集中“未登录词”的概率分布,从而在测试集上获得一个更加理想的概率分布预估 。**接下来我们对常用的平滑方法进行介绍。
P ( w i ∣ w i − 1 = 1 + c ( w i − 1 w i ) ∑ w i [ 1 + c ( w i − 1 w i ) ] = 1 + c ( w i − 1 w i ) ∣ V ∣ + ∑ w i c ( w i − 1 w i ) P(w_i|w_{i-1}= \frac{1+c(w_{i-1}w_i)}{\sum_{w_i}[1+c(w_{i-1}w_i)]} = \frac{1+c(w_{i-1}w_i)}{|V| + \sum_{w_i}c(w_{i-1}w_i)} P(wi∣wi−1=∑wi[1+c(wi−1wi)]1+c(wi−1wi)=∣V∣+∑wic(wi−1wi)1+c(wi−1wi),如公式所示,拉普拉斯平滑对所有事件的频次均进行了加1。拉普拉斯平滑是最为直观、容易理解的平滑方式,对事件发生的频次加一对于高频事件的概率影响基本可以忽略,它也同时解决了未登录词的概率计算问题。
但直接加1的拉普拉斯平滑也是一种较为“糟糕”的平滑方式,简单粗暴的加1有时会对数据分布产生较大的影响,有时却又微不足道。拉普拉斯平滑对未知事件的概率预测进行了平等对待,这显然不合理!加性平滑对这一点进行了改进,通过超参数的方式提升了拉普拉斯平滑的泛用性与效果。
P a d d ( w i ∣ w i − n + 1 i − 1 ) = δ + c ( w i − n + 1 i ) δ ∣ V ∣ + ∑ w i c ( w i − n + 1 i ) P_{add}(w_i|w_{i-n+1}^{i-1}) = \frac{\delta + c(w_{i-n+1}^{i})}{\delta|V| + \sum_{w_i}c(w_{i-n+1}^{i})} Padd(wi∣wi−n+1i−1)=δ∣V∣+∑wic(wi−n+1i)δ+c(wi−n+1i),在加性平滑中我们做出以下假设:我们假定每个 n-gram 事件额外发生过 δ \delta δ 次;一般而言 0 < δ ≤ 1 0<\delta≤1 0<δ≤1,当 δ = 1 \delta=1 δ=1,时等价于拉普拉斯平滑,当 δ < 1 \delta<1 δ<1时,表示对未登录词的概率分配权重减少。这种方法提升了拉普拉斯平滑的泛用性,但依然由于实际效果被很多人诟病。
古德图灵平滑是一种非常巧妙的平滑方式,直观上讲,它通过高频事件优化低频事件的概率表示,并最终通过层层迭代获取到未登录词的概率。具体而言,假定出现实际出现
r
r
r 次的事件的调整后频次为
r
∗
r^*
r∗,规定:
r
∗
=
(
r
+
1
)
n
r
+
1
n
r
r^* = (r+1)\frac{n_{r+1}}{n_r}
r∗=(r+1)nrnr+1,其中
n
r
n_r
nr表示 n-gram中恰好出现
r
r
r 次的不同序列数。根据 Zipf’s law,
n
r
n_r
nr分布如下图所示(横轴为
r
r
r,纵轴为
n
r
n_r
nr),由图可知,通常而言
r
∗
<
r
r^*<r
r∗<r。
注:一般来说,出现一次的词的数量比出现两次的多,出现两次的比三次的多,这种规律称为 Zipf 定律(Zipf’s Law)
根据调整后频次可以得到相应优化后的概率:
P
G
T
(
x
:
c
(
x
)
=
r
)
=
r
∗
N
P_{GT}(x:c(x) = r) = \frac{r^*}{N}
PGT(x:c(x)=r)=Nr∗,其中,
N
=
∑
r
=
0
i
n
f
r
∗
n
r
=
∑
r
+
0
i
n
f
r
n
r
N=\sum_{r=0}^{inf}r^*n_{r} = \sum_{r+0}^{inf} rn_r
N=∑r=0infr∗nr=∑r+0infrnr
古德图灵平滑同样存在一些问题,随着
r
r
r 上升,很容易出现的情况
n
r
+
1
=
0
n_{r+1}=0
nr+1=0,直观上讲,高频词的序列数往往很不稳定,甚至会出现很多为0的真空频次。可以通过手动设定一个阈值
k
k
k 来解决这个问题:当
r
<
k
r<k
r<k 时,重新估计该类别的概率,这么做的理论依据是高频词的统计估计通常是比较准确的,不需要对其进行折扣。整体而言,我们对未登录词分配一部分概率比例,测试集中的未登录词平分这部分概率。
n-gram 的优点有很多,首先它是一种直观的自然语言理解与处理方式,对参数空间进行了优化,并具有很强的解释性。它包含前 n − 1 n-1 n−1 个词的全部信息,不会产生丢失和遗忘。除此以外,它还具有计算逻辑简单的优点 。但与此同时,n-gram 也具有本质上的缺陷:n-gram 无法建立长期依赖,当 n n n 过大时仍会被数据的稀疏性严重影响,实际使用中往往仅使用 bigram 或 trigram;n-gram 基于频次进行统计,没有足够的泛化能力。因此,神经网络语言模型逐渐取代传统的统计自然语言模型成为主流,接下来我们对神经网络语言模型进行介绍。
统计语言模型在学习单词序列的联合概率时,一个比较显然的问题是维度灾难,计算和存储参数巨多,在高维下,数据稀疏会导致统计语言模型存在很多为零的条件概率。举个直观的例子,我们有词表
∣
V
∣
=
1
0
5
|V|=10^5
∣V∣=105的语料库,学习长度为
l
=
10
l=10
l=10 的单词序列的联合概率,潜在参数空间大小为
10000
0
1
0
=
1
0
5
0
100000^10=10^50
10000010=1050,传统语言模型花了很多精力解决零概率问题。n-gram 的思想是考虑对词序较近的词依赖更大,降低上下文长度,减少了参数数量,但丢失了远距离信息,若
n
n
n 元取值较大,则会导致稀疏问题;另外统计语言模型中的变量都是离散型,每个变量的轻微改变都会对联合概率产生很大影响,且基于离散变量的概率分布很难通过汉明距离捕获句子之间的相似性,如"The cat is walking in the bedroom","A dog was running in a room"中“dog” and “cat”扮演着相似的语义和语法角色,但不会因为两个句子非常相似而让该句子的概率变高。
2003年 Bengio 提出,神经网络语言模型( neural network language model, NNLM)的思想是提出词向量的概念,代替 ngram 使用离散变量(高维),采用连续变量(具有一定维度的实数向量)来进行单词的分布式表示,解决了维度爆炸的问题,同时通过词向量可获取词之间的相似性。NNLM 将联合概率通过拆分为两步来计算:将词汇表中的每个词对应一个分布式向量表示,对句子中的词向量通过函数得到联合概率,在大语料上通过神经网络来学习词向量和联合概率函数的参数。
给定训练语料的一个单词序列
w
1
,
…
w
T
,
w
t
∈
V
w_1,\dots w_T, w_t \in V
w1,…wT,wt∈V,
V
V
V是词汇表。NNLM 的目标是给定前
t
−
1
t-1
t−1 个词,得到第
t
t
t 个词概率的一个函数
f
(
w
1
,
…
,
w
t
−
1
)
=
P
^
(
w
t
∣
w
1
,
…
,
w
t
−
1
)
f(w_1,\dots,w_{t-1}) = \hat P(w_t|w_1,\dots,w_{t-1})
f(w1,…,wt−1)=P^(wt∣w1,…,wt−1)通过条件概率的连乘,得到单词序列的联合概率模型。给出
w
1
,
…
,
w
t
−
1
w_1,\dots,w_{t-1}
w1,…,wt−1,函数
f
f
f 满足
∑
i
=
1
∣
v
∣
f
(
i
,
w
1
,
…
,
w
t
−
1
)
=
1
\sum_{i=1}^{|v|}f(i, w_1,\dots,w_{t-1}) = 1
∑i=1∣v∣f(i,w1,…,wt−1)=1,且
f
>
0
f>0
f>0。相比 n-gram 通过复杂平滑策略给出未登录词概率,NNLM 通过分布式表征对未登录词给出更高的似然概率。
f
f
f 的实现分特征映射和计算条件概率分布两步:
n-gram 语言模型的问题在于捕捉句子中长期依赖的能力非常有限,NNLM 对输入数据要求固定长度(一般取5-10),直观上看就是使用神经网络编码的 n-gram 模型,也无法解决长期依赖的问题。语言模型任务是一个序列预测问题,RNN 是天然用来解决序列问题的模型,2010年 Mikolov 提出 RNNLM,RNNLM 的历史信息是句子前边所有的词,使其可以捕获更长的历史信息。RNNLM 对后边 elmo 的提出有着启蒙作用。
如图,RNNLM 的输出为下一个位置的单词预测概率分布
o
u
t
p
u
t
(
t
)
output(t)
output(t);输入由两部分组成,当前位置单词的词向量
i
n
p
u
t
(
t
)
input(t)
input(t) 和
t
−
1
t-1
t−1 时刻的隐状态
c
o
n
t
e
x
t
(
t
−
1
)
context(t-1)
context(t−1) 相加,隐层激活函数为 sigmoid。
直观上来说,RNN 网络打破了上下文窗口的限制,使用隐藏层的状态概括历史全部语境信息,对比 NNLM 可以捕获更长的依赖,在实验中取得了更好的效果。RNNLM 超参数少,通用性更强;但由于 RNN 存在梯度弥散问题,很难捕获更长距离依赖。
目前最火的语言模型做词向量的工具是 Mikolov 提出的 word2vec.word2vec 的网络结构和 NNLM 类似,主要差别在训练方式上。CBOW 如下图:
CBOW 的思想是从句子中抠掉一个词,用这个词的上下文去预测这个词。即已知
w
t
−
2
,
w
t
−
1
,
w
t
+
1
,
w
t
+
2
w_{t-2},w_{t-1},w_{t+1},w_{t+2}
wt−2,wt−1,wt+1,wt+2,预测
w
t
w_t
wt,预测目标函数取对数似然函数为
L
=
∑
w
∈
C
log
P
(
w
∣
C
o
n
t
e
x
t
(
w
)
)
L=\sum_{w\in C}\log P(w|Context(w))
L=∑w∈ClogP(w∣Context(w)),Skip-Gram的思想是输入一个单词,通过网络去预测它的上下文。即已知
w
t
w_t
wt,预测
w
t
−
2
,
w
t
−
1
,
w
t
+
1
,
w
t
+
2
w_{t-2},w_{t-1},w_{t+1},w_{t+2}
wt−2,wt−1,wt+1,wt+2,预测目标函数取对数似然函数为
L
=
∑
w
∈
C
log
P
(
C
o
n
t
e
x
t
(
w
)
∣
w
)
L=\sum_{w\in C}\log P(Context(w)|w)
L=∑w∈ClogP(Context(w)∣w)
这两种方式与 NNLM 有很大的不同,NNLM 的主要任务是预测句子概率,词向量只用到了上文信息,是其中间产物;word2vec 是为获得单词的分布式表征而生,根据句子上下文学习单词的语义和语法信息。
除了网络结构更加结合上下文信息,word2vec 的另一大贡献在计算优化上。word2vec 去掉了非线性隐层,CBOW 将输入直接相加通过 softmanx 进行预测,减少了隐层的大量计算,同时通过分层 softmax (hierarchical Softmax) 和负采样(Negative sampling) 对 softmax 的计算也做了很大优化。
与传统的神经网络 softmax 输出不同,word2vec 的 hierarchical softmax 结构把输出层改成了一颗 Huffman 树( huffman 树在训练时预先构造好,每条边是一个随机初始化的向量,和隐层输出计算 sigmoid 概率),其中图中白色的叶子节点表示词汇表中所有的
∣
V
∣
|V|
∣V∣个词,黑色节点表示非叶子节点,每一个叶子节点都对应唯一的一条从 root 节点出发的路径。我们的目的是使得
w
=
w
o
u
t
p
u
t
w=w_{output}
w=woutput这条路径的概率最大,即:
P
(
w
=
w
o
u
t
p
u
t
∣
w
i
n
p
u
t
)
P(w=w_{output}|w_{input})
P(w=woutput∣winput)最大,假设最后输出的条件概率是
w
2
w_2
w2最大,那么我只需要去更新从根结点到
w
2
w_2
w2这一个叶子结点的路径上面节点的向量即可,而不需要更新所有的词的出现概率,这样大大地缩小了模型训练更新的时间。
当我们计算
w
2
w_2
w2输出概率时,我们需要从根节点到叶子结点计算概率的乘积。
p
(
n
,
l
e
f
t
)
=
σ
(
v
′
n
T
⋅
h
)
p
(
n
,
r
i
g
h
t
)
=
1
−
σ
(
v
′
n
T
⋅
h
)
=
σ
(
−
v
′
n
T
⋅
h
)
p
(
w
2
=
w
o
u
t
p
u
t
)
=
p
(
n
(
w
2
,
1
)
,
l
e
f
t
)
⋅
p
(
n
(
w
2
,
2
)
,
l
e
f
t
)
⋅
p
(
n
(
w
2
,
3
)
,
l
e
f
t
)
在 NNLM 和 word2ve 的方法输出层的维度均为词表大小 ∣ V ∣ |V| ∣V∣,从而输出权重矩阵为 d m × ∣ V ∣ d_m \times |V| dm×∣V∣,矩阵高维稀疏,计算成本高且需要大量的训练数据。当训练一个样本时,我们主要目标是让预测这个训练样本更准,对负样本只有微调,如果对整个输出权重都进行微调,在预测时会存在一些过拟合,负采样( Negative Sampling )提高了训练速度和词向量的质量,一定程度上缓解了过拟合。
如假设 ∣ V ∣ = 1 0 5 |V|=10^5 ∣V∣=105,词向量维度 d m = 300 d_m=300 dm=300我们随机选择一小部分负例单词来调整权重,(如10个负例词),则模型每次运行的计算量从 300 × 1 0 5 300\times10^5 300×105降低为 300 × 10 300\times10 300×10,大幅降低计算。
负采样的选择利用带权采样,即根据出现概率来选,经常出现的词更容易被选为负例样本。公式如下:
P
(
w
i
)
=
c
o
u
n
t
(
w
i
)
0.75
∑
j
=
0
n
(
c
o
u
n
t
(
w
j
)
0.75
)
P(w_i)=\frac{count(w_i)^{0.75}}{\sum_{j=0}^{n}(count(w_j)^{0.75})}
P(wi)=∑j=0n(count(wj)0.75)count(wi)0.75
这里的0.75是一种平滑策略,让低频词出现的机会更大一些。
直观上来说,word2vec 已经成为 NLP 深度学习的标配,预训练词向量的好坏直接影响着模型的效果。word2vec 由于其模型网络结构,很方便在海量数据集上进行预训练,在海量语料预训练+任务数据 finetune 的半监督方法开始兴起,当任务标注数据较少时表现出明显的优势。TextCNN 论文里曾经对比过四种形式的词向量:
在实验结果中可以看到 non-static 的方法大多数时候都是要比 static 方法稍好的,而 static 方法比 rand 的方法要好( rand 是指 word embedding 过程中词的编码随机给出)。而结合 static 和 non-static 的 multichannel 方法相较于单纯的 static 和 non-static 方法,在较小的数据集上表现比他们都要好(因为这种混合的方法体现了一种折衷的想法,即不希望被微调的单词向量与原始产生的单词向量差距太大,也希望保持一定的动态变化空间)。
Word2Vec 珠玉在前,GloVe 由于更加复杂,使用者明显要少很多,但同时实验论证部分场景下 GloVe 效果更好,并且 GloVe 的思想还是非常值得学习的。
GloVe 提出于2014年,当时词向量的主流生成方法有两种,一种基于矩阵因子分解方法,另一种则基于浅层滑动窗口,Glove 将两者的优势合二为一。GloVe 属于统计语言模型,它的主要优化点在于引入了共现矩阵,利用词向量间的相似性逼近全局共现次数,本质是对共现矩阵进行降维。
接下来用一个直观的例子说明共现概率矩阵( Co-occurrence Probabilities Matrix )的含义。假设词表大小为
V
V
V,共现矩阵
X
X
X大小则为
[
V
,
V
]
[V,V]
[V,V],
X
i
,
j
X_{i,j}
Xi,j表示以
w
i
w_i
wi为中心词时背景词
w
j
w_j
wj出现的次数,其中
0
<
=
i
,
j
<
V
0<=i,j<V
0<=i,j<V,特别规定条件概率
P
i
,
j
=
P
(
w
j
∣
w
i
)
P_{i,j}=P(w_j|w_i)
Pi,j=P(wj∣wi)。这里通过一个简单的例子对共现概率矩阵的推导进行说明,对于句子“我老爱我老婆了”,为了简化,我们从字级别进行考虑,滑动窗口大小设定为2,则通过以下方式对共现概率矩阵进行推导:
Glove 的本质是通过相似度对共现次数进行逼近。相似度可通过单词的向量乘积
v
i
T
v
j
v_{i}^{T}v_{j}
viTvj求得,利用exp使乘积不为负。
e
x
p
(
v
i
T
v
j
)
−
>
P
i
j
exp(v_{i}^{T}v_{j})->P_{i_j}
exp(viTvj)−>Pij两边同时取对数可得
v
i
T
v
j
−
>
log
(
X
i
,
j
X
i
)
v_{i}^{T}v_{j}->\log(\frac{X_{i,j}}{X_{i}})
viTvj−>log(XiXi,j):逼近即为
min
v
i
T
v
j
−
log
(
X
i
,
j
X
i
)
\min v_{i}^{T}v_{j}-\log(\frac{X_{i,j}}{X_{i}})
minviTvj−log(XiXi,j)通过最小化平方损失函数可得每个词的词向量表示:
l
o
s
s
=
∑
i
=
1
V
∑
j
=
1
V
f
(
X
i
,
j
)
(
v
i
T
v
j
+
log
X
i
−
log
(
X
i
,
j
)
)
2
=
=
∑
i
=
1
V
∑
j
=
1
V
f
(
X
i
,
j
)
(
v
i
T
v
j
+
b
i
+
b
j
−
log
(
X
i
,
j
)
)
2
loss = \sum_{i=1}^{V}\sum_{j=1}^{V}f(X_{i,j})({v_{i}^{T}v_{j}}+\log X_i-\log(X_{i,j}))^2 == \sum_{i=1}^{V}\sum_{j=1}^{V}f(X_{i,j})({v_{i}^{T}v_{j}}+b_i + b_j - \log(X_{i,j}))^2
loss=i=1∑Vj=1∑Vf(Xi,j)(viTvj+logXi−log(Xi,j))2==i=1∑Vj=1∑Vf(Xi,j)(viTvj+bi+bj−log(Xi,j))2
其中
log
X
i
\log{X_i}
logXi可理解为边缘分布,利用偏置项
b
i
,
b
j
b_i,b_j
bi,bj代替
f
(
X
i
,
j
)
=
(
X
i
,
j
/
X
m
a
x
)
α
i
f
X
i
,
j
<
X
m
a
x
e
l
s
e
1
f(X_{i,j}) = (X_{i,j}/X_{max})^{\alpha} \qquad if \quad X_{i,j} < X_{max} \quad else \quad 1
f(Xi,j)=(Xi,j/Xmax)αifXi,j<Xmaxelse1
f
i
,
j
f_{i,j}
fi,j表示对每个词重新分配一个权重,
X
m
a
x
X_{max}
Xmax和
α
\alpha
α为手动设定的阈值,glove 给出的经验值
α
=
3
4
,
X
m
a
x
=
100
\alpha=\frac{3}{4},X_{max}=100
α=43,Xmax=100,
f
f
f 权重取值示意图。
在实践中,GloVe 和 Word2Vec 各有优势,具体任务使用哪种词向量仍需要实验得出结论。与此同时,GloVe 对并行的支持更好,往往训练起来耗时更短,然而内存消耗更大。
多义词是自然语言中经常出现的现象,也是语言灵活性和高效性的一种体现,比如苹果可能指手机,也可能指水果。在用语言模型训练的时候,不论什么上下文的句子经过 word2vec,都只能得到苹果的一个静态表达,所以 word embedding 无法区分多义词的不同语义,这就是它的一个比较严重的问题。直观上来讲, ELMo(Embedding from Language Model, 2018年提出)解决了一词多义的问题,在询问“苹果”的词向量时,ELMo 会考虑是什么语境下的“苹果”,我们应该去询问“苹果股价”里的“苹果”词向量是什么。ELMo 通过提供词级别、携带上下文信息的动态表达,能有效的捕捉语境信息。ELMo 的提出对后面的 GPT 和 BRET 有一个很好的引导和启发的作用。ELMo 包括预训练+微调两个阶段:预训练网络结构采用双向两层 LSTM,在大数据集上利用语言模型任务,根据单词的上下文去正确预测单词,图左侧 LSTM 的输入是的上文,右侧 LSTM 的输入是的下文,模型参数共享输入 Embedding 层和 Softmax 层,目标函数为:
∑
k
=
1
N
(
log
(
t
k
∣
t
1
,
…
,
t
k
−
1
)
+
log
(
t
k
∣
t
k
+
1
,
…
,
t
N
)
)
\sum_{k=1}^{N}(\log(tk|t1,\dots,t_{k-1}) + \log(tk|t_{k+1},\dots,t_{N}))
k=1∑N(log(tk∣t1,…,tk−1)+log(tk∣tk+1,…,tN))
ELMo 预训练得到对应单词的 Embedding 层和两方向 LSTM 层,这些向量将用在下游任务里。
在做下游任务时,通过预训练网络得到单词的 Embedding 层和多层双向 LSTM 层,归一化加权成一个向量输入到下游任务中。相比 word2vec 的静态词向量, ELMo 在 embedding 层得到词向量,通过两层 LSTM 网络增加了上下文语境信息,生成动态词向量。
ELMo 不仅学习了单词的词向量,还学习了一个双层双向 LSTM 网络,且实验表明较低层的 LSTM 抓住的是词汇的句法信息,较高层次的 LSTM 向量抓住的是词汇的语义信息。通过 LSTM 网络对最底层 word Embedding 的动态调整,实现多义词的功能。
2018年提出的 GPT,全称是生成式的预训练,它是一种基于多层 transformer 的单向语言模型。GPT 总体包括两个阶段:首先利用其语言模型的特性在海量语料库上进行预训练;完成预训练后,通过 fine-tune 的模型解决下游任务。如下图所示,GPT 可以用于丰富的任务类型。
乍看之下,GPT与 ELMo 很像,区别主要在于:
GPT 在12个 NLP 任务中有9个取得了 SOTA,效果十分惊艳。GPT 是语言模型中浓墨重彩的一笔,对之后的语言模型发展产生了很多影响。
ELMo 通过双向拼接融合词向量表征上下文,GPT 利用单向语言模型来获取向量表达,2018年提出的 BERT对GPT 的改进有点借鉴于 NNLM 到 CBOW 的改进,将任务从预测句中下一个词变为从句子中抠掉一个词用上下文去预测这个词,同时增加了预测是否是下一个句子的任务。模型结构沿用 GPT 的思想,利用 transformer 的 self-attentnion 和 FFN 前馈网络叠加,充分利用 transformer 强大特征抽取能力。
相比 GPT 在微调时需要加入起始符、终结符和分隔符等改造,BERT 在训练时就将其加入,保证预训练和微调的输入之间没有差异,提高预训练的可利用性。
BERT 是对近几年 NLP 进展(特征抽取器、语言模型)的集大成者,充分利用大量的无监督数据,将语言学知识隐含地引入特定任务。
2019年提出的 GPT-2 文本生成的效果十分惊艳。这里对 GPT-2 进行简单的讨论,主要关注其优化点。
直观上而言就是 GPT-2 使用更多更优质更全面的数据,并增加模型的复杂度。除此以外,GPT-2 其实还蕴含了很多深意,值得进行深入研究。
有意思的是,GPT-2 依然坚持使用单向语言模型,bert 论文中得到的结论是“双向语言模型所获得的提升最大,其次预测下个句子对部分任务影响较大”,既然如此,那么为什么 GPT-2 依然坚持使用单向语言模型呢?这个问题看似是 GPT-2固执己见,但可能涉及到了语言模型的根本思想,就是一个语言模型的本质是什么。语言模型是否应该是单向的呢,bert 的 mask 操作是否会造成一定的局限性呢,而这是否又是GPT-2 中文文本生成任务如此惊艳的原因呢。GPT-2 可能是想要解决这些问题才会坚持使用单向语言模型,这里希望大家可以继续深入讨论,期待 GPT-3会得到更加丰满的解释。
与此同时,GPT-2 由于参数量实在是太大,同等参数量大小,大部分任务效果并不如 bert,但它仍然值得我们进行深入探究。
我们对比了两个模型 LSTM+CRF 和 BERT+CRF 的在开源数据集 MSRA 上的效果,BERT 优势明显。
在我们对话系统的槽位提取任务中,利用当前有限的标注数据,BERT+CRF 模型取得了 精度86.1%,召回88.9%,F1值87.5% 的效果;
在意图分类任务中,利用 BERT+FST 模型取得 精度69.71%,召回73.8%, F1值71.7% 的效果。
当前,我们在验证使用 BERT+CRF 模型做分类和槽提取的多任务联合模型。
参考:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。