前言
自然语言处理(Natural Language Process,NLP)的发展目前大致经历了统计语言模型阶段、深度学习阶段、预训练语言模型阶段和大语言模型阶段。每个不同的阶段都有比较经典的算法模型,想要了解每个阶段具体的相关内容,可以参照博客NLP的发展阶段。本篇主要是对其中第三个阶段,即预训练语言模型阶段常见的模型进行分类。
目前常见的预训练模型基本都是基于Transformer架构进行调整以后所得到的,而Transformer架构本身是一个Seq2Seq的架构,不同的预训练模型采用的架构也不太一样,但是基本上可以分为基于编码器部分的自然语言理解模型,基于编码器部分的自然语言生成模型以及基于编码器-解码器的模型。但在介绍这些预训练模型之前,还需要对动态词向量算法模型ELMo进行相应的理解。
ELMo
ELMo模型可以看做是NLP领域内第一个预训练模型, 也可以说该模型是介于深度学习阶段和预训练语言模型阶段中间的一个模型。主要是因为该网络模型仍然跟深度学习相关算法一样采用LSTM网络来进行相关数据的处理。该网络模型是一个双向语言模型,同时从两个方向进行语言模型建模:从左到右前向建模和从右到左后向建模。双向建模带来了更好的上下文表示,文本中的每个词都可以同时利用其左右两侧文本的信息。网络结构分为输入层、隐藏层和输出层三个部分,具体的结构图如下图所示:
输入层
输入层为了减少词不再词表中(Out of Vocabulary, OOV)的情况,对输入文本进行字符级别的编码。然后使用卷积神经网络对字符级的表示进行语义组合,通过调整卷积神经网络的卷积核与通道数,可以得到不同粒度的字符级上下文信息。随后,在每个位置的卷积输出上使用池化层,得到词
w
i
w_i
wi的词级别表示
v
^
i
\hat v_i
v^i。在得到卷积神经网络的输出
v
^
i
\hat v_i
v^i后,为了避免梯度消失或爆炸,模型使用 Highway 网络对
v
^
i
\hat v_i
v^i进一步转换:
v
i
=
g
.
v
^
i
+
(
1
−
g
)
.
R
e
L
U
(
W
v
^
i
+
b
)
v_i=g.\hat v_i + (1-g).ReLU(W \hat v_i + b)
vi=g.v^i+(1−g).ReLU(Wv^i+b)
其中,
g
g
g为门控向量,以卷积神经网络输入
v
^
i
\hat v_i
v^i为输入:
g
=
σ
(
W
g
v
^
i
+
b
g
)
g = \sigma (W^g \hat v_i + b^g)
g=σ(Wgv^i+bg)
在得到每个词上下文无关的词向量后,接下来ELMo的编码层将从两个方向对词向量进一步编码。
编码层
ELMO使用两个独立的编码器分别对前向和后向进行语言模型建模,在进行预训练时,分别取最高层的正向和反向LSTM的输出预测下一时刻的词。对于给定的一段文本
w
1
w
2
.
.
.
w
n
w_1w_2...w_n
w1w2...wn而言,前向语言模型在
t
t
t时刻的目标词为
w
t
+
1
w_{t+1}
wt+1,而后向语言模型的目标词则为
w
t
−
1
w_{t-1}
wt−1。采用前向和后向语言模型的建模过程可以表示为:
P
f
o
r
w
a
r
d
(
w
1
w
2
.
.
w
n
)
=
∏
i
=
1
n
P
(
w
i
∣
w
1
:
i
−
1
;
θ
f
)
P
b
a
c
k
w
a
r
d
(
w
1
w
2
.
.
w
n
)
=
∏
i
=
1
n
P
(
w
i
∣
w
1
:
i
+
1
;
θ
f
)
P_{forward}(w_1w_2..w_n) = \prod_{i=1}^{n} P(w_i|w_{1:i-1};\theta _f) \newline P_{backward}(w_1w_2..w_n) = \prod_{i=1}^{n} P(w_i|w_{1:i+1};\theta _f)
Pforward(w1w2..wn)=i=1∏nP(wi∣w1:i−1;θf)Pbackward(w1w2..wn)=i=1∏nP(wi∣w1:i+1;θf)
特别需要注意的是双向模型共享输出层的参数。
ELMO算法的编码层采用多层双向LSTM结构,通常认为,模型低层能捕捉语法等基础特征,高层能捕捉语义语境等更深层次的语言特征,双向的LSTM能保证在编码过程中每个位置都能获得该位置过去和未来位置的词信息。对于词
w
i
w_i
wi来说,一个L层的ELMo模型会产生2L+1个向量表示。
自编码模型
在自编码系列的模型当中,比较经典的是BERT模型,该模型是谷歌于2018年提出的一个预训练语言模型。利用了掩码机制构造基于上下文预测中间词的预训练任务,相较于传统的语言模型建模方法,BERT能更进一步挖掘上下文所带来的丰富语义。模型的可以分为输入层、编码层和输出层。在预训练时,模型的最后有两个输出层MLM和NSP,分别对应了两个不同的预训练任务:掩码语言模型(Masked Language Modeling, MLM)和下一句话预测(Next Sentence Prediction, NSP),BERT模型具体的网络结构如下图所示:
BERT系列算法由于采用的是Transformer架构的编码器部分,因此这一系列模型通常叫做自编码模型,通常适用于自然语言理解(NLU)任务,如文本分类,命名实体识别等,该系列常见的模型有BERT、AlBERT、DeBERTa、RoBERTa等。接下来将以BERT模型为例,简单的介绍一下对应模型的基本结构。
输入层
BERT的输入层也就是所谓的词嵌入层,该部分有三个不同的嵌入模块组成,分别是:词嵌入模块(Token Embedding),段嵌入模块(Segment Embedding)和位置嵌入模块(Position Embedding)。每个词的输入表示
v
v
v可以表示为
v
=
v
t
+
v
s
+
v
p
v = v^t + v^s + v^p
v=vt+vs+vp
其中,
v
t
v^t
vt代表词嵌入,
v
s
v^s
vs代表段嵌入,
v
p
v^p
vp代表位置嵌入;三种嵌入维度均为
e
e
e。
词嵌入用来将词转换为向量表示。完成分词后,切分完的子词通过词嵌入矩阵转化为词嵌入表示。
段嵌入用来区分不同词所属的段落(Segment),同一个段落中所有词的段嵌入相同。每个段落有其特有的段编码(Segment Encoding),段编码从0开始计数。
位置嵌入用来表示不同词的绝对位置编码。将输入序列中你每次从左到右编码后,每个词都获得位置独热编码
e
p
e^p
ep,通过可训练的位置嵌入矩阵
W
p
W^p
Wp即可得到位置向量
v
p
v^p
vp。Transformer当中采用的位置编码方式为三角函数式位置编码,关于常见的位置编码可以参照博客Transformer中的位置编码。
BERT模型输入层的表示可以如下图所示:
预训练阶段
BERT模型是在Transformer架构上进行调整以后所得到的,在训练的过程中完全舍弃了Transformer架构的Decoder部分,只采用了Encoder部分。为了能够实现同时在两个方向上对相应的数据进行处理,采用了双向的Encoder模块。
为了能够更好的相应的任务进行处理,BERT模型在训练的过程中使用了两个无监督的任务对BERT模型进行预训练,分别是带掩码的语言模型(Masked Language Model, MLM) 和 **下一句话预测(Next Sentence Prediction, NSP)**任务。
MLM
虽然说双向的语言模型比单向的模型功能更强大,但是标准的条件语言模型只能单向进行训练,因为双向条件可以让每个单词间接地“看到自己”,并且模型可以在多层语境中预测目标单词。为了训练一个深层的双向表示模型,BERT模型在训练的过程中随机屏蔽掉了一些输入的tokens,然后预测这些倍遮蔽掉的tokens。在对应的实验中,随机屏蔽掉了每个序列中15%的tokens。与去噪自编码不同,这一块只预测被遮掩掉的单词,而不是重建整个输入。
虽然说这一块可以获得一个双向的预训练模型,但是在微调阶段却不会出现被遮蔽的相关内容。为了缓解这种情况,并不总是使用[MASK]来进行替换,而是随机选择15%的token进行预测,这15%中的80%使用[MASK]进行替换,10%使用一个随机tokens进行替换,剩下的10%保持不变。
NSP
许多下游任务,如问答(QA)和自然语言推理(NLI)都是基于对两个句子之间的关系的理解,而语言建模并不能直接捕捉到这种关系。为了训练能够理解句子关系的模型,对下一句预测任务也进行了预训练,该任务可以从任意单语言的语料库中轻松的生成。具体来说,在选择对应额句子时,50%的句子是实际跟在对应句子后的下一个句子(标记为isNext),剩下的50%使用语料库中的一个随机句子替换(标记为NotNext)。NSP与表征学习目标密切相关。而在之前的工作中,只有句子嵌入被转移到下游任务中,其中BERT转移所有参数来初始化结束任务模型参数。
预微调阶段
经过了Transformer的处理以后,紧接着就进入到了预微调模块。在这一部分,为了能够满足更多用户的需求,用户可以根据自己的需求来对BERT模型的最后一层进行相应的调整。
自回归模型
自回归系列模型当中比较经典的是GPT算法,该算法是OpenAI于2018年提出的一个典型的生成式预训练模型。具体的网络结构如下图所示,是由多层Transformer组成的单向语言模型,但是这一块是一个经过调整以后得Transformer模块,其中舍弃了Encoder部分,同时去掉了Decoder模块当中第二个子层,即多头注意力子层。
GPT系列算法由于是一个单向的语言模型,通常在处理相关数据的时候,都是将生成的新单词放到原来生成的单词后面,添加后的新序列又会成为模型下一步的新输入,这个过程也叫作自回归机制。生成式模型通常使用的都是自回归机制,目前常见的生成式模型就是GPT系列算法,主要包括GPT-1,GPT-2,GPT-3等。接下来将以GPT-1为例,简要的介绍一下模型的训练过程。
GPT训练过程
GPT的训练过程可以分为两个不同的阶段,一是无监督的预训练,二是有监督的下游任务微调。
无监督的预训练
GPT在训练的过程中采用的是生成式的预训练方法,只能从左到右或者从右到左对文本序列进行建模,采用的Transformer结构和解码策略保证了输入文本中每个位置只能依赖过去时刻的信息。
在给定的文本序列
w
=
w
1
w
2
.
.
.
w
n
w=w_1w_2...w_n
w=w1w2...wn中,GPT首先在输入层中将其映射为稠密的向量:
v
i
=
v
i
t
+
v
i
p
v_i = v_i^t + v_i^p
vi=vit+vip
其中,
v
i
t
v_i^t
vit是词
w
i
w_i
wi的词向量,
v
i
p
v_i^p
vip是词
w
i
w_i
wi的位置向量,
v
i
v_i
vi是第
i
i
i个位置的单词经过模型输入层(第0层)后的输出。GPT需要添加位置向量的原因是因为在Transformer结构中模型自身是无法感知位置导致的,这就需要来自输入层的额外位置信息。
在经过输入层编码以后可以得到对应的向量序列,将其送入到编码层以后,在自注意力机制的作用下,每一层的每个表示向量都会包含之前位置表示向量的信息,使得每个表示向量都具备丰富的上下文信息,再经过多层编码以后,就可以得到每个单词层次化的组合式表示。
有监督的下游任务微调
经过无监督语言模型的预训练以后,GPT模型就已经具备了一定的通用语义表示能力。接下来就可以在此基础上,根据下游任务的特性对其进行适配。下游任务通常需要利用有标注数据集进行训练及微调。在微调过程中,通常会针对任务目标进行优化,很容易使得模型遗忘预训练阶段所学习到的通用语义知识表示,从而损失模型的通用性和泛化能力,造成灾难性遗忘。因此,通常需要混合预训练任务损失和下游微调损失的方法来缓解上述问题。
序列到序列算法
上面介绍了常见的自编码和自回归系列算法,自编码系列模型由于只采用了Transformer架构的Encoder部分,因此更加适合于自然语言理解任务;而自回归仅采用了Decoder部分,这一系列算法更加擅长的是自然语言生成任务。在实际应用过程中,针对不同的任务需要选择不同的模型,因此可以考虑将二者结合起来,形成一个序列到序列的基本框架,这个框架当中比较经典的就是T5模型,该模型将所有基于文本的语言问题构建了一个任务同意的框架:将所有的NLP任务都看做是文本转换任务。该模型的架构图如下所示:
模型结构
通常的预训练模型基本采用的都是Transformer架构中的编码器或者解码器,因此相关模型只能在自然语言理解或者自然语言生成任务的一个方面表现得非常优秀,而另外一方面表现出来的效果却并不理想,因此T5模型使用了一个完整的编码器-解码器的结构,发现无论实在生成还是分类任务上都取得了非常不错的效果。T5模型的结构与
B
E
R
T
B
A
S
E
BERT_{BASE}
BERTBASE相似,无论编码器和解码器都是由12个块堆叠而成。但是采用的结构并不是跟Transformer一致,而是做了如下的修改:
①采用了简化版本的Layer Normalization,去掉了Layer Norm的bias,将Layer Norm放在残差连接外面;
②采用了一种简化版的相对位置编码,即每个位置编码都是一个张量,被加到logits上用于计算注意力权重,各层共享位置编码,但是在同一层内,不同的注意力头的位置编码都是独立学习的
③一定数量的位置Embedding,每一个对应一个可能的key-query位置差。学习了32个Embedding,至多适用于长度为128的位置差,超过位置差的位置编码都是用相同的Embedding。
训练过程
自监督预训练:采用了类似于BERT模型的MLM预训练任务
多任务预训练:除了使用大规模数据进行无监督预训练以外,T5模型还可以利用不同任务的标注数据进行有监督的多任务预训练。