LLM模型蒸馏与微调实操:Qwen-VL、R1风格推理与Qwen2.5-7B
摘要
本文以 Qwen2.5-7B 指令微调、基于 GRPO 的 R1 风格推理训练和 Qwen2.5-VL 视觉微调为主线,梳理蒸馏、SFT、LoRA 与强化学习的关系,结合当前代码说明数据、训练、评估和工程边界。
LLM模型蒸馏与微调实操:Qwen-VL、R1风格推理与Qwen2.5-7B
写在前面
大语言模型的训练经常被笼统地称为微调,但数据来源、优化目标和可训练参数其实是三个独立维度。把教师模型输出作为训练样本,是知识蒸馏;用输入和目标回答做交叉熵优化,是 Supervised Fine-Tuning,监督微调,简称 SFT;根据最终结果的奖励更新策略,是强化学习;用少量低秩矩阵更新大模型,则是 Low-Rank Adaptation,低秩适配,简称 LoRA。它们可以组合,但不能相互替代。
本文围绕三条可复用训练路径展开。第一条以 alpaca-cleaned 训练 Qwen2.5-7B,说明如何完成基础的指令监督微调。第二条使用 Group Relative Policy Optimization,组相对策略优化,简称 GRPO,在 GSM8K 数学题上训练带有 reasoning 与 answer 标签的 R1 风格输出。第三条以 Qwen2.5-VL-3B 为基座,把车辆里程表图片和字段标注组织成多模态对话样本,完成视觉语言模型微调。
三者的共同目标是把通用模型变成可控的特定能力,但它们使用的监督信号不同:文本 SFT 学习示范回答,GRPO 学习可验证结果下更优的生成策略,视觉 SFT 学习图像与结构化字段之间的映射。文章先厘清方法选择,再分别解释三个案例的实现、结果边界和可改进点。
一、项目概览
项目项 | 内容 |
|---|---|
主线任务 | 基于 Qwen 模型完成文本指令对齐、R1 风格推理训练和视觉字段抽取 |
基座模型 | Qwen2.5-7B-Instruct、Qwen2.5-VL-3B-Instruct |
文本 SFT 数据 | 本地 |
推理训练数据 | GSM8K,代码使用 |
视觉数据 | 2 条里程表图片、提示词和目标响应组成的 Excel 标注集 |
参数高效方法 |
|
主要工具 | Unsloth、Transformers、TRL、Datasets、vLLM |
当前结果边界 | 已提供完整训练和推理脚本、样本及评估框架;未保留可复核的训练日志、独立测试集结果或对比指标 |
下图给出三条路径的关系。蒸馏描述的是示范数据从何而来,SFT 和 GRPO 描述的是如何优化,LoRA 与量化描述的是如何在有限显存中完成更新。真正的起点始终是任务验收标准,而不是先选一个训练框架。

