AIGC系列-GPT论文阅读笔记

358 阅读4分钟

前言

随着ChatGPT的横空出现,AIGC迅速成为当下最热门的技术领域,但是构建ChatGPT的底层相关研究——NLP、多模态、大模型已陆续发展多年。作为一位非算法的研发工程师,本着持续学习、保持进步的初心,也计划对相关论文进行系统的梳理、阅读,计划包含以下部分:

  • Transformer;
  • BERT;
  • GPT系列论文;
  • CLIP;
  • Diffusion;

本文是对GPT论文的阅读笔记。

背景

《Improving Language Understanding by Generative Pre-Training》是OpenAI于2018年发表的一篇论文。在这篇论文中,OpenAI首次提出了GPT(Generative Pre-Traning)模型(稍早于Google的BERT),其核心思想是先在大规模未标注数据集上预训练一个通用语言表征大模型,再在特定NLP子任务标注数据集上进行输入和输出的微调,从而将大模型的语言表征能力迁移至特定子任务中。以该文为开端,在GPT的基础上,后续OpenAI不断演进,陆续构建了GPT2、GPT3、InstructGPT等一系列大模型。后续会分篇介绍该系列模型。

模型结构

预训练

图1 预训练模型结构

一个句子是由多个词元(token)组成的序列,令词元序列U={u1,...,un}\mathcal{U}=\{u_1,...,u_n\}。预训练通用语言表征模型的目标函数是最大化以下对数似然函数:

L1(U)=ilogP(uiuik,...,ui1;Θ)L_1(\mathcal{U})=\sum_i{\log P(u_i | u_{i-k},...,u_{i-1};\Theta)}

即对于训练样本序列中的某个词元uiu_i,在给定前kk个词元和模型参数Θ\Theta的前提下,通过模型输出的概率最大,也就是说根据前kk个词元预测当前词元。 论文中提到,该通用语言表征模型结构就是Transformer的解码器部分,如图1所示,这也是GPT和BERT相比较大的一个区别。BERT预训练时,对样本词元序列随机选择词元进行掩码替换,通过掩码两边的词元序列预测被掩码替换的原词元,类似完型填空,因此需要词元序列的完整信息,所以采用Transformer的编码器部分。而GPT预训练时,通过前序词元序列预测当前词元,并不需要后序词元序列的信息,而Transformer解码器中带掩码多头注意力层的掩码机制正好可以解决这一问题。 GPT模型结构中,词元序列在经过词元和位置Embedding层后,输入多层(12层)解码器,每层解码器又包含两个子层:带掩码的多头自注意力层和逐个位置的前馈全连接网络层,每个子层的输出均会经过残差连接和层归一化。关于Transformer的详细介绍可以参见《AIGC系列-Transformer论文阅读笔记》,这里不再详述。图1的网络结构可以用以下公式描述:

h0=UWe+Wph_0=UW_e+W_p
hl=transformer_block(hl1)l[1,n]h_l=\text{transformer\_block}(h_{l-1})\quad \forall l \in [1,n]
P(u)=softmax(hnWeT)P(u)=\text{softmax}(h_nW_e^T)

其中,U=(uik,...,ui1)U=(u_{i-k},...,u_{i-1})表示前kk个词元,WeW_eWpW_p分别表示词元和位置的Embedding矩阵,h0h_0表示前kk个词元经过词元和位置Embedding层后的输出(即解码器层的初始输入)。解码器层共nn层,hlh_l表示第ll层解码器的输出,并作为下一层的输入。最后一层解码器的输出hnh_n会作为输入、经过线性层(权重矩阵为WeTW_e^T)和Softmax层得到每个词元在当前位置的概率,作为模型的输出。

微调

预训练所得的通用语言表征模型进一步会在各NLP子任务中,使用子任务本身带标注的数据集进行监督训练,作微调。这些子任务包括分类、问答、蕴含和相似判断(蕴含和相似判断也可转化为分类)。 令某个子任务的带标注数据集为C\mathcal{C},其中每个样本均是句子词元序列,表示为x1,...,xmx^1,...,x^m,并被标注为yy,则针对该子任务,调整通用语言表征模型的输出层,用以下公式描述:

