预训练大语言模型的三种微调技术
你猜怎么着?最近好几个朋友跑来问我同一个问题:“大模型这么火,我到底怎么把它调成我想要的?”我一看,网上教程铺天盖地,都在堆知识,可没人告诉我实际用起来到底啥区别。
得了,我干脆自己动手。花了一周时间,在几个任务上各跑了一遍,踩了一堆坑,把血泪史整理出来。
先说个让你心跳加速的结论:这三种方法,效果差距不到2%,但投入的资源,差了10倍不止!
讲个真实的故事
前阵子我参加一个技术沙龙,有个创业公司的技术负责人特别激动地说:“我们花了20万买了张A100,想搞全量微调,结果训练了三天,显存炸了两次,最后准确率还没网上的开源方案高。”
全场都笑了。笑完之后发现——怎么身边所有人都在盲目选方法,却没人真的对比过?
所以我干脆自己干。
三种“微调”,到底是什么
1. 全量微调(Fine-tuning)——所有参数都动,从头训到尾。又笨重,又贵,动不动就炸显存。
2. 参数高效微调(PEFT)——经典代表是LoRA,只改一小部分权重,原模型冻住。
3. 提示微调(Prompt-tuning)——在输入里加可学习的向量,比如Prefix Tuning。有些论文把它归进PEFT,但为了方便理解,这三个我分开测。
我到底测了什么
拿文本分类开刀。数据集SST-2(情感二分类,67k条),基座模型BERT-base(110M参数)。环境Python 3.10,单卡A100 80G。每个配置至少跑两遍,取平均值。
全量微调:最老实的办法
直接加载BERT-base,标准分类头,batch size 32,序列长度128,学习率2e-5,训练3个epoch。
显存占用:4.2GB。时间:15分钟。准确率:92.5%。
听起来还行?但换任务就得重新训练整个模型,而且之前的通用能力多多少少会丢。后来我在其他领域数据上试,确实有灾难性遗忘。调参也麻烦——学习率、哪些层冻、哪些层释放,每一步都像踩地雷。
参数高效微调(LoRA):让我意外
用Peft库的LoRA,只改query和value两个模块,r=8,alpha=16。可训练参数只占原模型权重的约0.02%(你没看错,真的是百分之零点零二)。
学习率提到1e-4,batch size和全量一样。
结果:
- 显存2.8GB,时间8分钟,准确率91.8%,**只掉了不到1个点**。
换个任务只要改一下LoRA权重就行,原模型还能留着。后来我在同一个基础模型上同时跑了三个不同领域的分类任务,每个任务挂自己的LoRA适配器,推理时动态切换,稳得很。
坑也不少:
- 学习率不能照搬全量微调。一开始用2e-5,结果训不动;换成1e-4才正常收敛。
- 秩r和alpha的比例对效果影响很大。官方推荐alpha是r的两倍,我直接用了16/8,正好符合,效果不错。
提示微调(Prompt Tuning):轻到极致
这里用的是Lester等2021年提出的Prompt Tuning——不是设计自然语言提示,而是加入可学习的虚拟token。
我在输入序列前面插入5个连续的向量,每个向量的维度设为768(与BERT词嵌入一致),随机初始化,只训练这些token embedding,其余全部冻结。
显存2.5GB,时间6分钟。准确率90.5%,比LoRA再低1个点。
切换任务时只需要换一组prompt向量,模型本体完全不动。假如有10个任务,只需存10组很小的prompt嵌入,推理时挂上就行。甚至可以在一次forward里同时跑多个不同prompt的版本。
不过效果对prompt长度和初始化很敏感。我试了3个token(89%)、5个(90.5%)、10个(90.8%),再长性能就不再涨。初始化用随机embedding收敛不稳定,换成词汇表中已存在的词向量才稳。
一句话总结三兄弟的底牌
| 维度 | 全量微调 | LoRA | Prompt Tuning |
|------|----------|------|---------------|
| 训练参数量 | 全部(1.1亿) | ~0.02%原始参数 | 额外token嵌入(极小) |
| 显存占用 | 4.2 GB | 2.8 GB | 2.5 GB |
| 训练时间 | 15 min | 8 min | 6 min |
| 准确率 | 92.5% | 91.8% | 90.5% |
| 切换任务成本 | 重训整个模型 | 换LoRA权重 | 换prompt嵌入 |
| 灾难性遗忘风险 | 较高 | 极低 | 极低 |
数据均基于BERT-base在SST-2上测得。不同模型结果会有变化,但趋势一致。
最反直觉的是——你以为全量微调效果最好?其实只比LoRA高了0.7个点,但代价是显存多了1.4GB,时间多了将近一倍。
我该用哪个?
没有银弹,但看菜下饭。
如果预算充足、数据量大、目标单一且追求极致性能,全量微调依然最稳。我见过一些公司给GPT-3做全量微调后在客服场景下效果暴打所有PEFT方案,但你需要准备好显存和调参的血本,尤其大模型下光加载模型就够喝一壶了。
资源有限、任务多、需要频繁切换的,好好考虑LoRA。我在同一个7B模型上挂了四个不同的LoRA适配器,每个任务只需几百MB额外空间,切换零延迟,性能损失完全可接受。后来跑生成任务,用Llama-2-7B 4bit量化后,LoRA微调在摘要任务上BLEU比起全量微调只差0.8个点,显省了将近60%。
多任务或持续学习、对推理速度有极高要求的,Prompt Tuning值得一试。几乎没有额外存储开销,一次forward可并行跑多个prompt。我见过同事在一个基础模型上挂了20多个分类任务,每任务一个prompt,线上只有一个模型副本。缺点是效果上限偏低,复杂生成任务表现不够好。
踩过的几个坑,直接甩给你
全量微调千万别用默认学习率到底。BERT类学习率从2e-5起,GPT/ChatGLM类大多需要降到1e-5以下。我在T5上翻过车,那个教训记一辈子。
LoRA的target_modules别乱选。我试过只加在FFN上,结果比全冻结还差。经验是query和value最稳妥,有些论文推荐Q、V、K都加,但收益不大。
Prompt Tuning的token数别贪多。超过10个基本上不涨,反而增加显存和训练时间。初始化最好用领域相关词汇,随机初始化收敛慢。
三者不能直接换着用——你拿Prompt Tuning的超参数去训LoRA会炸,反之亦然。
最后说点偏爱的
三种我都用,但
读者评论 2