verl 多模态 RL 训练实战指南:基于 Geo3K 的 GRPO 图像推理训练全流程
2026/9/13 16:34:03 网站建设 项目流程

verl 多模态 RL 训练实战指南:基于 Geo3K 的 GRPO 图像推理训练全流程

【免费下载链接】verlverl/HybridFlow: A Flexible and Efficient RL Post-Training Framework项目地址: https://gitcode.com/GitHub_Trending/ve/verl

verl(HybridFlow)现已原生支持多模态强化学习训练,可对视觉语言模型(VLM)执行 GRPO/PPO 等后训练任务。本文以 Geo3K 几何推理数据集 + Qwen2.5-VL-7B-Instruct 为例,完整讲解从数据集预处理、模型下载到 FSDP × vLLM/SGLang 多模态 GRPO 训练的三个核心步骤,并结合仓库源码与脚本深入拆解多模态数据格式、关键训练参数及其底层实现,帮助读者在 NVIDIA GPU 与 Ascend NPU 上快速复现多模态 RL 流水线。

多模态 RL 支持现状

根据 multi_modal_example.rst 的说明,verl 已支持多模态训练,目前可通过FSDP(actor 训练后端)+ vLLM/SGLang(rollout 推理后端)的组合启动多模态 RL 任务,Megatron 支持也已进入实现阶段。这意味着图像、视频等视觉输入可以与文本一起参与 RL 后训练——模型不仅要在<think>推理过程中给出逐步推理,还要把最终答案放入\boxed{}中,由规则奖励函数进行评判。

仓库中与多模态训练直接相关的配套资源包括:

用途文件
数据集预处理geo3k.py、openr1mm.py、tinyllava_video_r1.py
FSDP 训练脚本run_qwen2_5_vl_7b_fsdp.sh、run_qwen3_vl_8b_fsdp.sh
Megatron 训练脚本run_qwen2_5_vl_7b_megatron.sh
多模态数据加载rl_dataset.py(image_key/video_key与视觉信息处理)
训练入口main_ppo.py

快速开始:三步启动多模态 GRPO 训练

Step 1:准备数据集(Geo3K 预处理)

运行仓库提供的预处理脚本,将 Hugging Face 上的hiyouga/geometry3k数据集转换为 verl 标准 parquet 格式:

# it will be saved in the $HOME/data/geo3k folder python examples/data_preprocess/geo3k.py

从源码看,该脚本的核心逻辑在 geo3k.py 中完成:

  • 数据源:默认从hiyouga/geometry3k加载 train/test 两个 split;若已存在本地原始数据,可通过--local_dataset_path直接指定本地路径加载,避免重复下载。
  • 指令注入:为每个问题拼接统一的推理指令模板——要求模型先以内部独白形式思考,推理过程必须放在<think> </think>标签内,最终答案必须放入\boxed{}中。
  • 字段重组:将原始problemanswerimages重组为 verl 的 RL 数据集 schema,其中prompt是包含 role/content 的对话结构,images存放原始图像字节,reward_model标注为 rule 风格、以ground_truth为评分依据。
  • 并行加速:使用num_proc=8并行执行 map,最终输出train.parquettest.parquet
  • 可选 HDFS 导出:传入--hdfs_dir时会将本地 parquet 拷贝到 HDFS,适合大规模多机训练场景(底层使用 hdfs_io.py 的copy/makedirs工具)。

注意脚本参数:--local_dir已废弃,推荐使用--local_save_dir(默认~/data/geo3k)。

Step 2:下载模型

通过 transformers 的 pipeline 触发模型下载,将 Qwen2.5-VL-7B-Instruct 拉取到本地缓存:

# download the model from huggingface python3 -c "import transformers; transformers.pipeline(model='Qwen/Qwen2.5-VL-7B-Instruct')"

之后即可在训练脚本中通过MODEL_PATH环境变量指向该模型(默认Qwen/Qwen2.5-VL-7B-Instruct,也支持替换为本地已下载的模型路径)。

Step 3:执行 GRPO 多模态训练

运行仓库自带的训练脚本,即会通过 Ray 拉起 actor(FSDP 训练)与 rollout(vLLM/SGLang 推理)等分布式角色,完成整个多模态 GRPO 训练流程:

# run the task bash examples/grpo_trainer/run_qwen2_5_vl_7b_fsdp.sh

该脚本兼容 NVIDIA GPU 与 Ascend NPU(DEVICE通过探测torch_npu自动识别),推理后端通过INFER_BACKEND环境变量在vllm | sglang | trtllm之间切换,默认vllm

训练脚本参数全解

run_qwen2_5_vl_7b_fsdp.sh 将全部配置组织为若干参数数组,最终以python3 -m verl.trainer.main_ppo的 Hydra 覆盖参数形式传入。以下按功能组拆解其默认值与含义:

数据组(DATA)

