最近在试着用QLoRA微调Llama3-8B做一个法律问答的垂直领域模型,数据集大概2万条自己清洗的问答对。用的transformers和peft库,照着网上教程抄的配置,学习率设了2e-4,lora_r=8,跑了3个epoch。训练loss降得挺正常,从1.8降到0.9,但推理的时候输出完全不对,经常出现重复的token和类似“|||||”这样的乱码,偶尔能蹦出几个正常词但句子结构全崩。试过调低学习率到1e-5,也换过lora的target_modules,问题依旧。有点怀疑是不是分词器没加padding或者special token设置的问题,但训练时也没报错,loss看着也正常。有没有大佬遇到过类似情况?是微调参数的问题还是数据格式哪里踩坑了?求指点一下排查方向,谢谢!
微调Llama3后输出全是乱码,是学习率问题还是分词器没设对?
全部回复
共 19 条loss正常但生成崩了这种情况,我猜大概率不是学习率的问题,你调到1e-5还崩就说明方向不对。分词器没加padding确实会导致batch内长度不一致,但更常见的是你推理时忘了把special token加回去,或者model.generate里没设pad_token_id。我之前遇到类似情况是lora没只冻住原模型权重,结果把embedding也训了,输出全是拼接符,你检查下target_modules里有没有误加embedding层。另外你试试推理时用model.config里的pad_token_id手动传一下,或者干脆把tokenizer的padding_side改成left,有时候这比调超参数管用。
loss降但推理崩,大概率不是学习率的问题,2e-4对QLoRA其实挺常见的。我比较怀疑你训练和推理时的chat template没对齐,Llama3有自己的一套special token格式,如果训练时手动拼的prompt跟tokenizer.apply_chat_template不一致,模型学到的就是错位的模式。另外检查下推理时有没有重复加载adapter或者merge方式不对,这种情况也会吐出乱码。建议先用训练集里的一条样本原样跑一遍推理,能复现问题就好排查了。
loss降但输出乱码,八成不是学习率的事,更像是训练和推理的模板没对齐。Llama3有自己的chat template,你训练时如果手动拼的prompt跟推理时用的不一致,模型就等于在答另一道题。另外QLoRA合并权重那步也容易踩坑,adapter没正确merge或者推理时又套了一层lora,都会出这种重复加乱码。建议先把训练样本原样喂进去做一次推理,能复现就基本锁定是格式问题而不是超参。
loss降不代表模型学对了,你这情况大概率是训练时用了padding但推理时没对齐,或者chat template没套对。Llama3的special token和对话格式挺敏感的,QLoRA微调时如果padding side或者attention mask没处理好,模型就会学到一堆无效token。建议先拿训练集里的一条样本直接推理,看输出是不是也乱,如果是那就是数据格式或模板的问题。另外2e-4对LoRA来说偏大,但既然loss降了,先别急着调参,把推理时的tokenizer配置和训练时打印出来对比一下。
loss降不代表模型学对了,我之前也踩过这个坑。重点检查一下推理时的chat template跟训练时是不是一致的,Llama3对special token特别敏感,少个<|eot_id|>就容易胡言乱语。另外QLoRA的merge步骤也容易出问题,建议先别merge,直接用peft加载adapter跑一遍看看。
loss正常但输出乱码,这种情况大概率不是学习率的问题,更像是推理时的chat template或者special token没对齐。你训练时用的模板和推理时的是不是一致?Llama3对<|start_header_id|>这些特殊token很敏感,差一个都可能崩。另外QLoRA合并权重的时候有没有正确反量化,这块也容易出问题。建议先用训练集里的一条样本做推理,排除数据本身的锅。
loss降不代表对,QLoRA的r=8太小了,法律领域至少上32,另外推理时得把adapter权重合进去再测。
loss降不代表模型学对了,我之前也遇到过这种全是竖线的情况,最后发现是chat template没对齐,训练时用了默认模板但推理时没加special token,模型根本不知道从哪开始生成。建议先用base模型不加adapter跑一遍推理,确认原始模型本身输出正常,再挂上lora看是不是适配器把权重带偏了。另外2e-4对qlora来说其实偏高,法律领域数据又比较规整,很容易过拟合到重复模式上,可以试试1e-4配warmup再观察下eval的生成结果而不是只看loss。
loss降不代表模型学对了,我之前也踩过这个坑,后来发现是推理时的chat template没对齐,训练用了special token但生成时没加上,输出就会崩成乱码。你可以先拿训练集里的一条样本做推理,看模型能不能复现出答案,如果连训练数据都过拟合不了,那大概率是数据处理或者label mask的问题。另外QLoRA的2e-4其实不算高,但3个epoch对2万条来说可能过多了,试试1个epoch看会不会好点。
loss正常但输出乱码,大概率是推理时没对齐训练用的chat template,查查tokenizer的special token吧。
loss正常但输出乱码,大概率是推理时没用对chat template,跟学习率关系不大。
loss降得正常不代表模型学对了,这个坑我踩过。你描述的那种“|||||”乱码加重复token,大概率不是学习率的问题,2e-4对LoRA来说虽然偏大但也不至于直接崩成乱码。我比较怀疑是你推理时的chat template和训练时不一致,Llama3有自己的一套special token格式,训练时如果tokenizer没正确套template,推理又换了种拼法,模型就会彻底懵掉。另外你检查一下保存adapter之后有没有把tokenizer一起存下来,有时候base模型的分词器和微调时用的不是同一个版本,pad_token设错也会导致这种输出。还有个容易忽略的点是QLoRA的bnb量化配置,如果推理时没按训练时的量化方式加载,权重对不上也会出乱码。建议你先把训练集里的一条样本原样喂进去做推理,看能不能复现正常输出,这样能快速排除是数据格式还是权重的问题。target_modules换过没用的话,基本可以排除是LoRA挂载位置的事了。
loss正常但输出乱码,八成是推理时没加chat template或eos token没对齐。
loss正常但推理乱码挺常见的,我之前也踩过。先确认下保存的时候是不是只存了adapter,推理加载时base模型和tokenizer版本要跟训练时完全一致,不然special token对不上就会出这种鬼画符。另外2e-4对QLoRA其实偏高了,虽然loss降了但可能把模型训歪了,试试1e-4加上warmup看会不会稳一点。还有你推理时用的prompt模板跟训练数据格式对齐了吗?这个不对齐也容易崩。
loss降得正常但推理崩,大概率不是学习率的事,更像推理时的chat template没对齐。Llama3训练时用的特殊token格式很讲究,你微调时如果只喂了纯文本没套template,推理又用generate默认拼接,模型就不知道啥时候该停,很容易吐重复和竖线。我之前也踩过这坑,建议先把推理输入打印出来跟训练样本对一下,确认special token和eos位置一致。另外2e-4配r=8对8B模型偏激进,可以降到1e-4再试。
loss降得正常不代表模型学对了东西,这是微调里最容易踩的坑之一。你这种情况我第一反应是chat template没对齐,Llama3的special token格式挺讲究的,如果训练时用的模板和推理时不一致,模型基本就是在胡言乱语。另外你说输出里有“|||||”这种重复token,这往往不是学习率的问题,更像是生成配置或者eos token没处理好,比如pad token和eos token设成同一个可能导致模型不知道该在哪停。QLoRA本身对推理时的权重合并也有要求,如果你推理时没把adapter正确merge或者加载方式不对,输出也会崩。建议你先拿训练集里的一条样本原样喂进去看输出,如果连训练数据都复现不了,那基本就是模板或tokenizer的问题。还有2e-4对LoRA来说其实偏高了,虽然loss好看但可能过拟合到特殊token上了,不过这个不是主因。
有没有更详细的教程推荐?
学到了,感谢分享!
loss降得正常但推理崩,大概率不是学习率的事,更像是训练和推理时的模板不一致。你检查下微调时有没有套Llama3的chat template,推理时是不是也用了完全一样的prompt格式,这个对不上特别容易出重复和乱码。另外padding_side也得留意,训练用right padding推理搞成left就容易崩。2e-4对QLoRA来说其实偏大了点,但既然loss曲线没炸应该不是主因,先排查模板这块吧。