这张图强调了一个容易混淆的事实。alpaca-cleaned 和视觉里程表案例走的是 SFT 路径,区别只在输入模态;GSM8K 案例走的是 GRPO 路径,数据中只需要问题和可验证最终答案。三者最后都必须进入独立测试集和误例分析,否则训练过程只能证明代码可运行,不能证明模型已经获得可泛化能力。
二、先区分蒸馏、SFT、GRPO与LoRA
1. 它们解决的问题不同
概念 | 本质 | 训练信号 | 适用场景 | 主要风险 |
|---|---|---|---|---|
知识蒸馏 | 将教师模型或人工专家的能力转移给学生模型 | 教师 logits、教师回答或推理轨迹 | 小模型复现特定风格、知识或推理过程 | 教师错误、数据版权、能力差距过大 |
SFT | 让模型拟合给定输入的目标输出 | 输入-答案对的 token 级交叉熵 | 指令遵循、领域问答、抽取、格式化输出 | 标注噪声、模板记忆、领域外退化 |
GRPO | 用同题候选答案之间的相对奖励更新策略 | 可验证答案、格式或规则奖励 | 数学、代码、结构化推理等有可靠反馈的任务 | 奖励投机、训练不稳定、推理伪装 |
LoRA | 只训练部分低秩增量参数 | 与 SFT 或 GRPO 共用目标 | 显存受限的快速适配 | 目标模块或秩选择不当,能力不足或过拟合 |
| 用低比特加载基座模型,同时训练 LoRA | 与 LoRA 相同 | 更严格的显存预算 | 量化、训练库和模型版本兼容性 |
经典蒸馏需要教师模型的完整概率分布,常用目标可以写为:
其中 L_hard 是真实标签的交叉熵,KL 是 Kullback-Leibler Divergence,KL 散度,T 是温度系数。温度升高会使教师分布更平滑,保留类别之间的相对关系。
但闭源模型 Application Programming Interface,应用程序接口,简称 API,通常只返回文本,不返回 logits。因此,工程中更常见的是 API 蒸馏:先由教师模型生成高质量回答或推理轨迹,再把这些文本作为 SFT 数据。s1 使用外部模型生成推理轨迹后微调 Qwen,就属于这一类。本文的三个案例没有直接访问教师 logits,核心实现分别是普通 SFT、多奖励 GRPO 和视觉 SFT。
2. 训练方法由反馈能力决定
选择 SFT 还是 GRPO,不应只看任务是否复杂,而应先判断正确性是否可低成本验证。
如果拥有稳定的输入-输出标注,例如图片与字段值、用户指令与标准回答,SFT 是更直接、更稳定的选择。若任务只提供问题和最终可验证答案,例如数学题、单元测试或 SQL 执行结果,GRPO 可以让模型自己探索中间过程,再用奖励函数区分候选答案。若既没有可靠标注,也没有可靠验证器,先补数据和定义验收标准,比直接进行强化学习更重要。
三、三条路径共享的训练底座
1. 用 LoRA 和量化降低训练门槛
三个训练脚本都没有全量更新模型权重。文本 SFT 与视觉 SFT 使用 LoRA 秩 r=16,GRPO 使用 r=32。文本模型的目标模块覆盖注意力投影 q_proj、k_proj、v_proj、o_proj,以及前馈网络的 gate_proj、up_proj、down_proj。这使模型只学习一小部分适配参数,训练完成后保存的也是 LoRA adapter,而不是完整基座权重。
Qwen2.5-7B 脚本采用 4-bit 加载,GRPO 同时启用快速推理接口。其目的不是改变模型能力,而是把有限显存优先留给激活、候选生成和梯度。GRPO 每个问题需要采样多个候选,推理侧资源往往会先成为瓶颈,因此它的资源结构与纯 SFT 不同。
当前依赖文件固定了 transformers==4.49.0、trl==0.25.1、unsloth==2025.11.3 和 vllm==0.11.0 等版本。训练库的接口变化很快,复现实验时应从这组固定版本开始,而不是直接安装最新版后假设配置仍然兼容。
2. 训练前后应保持同一条输入链
微调失败常常不是优化器问题,而是训练和推理格式不同。文本 SFT 在训练时使用 Alpaca 模板,推理时也必须用同一模板并将输出位置留空;GRPO 的系统提示要求 <reasoning> 和 <answer>,奖励函数也按这两个标签解析;视觉 SFT 的训练样本是图像和文本混合消息,推理时同样需要将图像对象和对应提示一起传入。
因此,一个训练项目至少要固定五项内容:基座模型和 tokenizer 或 processor、对话模板、结束标记、推理参数、答案解析逻辑。只保存 LoRA adapter 而不保存这些配置,后续很难获得可复现的推理结果。
四、案例一:Qwen2.5-7B在Alpaca-cleaned上的指令微调
1. 场景与数据
这个案例的目标不是构建某一具体领域模型,而是搭建一条最小、完整的文本 SFT 流程:加载指令数据,将三列样本格式化为模型文本,训练 LoRA adapter,再以同一模板完成推理验证。
本地 alpaca-cleaned 包含 51,760 条记录,字段为 instruction、input 和 output。其中 19,157 条具有非空补充输入,32,603 条仅包含指令和回答。该数据集是 Stanford Alpaca 的清理版本,修复了原始数据中的合并指令、空输出、格式不一致和部分明显错误等问题;但它仍是英文的合成指令数据,不能视为任何中文或垂直领域任务的高质量评测集。数据卡
样本被转换为单条因果语言模型文本:
<eos> 是结束标记。它告诉模型回答在何处收束;如果训练样本未加入结束标记,生成时模型容易持续续写到无关内容。模板本身不是算法创新,但它是训练输入、损失位置和推理行为一致的基础。
2. 关键实现
脚本先以 4-bit 方式加载 Qwen2.5-7B-Instruct,再对注意力层和前馈层注入 LoRA。随后使用 SFTTrainer 对格式化后的 text 列进行训练。
训练配置为单卡 batch size 2、梯度累积 4、有效 batch size 8,最大序列长度 2,048,学习率 2e-4,最多 60 步。这里的 max_steps=60 是一次流程验证配置,不是对 51,760 条数据完成一轮训练。若数据以 batch size 8 计算,一次完整遍历约需要 6,470 个有效 batch;因此不能把这个脚本的默认训练当作完整 Alpaca 训练实验。
训练后代码用斐波那契数列和巴黎地标问题进行生成,并保存 lora_model。这类输入适合作为冒烟测试,用于确认 adapter、tokenizer、模板和生成链路都能工作;它们不构成对指令遵循能力的定量评估,因为没有独立测试集、统一解码配置和评分规则。
3. 这个案例真正说明了什么
文本 SFT 解决的是行为对齐问题。它能让模型适配特定模板、语言风格、字段格式或领域答案结构,但不会自动补齐数据中缺失的专业知识,也不会保证数学、代码等任务的推理正确性。
将该流程迁移到真实项目时,最重要的改动不是把 max_steps 增大,而是替换数据和评测:以真实任务样本替代通用英文 Alpaca,保留时间或来源隔离的测试集,并检查领域事实、拒答边界、格式遵循和延迟。只有在基座模型与 SFT 模型使用同一测试集比较后,才可以判断微调是否值得上线。
五、案例二:用GRPO训练R1风格的结构化推理
1. 这是 R1 风格训练,不是从零复刻 R1
代码以 Qwen2.5-7B-Instruct 为基座,通过 LoRA 和 GRPO 训练数学问题的结构化输出。它模仿的是 R1 类模型的一个外显形式:把中间过程写在 <reasoning> 中,把最终答案写在 <answer> 中。模型规模、数据规模、训练时长、奖励体系和基础能力都与 DeepSeek-R1 的完整训练方案不同,因此更准确的名称是 R1 风格推理训练样例,而不是复刻完整 R1 模型。
GSM8K 是由英文小学数学应用题构成的数据集,主要考察 2 到 8 步的基础数学推理。本地数据包含 main 配置的 7,473 条训练题与 1,319 条验证题。原始 answer 字段含有自然语言解题过程和 #### 后的最终答案;当前代码调用 extract_hash_answer() 后只保留最终数值作为奖励依据。GSM8K 数据卡
这使该案例与 SFT 有根本区别:训练数据不为模型提供 <reasoning> 的参考文本,而是只告诉它最后答案是否正确。推理过程的格式由系统提示和格式奖励塑造,内容质量则依赖模型预训练能力与最终答案奖励共同约束。
2. GRPO 的完整闭环

