最近在微调7B模型做中文医疗问答,用的LoRA,训练集大概1.2万条清洗过的对话,跑了两轮loss从1.8降到1.4就死活不动了,验证集loss还轻微反弹。试过把学习率从2e-4降到1e-5,batch size也调过,效果不明显。看tensorboard感觉loss曲线很平滑,不像爆炸,但就是卡住。数据里长回答和短回答都有,我也做了长度截断和去重,难道是数据分布本身有问题?还是说7B太小,知识容量不够?有没有大佬遇到过类似情况,怎么判断是欠拟合还是数据噪声?目前用的是alpaca模板,会不会是模板太简单导致模型没学到上下文?求指点,感谢!
微调LLM时loss降不下去,是数据问题还是学习率没调好?
全部回复
共 44 条验证集反弹大概率是数据噪声,先抽50条看看标注质量,别急着调参。
我也踩过类似的坑,LoRA微调时loss卡在1.4附近真的挺典型的。你试过把rank从8提到16或者32吗?有时候低秩矩阵容量不够,模型想学但表达不了,loss就会平着走,跟学习率关系不大。另外你1.2万条数据对7B来说其实不算多,尤其医疗领域术语密集,如果原始模型在中文医学语料上预训练不充分,LoRA能调整的参数空间可能真不够用。我建议你抽20条训练样本看看模型输出,如果答案里已经有正确的医学概念但表述不完整,那大概率是容量问题;如果回答完全跑偏,那可能是模板或数据格式的问题。alpaca模板对这类任务确实偏弱,你可以试试改成“问题+详细病情描述”的结构,或者加个system prompt限定角色,有时候差别很大。验证集反弹的话,可以试试warmup比例调高一点,或者加个梯度裁剪,偶尔能稳住。你现在的tokenizer对中文长回答的截断策略是什么?如果是硬截断,可能把关键治疗信息切掉了,导致loss降不下去。
说实话你这情况我太熟了,之前微调法律问答模型也卡在loss 1.5左右死活不动。我觉得先别急着怀疑数据噪声,1.4这个loss在7B上其实不算特别离谱,你试试把验证集里那些长回答单独拎出来看下预测结果,如果长回答的生成明显比短回答差,那大概率是长度分布不均导致模型只顾着学短样本的简单模式。另外alpaca模板确实有点问题,中文医疗这种专业领域,模板太通用会让模型忽略诊断逻辑的细节,我后来换成了带角色前缀和结构化字段的模板,loss直接掉了0.2。还有个小技巧,你检查下是不是所有样本的loss都在同一水平,如果某些样本loss特别高但梯度被平均了,可以试试给这些难样本加权,或者干脆把loss计算改成per-token的均值而不是sequence均值,有时候长句子的尾部token会拖累整体。至于欠拟合还是噪声,我一般先看训练集随机抽20条人工跑一遍推理,如果模型对训练集本身都复述不全,那就是容量或学习率问题,如果能背下来但验证集差,那就是数据分布不干净。你也可以试下warmup比例调大点,比如到10%,有时候前期学习率爬太快会进到差的局部最优。最后说句实在的,1.2万条对医疗多轮对话来说可能真不够,特别是长尾症状描述,我后来加了5000条从公开病历里抽的问答对才明显改善。
这loss曲线平滑卡住,大概率是数据里长回答的噪声在拖后腿,试试把长短回答分开训或者过滤下超长样本。