参数默认值说明
algorithm.adv_estimatorgrpo优势估计器,本示例使用 GRPO
algorithm.use_kl_in_rewardFalseKL 项不并入奖励,由 actor 侧use_kl_loss单独控制
data.train_files/data.val_files$HOME/data/geo3k/train.parquet/test.parquet训练/验证数据路径
data.image_keyimages多模态样本中图像字段的 key,与预处理脚本输出的列名对应
data.train_batch_size512每个训练 step 的样本数
data.max_prompt_length/data.max_response_length1024 / 2048prompt 与 response 的最大 token 长度
data.filter_overlong_promptsTrue过滤超长 prompt 样本
data.truncation'error'截断策略;设为error表示超出长度直接报错而非静默截断

模型组(MODEL)

  • actor_rollout_ref.model.path:模型路径(可被MODEL_PATH覆盖);
  • actor_rollout_ref.model.use_remove_padding=True:训练时去除 padding,与动态 batch 配合节省显存;
  • actor_rollout_ref.model.enable_gradient_checkpointing=True:开启梯度检查点,用计算换显存,对 7B 级 VLM 尤为关键。

Actor 训练组(ACTOR)

  • actor_rollout_ref.actor.strategy=fsdp2(EXTRA 组):使用 FSDP2 作为 actor 分布式策略;
  • actor_rollout_ref.actor.optim.lr=1e-6:学习率;
  • actor_rollout_ref.actor.ppo_mini_batch_size=128:PPO mini-batch 大小;
  • actor_rollout_ref.actor.use_dynamic_bsz=Trueppo_max_token_len_per_gpu=24576:按 token 而非样本数动态分配 batch,最大化显存利用率;
  • actor_rollout_ref.actor.use_kl_loss=Truekl_loss_coef=0.01kl_loss_type=low_var_kl:低方差 KL 惩罚,稳定策略更新;
  • actor_rollout_ref.actor.fsdp_config.param_offload=False/optimizer_offload=False:GPU 上不 offload 参数与优化器(NPU 场景会在 EXTRA 中开启 offload)。

Rollout 推理组(ROLLOUT)

  • actor_rollout_ref.rollout.name=${INFER_BACKEND}:推理后端(vllm/sglang/trtllm);
  • actor_rollout_ref.rollout.tensor_model_parallel_size=2:vLLM 的 TP 并行度;
  • actor_rollout_ref.rollout.gpu_memory_utilization=0.6:推理引擎可用的显存比例;
  • actor_rollout_ref.rollout.n=5:每个 prompt 采样的 rollout 条数(GRPO 依赖组内多条样本计算相对优势);
  • log_prob_use_dynamic_bsz=Truelog_prob_max_token_len_per_gpu:对 actor/ref 的 log-prob 计算同样启用动态 batch。

训练器组(TRAINER)

  • trainer.logger='["console","wandb"]':同时输出到控制台与 wandb;
  • trainer.project_name=verl_grpo_geo3ktrainer.experiment_name=qwen2_5_vl_7b_${INFER_BACKEND}_fsdp:实验命名;
  • trainer.n_gpus_per_node=8trainer.nnodes=1:单机 8 卡(NPU 场景自动调整为 16);
  • trainer.total_epochs=15save_freq=20test_freq=5:总轮数、checkpoint 保存频率与验证频率。

设备差异与启动方式

脚本针对 GPU/NPU 做了差异化配置:NPU 场景下会将mm_processor_cache_gb设为 0(不缓存视觉 processor,降低显存占用)、关闭 fused kernels 与多阶段唤醒、调低显存利用率至 0.5 并调整log_prob_micro_batch_size_per_gpu。启动时默认通过uv run --frozen --all-packages --extra <backend> --extra fsdp运行以匹配 uv.lock 中的依赖组合,若需使用系统 Python 可设置VERL_USE_UV=0

多模态数据格式与底层处理

图像数据(Geo3K / OpenR1-MM)

预处理脚本产出的样本包含data_sourcepromptimagesabilityreward_modelextra_info六个字段。其中prompt是标准对话结构:

