收藏 | NLP核心GPT调教指南:让你的语言模型性能时时SOTA
点上方人工智能算法与Python大数据获取更多干货
在右上方 ··· 设为星标 ★,第一时间获取资源
仅做学术分享,如有侵权,联系删除
转载于 :新智元
有些语言模型虽然在一些快速实验中表现SOTA,对于任何真实应用部署,仍需特定训练,这就需要「微调」。本文提供了一份详细指南,教你如何微调常用语言模型,还会通过在twitter情感检测数据集上微调来比较其性能。
文本生成是一项有趣的NLP任务:输入提示→生成文本。
△ T5文本到文本框架示例(来源:Google AI Blog)
在这一过程中,会用到某种形式的「序列到序列」这一王者模型,如语言模型——应用语言模型根据前面的句子预测接下来的单词。
近年来,这一研究领域非常热门,主要因为:1)有几个高性能的预训练模型可供使用; 2)NLP任务转化为「text-in text-out」问题比较容易。
T5开发者非常直观地呈现了这些,相同的模型可以用于语言翻译、文本回归、摘要等。
本文主要关注GPT-2,GPT-Neo和T5:
GPT-2: 它是OpenAI发布的一系列原始语言模型的第二次迭代。正是这一系列模型让GPT出名的。GPT即「Generative Pre-trained Transformer」,目前有3个版本(v1、 v2和 v3)。目前只有 GPT-1和 GPT-2是开源的,本实验将选择最新的版本。在技术方面,GPT-2的体系结构由Transformer架构的解码部分组成。
GPT-Neo: 该模型由EleutherAI开发,为了对抗GPT-3, 目前尚未开源,其架构与GPT-3相当类似,不过它的训练文本数据集是825 GB.
T5: 即「Text-to-Text Transfer Transformer」,是Google贡献的开源语言模型,展示了使用完整的编解码器架构(transformer)优于仅使用解码器(如GPT),因此T5保持了原有的transformer架构。
需要注意的是,每个模型都根据可调参数大小进一步发布了几个版本。本文选择的是117M 的 GPT-2,125M 的 GPT-Neo 和220M 的 T5。
3个模型对比如下,
情感检测任务和数据集
为了检验不同模型的性能,实验在对简单任务(情感检测)进行微调之后对比其准确性。
本测试用的是Twitter情感分析数据集,其中包含160万条推文,消极言论、积极言论均有。
△Twitter情感分析数据集下载地址:
https://www.kaggle.com/kazanova/sentiment140
为了提高计算效率,实验从中抽取了10000条推文,情感类型分布平均。
然后,用95%的数据训练模型,5%的数据用于测试目的。
为了公平比较,实验使用了相同的测试,并对所有三种模型进行分组训练。
最后,实验将对每个模型进行3次分别测试并对每个模型进行训练,这是一种复制3次验证试验的方法。
实验报告了个人和聚合(平均) f1宏评分,可用于模型的性能比较。
现在有一个问题,如何将情感检测任务转换成文本生成任务?
答案很简单,创建一个直观的提示符(带数据的模板) ,它可以反映出类似的表示如何在网络上发生。
即把一条推文作为输入,想要产生情感输出。
所以对于提示,实验把一条推文放在
后,期待模型预测出情感,生成在下一行
后面。
这种产生有效提示的过程叫「prompt engineering」,显示出了仅改变提示就能使语言模型表现更佳!
实验先从最简单的提示格式开始展示,有两种不同的提示,分别用于训练和测试,展示如下:
训练提示(我们希望模型学习这个「模式」来解决「任务」)
测试提示(现在我们希望模型已经学习了「任务」,因此可以完成「模式」)
因此,在测试过程中,作者只提取模型预测的、在
后的单词,并将该单词作为预测的情感标签。
现在,实验开始!
微调GPT-2和GPT-Neo
由于GPT-2和 GPT-Neo 架构几乎相同,因此大多数微调代码保持不变。因此,为了简洁起见,作者只分享了 GPT-2的代码,但也将指出适用于 GPT-Neo 模型所需的更改。接下来就从处理数据集开始,首先创建一个 Pytorch
,用它定义如何为训练准备数据。
这包括三个模块:
标记和存储的数据的地方
:返回总数据集的长度。这是每个epoch内计算步长所必需的
:获取数据,然后返回
另外,(1) 在第8行,作者定义了用于将原始数字情感标签转换为文本标签的映射,(2)在第12行,作者将数据转换为我们决定的训练提示符,(3)在第14行,作者执行tokenization(将推文分割成token+用它们唯一的 id 替换它们)。
接下来,将数据与Dataset类连接起来。代码分解如下:
第4-8行:从加载数据集开始。数据集可以下载(https://www.kaggle.com/kazanova/sentiment140)并在第4行修改本地路径。接下来,只对相关列设为子集,并且重命名。在第 8 行,作者实验采样了1万条推文。
第10-13行:将数据拆分为训练和测试,分别为95%和5%. 使用「stratify」标志,让拆分在情感类别中均匀分布。
第16行:将数据传递给「Sentiment Dataset」。可以对测试数据做同样的事情,测试时只是以原始形式返回了测试数据。
现在准备训练模型。代码分解如下:
第10-13行:加载分词器,添加一些特殊的标记,用来表示推文的不同部分,最后加载模型。
请注意,第5行已经定义了模型名称:GPT-2. 另外,添加特殊标记是为了让模型学习提示的开始和结束。这有助于稍后的测试阶段,因为我们不希望模型继续写下一个单词,但模型应该知道什么时候停止书写。要实现这一点,可以设置「eos_token」,训练模型在分类标签后进行预测。
第16行:用之前定义的函数加载和准备数据集。
第21-24行:为训练过程设置配置。简而言之,定义了模型的保存位置和时间、训练时间的长度和日志保存的位置,以及使用「batch_size」、「warmup_steps」和「weight_decay」的训练策略。
第27-31行:连接模型与训练数据集,开始训练。在「data_collator」中定义了如何处理训练数据。collator 中的前两个元素是「input_ids」——经过标记的提示和「attention_mask」——一个简单的1/0向量,表示已标记向量的提示和填充部分。
最后一部分非常有趣,将输入数据作为标签传递,而不仅仅是情感标签。这是因为我们正在训练一个语言模型,因此希望模型能够学习提示的模式,而不仅仅是情感类标签。
从某种意义上说,该模型是在学习预测输入推文的单词+提示中结构化的情感,并在此过程中学习情感检测任务。
训练即将开始。计算机不同,耗费的时间也不一样。
最后对测试块进行了定义,获取训练过的模型并将其应用于保留的测试数据。以下是代码分解:
第5行:在模型上开启评估模式。
第8-15行:对于每个测试数据,首先会准备提示,但一个很不同的地方就:不包括情绪标签,因为这是我们希望模型预测的内容。另外,我们希望模型能够预测情感标签「eos_token」,然后通过输出「eos_token」来中断操作。最后,标记测试提示。
第17行:接受测试提示并预测下一组单词。这个函数中有很多参数,定义了如何预测下一个词。
第20-30行:从解码预测文本开始,即,将预测的标记id重新转换为文本。然后我们提取预测的情感标签并将所有相关信息存储到列表中。
第33-37行:首先将所有提取的信息合并到pandas dataframe中,提高可读性,然后使用sklearn包中的「f1_score」函数来计算完整模型的性能。
在运行GPT-2代码,并在数据集拆分代码中执行三次不同的「random_state」操作时,我们观察到该模型实际上能够像预期那样进行完美预测。它能够预测标签,然后使用「eos_token」中断执行。
f1宏评分为81.7%. 这与实验预料中的专用情感检测模型执行的效果进行了比较,这进一步强调了在NLP中,使用文本生成模型进行迁移学习非常容易。
GPT-Neo兼容代码
为了让GPT-2代码适用于GPT-Neo,必须做出以下修改:
导入「GPTneoForCausalLM」 将「model_name」设置为「EleutherAI/gpt-neo-2.7B」(从任何可用大小的模型中选择) 加载模型时使用 「GPTNeoForCausalLM」代替「GPT2LMHeadModel」。
微调T5
研究结果
参考资料:
GPT资源:http://mohitmayank.com/a_lazy_data_science_guide/natural_language_processing/GPTs.html#finetuning-gpt-2-for-sentiment-classification
T5资源:http://mohitmayank.com/a_lazy_data_science_guide/natural_language_processing/T5.html#t5-finetuning
---------♥---------