最近在跟一个项目,老板让用LLaMA-2-7B做中文客服问答,说必须微调。我按网上教程,用中文alpaca数据集的子集,跑了LoRA(r=8,alpha=16),只冻结原模型、训adapter,大概2万条样本,1张A100,batch size调小到4,训了3个epoch。结果测试时,回复经常答非所问,有时候还带英文混排。反而我用gpt-3.5-turbo配一个简单的few-shot prompt,效果明显更好。难道微调还不如直接调prompt?还是我的数据预处理有问题?比如要不要先做中文分词?或者直接用英文基座模型本身就不适合中文场景?有没有大佬踩过类似的坑,求分享下经验,真的很困惑。
用LoRA微调LLaMA做中文客服,效果还不如prompt工程,求指点
全部回复
共 72 条大概率是数据质量背锅,alpaca子集本身口语化程度就不够,中文客服场景得自己清洗语料。另外LoRA秩和alpha调大点试试,8确实太保守了。
说实话你这个结果挺正常的,LoRA在小数据量下学到的中文语义表征本来就有限,2万条样本对7B模型来说真不够看,而且alpaca那个数据集质量参差不齐,直接拿来用很容易把模型带偏。我个人觉得你老板要的微调可能只是想要个“我们做了”的交代,但实际效果上,纯中文场景下用基座模型加规则兜底都比硬调强。建议你先试试把英文基座换成Chinese-LLaMA或Baichuan这类中文预训练模型,再对比一下,可能差距就没那么大了。另外你检查过tokenizer对中文的分词效果吗?如果词表里中文覆盖不好,LoRA再调也白搭。
这情况太正常了,小模型微调数据不够真不如直接调大模型prompt,别死磕微调。
中文分词倒不是关键,2万条数据对LoRA来说有点少,试试加大rank和epoch看看。
这问题太典型了,2万条LoRA数据量本来就不够,不如直接上qwen或baichuan基座。
微调前先拿中文基座试试,分词那些都是次要的,数据和基座匹配才是关键。
说实话你这个结果我一点都不意外,LLaMA-2-7B本身中文语料占比就低,你拿alpaca中文子集去LoRA,2万条样本其实有点少了,而且r=8的容量可能根本学不动中文的句法和表达习惯。我做过类似的实验,中文任务上微调基座模型前一定要先看看它在中文上的perplexity,如果基础就很差,那adapter只是在硬掰,效果自然不如GPT-3.5这种原生多语模型配few-shot。你提到的英文混排,大概率是分词没处理好,LLaMA的tokenizer对中文是按字节拆的,训练时你最好把中文文本统一加个空格预处理,或者用sentencepiece重新训练个中文分词器,但那样成本就高了。另外我建议你对比一下只用LoRA训最后几层和训全部参数的效果,有时候冻结太多层会让adapter学不到深层语义。还有个思路,可以试试先用中文继续预训练几百步,把词表扩展一下再加LoRA,虽然慢但效果会稳很多。至于老板说必须微调,你可以拿你这组对比数据去说服他,prompt工程在数据量小的时候确实是性价比更高的方案,微调不是万能的。
说实话你这结果真不意外,7B的中文能力本来就一般,LoRA调出来的知识还是从基座里来的,不如直接靠GPT-3.5的上下文理解硬撑。我之前试过用中文指令集微调,效果飘得厉害,后来发现清洗数据比调参重要多了,比如去掉那些带英文标点的样本,分词倒真没太在意。你不如先拿同样的数据跑个量化版的Qwen或者ChatGLM对比下,大概率不是你的问题,是基座选错了。
同感,我拿中文数据集微调llama也踩过这坑,后来发现chinese-llama的增量词表很关键,直接拿原版跑中文等于让模型硬猜字。另外你这r=8可能太小了,我试过r=32效果明显好一些,但数据量2万条对7B来说确实有点少。其实客服场景如果prompt能解决,真没必要硬上微调,老板那边可以拿对比结果说服他,省下来的A100时间干点别的更香。
2万条对7B中文场景真不够,而且alpaca那数据质量太糙,建议先上全量SFT或者换中文基座。
中文alpaca那批数据质量本来就不行,清洗下可能比换模型更有效。
建议先拿你那个prompt结果当baseline,微调后打不过说明数据分布跟真实客服场景偏离太大了。
说实话你这情况太正常了,基座模型本身中文能力就弱,LoRA那点参数量根本掰不过来。建议先试试用中文版或者双语指令微调过的基座,比如Chinese-LLaMA或者Qwen,再在垂直领域数据上做适配。另外2万条样本对客服场景来说可能不够,而且alpaca那种通用指令数据跟你实际业务分布差太远,不如直接收集真实对话去重清洗。你那个batch size和epoch倒还好,但r=8可能欠拟合,试试r=32或者加两层adaptor。
说实话你这个现象挺常见的,LoRA在小数据量下真的不一定打得过精心设计的prompt。我怀疑问题出在数据上,alpaca子集本身是英文指令翻译过来的,中文表达和客服场景差挺远,2万条样本还可能不够适配特定话术。分词倒不是关键,更建议你试试直接用中文基座比如Baichuan或Qwen做LoRA,或者先拿你那套prompt的输出当训练数据,效果可能立竿见影。另外英文混排大概率是tokenizer对中文支持差导致的,换模型比调参划算多了。
说实话这结果不意外,LoRA那套在中文上经常翻车,尤其LLaMA的词表里中文token切得稀碎,你r=8容量又小,2万条样本真不够它学出什么泛化能力。建议先看看是不是数据里混了太多英文模板,预处理别急着分词,先跑个tokenizer对比下中文字符的切分质量。另外你拿微调跟GPT-3.5比本来就不公平,人家预训练数据里中文语料占比高太多,真要追效果不如换个中文基座试试,比如Yi或Qwen,哪怕只做prompt工程都更靠谱。
效果比不过prompt太正常了,LoRA在7B上本来就是个低秩近似,你数据量又不大,学到的可能只是表面格式而不是语义。我怀疑你alpaca子集里中文质量本身就不行,很多是机翻的,模型反而被带偏了。建议先拿几十条人工标注的高质量问答做few-shot对比一下,如果还是不行就检查下是否该用全参数微调或者换更大rank。至于中文分词,完全没必要,BPE对中文效果还行,问题更多出在基座本身对中文的编码上。
我遇到过类似情况,后面发现是学习率和batch size的锅,你3个epoch在2万条上可能过拟合了,试试把学习率降到1