最近在试着用LoRA微调Llama3-8B做中文法律问答,数据集是自己整理的几千条问答对,格式参考了alpaca。训练loss能降到0.8左右,但推理时模型经常生成一堆重复的“###”或者无意义符号,偶尔还会蹦出英文。
我用的peft+transformers,学习率设了2e-4,epoch设了3,max_seq_len是1024。看很多教程说这个参数没问题,但我的输出明显崩了。想问问有经验的朋友,这种情况一般是数据预处理的问题(比如模板没对齐),还是微调过头导致灾难性遗忘?或者跟base model的tokenizer有关?
自己调了一周没头绪,求指点排查方向,感谢!
微调Llama3后输出全是乱码,是学习率太大还是数据格式问题?
全部回复
共 9 条之前跑别的任务也遇到过一模一样的现象,loss看着正常但生成全是特殊符号,最后排查下来是模板对齐的锅。你用的alpaca格式里那个“input”字段是不是有的为空有的不为空?llama3的chat模板跟llama2不太一样,如果数据里instruction和input拼接方式跟base model微调时不一致,模型很容易学到乱输出分隔符。建议先拿一条训练数据单独推理看看,如果连训练集都复现不出来那大概率是数据格式问题,能复现就考虑超参。
另外2e-4的LoRA学习率对llama3来说其实略微偏高,这模型对学习率比llama2敏感,我试过同样设置跑英文任务没问题但中文就崩,可能是中文token embedding更新太剧烈导致灾难性遗忘。你可以降到5e-5试两轮epoch,同时把LoRA的alpha调成跟rank一致或者更小。还有个小排查点:max_seq_len设1024但你的数据里有没有超过这个长度的?超长截断后标签错位也会造成这种乱码现象,建议先检查一下数据长度分布。英文蹦出来大概率是tokenizer的special token没处理好,看看是不是把padding或者eos当普通文本训练了。
这情况八成是数据格式问题,alpaca模板里prompt和response的分隔符没对齐,LoRA学串了。
建议先拿一条原始数据单独跑下生成,看看是不是模板拼接时把特殊token搞丢了。
我之前也遇到过类似情况,loss能降但生成崩多半是数据格式和模板没对齐的问题,alpaca模板里system和instruction的字段分隔符必须严格一致,建议你打印一条训练样本看看模型实际看到的input长啥样。
另外2e-4对LoRA来说确实偏高,尤其数据量不大的时候容易让模型把注意力全放在特殊符号上,可以试降到5e-5或1e-5,顺便把epoch降到1~2看看。
还有个排查技巧:用你训练时的同一个模板去跑base model(不微调),如果它本身就输出乱码,那就是模板和tokenizer的兼容性有问题,比如加了不该加的BOS或EOS。
我之前调中文任务时发现max_seq_len太长反而会让重复变严重,可以先砍到512试试,排除长度干扰。
我之前也踩过类似的坑,loss能降下来但生成乱码,大概率不是学习率的问题,2e-4对LoRA来说挺常规的。你重点查一下模板对齐吧,llama3的chat模板和alpaca格式差挺多的,尤其那个system prompt和终止符,如果训练时输入输出拼接的方式跟推理时不一致,模型很容易学乱。另外你确认一下数据里有没有空label或者特别短的回复,这种样本会让模型学到输出分隔符而不是内容,我之前清洗掉一批后好多了。至于灾难性遗忘,epoch3一般不至于,除非你数据量太小或者重复太多,但我怀疑还是预处理环节出的问题。还有个排查技巧,你拿一条训练数据原样喂给模型看看能不能复现出正常回答,如果能但新输入就崩,那基本就是模板泛化的问题了。实在不行可以把base model换成llama3的instruct版试试,它原生的对话格式更稳,少折腾一点。
我之前也踩过类似的坑,loss降到0.8看着正常,但生成崩了多半是模板没对齐。你数据是alpaca格式的话,推理时的prompt模板必须跟训练时完全一致,尤其是那个“###”分隔符,差一个空格都会让模型发疯。另外2e-4对LoRA其实偏高,你可以试试降到1e-4或5e-5,同时把epoch降到1-2,看输出会不会稳一点。还有一个排查技巧:拿一条训练数据直接喂进去看能不能复现,如果也乱码那就不是数据问题,而是模型本身学崩了,先回退到原始权重再调参吧。
loss能降到0.8不代表模型学对了,你描述的“###”重复和无意义符号,很像训练时模板没对齐导致的。建议先检查数据里instruction/input/output的拼接方式,尤其是eos token有没有加对,Llama3的chat template用错了很容易崩。另外2e-4对LoRA来说偏大,我一般用1e-4甚至5e-5,跑3个epoch确实容易过拟合。你可以先拿20条训练数据做推理测试,看模型能不能复现,如果连训练集都答不对那基本就是格式问题。
2e-4对LoRA有点高,我一般1e-4以内;先查下数据里有没有空回复或模板错位吧。
2e-4对LoRA确实偏大,我一般1e-4起步。不过输出“###”更像是模板没对齐,检查下推理时的prompt格式跟训练时一致不。
2e-4对LoRA来说确实偏高了,尤其你才几千条数据,很容易过拟合到模板的边界上,然后推理时就乱吐特殊token。我建议先降到5e-5甚至1e-4试试,同时把epoch压到1或者2,看loss曲线其实参考意义不大。另外检查一下alpaca模板里###有没有正确加到eos后面,如果推理时没按训练格式拼prompt,模型也会懵。