在每个训练步中,模型针对同一个问题生成 6 个候选回答。每个回答先被解析出 <answer> 字段,再依次计算格式、类型与正确性奖励。GRPO 不需要像 Proximal Policy Optimization,近端策略优化,简称 PPO 那样额外训练价值网络;它直接将候选答案的奖励与同组平均奖励比较,得到相对优势,再在 KL 散度约束下更新策略。TRL 的 GRPOTrainer 也采用同题多候选、按组内奖励计算相对优势的机制,并支持将多个自定义奖励函数相加。GRPOTrainer 文档
当前代码的奖励设计如下。表中的 XML 是 Extensible Markup Language,可扩展标记语言,用于明确推理块和最终答案块的边界。
奖励函数 | 满足条件 | 单项最高分 | 作用 |
|---|---|---|---|
| XML 起止标签出现次数正确 | 0.5 | 降低残缺标签和尾随文本 |
| 包含 | 0.5 | 先建立基本输出结构 |
| 完整匹配严格 XML 格式 | 0.5 | 约束换行和边界 |
|
| 0.5 | 与 GSM8K 数值答案匹配 |
| 解析出的答案等于标准答案 | 2.0 | 将最终正确性作为主要信号 |
这套权重的最大总分为 4.0,其中正确性占 2.0。设计顺序是合理的:先确保输出可解析,再强调最终答案。但它也有明确盲点。模型可以生成很长、格式正确却没有因果价值的 reasoning;整数奖励只适合当前数值型数据;字符串完全相等会对单位、分数或等价表达不鲁棒。奖励函数本质上定义了模型会优化什么,任何没有写进奖励的目标都只能依赖模型原有能力。
3. 核心配置与代码逻辑
相较于 SFT,这里学习率从 2e-4 降到 5e-6,因为模型在在线采样的输出分布上更新,较大的步长更容易破坏已有语言能力。num_generations=6 意味着每个问题都要完成 6 次生成和奖励计算;训练吞吐不再由反向传播单独决定,候选生成速度、最大 completion 长度和 Graphics Processing Unit,图形处理器,简称 GPU,的显存利用率都会直接影响成本。
代码在加载模型时设置 fast_inference=True 与 gpu_memory_utilization=0.6,用于给多候选生成预留资源。保存阶段只导出 grpo_saved_lora,也提供合并 16-bit、4-bit 和 GGUF 的导出选项。部署时需要同时记录基座模型、LoRA adapter、系统提示、答案提取器和推理采样参数;少其中任何一项,结构化输出都可能改变。
4. 如何理解没有显式推理标注也能产生 reasoning
系统提示先要求模型使用 XML 格式输出,格式奖励再鼓励这种结构,而正确性奖励只关注最终答案。模型如果在预训练或指令阶段已经具备一定的数学推理能力,就可能发现写出中间步骤更有利于得到正确答案,从而在 <reasoning> 中形成更稳定的外显过程。
但这不等于奖励函数凭空创造了推理能力。对于基础能力不足的模型,格式奖励更可能得到的是形式化的长文本;对于过强的格式奖励,模型还可能把 token 预算花在无关解释上。因此,真正应评估的是独立题目的最终答案准确率和错误模式,而不是 reasoning 块是否存在或是否足够长。
5. 合理的评估方式
当前代码用 Calculate pi. 做训练后推理示例,这只能检查模型是否可以返回结构化文本,不能评估 GSM8K 推理能力。更严谨的评估应使用 main/test 或保留验证集,统一模型、提示、温度、最大输出 token 和答案提取规则,再比较基座、SFT 和 GRPO adapter。
维度 | 建议指标 | 原因 |
|---|---|---|
最终正确性 | 解析后答案 Exact Match | 直接对应可验证任务目标 |
格式稳定性 |
| 影响下游解析和服务稳定性 |
推理成本 | 平均生成 token、第 50/95 百分位延迟 | GRPO 模型不能只比较正确率 |
奖励健康度 | 各奖励均值、方差、零方差比例 | 判断候选是否缺乏区分度或出现奖励饱和 |
误例 | 算术错误、解析错误、格式正确但答案错误 | 决定下一轮奖励或数据修改方向 |
六、案例三:Qwen2.5-VL视觉模型微调
1. 场景:从仪表图片中抽取可用字段
视觉语言模型的任务不是单纯 OCR。里程表图片中同时存在刻度、数值、单位、时间、温度、挡位和警示符号,目标输出需要把这些视觉线索转换为字段化信息。Qwen2.5-VL-3B 是图文到文本模型,官方模型卡明确列出文档、图表、图标和布局理解能力,也支持结构化输出;这使它适合作为图像字段抽取的基座。Qwen2.5-VL-3B 模型卡
当前标注表包含 id、prompt、image、response 四列,只有 2 条训练样本。每条样本用相同的领域提示询问图像中的关键信息,响应中给出总里程、当前速度、时间、温度和挡位等字段。下面保留一条图像、提示和标注响应的核心区域,用于说明多模态监督数据的输入输出形态。