P(yx1,...,xm)=softmax(hlmWy)P(y|x^1,...,x^m)=\text{softmax}(h_l^mW_y)

其中,hlmh_l^m表示子任务句子词元序列输入通用语言表征模型后最后一层解码器的输出,通过该子任务特定的线性层(权重矩阵为WyW_y)和Softmax层,最后输出标注yy的概率。 进而微调阶段的目标函数是最大化以下对数似然函数:

L2(C)=(x,y)logP(yx1,...,xm)L_2(\mathcal{C})=\sum_{(x,y)} \log P(y|x^1,...,x^m)

论文将L2L_2L1L_1进行加权求和作为最终微调阶段的目标函数,如下所示:

L3(C)=L2(C)+λL1(C)L_3(\mathcal{C})=L_2(\mathcal{C})+\lambda *L_1(\mathcal{C})

论文中提到,加权求和后的目标函数可以提升子任务的泛化性。 从上述过程中可以看出,微调阶段的主要工作中就是针对各子任务的小规模标注数据集构造模型输入,并针对子任务的目标函数,微调各子任务特定的线性层权重矩阵WyW_y。 各种子任务在预训练所得的通用语言表征模型基础上,如何构造模型输入和如何设计输出层,如图2所示。

图2 各类子任务的输入和输出

其中:

  • 对于分类任务,输入上,在原词元序列的基础上,增加两个特殊的词元标记句子的开头和结尾,作为输入,输出上,通过线性层和Softmax层输出各分类的概率;
  • 对于蕴含任务(即从前一句是否能推导出后一句),可将其转化为二分类(蕴含、矛盾)或三分类(蕴含、矛盾、中立)任务,输入上,在原词元序列的基础上,增加三个特殊的词元标记句子对的开头、结尾和两句之间的分隔,输出上,通过线性层和Softmax层输出各分类的概率;
  • 对于相似性判断任务,可将其转化为二分类(相似、不相似)任务,输入上,由于相似的两个句子并没有先后顺序,因此构建两个输入;这两个输入都是在原词元序列的基础上,增加三个特殊的词元标记句子对的开头、结尾和两句之间的分隔,不同之处只是调整两个句子的先后顺序;两个输入分别通过通用语言表征模型得到各自的输出,再按向量元素逐个求和后,通过线性层和Softmax层输出相似、不相似的概率;
  • 对于问答任务,由于存在候选答案,因此也将其转化为多分类任务,输入上,对于每个候选答案,构建问题、答案对作为输入,其中增加三个特殊的词元标记句子对的开头、结尾和两句之间的分隔,对于每个输入通过通用语言表征模型和一个线性层得到其输出,最后通过Softmax层输出各候选答案的概率。

实验

论文中使用的预训练大规模数据集是BooksCorpus,其包含了7000本未出版的书籍,其中包含较多的长文本,便于通用语言模型学习长序列信息。 论文在这里介绍了预训练通用语言表征模型的规模,其解码器层数为12,模型中向量维度为768,多头注意力层数为12,逐个位置的前馈全连接网络中的隐层维度为3072,因此模型参数量在1亿量级(目前看,模型规模算是小的,GPT3模型参数量已达到1750亿)。 另外,论文还对预训练和微调涉及的超参(优化器、学习率、批次、周期、激励函数、正则化方法等)进行了介绍,这里不再详述。 论文对于蕴含类子任务的实验结果如图3所示,在5个任务中的4个上取得了当时最高的准确率(NLP领域准确率衡量指标一般采用BLEU指标,计算预测序列和测试序列的重合度)。

图3 蕴含子任务实验结果

论文对于问答类子任务的实验结果如图4所示,在2个任务上都取得了当时最高的准确率,说明模型对于长文本的理解更有效。

图4 问答子任务实验结果

论文对于相似判断和分类子任务的实验结果如图5所示,在5个任务中的3个上取得了当时最高的准确率。

图5 相似判断和分类子任务实验结果