前言
GPT1是OpenAI公司在2018年6月发表的一篇论文,在Transformer论文发表的一年后。GPT1论文的全称为《Improving Language Understanding by Generative Pre-Training》,通过使用生成式的预训练提高语言的理解能力。接下来对GPT1进行详细介绍。
一、GPT1理论
在NLP领域存在着大量的没有标签的数据,而有标签的数据只有一小部分,同时NLP领域有很多的下游任务,针对于每一种下游任务进行单独的重新训练是一件非常麻烦的事情,同时对于不同的任务选取合适的目标函数也是意见困难的事情。GPT1证明了在大量没有标签的数据上进行预训练,然后针对不同的下游任务进行微调可以实现很大的收益。在针对不同任务进行微调的时候,GPT1不需要改变模型的结构,只需要对于输入的形式进行改变就可以,实现了对于不同的下游任务进行通用的表示方法。
GPT1的模型结构由Transformer的解码器堆叠而成,与原始的Transformer解码器相比,GPT1由于没有编码器的存在所以去除掉了解码器中的交叉注意力层。下图为GPT1的组成结构,由12个Transformer解码器组成,向量维度为768,共12个自注意力头,隐藏层的维度为3072,总参数量达到了1.5亿。同时,GPT1中的位置编码是可以学习的,就是可以看作每一个位置都是可以学习的embedding。在预训练时输入的tokens长度为512。
二、GPT1预训练
GPT1进行无监督预训练采用的数据集是BooksCorpus dataset,包含了7000多本未出版的书籍。
由于解码器中采用有掩码机制的存在,对于输入的序列,模型只能看到当前单词前面的信息,而看不到后面的信息。因此在预训练的时候,模型的训练目标相当于是根据当前的输入序列去预测下一个单词可能是什么,类似于预测未来。(BERT相当于是做完形填空)这个过程可以建模为
其中 k k k是窗口的长度, Θ \Theta Θ是模型的参数, P P P为条件概率分布, U U U为输入的序列,之所以使用 log \log log是为了把联合概率分布从乘法变成加法。这是一个标准的语言建模目标。例如:
输入: [ u 1 , u 2 , u 3 ] [u_1,u_2,u_3] [u1,u2,u3]
首先,给模型输入
u
1
u_1
u1,使模型输出
u
2
u_2
u2的概率最大,然后给模型输入
[
u
1
,
u
2
]
[u_1,u_2]
[u1,u2],使模型输出
u
3
u_3
u3的概率最大。虽然看起来是一个自回归的问题,但是由于解码器中存在着因果掩码,所以可以进行并行训练,即给模型一次性输入长为4的序列
[
′
B
O
S
′
,
u
1
,
u
2
,
u
3
]
['BOS',u_1,u_2,u_3]
[′BOS′,u1,u2,u3],然后模型同样输出长度为4的序列
[
u
1
,
u
2
,
u
3
,
′
E
O
S
′
]
[u_1,u_2,u_3,'EOS']
[u1,u2,u3,′EOS′],然后让其与标签(即模型的输入)算Loss,然后进行反向传播更新参数。其实本质上与Transformer的训练过程差不多,只不过是少了解码器的输入。关于Transformer的训练和推理过程可以看一下这篇博客:
Transformer训练、推理过程详解
三、GPT1微调
当模型的预训练完成后在有标签的数据集 C C C上进行微调,假设输入的tokens为 x 1 , x 2 , . . . x n x^1,x^2,...x^n x1,x2,...xn,标签为 y y y,则优化目标可以建模为
同时作者说明在微调的时候加上预训练时的训练目标,则模型的性能提升更好。
所以,最后微调的时候的优化目标为:
通俗的说,在微调的时候,对于输入的
[
x
1
,
x
2
,
.
.
.
x
m
]
[x^1,x^2,...x^m]
[x1,x2,...xm],模型输出为
[
y
1
,
y
2
,
.
.
.
y
m
]
[y^1,y^2,...y^m]
[y1,y2,...ym],然后我们将输出的最后一个元素
y
m
y^m
ym经过一个全连接层然后做softmax操作得到最后预测的标签
y
p
r
e
d
y_{pred}
ypred,我们的优化目标是让模型的输出
[
y
1
,
y
2
,
.
.
.
y
m
]
[y^1,y^2,...y^m]
[y1,y2,...ym]以及softmax后的标签
y
p
r
e
d
y_{pred}
ypred和输入
[
x
1
,
x
2
,
.
.
.
x
m
]
[x^1,x^2,...x^m]
[x1,x2,...xm]以及真实的标签
y
y
y差距最小。
在进行微调时,对于不同的下游任务,则输入的形式也不一样,如下图所示:
1.分类任务:输入为一个文本,前面加上起始符’start’,最后加上提取符’Extract’,然后将输入送进Transformer中,然后将提取符’Extract’对应的输出送进全连接层然后进行分类,因为提取符’Extract’可以看作是结合了前面整个句子的所有信息,所以可以把最后一个特殊符号看作整个句子特征的代表。
2.蕴含: 这个任务具体来说,给一个假设和一段文本,看一下文本中的内容是否蕴含这个假设,这可以看作是一个三分类问题,标签为“蕴含”,“不蕴含”,“不清楚”。输入的开头仍然是起始符’start’,然后是假设,后面加入一个分隔符’Delim’,然后是文本,最后加上提取符‘Extract’,经过Transformer后将提取符对应的输出经过全连接层进行分类。
3.相似性判断: 这个任务主要是判断输入的两个句子是否是相似的,通过将两个句子构造成两个输入,然后分别通过Transformer后得到输出,然后相加,最后将提取符所代表的输出送进全连接层进行分类。
4.多选题: 这个任务会给你一个问题,然后给你几个答案,让模型选出你觉得正确的答案。首先有几个答案就构造几个输入,每一个输入都是问题序列在前,答案序列在后,将这些输入分别通过Transformer层后然后经过全连接层得到每一个答案是正确答案的置信度,然后这这些置信度经过softmax得到最终的正确答案是哪一个。
总结
GPT1作为OpenAI推出的第一代生成式预训练模型,在NLP领域取得了显著的成果,但是其在预训练时所使用的数据集规模不是很大,数据存在局限性,导致其泛化性有限。与BERT不同的是,BERT偏向于理解句子信息,而GPT偏向于预测句子的未来输出,是一种生成式模型,所以在更大的模型参数以及更大的数据集上GPT的上限要更高。