强化学习中参数的设置

一个GRPO的例子

🚀 分布式训练参数 (torchrun)

bash 复制代码
--nproc_per_node="4"        # 每个节点使用4个GPU
--nnodes="1"                # 使用1个计算节点
--node_rank="0"             # 当前节点的编号(单节点时为0)
--master_addr="127.0.0.1"   # 主节点的IP地址(本地训练)
--master_port="12362"       # 主节点通信端口

📁 路径和配置

bash 复制代码
--deepspeed                 # DeepSpeed配置文件(ZeRO-3优化,显存优化)
--output_dir                # 模型检查点和日志的输出目录
--model_name_or_path        # 预训练模型或checkpoint的路径
--train_data_path           # 训练数据JSON文件
--eval_data_path            # 验证数据JSON文件
--video_folder              # 视频文件存放目录
--dataset_name charades     # 数据集名称(Charades视频理解数据集)

🎯 GRPO核心参数

bash 复制代码
--max_prompt_length 8192       # 输入提示的最大token长度
--max_completion_length 1024   # 模型生成回复的最大token长度
--num_generations 8            # 每个提示生成8个候选回复
                               # GRPO会从这些候选中学习相对优劣

GRPO原理:通过生成多个候选答案,基于奖励函数对它们进行排序,学习相对优势而非绝对分数,这样更稳定。

⚙️ 训练超参数

bash 复制代码
--per_device_train_batch_size 4  # 每个GPU的batch size
--gradient_accumulation_steps 2   # 梯度累积步数
# 实际batch size = 4 GPU × 4 × 2 = 32

--num_train_epochs 1             # 训练轮数
--logging_steps 1                # 每1步记录一次日志
--save_steps 100                 # 每100步保存一次checkpoint
--save_total_limit 3             # 最多保留3个checkpoint

💾 内存和精度优化

bash 复制代码
--bf16                          # 使用bfloat16混合精度训练
--torch_dtype bfloat16          # 模型权重使用bfloat16格式
--gradient_checkpointing True   # 开启梯度检查点(节省显存,略降速度)

优势:bf16比fp16数值范围更大,训练更稳定;梯度检查点可大幅减少显存占用。

🔧 其他设置

bash 复制代码
--data_seed 42              # 数据随机种子(确保可复现)
--report_to tensorboard     # 使用TensorBoard记录训练过程
--run_name qwen2vl-baseline # 实验运行名称

更加详细的参数设置例子

VERL GRPO训练参数详解

📊 完整参数表格

