最近在试着用LoRA微调Llama3-8B做中文法律问答,数据集是自己整理的几千条问答对,格式参考了alpaca。训练loss能降到0.8左右,但推理时模型经常生成一堆重复的“###”或者无意义符号,偶尔还会蹦出英文。
我用的peft+transformers,学习率设了2e-4,epoch设了3,max_seq_len是1024。看很多教程说这个参数没问题,但我的输出明显崩了。想问问有经验的朋友,这种情况一般是数据预处理的问题(比如模板没对齐),还是微调过头导致灾难性遗忘?或者跟base model的tokenizer有关?
自己调了一周没头绪,求指点排查方向,感谢!
微调Llama3后输出全是乱码,是学习率太大还是数据格式问题?
全部回复
共 18 条之前跑别的任务也遇到过一模一样的现象,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,模型也会懵。
我之前也遇到过类似情况,loss看着正常但推理直接崩,最后发现是训练时的prompt模板和推理时不一致,alpaca格式里instruction和output的分隔符没对齐。你可以先拿训练集里的一条数据原样喂进去测一下,如果也崩那基本就是模板问题。另外2e-4对LoRA来说偏大了点,我一般用1e-4或者5e-5,epoch 3在几千条数据上确实容易过拟合,试试降到1-2个epoch看看效果。
loss降到0.8不一定代表训好了,LoRA学习率2e-4对Llama3来说确实偏高了,我一般用1e-4甚至5e-5就比较稳。你这种满屏###和乱码,更像是模板没对齐或者special token处理有问题,检查下训练时有没有正确mask掉prompt部分的loss。另外推理时的prompt格式得跟训练时完全一致,差一个换行都可能崩。建议先拿几条训练数据直接过一遍模型,看能不能复现出正常回答,不行的话就是数据层面的事。
先查数据模板有没有对齐,再试试把学习率降到1e-4以下,2e-4对LoRA确实容易训崩。
2e-4对LoRA来说确实偏大了,尤其你还跑了3个epoch,很容易把base模型带偏。loss降到0.8不代表模型学会了,可能只是在背模板。建议先降到1e-4甚至5e-5,epoch减到1试试。另外检查下训练时的prompt模板和推理时是不是完全一致,这个不一致特别容易出乱码。
这个现象我遇到过,大概率不是学习率的问题,2e-4对LoRA来说确实算常规范围。你描述的那种重复“###”或者乱蹦符号,很像训练时模板没对齐导致的,特别是alpaca格式里instruction、input、output的分隔符和推理时用的prompt不一致。可以检查一下训练数据里是不是有的样本output字段为空或者混入了特殊token,几千条里只要有一小撮脏数据,模型就会学到奇怪的pattern。另外loss降到0.8不代表模型真的学会了,LoRA有时候会过拟合到训练集的表面格式上,尤其epoch=3对几千条数据可能偏多。我建议先拿20条训练样本直接推理,看输出跟标签差多远,如果连训练集都复现不了,那基本是数据或模板问题。还有tokenizer这块,Llama3的中文token效率一般,如果max_seq_len=1024截断了很多长样本,模型可能只学到半截问答对,输出自然崩。排查顺序可以试试:先固定推理prompt和训练模板完全一致,再把epoch降到1、lr降到1e-4跑一版对比,最后检查有没有pad token被误当成label算loss。
2e-4对LoRA来说确实偏大了,我一般从1e-4甚至5e-5起步,loss降到0.8不一定代表泛化好,很可能已经过拟合了。你那个“###”重复基本是模板没对齐的典型症状,检查下训练时的prompt是不是把###当成了特殊分隔符,推理时又没给对。另外法律问答几千条数据量不算大,epoch 3容易把模型带偏,建议先降到1e-4跑一个epoch看看输出有没有改善。
2e-4对Llama3微调有点猛了,先降到5e-5试试,还崩就查数据模板跟推理时是否一致。
有没有更详细的教程推荐?
2e-4对LoRA来说确实偏大了,我一般从1e-4甚至5e-5起步,loss降到0.8不代表收敛得好,可能已经过拟合到模板上了。你那个“###”重复很像训练数据里eos token没加或者padding位置不对,模型学不到什么时候该停。建议先拿几条训练样本原样喂进去做推理,看输出跟label差多少,如果连训练集都复现不了就是数据格式问题。另外alpaca模板里如果有中文冒号或换行不一致,tokenizer切出来的边界会很乱,这个坑我踩过。