赞
踩
首先想感慨一波
细品一下,虽然当时这篇论文平平无奇,但是历史见证它的后劲很强大。下面会逐一的记录一下我看了这篇论文后的理解。
首先我们来回顾一下在自然语言任务中,尤其是自然语言理解任务中,大概有以下的几种任务包括:文本蕴含、问题回答、语义相似度评估和文档分类等。
那如何通过AI算法的手段去解决和完成这些NLI任务呢?
在传统的AI算法开发的过程中,一般是利用标注好的数据去训练一个模型,然后再将训练好的模型应用于具体的业务领域,下面就以NLP中的情感分类来举例子:
数据(feature) | 标签(label) |
---|---|
你真的狗阿 | 负面 |
小明的表现还是很不错的 | 负面 |
。。。 | 。。。 |
但是以上的这种传统的做法还是存在着一些局限,如:
总结一下就是,在传统的AI任务中,你需要标注一堆的数据,然后去训练一个模型,训练好后的模型去上线预测的时候,只能完成单一任务,且单一任务中进来的数据也要和原始训练数据呈现独立同分布的规则,这种模型或者训练的范式,我们称之为狭窄专家。
其实这就为现实的发展增加了不少的阻碍,最明显的地方在于有些领域的原始数据语料本身就特别少,那这种有监督式的训练就不能够sota了。所以探索一种能够在少样本下sota的模型,变得有现实意义。
以上已经描述了监督学习在NLI任务上可能存在的阻碍,那到底该如何改善呢?该怎么做呢?作者最先想到的点子就是:
我们写过论文的都知道,既然你在论文中提出来了这个假设,自然肯定是能实现了哈哈,同样的作者提出的这种思想,在很多地方也找到了佐证。最典型的就是词向量的表示。
还记得以前的word2vec是如何工作的吗?先训练好word2vec,然后单词通过模型之后,就会得到词向量,有了词向量就可以做很多的事情,通常情况下,不会直接来使用这个词向量来完成具体的NLI任务,当然了它也完不成,一般情况是将词经过word2vec向量化表示,然后接着利用向量化后的特征来训练其他的模型(如rnn或lstm等)来完成具体的NLI任务。这是不是有点验证了作者提出的猜想呢?
以上的工作模式被证明有一定的效果。
基于以上的种种,作者提出(或者说是普及了)的这种基于transformer的两段式训练范式:预训练+微调。打开了未来的大门。
接着,作者在论文中分析了,基于LSTM这种两段式的训练有一个问题:LSTM很难处理一些长文本信息,这是循环神经网络不可避免的问题,所以作者提出了一种新的模型,就是基于transformer的decoder模型架构。以这种架构来完成模型的预训练和微调。
transformer结构
作者提出的GPT-1的结构其实就是基于transformer的解码器的简单的堆叠,那么我们先来看看transformer是怎么样的。
以上就是transformer的结构,左边是编码器encoder,右边是解码器decoder,解码器块和编码器块的差别其实就在于解码器块多了一个掩码机制(Masked Multi-Head Attention)。这个掩码机制会将要预测的token的未来token进行掩码。避免信息穿越。
举一个例子,比如在将“你发工资了嘛”这句话输入到模型进行模型训练时,在预测“发”时,输入的时“你”,预测“工”时,输入的时“你发”。它是不能看到句子未来的词的,这时和bert是完全不一样的。
具体关于transformer的内容,会在transformer论文中分享,这里只做最简单的介绍。
GPT-1结构
GPT-1的模型结构非常简单,其实就是基于transformer的decoder部分做了一个12层的堆叠,下面我先绘制一个GPT-1的结构图
可以看出这就是基于transformer的decoder部分来设计的,但是还是有了一些简单的修改,具体一些在架构上显著的修改,我用红色的标注出来了。下面我大概描述一下。
关于GPT-1的结构,以及和transformer的差别就是这么多,这也就可以理解为啥当初论文发出来之后响应没那么大,这放到现在的研究生论文中,高低会质疑创新不足吧哈哈。
前面都介绍了模型的具体的结构了,下面就只需要说说结构里面具体的参数设定了
模块 | 参数 |
---|---|
解码器块 | 12层 |
多头注意力 | 12头 |
词embedding | 768维 |
前馈神经网络隐藏层维度 | 3072维 |
有这些参数就可以具体确定这个模型了,如果不懂这些参数对应什么,强烈建议看看transformer的原理,后期我也会补一篇关于transformer论文的分析。
虽然我们已经有了模型,但是我们该如何训练呢?而训练很大程度是由训练目标决定的,比如我们的训练目标是二分类,那么我就知道模型其实就是把特征输入进行,做一个sigmoid做二分类预测,最后计算loss反向BP。所以我们接下来就要知道预训练和微调阶段的各自训练目标是啥。
前面已经说了,作者看了很多论文之后,提出了这种预训练+微调的两段式训练范式。而在预训练阶段是通过在未标注数据上进行大量训练。而这里就有一个疑问了:
这样所有的都解决了阿,所有的未标注的数据都可以用起来啦。我还是举一个例子吧,以:“你是一个打不死的码农”为例
特征(feature) | 标签(label) |
---|---|
你 | 是 |
你是 | 一 |
你是一 | 个 |
你是一个 | 打 |
你是一个打 | 不 |
你是一个打不 | 死 |
。。。 | 。。。 |
将特征输入到模型,来预测标签,当然表格中的特征长度虽然是不一样的,但是实际情况下,是会把输入都padding到同一个长度的,这是搞模型的基操了:保证输入维度不变。同时这也就是下面要提的“最长文本输入”的概念。
而在具体的训练中,有一些具体的细节参数还是需要留意的,下面我把主要的参数进行罗列
数据集这一块主要是用到了两个数据集
现在,有了模型、有了优化目标、有了具体模型参数和训练参数、还有了数据。就可以做模型的预训练了,预训练结束后的模型,就会学到词的通用embedding表示啦。
在原始论文中,给出了一个计算的公式
从上面可以看得出来,最终自注意力块的输出之后还要和原始输入的词的embedding转置进行相乘,这就是我的疑问点所在。
以我对transformer的decoder的理解,以及在看了minGPT的实现之后,得到的结论是:最后的这个We的转置其实本身就不是We,而是会额外的加入一个线性层进行学习。同时以日常的经验,我认为确实也应该这么做,而不是像GPT-1提出的这么做。这里给朋友们留一个讨论空间。
注:minGPT工程是一个大神对GPT的实现。文章末尾有连接跳转。
在预训练阶段,模型学到了如何利用出现的词来预测下一个词。顺带学会了词的embedding表示。按理来说要让他做具体的自然语言理解(NLI)任务是不太可能的,所以也就有了微调这一步,在微调阶段,模型只需要在少量的具体任务的标注数据,就可以达到sota。那对于每一个NLI任务具体该怎么做呢?
自然语言理解任务(NLI)其实是有很多种的,诸如:情感分析、文本蕴含、相似度计算、多项选择、摘要总结等。对于这么多的任务,输入部分是可大致总结为有两种输入的形式:
所以针对这么多的NLI任务,GPT-1统一了输入的范式:
输入的序列(可以是单个或多个)以<s>开头。
输入序列的结尾用<e>作为结束。
以上就是关于输入的范式规定,下面我给出一张官方的图就一目了然了。Start部分就是<s>,Delim部分就是$,而Extract部分就是<e>
在微调部分的训练,其实就是标准的有监督学习,自然要先计算loss,然后根据loss来进行反向BP优化参数。下面我会根据上图来挨个讲解不同NLI任务大概是如何训练的。
单句子分类任务
上图中的分类任务是单句子的二分类任务,诸如情感分类。
句子开头添加<s>,句子结尾添加<e>
多句子分类任务
上图中的分类任务是多句子的二分类任务,诸如文本蕴含,就是预测一个句子是否含在另一个句子中。
句子开头添加<s>,句子结尾添加<e>,句子与句子之间用$分隔
相似度计算任务
这类任务其实也可以看作是一个二分类任务,以概率来表示他们的相似程度。
5. 数据准备:句子开头添加<s>,句子结尾添加<e>,句子与句子之间用$分隔
6. 在原有模型上添加二分类头
7. 数据训练:数据输入到模型中,预测二分类,根据loss,反向BP更新模型参数
注:在数据输入部分,由于是两段文本,所以谁在前都行,既然谁在前都行,官方的做法就是分别让每一句话都在前一次,然后分别输入到模型,最后将两次的结果进行相加,进行二分类的概率预测。
多项选择任务
多项选择原理上是一个多分类任务,所以同样是用概率来表示选谁,区别与之前的任务的地方在于别的是用sigmoid做二分类任务,而这里是用softmax做多分类任务。但是这里的softmax并不是直接在线性层上去叠加的。
句子开头添加<s>,句子结尾添加<e>,句子与句子之间用$分隔,分别将问题和答案做组合,非正确答案的组合的标签就是0,正确答案的组合的标签就是1,这样多个选择就会有多组数据
注:这里最重要的就是在模型的设计上加入多分类头,比如对于4选项的任务来说,并不是直接在输出层添加一个输出维度为4的线性层,然后再softmax,而是添加了一个二分类头,每一个数据都分别进入模型,得到一个二分类的概率结果,然后再在这4个二分类结果上用softmax归一化,用最终的softmax结果计算loss。结合着图去理解这段话就非常清楚了。
有了目标,有了数据,有了模型,就可以微调了。
当然了,官方论文给出了关于一些微调时候训练参数的建议
这个疑问点来自于微调阶段的loss的计算,在原始论文中,给出了一个公式
而是只算开始符号<s>、结尾符号<e>和分隔符$的loss。
个人说明和理解
在微调部分,总的loss是L1和L2的相加。模型会根据总的loss进行反向BP,我想做两点说明:
<s>、$、<e>
这几个特殊符号的loss呢?我个人理解是,在预训练阶段常规的文本模型都见过了,而这几个特殊符号是在微调阶段为了满足不同的下游任务而设计的输入范式,所以可以理解为模型之前没见过,那这里只计算他们的loss也合理。个人的困惑和建议
但是在minGPT工程中,以及现在流行的大模型的实现中,其实都不这么做,都是只使用L2来计算loss,然后反向BP。包括在minGPT工程中,也是只用了L2。也就是现在的做法是:在微调阶段就只计算具体微调任务的loss。不会有什么辅助目标了。
这就是论文和实现的差距。同时以我的建议,我建议也是不要像原文一个添加辅助目标了。
最终作者在很多的NLI任务上做了多次的实验,得出了两个很重要的结论。
关于第1条的结论应该属于顺理成章,而关于第2点,文章作者最开始的本意可能只是想在预训练阶段让模型学到一些词级别或者是短语级别的能力,诸如word2vec能力,而训练完之后,却2发现,这个预训练的模型不仅仅具有简单的词embedding的能力,居然就已经有一些能够解决具体NLI任务的基础能力,只是效果不一定好。这应该是属于意外之喜。
从现在来看,以上的两个结果,指导着当下(2024)年大模型的发展,现在的GPT4,已经完全验证了当初的这两个实验结论了。OpenAI牛逼。
如果你通读了这篇文章,你会发现一些明显的缺陷:
后来的Openai也是基于这些个缺点以及实验结论去做迭代,这也是GPT-2和3在寻找的,同时当下的大模型几乎都是不需要更改模型结构的。
好啦,关于GPT-1的讲解就到这,也强烈建议大家看一下论文:Improving Language Understanding by Generative Pre-Training
还有一个是文中提到的:minGPT,他是由一个国外的大佬开发的关于GPT的系列实现,通俗易懂,推荐阅读。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。