参数类别 参数名 值 含义说明
🔧 算法配置
algorithm.adv_estimator grpo 优势估计器类型:GRPO(组相对策略优化)
algorithm.use_kl_in_reward False 是否在奖励函数中加入KL散度惩罚
📁 数据配置
data.train_files ~/data/geo3k/train.parquet 训练数据文件路径(Parquet格式)
data.val_files ~/data/geo3k/test.parquet 验证数据文件路径
data.train_batch_size 512 训练批次大小(rollout阶段生成的样本数)
data.max_prompt_length 1024 输入提示的最大token长度
data.max_response_length 2048 模型生成回复的最大token长度
data.filter_overlong_prompts True 是否过滤超长提示(超过max_prompt_length)
data.truncation error 截断策略:遇到超长序列直接报错
data.image_key images 数据中图像字段的键名(VLM需要)
🤖 模型配置
actor_rollout_ref.model.path /path/to/Qwen2.5-VL-7B-Instruct 预训练模型路径
actor_rollout_ref.model.use_remove_padding True 移除padding提高效率(适用于变长序列)
actor_rollout_ref.model.lora_rank 64 LoRA秩(低秩适配矩阵的维度)
actor_rollout_ref.model.lora_alpha 32 LoRA缩放系数(实际学习率 = lr × alpha/rank)
actor_rollout_ref.model.target_modules all-linear LoRA应用的模块:所有线性层
actor_rollout_ref.model.exclude_modules '.*visual.*' 排除视觉编码器,仅训练语言部分
actor_rollout_ref.model.enable_gradient_checkpointing True 启用梯度检查点节省显存
🎯 Actor训练配置
actor_rollout_ref.actor.optim.lr 3e-6 学习率(0.000003)
actor_rollout_ref.actor.ppo_mini_batch_size 128 PPO更新时的小批次大小
actor_rollout_ref.actor.ppo_micro_batch_size_per_gpu 10 每个GPU的微批次大小(实际前向传播单位)
actor_rollout_ref.actor.use_kl_loss True 在Actor损失中加入KL散度损失
actor_rollout_ref.actor.kl_loss_coef 0.01 KL损失系数(防止策略偏离参考模型太远)
actor_rollout_ref.actor.kl_loss_type low_var_kl KL散度计算方式:低方差估计
actor_rollout_ref.actor.entropy_coeff 0 熵正则化系数(0表示不鼓励探索)
actor_rollout_ref.actor.fsdp_config.param_offload False FSDP参数卸载到CPU(False=全在GPU)
actor_rollout_ref.actor.fsdp_config.optimizer_offload False FSDP优化器状态卸载到CPU
🎲 Rollout配置
actor_rollout_ref.rollout.log_prob_micro_batch_size_per_gpu 20 计算log概率时的微批次大小
actor_rollout_ref.rollout.tensor_model_parallel_size 2 张量模型并行度(模型切分到2个GPU)
actor_rollout_ref.rollout.name vllm 推理引擎:vLLM(高性能推理)
+actor_rollout_ref.rollout.engine_kwargs.vllm.disable_mm_preprocessor_cache True 禁用多模态预处理缓存
actor_rollout_ref.rollout.gpu_memory_utilization 0.6 GPU显存利用率(为其他组件预留40%)
actor_rollout_ref.rollout.enable_chunked_prefill False 禁用分块预填充(可能影响长序列性能)
actor_rollout_ref.rollout.enforce_eager False 不强制eager模式(允许CUDA图优化)
actor_rollout_ref.rollout.free_cache_engine False 不在rollout后释放缓存引擎
actor_rollout_ref.rollout.n 5 每个提示生成5个候选回复(GRPO核心)
🔄 Reference模型配置
actor_rollout_ref.ref.log_prob_micro_batch_size_per_gpu 20 参考模型计算log概率的微批次大小
actor_rollout_ref.ref.fsdp_config.param_offload True 参考模型参数卸载到CPU节省显存
📈 Trainer配置
trainer.critic_warmup 0 Critic预热步数(GRPO不使用Critic)
trainer.logger ["console","wandb"] 日志记录器:控制台+Weights & Biases
trainer.project_name verl_grpo_example_geo3k WandB项目名称
trainer.experiment_name qwen2_5_vl_7b_function_rm 实验名称
trainer.n_gpus_per_node 4 每个节点使用4个GPU
trainer.nnodes 1 使用1个计算节点
trainer.save_freq 20 每20次迭代保存一次checkpoint
trainer.test_freq 5 每5次迭代进行一次验证
trainer.total_epochs 15 总训练轮数

🔑 关键概念解析

1️⃣ 批次大小关系

复制代码
总样本数 = data.train_batch_size (512)
         ↓ (每个提示生成n个候选)
生成候选数 = 512 × 5 = 2560个回复
         ↓ (分批更新策略)
Mini batch = ppo_mini_batch_size (128)
         ↓ (每GPU实际处理)
Micro batch/GPU = ppo_micro_batch_size_per_gpu (10)

实际训练:

  • 每次迭代从512个提示生成2560个候选
  • 策略更新时分为 2560/128 = 20 个mini-batch
  • 每个GPU每次处理10个样本

2️⃣ GRPO vs PPO

特性 GRPO PPO
优势计算 相对排序(组内比较) 绝对值估计(需Critic)
是否需要Critic ❌ 不需要 ✅ 需要
采样效率 高(每提示生成多个) 低(每提示1个)
稳定性 高(相对比较更稳定) 中等

3️⃣ LoRA参数高效训练

python 复制代码
实际更新参数量 = lora_rank × lora_alpha / total_params
              = 64 × 32 / 7B ≈ 0.03%

仅训练0.03%的参数,大幅降低显存和计算需求。

4️⃣ KL散度控制

  • use_kl_loss=True :在Actor损失中加入KL项
    • 防止新策略偏离参考模型太远
    • 系数0.01意味着1%的权重用于KL约束
  • use_kl_in_reward=False :不在奖励函数中加KL
    • 两种方式任选其一即可

5️⃣ 显存优化策略