"prompt": [ { "role": "user", "content": prompt, # 文本问题 + 推理指令 } ], "images": images, # 与图像占位符对应的图像字节 "reward_model": {"style": "rule", "ground_truth": answer},

openr1mm.py 展示了另一种图像数据处理细节:对lmms-lab/multimodal-open-r1-8k-verified,图像以原始字节 dict({"bytes": ...}形式保留在 parquet 中,不做解码、不做 resize——Qwen 视觉 processor 会在运行时按需缩放,既避免有损重编码,也让 RL 阶段的动态 batch 处理更高效。该脚本还会以seed=42做 90/10 的 train/test 切分并只保留 6 个目标列。

视频数据(TinyLLaVA-Video-R1)

tinyllava_video_r1.py 展示了 verl 对视频输入的支持方式:prompt 中使用<video>占位符,videos字段记录视频绝对路径,并附带采样参数:

video_entry = {"video": video_path} video_entry["fps"] = video_fps # 默认 1,视频采样帧率 video_entry["max_frames"] = video_max_frames # 默认 32,最大帧数

该脚本同时演示了完整的视频数据集准备流程(下载 → 解压 → 预处理),并在 map 过程中对缺失视频文件给出 WARN 提示。

数据集加载源码视角

多模态数据在训练时由 rl_dataset.py 中的RLHFDataset处理:

  • 字段名通过image_key(默认images)与video_key(默认videos)配置读取,与训练脚本中data.image_key=images一一对应;
  • 样本进入训练前调用_process_multi_modal_info统一抽取图像/视频/音频,并通过process_vision_info(内部在线程池中执行)交给视觉 processor 完成 tokenize 与张量化;
  • 在处理对话式多模态输入时,会依据<image>/<video>占位符与多模态内容的顺序对应关系维护image_offset/video_offset游标,确保每个占位符替换为正确的视觉 token,并在处理结束后断言所有视觉内容都被消费(image_offset == len(images)),防止占位符与资源错位;
  • 处理完成后从原始行中移除image_key/video_key列,避免视觉原始数据混入后续特征字典。

进阶扩展:Qwen3-VL 与 Megatron 后端

Qwen3-VL 基线(GPU/NPU 通用)

run_qwen3_vl_8b_fsdp.sh 是仓库中 Qwen3-VL-8B 在 Geo3K 上的标准基线脚本,其整体结构与此前脚本一致,差异点包括:

  • 模型默认Qwen/Qwen3-VL-8B-Instruct,实验名自动附加时间戳;
  • 训练/验证数据路径通过TRAIN_FILE/TEST_FILE单独可配;
  • NPU 分支额外导出HCCL_CONNECT_TIMEOUTHCCL_HOST_SOCKET_PORT_RANGE等集合通信环境变量,并设置RAY_EXPERIMENTAL_NOSET_ASCEND_RT_VISIBLE_DEVICES=1
  • NPU 场景可通过SP_SIZE配置 Ulysses 序列并行,GPU 场景则开启 fused kernels 与free_cache_engine(释放推理缓存引擎以降低显存碎片)。

Megatron 训练后端

run_qwen2_5_vl_7b_megatron.sh 展示了多模态 + Megatron 的组合:通过model_engine=megatron切换训练后端,并新增actor_rollout_ref.actor.megatron.*系列参数:

  • tensor_model_parallel_size=2pipeline_model_parallel_size=2:Megatron 的张量/流水线并行度;
  • use_mbridge=True:启用 Megatron 与推理引擎之间的通信桥(megatron bridge),负责 actor 权重与 rollout 后端之间的高效同步;
  • ref 策略模型配置同样的 TP/PP 与use_mbridge,保证 rollout 阶段的 log-prob 计算与 actor 并行方案一致。

该脚本要求启动时使用--extra vllm --extra megatron的依赖组合(uv.lock 中对应 extra)。

常见问题与调优提示

  • 显存不足:优先检查data.filter_overlong_promptsenable_gradient_checkpointinguse_remove_padding,并确认rollout.gpu_memory_utilization未超过实际空闲显存;NPU 场景建议跟随脚本默认值(0.5)并开启 actor/ref 的参数 offload。
  • 动态 batch 报错ppo_max_token_len_per_gpu需根据单卡显存与 VLM 视觉 token 开销调整,图像会使单条 prompt 的实际 token 数显著大于纯文本估计。
  • 视觉 token 对齐失败:若出现image_offset >= len(images)之类的断言错误,说明样本中<image>占位符数量与images列表长度不匹配,请检查预处理脚本中占位符与图像列的对应关系。
  • 多卡/多机扩展:设置trainer.nnodestrainer.n_gpus_per_node即可横向扩展;数据量大时可在预处理阶段通过--hdfs_dir将 parquet 上推到 HDFS 供所有节点读取。

小结

通过geo3k.py数据预处理、模型下载与run_qwen2_5_vl_7b_fsdp.sh训练脚本三个步骤,即可在 verl 中完成一次完整的视觉语言模型 GRPO 后训练。verl 的多模态支持统一了图像(images)与视频(videos)两类输入的处理路径,并以image_key/video_key字段解耦数据 schema 与训练逻辑;训练端既支持 FSDP2(GPU/NPU 通用),也支持 Megatron(TP/PP 并行),推理端可在 vLLM/SGLang/TRTLLM 间切换。对于想要深入多模态 RL 研究的开发者,上述源码与脚本是绝佳的起点。

【免费下载链接】verlverl/HybridFlow: A Flexible and Efficient RL Post-Training Framework项目地址: https://gitcode.com/GitHub_Trending/ve/verl

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询