大语言模型中的Finetune vs. prompt
Posted 佛系调参
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了大语言模型中的Finetune vs. prompt相关的知识,希望对你有一定的参考价值。
一、对于LLM的两种期待
1. 成为专才,能够解决某一个特定任务。例如翻译,生成摘要
成为专才的好处: 专才在某一个任务上有机会赢过通才,例如目前chatGPT的文本翻译性能不如专门的谷歌或者腾讯的专门翻译模型
2. 成为通才
成为通才的好处:
只需要重新设计prompt就可以快速开发新功能,不用重新写程序
二、实现方法
1.成为专才的做法
1.在模型基础上增加新的输出层(head)
2.然后采用参数微调Finetune方式进行训练, 需要标注好的数据
- 一种方式是也需要对大模型的参数进行梯度更新
- 另一种方式,采用新增的Adapter,可以插在网络的各种位置,只需要对Adapter参数进行微调,大模型本身其他部分的参数是固定不动的。
各种Adapter 在https:/adapterhub.ml/中可以查看。下图中为对Transformer中可以添加的几种Adapter示例
2. 成为通才的做法
-
In-context learning(也就是Prompting)
就是在推理时给模型一些示例作为输入,让大模型知道要完成的任务是什么样的
简单来说,就是模型在不更新自身参数的情况下,通过在模型输入中带入新任务的描述与少量的样本,就能让模型”学习”到新任务的特征,并且对新任务中的样本产生不错的预测效果。
注意:并不是在训练时候给出这样的示例,因为并没有根据这些示例对大模型参数进行更新(另一个角度理解没有对大模型参数进行更新:大模型预训练好之后参数不动了,但是要完成的任务很多,且任务是各式各样)
有一篇论文对in-context learning进行了研究
- 对输入示例语句其中的label(正面或者负面)进行了随机,表明输入时即使给的示例的label是错误的,模型的预测性能也没有降低太多。表明Label其实不重要?(但是另外一篇论文研究表明,示例label错误的比例越高,模型性能越低,并且模型参数量越大的话性能降低的越多,这样前面工作的结论可能是因为采用的模型比较小)
- 将输入示例语句其中第一个分隔符之前的语句替换为不同场景/任务的句子,模型性能降低很多,表明示例任务的相关性很重要
- 给出的示例的数量也不是越多越好,越多的话性能反而可能会降低。一般4个或者8个就够了。
- 推论:大模型本来就有做某种任务的能力(比如情感分析),只是需要被指出需要做的任务的种类(比如情感分析),而输入的示例语句就是起到这样的作用(唤起大模型的能力)。
Learning In-context learning
其实也可以做 Learning In-context learning,就是在训练过程中采用In-context learning,做到真正的learning(模型参数进行了更新)
-
Instruction-tuning(指令微调)
做法:给出问题的描述
它的核心思想是尽可能收集不同类型的自然语言处理任务(包括理解和生成),并使用自然语言设计对应的任务指令,让模型试图理解不同任务的指令与特性,最终通过语言模型生成的方式完成不同任务的训练
注意:在训练和推理过程中都会用到指令微调,因此需要构建指令微调的训练集
-
chain of Thought(CoT)Prompting
思维链prompting
做法:在给模型示例的时候,顺便给出推论的中间过程
zero-shot-CoT
动机:很多时候没有解题的过程,因为解题的过程是人写的
做法:机器在回答之前加上一句 let's think step by step.,这样机器的推理能力就会提升了
NLP中的绿色Finetune方法大汇总
如果觉得我的算法分享对你有帮助,欢迎关注我的微信公众号“圆圆的算法笔记”,更多算法笔记、算法交流,以及世间万物的学习记录~
NLP中,预训练大模型Finetune是一种非常常见的解决问题的范式。利用在海量文本上预训练得到的Bert、GPT等模型,在下游不同任务上分别进行finetune,得到下游任务的模型。然而,这种方式的代价也很大,经常要对所有任务都保存一个完整的task-specific模型,随着预训练模型体积越来越大,这种方式会占用很多存储空间,当下游任务很多的时候要存储大量的预训练模型。同时,为每个任务finetune一个如此庞大的模型,训练资源的消耗也比较大。
为了实现更绿色、经济的NLP预训练模型迁移,近两年来业内提出了很多优化finetune的方法,例如adapter finetune、mask finetune等。最近很火的prompt更是极大减轻了finetune开销,甚至不进行finetune就能应用于下游任务。本文重点介绍近两年几个NLP中finetune优化的经典工作,包括adapter-finetune、side-tuning、mask-finetune以及prefix-finetune等工作。
1. Adapter-tuning
迁移NLP预训练模型的方法主要分为finetune和feature-based。Finetune将原来的模型在下游任务上进行训练,而feature-based方法使用预训练模型产出的词、句子等embedding作为输入,接下游一个独立的模型进行预测。其中finetune的效果往往由于feature-based方法。然而finetune的计算开销要比feature-based大很多,能不能采用一种折中的方式呢?Parameter-Efficient Transfer Learning for NLP(ICML 2019)提出了一种更经济的迁移学习方法adapter-tuning,只需要finetune少量参数就能达到和finetune整个模型不相上下的效果。具体做法为,在原来的Bert模型的每层中间加入两个adapter,adapter首先通过全连接对原输入进行降维进一步缩小参数量,经过内部的NN后再将维度还原,形成一种bottleneck的结构。在finetune过程中,原预训练Bert模型的参数freeze住不更新,只更新adapter的参数,大大减少了finetune阶段需要更新和保存的参数量。
AdapterFusion: Non-Destructive Task Composition for Transfer Learning(2021)在Adapter Finetune的基础上,提出当下游存在多个任务的时候,使用两阶段的Finetune。第一阶段和Adapter Finetune的思路一样,在预训练大模型基础上加上每个任务的adapter进行finetune,大模型参数freeze。在第二阶段,继续freeze预训练模型,同时freeze住第一阶段训练的adapter模型参数,学习一个AdapterFusion模型,这个模块的作用是融合各个adapter的信息,实现下游多个任务之间的信息共享。AdapterFusion部分的思路是,利用当前样本在FF层的输出和各个任务的adapter输出做Attention,实现从多个Adapter产出信息中的选择和融合。这样模型实现了根据每个样本选择合适的adapter输出,综合了多任务的adapter信息。
2. Side-Tuning
Side-tuning: A baseline for network adaptation via additive side networks(ECCV 2019)提出了一种side-tuning的方法。如下图,side-tune是在原来的预训练模型基础上,增加一个小的side network,然后将预训练模型的输入和side-network的输出进行融合。融合的方法文中提出使用一个可学习的参数α进行加权融合就能取得比较的效果。在训练过程中,预训练模型不会进行更新,只更新side-network部分的参数。Side模型的尺寸和复杂度也可以根据任务的难易程度进行调整。Side-tuning和adapt-tuning有相似之处,都是利用一个附属的小模型对原预训练大模型的表示进行更精细化的针对下游任务的调整。
3. Mask-tuning
Masking as an efficient alternative to finetuning for pretrained language models(2020)提出一种简单的mask方法实现高效finetune。相比一般的finetune,该方法在finetune阶段不对参数进行调整,而是学习一个mask矩阵。对于每一个Transformer层,都会学习一个0-1的矩阵,然后用这个矩阵对该层所有全连接权重进行缩放。公式如下,m表示矩阵中某一个元素,根据一个阈值设置为1或0,再用这个矩阵和每层的全连接参数相乘进行对应元素的缩放。
Mask-tuning的出发点为,在预训练模型finetune的过程中,其实不需要finetune那么多参数,只要finetune一些关键参数就能达到较好的效果,减少finetune阶段计算的冗余性。在How fine can fine-tuning be? Learning efficient language models(2020)一文中也提出了类似的思路。
Mask-tuning的出发点为,在预训练模型finetune的过程中,其实不需要finetune那么多参数,只要finetune一些关键参数就能达到较好的效果,减少finetune阶段计算的冗余性。在How fine can fine-tuning be? Learning efficient language models(2020)一文中也提出了类似的思路。
4. Prefix-tuning
REFORMER: THE EFFICIENT TRANSFORMER(ICLR 2020)提出了采用局部敏感哈希的方法提升Transformer效率。当序列较长时,QK^T的维度[batch_size, L, L]的计算量和存储开销会非常大,但是由于我们关注的是softmax后的结果,并不关注QK^T本身是什么,而softmax只关注值最大的几个元素,因此我们可以只选择k<<L个有最大概率和query最相似的key来计算QK^T即可近似实现目标。那么如果找到有最大概率和query相似的k个key呢?Reformer采用了局部敏感哈希的方法。局部敏感哈希指的是,将每个元素进行hash编码,hash前离得近的元素hash后大概率在一个桶里,那么这种hash就是局部敏感哈希。下图左侧是一个一般的hash,会把元素随机hash,而右侧的局部敏感哈希,哈希前相邻的元素大概率会分到同一个桶里。
Prefix-Tuning: Optimizing Continuous Prompts for Generation(2021)提出的方法只finetune 0.1%的参数就取得和finetune相当的效果,并且在少样本任务上效果优于finetune。本文提出针对自然语言生成任务(如摘要生成、table-to-text等任务)的迁移预训练大模型的方法。基于Language models are few-shot learners(2020,GPT3)等文章中提出的Prompt思路,只要能给模型一个合适的上下文信息context,预训练的语言模型不需要修改参数就能很好的解决下游问题。例如当我们想生成Obama这个词,只要上下文信息给Barack,模型就可有可能生成Obama,因为模型在预训练阶段已经学到了这些信息。
该方法的具体实现为,将预训练的Transformer模型参数整体Freeze住,当正常输入文本序列的时候,在最前端添加几个prefix id,每一个prefix id都对应一个随机初始化的embedding,不同的任务有不同的prefix id。这样在模型中,prefix之后每个时刻的表示都会受到prefix的影响,prefix代表某个对应具体任务的上下文信息。在Finetune过程中,模型的其他参数都Freeze,只finetune prefix的embedding,以及prefix后面接的一些全连接层,Finetune参数量只占整体模型的0.1%,远小于其他的Finetune方法。该方法核心思想利用了prefix embedding去学习对于某个任务来说,需要从预训练语言模型中提取什么样的信息。
5. 总结
NLP领域预训练大模型的发展,催生出很多针对如何提升迁移效率的研究工作。从目前的研究趋势来看,基于prompt思想的finetune是未来的一个重要研究趋势,充分利用预训练模型的信息,让下游任务更贴近预训练模型,而不是让预训练模型贴近下游任务。后续我们也会对prompt进行更为详细的介绍。
如果觉得我的算法分享对你有帮助,欢迎关注我的微信公众号“圆圆的算法笔记”,更多算法笔记、算法交流,以及世间万物的学习记录~ 如果有算法困惑也欢迎来交流~
以上是关于大语言模型中的Finetune vs. prompt的主要内容,如果未能解决你的问题,请参考以下文章
论文泛读124在自然语言生成的 Pretrain-Finetune 范式中桥接子词间隙
NoisyTune: A Little Noise Can Help You Finetune Pretrained Language Models Better论文研读