技术 参数 节省显存 速度影响
Gradient Checkpointing enable_gradient_checkpointing=True ⭐⭐⭐⭐ 🐌 慢15-20%
LoRA lora_rank=64 ⭐⭐⭐⭐⭐ ✅ 几乎无
Reference卸载 ref.fsdp_config.param_offload=True ⭐⭐⭐ 🐌 慢10%
张量并行 tensor_model_parallel_size=2 ⭐⭐ ✅ 几乎无

  1. 显存不足时调整优先级:

    bash 复制代码
    降低 gpu_memory_utilization: 0.6 → 0.5
    增加 tensor_model_parallel_size: 2 → 4
    开启 param_offload: False → True
  2. 加速训练:

    bash 复制代码
    减少候选数 n: 5 → 3
    增大 micro_batch_size: 10 → 16
    关闭梯度检查点(如显存够用)
  3. 提高采样多样性:

    bash 复制代码
    增加 entropy_coeff: 0 → 0.01
    增加候选数 n: 5 → 8

要注意的一些参数

1.设置 actor_rollout_ref.model.enable_gradient_checkpointing=True是一项关键的显存优化技术。它通过以计算时间换取显存空间的方式。

2.--per_device_train_batch_size 4 # 每个GPU的batch size

--gradient_accumulation_steps 2 # 梯度累积步数

实际batch size = 4 GPU × 4 × 2 = 32

3.Mini Batch Size和Micro Batch Size per GPU

📋 配置说明

python 复制代码
总样本数: 2560 个
Mini Batch Size: 128
Micro Batch Size per GPU: 10
GPU数量: 4

🚀 完整训练流程(第1个Mini Batch)

第1步:分配样本到4个GPU

复制代码
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Mini Batch 1: 从2560个样本中取出前128个
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

分配给4个GPU:

GPU-0: 样本1-32   (32个样本)
GPU-1: 样本33-64  (32个样本)
GPU-2: 样本65-96  (32个样本)
GPU-3: 样本97-128 (32个样本)

每个GPU分到:128 ÷ 4 = 32个样本

第2步:每个GPU分批处理(Micro Batch)

❗ 关键:因为显存限制,每个GPU无法一次处理32个样本

GPU-0 的详细处理过程:
python 复制代码
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
GPU-0 处理它的32个样本(分4次Micro Batch)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

🔸 Micro Batch 1(样本1-10)
───────────────────────────────────────────────
样本1:  "1+1=?" → "等于2"        | loss₁ = 0.5
样本2:  "1+1=?" → "等于2,因为..." | loss₂ = 0.3
样本3:  "1+1=?" → "等于3"        | loss₃ = 2.1
样本4:  "2×3=?" → "等于6"        | loss₄ = 0.4
样本5:  "2×3=?" → "是6"          | loss₅ = 0.6
样本6:  "2×3=?" → "等于5"        | loss₆ = 1.8
样本7:  "x²=16?" → "x=4"         | loss₇ = 1.2
样本8:  "x²=16?" → "x=±4"        | loss₈ = 0.2
样本9:  "5+3=?" → "等于8"        | loss₉ = 0.5
样本10: "5+3=?" → "8"            | loss₁₀ = 0.7

① 前向传播:计算10个样本的输出
② 计算loss:loss_micro1 = (0.5+0.3+2.1+...+0.7)/10 = 0.83
③ 反向传播:计算梯度 → grad_micro1
④ ⚠️ 不更新参数!只是把梯度存起来

───────────────────────────────────────────────

🔸 Micro Batch 2(样本11-20)
───────────────────────────────────────────────
样本11: "10-5=?" → "等于5"       | loss₁₁ = 0.4
样本12: "10-5=?" → "5"           | loss₁₂ = 0.6
...
样本20: "7×2=?" → "14"           | loss₂₀ = 0.8

① 前向传播:计算10个样本的输出
② 计算loss:loss_micro2 = 0.71
③ 反向传播:计算梯度 → grad_micro2
④ ⚠️ 不更新参数!继续累积梯度

───────────────────────────────────────────────

🔸 Micro Batch 3(样本21-30)
───────────────────────────────────────────────
① 前向传播 → ② 计算loss:loss_micro3 = 0.65
③ 反向传播 → grad_micro3
④ ⚠️ 不更新参数!继续累积梯度

───────────────────────────────────────────────

🔸 Micro Batch 4(样本31-32,只有2个)
───────────────────────────────────────────────
样本31: "9+1=?" → "等于10"       | loss₃₁ = 0.3
样本32: "9+1=?" → "10"           | loss₃₂ = 0.5

