VLM模型监督微调训练#
本文档介绍如何在 RLinf 框架中对VLM模型进行 全量监督微调(Full-parameter SFT)。
本教程重点需要关注两个文件:
启动脚本:
examples/sft/run_vlm_sft.sh训练配置:
examples/sft/config/qwen2_5_vl_sft_vlm.yaml
启动脚本:examples/sft/run_vlm_sft.sh
当前脚本默认使用配置yaml文件
examples/sft/config/qwen2_5_vl_sft_vlm.yaml重定向文件的输出在:
<repo>/logs/<timestamp>/实际执行命令:
python examples/sft/train_vlm_sft.py \
--config-path examples/sft/config/ \
--config-name <你的配置名> \
runner.logger.log_path=<自动生成的日志目录>
配置模板:examples/sft/config/qwen2_5_vl_sft_vlm.yaml
如果需要训练 qwen3_vl 或 qwen3_vl_moe 等模型,请确保当前环境中的 transformers 版本 高于或等于 4.57.1。
VLM 配置与 RLinf 中的其他 RL 训练文件结构基本一样,其中
data和actor.model的具体值改为 VLM 场景。
具体的运行流程开始前准备#
准备好环境,下载 RLinf 官方镜像
rlinf/rlinf:math-rlinf0.2-torch2.6.0-sglang0.4.6.post5-vllm0.8.5-megatron0.13.0-te2.1准备好模型权重目录,下载网址
https://huggingface.co/Qwen/Qwen2.5-VL-3B-Instruct准备好 Robo2VLM 数据集目录
https://huggingface.co/datasets/keplerccc/Robo2VLM-1修改
examples/sft/config/qwen2_5_vl_sft_vlm.yaml文件,运行脚本examples/sft/run_vlm_sft.sh
下面是 Qwen2.5-Vl-3B sft 的例子#
请注意,Robo2VLM数据集下载后由于它将 train 数据和 evaluate 数据放在一起,命名方式为 train-00000-of-00262.parquet 和 test-0000X-of-00003.parquet,所以需要将它们分开,并分别放在不同的文件夹下,否则 RLinf 会直接读取整个数据集。
测试中所有需要修改的值已经在下面样例中注释,其他在实验过程中使用的参数和如下 yaml 保持一致。
defaults:
- override hydra/job_logging: stdout
hydra:
run:
dir: .
output_subdir: null
cluster:
num_nodes: 1
component_placement:
actor: all
runner:
task_type: sft
logger:
log_path: "../results"
project_name: rlinf
experiment_name: "qwen2_5_vl_sft_demo"
logger_backends: ["tensorboard"]
max_epochs: 6000
max_steps: -1
val_check_interval: 1000
save_interval: 1000
data:
type: vlm
dataset_name: "robo2vlmsft"
# 数据路径,需要将 train 数据和 evaluate 数据分开,并分别放在不同的文件夹下
train_data_paths: "/path/to/Robo2VLM-1/train_data"
# 如果不需要进行训练,只需要进行评估,请对将 train_data_paths 设置为 null
val_data_paths: "/path/to/Robo2VLM-1/test_data"
# 数据字段名(要和你的数据列一致)
prompt_key: "question"
choice_key: "choices"
answer_key: "correct_answer"
image_keys: ["image"]
apply_chat_template: True
use_chat_template: True
max_prompt_length: 1024
lazy_loading: false
num_workers: 4
algorithm:
adv_type: gae
actor:
group_name: "ActorGroup"
training_backend: "fsdp"
micro_batch_size: 4
eval_batch_size: 4
global_batch_size: 256
seed: 42
model:
model_type: "qwen2.5_vl"
precision: fp32
# 模型路径,需要将模型权重下载后放在本地,并设置为模型路径
model_path: "/path/to/Qwen2.5-VL-3B-Instruct"
is_lora: False
optim:
lr: 1e-5
adam_beta1: 0.9
adam_beta2: 0.999
adam_eps: 1.0e-08
weight_decay: 0.01
clip_grad: 1.0
lr_scheduler: "cosine"
total_training_steps: ${runner.max_epochs}
lr_warmup_steps: 200
fsdp_config:
strategy: "fsdp"
sharding_strategy: "no_shard"
use_orig_params: False
gradient_checkpointing: False
mixed_precision:
param_dtype: bf16
reduce_dtype: fp32
buffer_dtype: bf16
reward:
use_reward_model: False
critic:
use_critic_model: False
启动训练#
在仓库根目录执行:
bash examples/sft/run_vlm_sft.sh
说明:
不传参数时,脚本默认
qwen2_5_sft_vlm如果你文件名不同,比如
my_vlm_config.yaml,就传参数:
bash examples/sft/run_vlm_sft.sh my_vlm_config
怎么看训练是否正常#
终端日志里看 loss 是否下降
查看脚本输出的日志目录(脚本会自动创建
logs/时间戳)用 TensorBoard 可视化:
tensorboard --logdir /path/to/RLinf/logs --port 6006
浏览器打开:http://localhost:6006
评估模型#
如果你只想跑 evaluate,把配置改成:
data.train_data_paths: nulldata.val_data_paths: "/path/to/validate_data"
其余启动命令不变,仍用:
bash examples/sft/run_vlm_sft.sh <配置名>
实验结果: RLinf 展示当前使用 Qwen2.5-VL-3B 模型的实验结果,当前实验在单台 8 x H100 Nvidia GPU 的机器上测试 6000 次迭代,实验结果如下:
6000 次迭代, 每 1000 iter 对 test_data 的评估结果:
grad_norm 曲线:
loss 曲线:
最后一次 Qwen2.5-VL-3B model 使用测试数据验证的正确率为 0.8995802998542786 (约 89.96%)。
RLinf 展示当前使用 Qwen3-VL-4B 模型的实验结果,当前实验在单台 4 x H100 Nvidia GPU 的机器上测试 6000 次迭代,实验结果如下:
6000 次迭代, 每 1000 iter 对 test_data 的评估结果:
grad_norm 曲线:
loss 曲线:
最后一次 Qwen3-VL-4B model 使用测试数据验证的正确率为 96.9% 。
RLinf 展示当前使用 Qwen3-VL-30B-A3B MoE 模型的实验结果,当前实验在两台 8 x A100 Nvidia GPU 的机器上测试 1000 次迭代,实验结果如下:
grad_norm 曲线:
loss 曲线:
评估在单台8 x A100 Nvidia GPU 的机器上,训练前使用测试数据验证的正确率为 58.4%, 训练后使用测试数据验证的正确率为 91.3%。
模型 checkpoint 说明#
当前 SFT 使用 FSDP 训练后保存的是 FSDP 权重(例如 full_weights.pt)。
如果需要转成 HuggingFace 权重,建议使用仓库内置脚本:
脚本:
toolkits/ckpt_convertor/fsdp_convertor/convert_pt_to_hf.sh配置:
toolkits/ckpt_convertor/fsdp_convertor/config/fsdp_model_convertor.yaml
先修改配置中的以下字段:
convertor.ckpt_path:指向full_weights.ptconvertor.save_path:输出 HF 权重目录model.model_path:原始基座模型路径model.model_type:对应模型类型(如qwen2.5_vl,qwen3_vl或qwen3_vl_moe)
运行命令:
bash toolkits/ckpt_convertor/fsdp_convertor/convert_pt_to_hf.sh
字段解释#
micro_batch_size:单卡一次前向/反向的样本数global_batch_size:全局 batch(需满足可整除关系)max_epochs:按数据集完整遍历的轮数save_interval:每多少 step 存一次 checkpointmodel_path:本地模型目录(必须存在)train_data_paths/val_data_paths:数据目录或文件路径
最常见报错与排查#
找不到模型路径 - 检查
actor.model.model_path是否正确、是否有读取权限数据字段不匹配 - 检查
prompt_key/choice_key/answer_key/image_keys是否和数据实际列名一致显存不足(OOM) - 先把
micro_batch_size降低 - 再减少num_workers- 必要时缩小模型或降低输入长度只想先跑通流程 - 用很小的数据子集 -
max_epochs设为 1 -save_interval设小一点方便观察