这张图是标注示例,不是独立测试结果。它首先暴露了视觉微调中最重要的问题:字段边界必须在数据阶段明确。例如中央屏幕可能同时出现总里程、行程距离、温度和挡位;温度的小数点、单位及挡位高亮状态都可能在低清晰度图像中产生歧义。若标注定义不统一,模型会稳定地学习到不一致的输出。
2. 从 Excel 行到多模态对话
训练脚本读取 Excel,使用 PIL.Image.open() 加载 RGB 图像,并把每一行转换为标准消息结构。用户消息同时包含文本提示和图像对象,助手消息只包含目标回答。
这个转换决定了模型在训练时看到什么。文本模型只需要 tokenizer 处理字符序列,而视觉语言模型还需要 processor 或 data collator 将图像编码为视觉 token,并与文本 token 对齐。官方推理示例也采用同样的图像加文本消息结构,再由 processor 生成模型输入。模型调用说明
在生产任务中,建议将自由文本目标改为可验证的 JavaScript Object Notation,JavaScript对象表示法,简称 JSON,例如:
这不是当前训练集的原始输出格式,而是更适合工程验证的改进方向。JSON 能将总里程与行程距离分开,保留数值和单位,允许针对每个字段计算精确率,并可在写入业务系统前做范围、单位和枚举值校验。
3. 视觉与纯文本 SFT 的差异
视觉微调使用 FastVisionModel,而不是文本案例中的 FastLanguageModel。LoRA 配置同时打开视觉层、语言层、注意力模块和 MLP 模块的微调,秩为 16。这符合图像字段抽取的任务特征:只更新语言层可能无法适配新的视觉线索,只更新视觉层又可能无法形成稳定的领域字段表达。
训练器使用 UnslothVisionDataCollator,并设置 remove_unused_columns=False 与 skip_prepare_dataset=True。这些参数的目的不是优化效果,而是确保样本中的图像对象不会被常规文本训练流程丢弃。视觉任务如果错误地沿用纯文本 collator,往往表现为图像没有进入模型、列被删除或 batch 维度不匹配。
该案例设置每卡 batch size 2、梯度累积 4、有效 batch size 8、最大长度 2,048、学习率 2e-4、训练 30 步。代码会分别在训练前后对第一张里程表做推理,并打印训练时间与显存占用。由于当前目录中未保存这些运行日志,本文不报告具体耗时、显存或准确率。
4. 当前数据不能用于泛化结论
视觉样本只有 2 条,而且训练后推理使用的 1-vehicle-odometer-reading.jpg 同时存在于训练 Excel 中。这是训练集复测,不是独立测试。它最多说明模型可以记住或重现该样本的标注格式,不能说明模型能够识别新的车辆、拍摄角度、夜间噪声、英制单位、遮挡或不同仪表布局。
要把这个原型扩展为可靠的字段抽取模型,至少需要完成以下四件事。
环节 | 最低要求 | 原因 |
|---|---|---|
数据规模 | 每个字段和关键视觉条件下覆盖足够样本 | 2 条样本无法覆盖字体、反光、单位和布局变化 |
数据切分 | 按车辆、拍摄批次或场景切分,而非随机切分 | 避免同一仪表或近重复图片同时出现在训练与测试中 |
标注规范 | 明确总里程、行程距离、单位、小数点和缺失字段的写法 | 将视觉歧义转为可审核的标注规则 |
字段评测 | 分字段 Exact Match、数值误差、单位一致率、JSON 合法率 | 总体文本相似度无法发现关键数字错误 |
对于数值字段,还应设置业务校验。例如速度不应为负值,挡位只能属于有限集合,时间须匹配 HH:MM,总里程与行程距离不可混写。模型负责感知,规则负责验证;二者组合比让模型直接输出长段说明更稳定。
七、评估脚本能做什么,不能做什么
目录中的 model_comparison_eval.py 提供了一个很好的评估结构起点:它尝试比较基座模型、SFT 模型和 GRPO 模型的格式遵循、答案匹配、推理结构、回复长度和语言一致性。这说明训练完成后不应只看单个输出,而应建立多维对比。
不过,当前 demo_comparison() 使用的是手写的模拟回答,输出分数也来自模拟样本,不能作为任何模型的实测结果。脚本中的字符集合重叠 F1 也只适合粗略演示:它可能让语义错误却共享大量字符的答案获得较高分,无法替代领域准确率或人工评审。医疗场景的格式判断仅检查长度或标题符号,同样不适合生产验收。
更稳妥的做法是按任务替换评价器。
任务 | 主要指标 | 推荐验证方式 |
|---|---|---|
Alpaca 指令 SFT | 任务成功率、格式合规、人工偏好、拒答边界 | 固定指令集,双盲人工评审与规则校验结合 |
GSM8K GRPO | 最终答案 Exact Match、格式完整率、平均 token | 用未参与训练的验证或测试题,统一答案提取器 |
视觉字段抽取 | 分字段准确率、单位一致率、JSON 合法率、置信度校准 | 以车辆或场景隔离的测试集逐字段统计 |
评估集必须在训练开始前冻结。若训练过程中反复查看测试误例并修改模板、奖励或数据,测试集已经参与了模型选择,应再准备新的最终保留集。这个纪律比更换优化器更能保证结果可信。
八、从三个案例得到的工程方法
第一,蒸馏不是小模型化的同义词。它首先是能力迁移的数据策略。若教师可输出高质量领域回答,SFT 可以快速把风格、格式和一部分知识迁移到学生模型;若教师只提供答案,仍需要确认学生是否能在目标分布上学到有效规律。
第二,强化学习不应替代数据治理。GRPO 适合存在可靠验证器的任务,它通过组内候选比较提高正确行为的概率,但不能修复错误答案、含混题目或奖励缺失。奖励函数越简单,越要重点检查奖励投机和格式伪装。
第三,多模态微调的瓶颈通常在标注而不是模型。图像读数任务中,字段定义、单位、数值精度、模糊样本和测试切分决定了模型上限。先建立字段级评估和数据规范,再调 LoRA 秩、学习率和训练步数,效率更高。
第四,LoRA 降低了迭代成本,但没有降低验证要求。轻量 adapter 很适合并行试验不同数据版本、提示模板和奖励设计;每个 adapter 仍然应绑定基座模型版本、训练数据版本、配置、评测结果和已知限制,避免出现无法解释的模型差异。
小结
这三个案例构成了一条由易到难的模型适配路径。Qwen2.5-7B 的 Alpaca SFT 解决基本指令格式与训练链路问题;基于 GSM8K 的 GRPO 说明如何在可验证答案约束下优化 R1 风格的结构化推理;Qwen2.5-VL 的视觉微调把输入扩展到图像与文本联合建模,并把重点转向字段标注和跨场景泛化。
当前代码已经覆盖了模型加载、LoRA 注入、数据转换、训练、推理和 adapter 保存。下一步不应急于扩大训练步数,而应补齐独立测试集、真实日志、字段级指标和误例闭环。只有将这些证据加入训练链路,微调才能从可运行的实验脚本变成可判断、可迭代的工程能力。