① 前向传播 → ② 计算loss:loss_micro4 = (0.3+0.5)/2 = 0.4
③ 反向传播 → grad_micro4
④ ⚠️ 不更新参数!梯度累积完成

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
GPU-0 完成!现在有4个梯度:
grad_micro1, grad_micro2, grad_micro3, grad_micro4

GPU-0的总梯度 = (grad_micro1 + grad_micro2 + grad_micro3 + grad_micro4) / 4

GPU-0的平均loss = (0.83 + 0.71 + 0.65 + 0.4) / 4 = 0.647
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
其他3个GPU同时进行:
python 复制代码
GPU-1 处理样本33-64:
  → Micro Batch 1: 样本33-42  → loss=0.55, grad累积
  → Micro Batch 2: 样本43-52  → loss=0.68, grad累积
  → Micro Batch 3: 样本53-62  → loss=0.72, grad累积
  → Micro Batch 4: 样本63-64  → loss=0.45, grad累积
  → GPU-1总梯度 = 累积平均
  → GPU-1平均loss = 0.600

GPU-2 处理样本65-96:
  → ... (同样的过程)
  → GPU-2平均loss = 0.710

GPU-3 处理样本97-128:
  → ... (同样的过程)
  → GPU-3平均loss = 0.620

第3步:4个GPU同步,更新参数 ✅

python 复制代码
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
所有GPU完成Micro Batch处理后
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

① 计算Mini Batch的总loss:
   Mini_Batch_Loss = (GPU-0_loss + GPU-1_loss + GPU-2_loss + GPU-3_loss) / 4
                   = (0.647 + 0.600 + 0.710 + 0.620) / 4
                   = 0.644

② 聚合4个GPU的梯度:
   Final_Gradient = (GPU-0_grad + GPU-1_grad + GPU-2_grad + GPU-3_grad) / 4

③ 🎯 更新模型参数:
   θ_new = θ_old - learning_rate × Final_Gradient

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ 第1次参数更新完成!
   使用了128个样本(Mini Batch 1)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

第4步:继续处理剩余的Mini Batch

python 复制代码
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Mini Batch 2: 样本129-256
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
分配到4个GPU → 每个GPU分批处理 → 聚合梯度 → 更新参数 ✅
→ 第2次参数更新

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Mini Batch 3: 样本257-384
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
... → 第3次参数更新 ✅

... (总共20个Mini Batch)

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Mini Batch 20: 样本2433-2560
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
... → 第20次参数更新 ✅

🎉 所有2560个样本训练完成!
   总共进行了20次参数更新

📊 时间轴可视化

复制代码
时间 ────────────────────────────────────────────────────────►

Mini Batch 1 (样本1-128)
├─ GPU-0: [Micro1] [Micro2] [Micro3] [Micro4] ─┐
├─ GPU-1: [Micro1] [Micro2] [Micro3] [Micro4] ─┤
├─ GPU-2: [Micro1] [Micro2] [Micro3] [Micro4] ─┤ → 聚合 → ✅更新参数
└─ GPU-3: [Micro1] [Micro2] [Micro3] [Micro4] ─┘

Mini Batch 2 (样本129-256)
├─ GPU-0: [Micro1] [Micro2] [Micro3] [Micro4] ─┐
├─ GPU-1: [Micro1] [Micro2] [Micro3] [Micro4] ─┤
├─ GPU-2: [Micro1] [Micro2] [Micro3] [Micro4] ─┤ → 聚合 → ✅更新参数
└─ GPU-3: [Micro1] [Micro2] [Micro3] [Micro4] ─┘

...

Mini Batch 20 (样本2433-2560)
├─ GPU-0: [Micro1] [Micro2] [Micro3] [Micro4] ─┐
├─ GPU-1: [Micro1] [Micro2] [Micro3] [Micro4] ─┤
├─ GPU-2: [Micro1] [Micro2] [Micro3] [Micro4] ─┤ → 聚合 → ✅更新参数
└─ GPU-3: [Micro1] [Micro2] [Micro3] [Micro4] ─┘

🎯 核心问题回答

❓ 模型什么时候更新参数?

答:每处理完1个Mini Batch后更新1次

具体条件:

  1. ✅ 所有GPU都完成了它们的Micro Batch处理
  2. ✅ 梯度已经在4个GPU之间同步求平均
  3. ✅ 然后才更新参数

