在做毕设的多模态大模型微调时,我遇到了一个很奇怪的问题:模型明明已经给出了正确回答,却会在正确回答后紧接着输出一大段乱码。

经探索发现:这一问题的根源是结尾符(EOS Token)的输出问题。大语言模型的推理以自回归概率输出为基础,判断回答结束的方法也是识别到输出结果中的结尾符,而Qwen base模型的微调过程中正会出现与之相关的问题,导致了本文所述现象的发生。本文将探讨这一问题的原因和解决方案。

问题描述

在使用Qwen2.5-3B做岩相识别任务的多模态LoRA微调时,3个epoch后loss收敛到可接受范围,进一步测试时发现生成结果长这样:

结合数据集标注,该样本更可能为「斜长岩」。<U+FFFD>
ניוזל
始化
这组数据累计多少个样本?
useRalative
anton
累计数量为10 个样本。
...(无限续写)

第一行是模型生成的正确回答,但随后紧接着模型又输出了大量的希伯来文、乱码字节、莫名其妙的英文单词。这导致了两方面问题:

  1. 实际模型输出会包含这些乱码内容,不满足我们问答模型的需求
  2. 计算测试集评估指标时,这些垃圾内容把分数拉得很低

问题排查

大语言模型通过自回归按概率输出每个词,直到遇到结尾符(又称为停止token)才停止输出。在Qwen2.5 的Chat格式里,每一轮对话结束用的是 <|im_end|> 这个特殊 token(id=151645),而不是llama等常用的 <|endoftext|>(id=151643)结尾符。

注意到:我们的模型输出中完全没有包含这两个结尾符中的任意一个。进一步排查问题,最终在GitHub的一个issue:[[QwenLM/Qwen3 #1064]]1)里找到了答案,是一位开发者通过打印权重发现的:

# 打印 Qwen2.5-Base 的 lm_head 权重
print(model.lm_head.weight[151643])  # <|endoftext|>:正常,有独特的值
print(model.lm_head.weight[151644])  # <|im_start|>:所有值约为 ±1.17e-37
print(model.lm_head.weight[151645])  # <|im_end|>:和 151644 完全一样
print(model.lm_head.weight[151646])  # 其他视觉特殊 token:也一样
print(model.lm_head.weight[151647])  # ...
# 151644 ~ 151664 全部共享相同的权重值!

即:Qwen2.5-Base 在预训练时,从来没有训练过 <|im_end|> 这类特殊 token。它们的 lm_head(输出层)权重,全部被初始化成了同一个随机值,因此没有在训练中被更新。而我们用 LoRA微调时,LoRA只更新Transformer的注意力层,不更新lm_head。这意味着:

正因如此,<|vision_pad|><|object_ref_start|> 这些视觉token解码出来是 \uFFFD(Unicode 替换字符)和各种乱七八糟的字节,导致了这样的异常输出。

解决方案

在LoraConfig里加一行,让 lm_head 也参与训练:

lora_cfg = LoraConfig(
    r=lora_r,
    lora_alpha=lora_alpha,
    lora_dropout=lora_dropout,
    target_modules=target_modules,
    modules_to_save=["lm_head"],   # ← 加这一行
    bias="none",
    task_type="CAUSAL_LM",
)

modules_to_save的作用是在LoRA微调时,同时保存并更新这些模块的完整权重(不是低秩近似,而是原始的全参数)。这样lm_head就会在训练中被独立更新,不再和其他特殊token共享权重了。

事实上,这是Qwen官方文档对Base模型微调的推荐做法:"LoRA (emb) refers to training with embedding and output layers as trainable parameters, required when fine-tuning base models with new tokens."

代价是checkpoint会多保存一份完整的 lm_head权重(约600MB),训练时间基本不变。

Discussion

这个问题在Qwen2.5系列的Base模型微调里是一个已知的共性坑。我们的项目从Base→CPT→SFT的模型训练路线踩了这个坑。若使用instruct模型,则其在在RLHF阶段已经训练过<|im_end|>,lm_head 权重是独特的,不存在这个问题。

Reference