赞
踩
终于有时间做个最近工作的小结,最近一个多月,做了很多大模型微调的工作,包括了生成式任务以及判别式任务,典型的任务如文创、意图分类等。整理一下微调的经验与感想 (几十块A100的堆出来的,都是钱啊!)。
今天总结后分享给大家,想加入技术交流朋友,文末加入我们。
微调是指在已经预训练好的大型语言模型基础上,使用特定的数据集进行进一步的训练,使模型适应特定任务或领域。微调主要目的是,完成知识注入、指令对齐。目前微调的方式一般分为以下方式
在大模型应用中,指令微调已成为预训练大模型在实际业务应用最重要的方式。许多垂直领域模型,都是在预训练模型的基础上,通过针对性的指令微调,可以更好地适应最终任务和对齐用户偏好。在进行指令微调的时候,会将Instruction(指令) 以及对应的answer拼接成文本(在拼接过程中一般会加入【USER】、【BOT】等角色,同时会加入开始、结束的special token,这样可以转换成一个chat式任务)。如一个翻译任务
instruction:
【USER】:将下列内容翻译成英语:{待翻译文本}
answer:
【BOT】:{翻译结果}
拼接后的文本:
<bos_token>【USER】:将下列内容翻译成英语:{待翻译文本}<special token>【BOT】:{翻译结果} <eos_token>
将拼接文本采用预训练任务的方式进行自回归预测,和预训练的区别在于loss的计算,同样使用Cross-Entropy作为loss,在指令微调的时候只会计算answer部分,Instruction部分通过设置ignore_index隐掉。在上面的案例中,我们只会计算 “【BOT】:” 之后的loss。
针对不同任务,添加特定任务层,如分类任务,在模型最后一层添加softmax层。典型的案例如reward模型的实现。
目前大模型具备超强生成能力,我们可以通过生成式的方式去解决判别式任务,如多目标的文本分类问题,我们可以采用指令微调方式去解决,效果非常好。甚至我们在7B、3B的base模型上,去生成一个复杂json结构(包含多层结构的标签)依然work。
微调样本在精不在多,高质量的样本远比大量中低质量的样本效果好,一般1万左右的样本数量就有较好的效果。Meta 在《LIMA: Less Is More for Alignmen》 这篇论文论述了高质量微调数据的重要性,因此我们应该花更多的时间去提升样本质量,而不是追求样本的数量。那这样就会带来一个新的问题,如何评估微调样本的质量,这个问题可以作为一个单独的话题去讨论。对于微调样本质量评估,一般需要评估样本多样性、answer质量。
微调方法分为全参数微调(Full Fine-tuning)、部分参数微调(Repurposing)典型全微调方法的如:SFT,部分微调的方法包括:LoRA、Adapter、Prefix-tuning、P-tuning、Prompt-tuning 、Freeze-tuning等。
如果在资源充足的情况下,建议使用SFT进行全量微调。部分参数微调的方法不稳定,在有的场景下效果不理想。
受GPT论文的影响,目前大模型通用训练模式是三阶段训练模式,第一阶段pre-train,第二阶段是SFT,第三阶段是RLHF。通过三阶段训练分别得到base模型以及chat模型,chat模型是在base模型基础进行通用任务的SFT以及RLHF,使模型具备了对话能力、推理能力、用户偏好对齐、以及其他的NLU的能力。
如果我们想在实际业务场景中使用大模型,一般还需要进行领域数据的微调。下面分享在领域数据SFT一些Trick。
在进行领域任务的SFT的时候我们通常会有以下训练模式进行选择,根据领域任务、领域样本情况、业务的需求我们可以选择合适的训练模式。
模式一:基于base模型+领域任务的SFT;
模式二:基于base模型+领域数据 continue pre-train +领域任务SFT;
模式三:基于base模型+领域数据 continue pre-train +通用任务SFT+领域任务SFT;
模式四:基于base模型+领域数据 continue pre-train +通用任务与领域任务混合SFT;
模式五:基于base模型+领域数据 continue pre-train(混入SFT数据) +通用任务与领域任务混合SFT;
模式六:基于chat模型+领域任务SFT;
模式六:基于chat模型+领域数据 continue pre-train +领域任务SFT
......
大模型的知识来自于pre-train阶段,如果你的领域任务数据集与pre-train的数据集差异较大,比如你的领域任务数据来自公司内部,pre-train训练样本基本不可能覆盖到,那一定要进行continue pre-train。
如果你的领域任务数据量较大(token在1B以上),并只追求领域任务的效果,不考虑通用能力,建议进行continue pre-train。
如果你有一个好的base模型,在base模型基础进行领域数据的SFT与在chat模型上进行SFT,效果上差异不大。
基于chat模型进行领域SFT,会很容导致灾难性遗忘,在进行领域任务SFT之后,模型通用能力会降低,如只追求领域任务的效果,则不用考虑。
如果你的领域任务与通用任务有很大的相关性,那这种二阶段SFT会提升你的领域任务的效果。如果你既追求领域任务的效果,并且希望通用能力不下降,建议选择base模型作为基座模型。在base模型上进行多任务混合训练,混合训练的时候需要关注各任务间的数据配比。
在资源运行的情况下,如只考虑领域任务效果,我会选择模式二;
在资源运行的情况下,如考虑模型综合能力,我会选择模式五;
在资源不允许的情况下,我会考虑模式六;
学习率是一个非常重要的参数 ,如果学习率设置不当,很容易让你的SFT模型烂掉。SFT数据集不是特别大的情况下,建议设置较小学习率,一般设置为pre-train阶段学习率的0.1左右,如在pre-train阶段的学习率为9e-5,则SFT学习率设置为9e-6。在10万SFT样本上,采用与pre-train一样的学习率,发现loss一直不收敛,在调低学习率至原来0.1之后,loss在两个epoch之后就收敛。
通常pre-train训练的warmup_ratio 0.01~0.015之间,warmup-steps在2000左右。在SFT的时候,建议使用更小的ratio,因为相较于pre-train,SFT样本非常小,较小warmup_ratio可以使模型收敛更平滑。但如果你的学习率设置较大,那可以增大你的warmup_ratio,两者呈正相关。
Epoch设置可以根据loss收敛情况设置,如果SFT样本较少,可以设置较大epoch,在较小的epoch上loss会不收敛,指令都很难遵循。较大epoch会容易导致过拟合,但过拟合要优于欠拟合。如果SFT样本数量较多,如在十万以上,一般2个epoch即可收敛。
如果SFT任务类型较多,可以尝试添加system_prompt,不同的任务使用不同的system_prompt;
一个好的基座模型非常重要!
在SFT的时候,loss依然是你最重要的指标!一般在SFT过程中,loss会先升后降;
可以尝试多种模式训练方案,如在continue pre-train 中添加SFT数据,在SFT数据添加高质量的pre-train数据;
模型的参数量非常重要;
通义千问1.5-72B-Chat
Yi-34B-Chat
mistralai/Mixtral-8x7B-Instruct-v0.1 (https://huggingface.co/mistralai/Mixtral-8x7B-Instruct-v0.1)
目前发现通义千问1.5-72B-Chat效果非常好,通过continue-pre-train之后的Mixtral-8x7B 效果也非常好。
全参数SFT+LoRA微调模式:尝试了将全参数SFT与LoRA进行结合,具体微调的方式:前10%-30% step 采用全参数SFT的方式,后面的step采用LoRA的方式,比单纯的LoRA要更加稳定,比全部采用全量参数SFT更加节省资源。该方式动机,通常来讲,大模型微调的时候,前面step中,模型参数变化最快,loss也是下降的最快,后面step模型参数变化幅度越来越小,loss变化幅度变小,逐渐收敛。因此,可以在微调的最开始step采用全参数SFT,让模型能够尽快的学习到指令,后面采用LoRA的方式,让模型能够更好的遵循指令。全参数SFT与LoRA 训练step配比,可以依据自己的tokens来定。
尝试LoRA的升级版本:DoRA,DoRA: Weight-Decomposed Low-Rank Adaptation(http://arxiv.org/abs/2402.09353),目前还没有看出DoRA较LoRA的特别大的优势,后面还需做更多的实验进行观察。
MoE微调还是非常棘手的,后面出个专门的文章讨论吧。
前沿技术资讯、算法交流、求职内推、算法竞赛、面试交流(校招、社招、实习)等、与 10000+来自港科大、北大、清华、中科院、CMU、腾讯、百度等名校名企开发者互动交流~
我们建了算法岗面试与技术交流群, 想要进交流群、需要源码&资料、提升技术的同学,可以直接加微信号:mlc2060。加的时候备注一下:研究方向 +学校/公司+CSDN,即可。然后就可以拉你进群了。
方式①、微信搜索公众号:机器学习社区,后台回复:技术交流
方式②、添加微信号:mlc2060,备注:技术交流+CSDN
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。