频率:

  • 你的配置:2560个样本 ÷ 128(Mini Batch)= 20次参数更新

❓ Loss是如何计算的?

第1层:Micro Batch Loss(单GPU内部)
python 复制代码
# GPU-0的第1个Micro Batch(10个样本)
loss_micro1 = (loss₁ + loss₂ + ... + loss₁₀) / 10
第2层:GPU Total Loss(单GPU所有Micro Batch的平均)
python 复制代码
# GPU-0处理了4个Micro Batch
loss_GPU0 = (loss_micro1 + loss_micro2 + loss_micro3 + loss_micro4) / 4
第3层:Mini Batch Loss(所有GPU的平均)
python 复制代码
# 4个GPU的loss求平均
loss_MiniBatch = (loss_GPU0 + loss_GPU1 + loss_GPU2 + loss_GPU3) / 4

这个最终的loss就是你在训练日志中看到的loss!


💡 关键理解

概念 作用 更新参数?
Micro Batch 因为显存限制,GPU分批前向传播 ❌ 不更新,只累积梯度
Mini Batch 决定多少样本做一次参数更新 ✅ 更新参数!

记忆方法:

  • Micro = 小步走(显存不够,慢慢算,梯度先存着)
  • Mini = 检查点(走完一段路,更新一次方向)

📈 训练日志示例

bash 复制代码
[Step 1] Mini Batch 1/20: Loss=0.644 (128 samples) → ✅参数更新
  ├─ GPU-0: loss=0.647 (32 samples, 4 micro batches)
  ├─ GPU-1: loss=0.600 (32 samples, 4 micro batches)
  ├─ GPU-2: loss=0.710 (32 samples, 4 micro batches)
  └─ GPU-3: loss=0.620 (32 samples, 4 micro batches)

[Step 2] Mini Batch 2/20: Loss=0.612 (128 samples) → ✅参数更新
  ├─ GPU-0: loss=0.605 (32 samples, 4 micro batches)
  ├─ GPU-1: loss=0.590 (32 samples, 4 micro batches)
  ├─ GPU-2: loss=0.638 (32 samples, 4 micro batches)
  └─ GPU-3: loss=0.615 (32 samples, 4 micro batches)

...

[Step 20] Mini Batch 20/20: Loss=0.421 (128 samples) → ✅参数更新

✅ Epoch 1 完成!总共更新了20次参数

🔑 总结

python 复制代码
# 一句话总结:
每个Mini Batch = 一次参数更新
每个Micro Batch = 显存不够时的分批计算(不更新参数)

# 你的配置:
2560个样本 → 20个Mini Batch → 20次参数更新
每个Mini Batch包含 4个GPU × 4个Micro Batch = 16次前向传播

# 参数更新时机:
只有当1个Mini Batch的所有Micro Batch都处理完,
并且4个GPU的梯度都聚合完成后,才会更新参数!
相关推荐
sell-cloud8 分钟前
Prompt Engineering要凉了?Fable 5.5能“猜“意图,但银行正在封杀AI Agent——企业AI的真正护城河是什么
人工智能·prompt
Navicat中国2 小时前
Navicat 18 内置 AI 助手让数据库开发从繁琐操作迈向智能协作
大数据·人工智能·数据库开发
4SAPI2 小时前
多模型请求路由怎么设计?成本、速度和能力如何平衡
人工智能·python·gateway·php
魔乐社区2 小时前
翼芯・智算测试与适配优化专区,让国产算力“选得准、跑得通、用得好“
人工智能·开源·大模型
XCDoris4 小时前
郴州logo设计机构
大数据·人工智能·python
Goboy4 小时前
一个人带三个Agent,我用全新TRAE从0到1搭了个资讯周刊站
人工智能·trae
俊哥V4 小时前
每日 AI 研究简报 · 2026-10-19
人工智能·ai
AI_AGENT_DEV_AI4 小时前
AI英语教培智能体的开发
人工智能
物联网软硬件开发-轨物科技5 小时前
【技术白皮书】光伏清检一体化机器人系统解决方案技术白皮书
大数据·运维·网络·人工智能·机器人
海宇数据5 小时前
零信任架构实战:基于海宇网上踪迹欺诈行为识别构建自动化信贷资信评估网关
运维·人工智能·架构·自动化