最近在试着用LoRA微调Llama3-8B做中文医疗问答,数据集是自己整理的8000条QA对,清洗过,utf-8编码。训练时loss从1.8降到0.9,看起来挺正常,但推理时经常输出重复的“嗯嗯嗯”或者夹杂英文和乱码,偶尔能出几句通顺的中文但答非所问。学习率用的2e-4,rank=8,alpha=16,max_length=1024,跑了3个epoch。想请教一下这种情况一般是数据量不够、格式问题(比如没加合适的system prompt),还是LoRA超参数设置不合理?另外看有人说要冻结embedding层,这个影响大吗?有点迷茫,希望有经验的朋友指点一下方向,谢谢。
用LoRA微调Llama3中文对话,loss降了但生成乱码,是数据问题还是参数没调好?
全部回复
共 28 条这情况八成是数据量太小加格式不对,试试加个统一system prompt再调低学习率到5e-5。
冻结embedding层影响不大,你先把重复问题解决了再说,8000条医疗数据确实不太够。
我之前也踩过类似的坑,loss降得好看不一定代表模型学对了东西,尤其你这种中文医疗问答,乱码和“嗯嗯嗯”反复出现,我怀疑是tokenizer或者数据格式的问题更大。你确认过原始数据里的中文是不是都被正确编码了吗?有时候清洗过程会把特殊符号或者换行符搞乱,导致模型学到的是破碎的文本模式。另外,8000条QA对做医疗领域其实偏少,LoRA虽然省资源,但参数效率高不代表数据效率高,模型很可能在死记硬背而不是理解语义。学习率2e-4对LoRA来说稍微偏高,我试过1e-4或者5e-5会更稳,不然容易让低秩矩阵学得过于激进,生成时发散。关于冻结embedding层,这个影响确实不小,尤其中文词表大,如果不冻结,训练时embedding被扰动,推理时就容易出现乱码或者混英文的情况。你可以先试试把embedding冻住,再把学习率调低到1e-4,跑一两个epoch看看输出有没有改善。如果还是乱码,建议检查一下模板,比如每个QA前面加个固定的system指令,让模型明确“你是医疗助手”,而不是裸奔问答。最后,如果loss还在降但生成烂,可以看看验证集上的生成样例,别只看loss曲线,有时候过拟合了反而更糟。
我之前也踩过类似的坑,loss降了真不代表模型学会了,尤其是中文医疗这种垂直领域,数据量8000条其实很紧张,LoRA本身参数效率再高也架不住知识密度不够。你提到的乱码和“嗯嗯嗯”重复,我猜更多是生成参数的问题,试一下推理时把temperature调低到0.1、top_p调成0.9,再用repetition_penalty=1.2,很多时候能立竿见影。另外,system prompt影响确实很大,Llama3的中文对话能力本身就一般,不加一个明确的“你是一个严谨的中文医疗助手”这种角色设定,模型很容易飘。关于冻结embedding,我自己的经验是rank和alpha小的时候影响不大,但如果你的词表里中文token占比高,不冻结反而可能让embedding被拉偏,建议你试一版冻结的对比下。还有个小细节,max_length=1024如果数据里长问答多,截断会导致后半段信息丢失,模型只能瞎编,你可以统计下实际长度分布。最后,如果还不行,先拿几百条数据过拟合看看能不能背下来,能背下来说明代码没问题,再逐步加数据量,不然就是预处理或tokenizer的锅。
说实话你这loss曲线我熟,降到0.9不代表模型学到了东西,LoRA微调小模型经常这样,loss好看但生成崩了。我怀疑主因是数据格式,8000条QA对本身不算太少,但如果你没有用llama3原生的chat模板,直接拼成“问题:xxx 回答:xxx”喂进去,模型根本不知道什么时候该结束,就会一直嗯嗯嗯地兜圈子。你可以试试把每条数据包成标准的user/assistant轮次,加上system提示“你是医疗助手”,哪怕简单点也比裸文本强。另外rank=8和alpha=16对8B来说偏保守,尤其医疗领域术语密集,可以试试rank=32或者64,让适配器有更多容量去记那些专业表达。关于冻结embedding,我个人建议别动,中文tokenizer对医疗词本来就分得碎,如果embedding不更新,模型很难把“阿莫西林”这种词和上下文绑定好,反而更容易乱码。你还可以检查一下推理时的temperature和top_p,如果默认值太高,哪怕模型学到了正确分布也会被采样带偏,先调低到0.1试试。最后建议你拿几十条训练集里的样本做一次过拟合测试,如果连原样都复现不出来,那多半是数据格式或者tokenizer截断出了问题,而不是超参的锅。
查查数据里有没有重复或空回复的样本,八成是混进了“嗯嗯”这类噪声。
loss降到0.9不代表学对了,中文医疗问答这种领域要是数据本身多样性不够,模型很容易走捷径学成复读机,你试试把重复惩罚调高一点,或者采样时改下temperature。我个人感觉8000条对LoRA来说偏少了,至少得2万起步,而且你得确认下有没有把system prompt统一好,不然模型连任务边界都摸不清。embedding冻结那块我倒觉得影响没那么大,反而是你max_length=1024如果实际问答常超长,截断后乱码也正常,先看看bad case是不是都集中在长文本上。
我之前也遇到过类似情况,loss掉得挺顺但生成完全没法看。你这大概率不是LoRA参数的问题,8000条数据对微调来说确实偏少,而且医疗领域术语密集,模型很容易学飞。可以试试把max_length降到512,学习率再调小点比如1e-4,另外加个简单的system prompt明确“你是医疗助手”往往会有奇效。冻结embedding层我试过对稳定性有点帮助,但主要还是先确认下推理时是不是忘了加与训练一致的模板,这个坑挺常见的。
这loss曲线八成是过拟合到噪数据了,8000条QA做医疗问答确实偏少,先加大数据量试试。