强化学习中参数的设置

一个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的梯度都聚合完成后,才会更新参数!
相关推荐
Francek Chen17 小时前
【自然语言处理】应用06:针对序列级和词元级应用微调BERT
人工智能·pytorch·深度学习·自然语言处理·bert
RPA机器人就选八爪鱼17 小时前
RPA财务机器人选型攻略:5步搭建高性价比自动化体系
大数据·人工智能·机器人·自动化·rpa
予枫的编程笔记17 小时前
Elasticsearch深度搜索与查询DSL实战:精准定位数据的核心技法
java·大数据·人工智能·elasticsearch·搜索引擎·全文检索
小北方城市网17 小时前
第 6 课:云原生架构终极落地|K8s 全栈编排与高可用架构设计实战
大数据·人工智能·python·云原生·架构·kubernetes·geo
创作者mateo17 小时前
机器学习基本概念简介(全)
人工智能·机器学习
飞睿科技17 小时前
乐鑫ESP32-S3-BOX-3,面向AIoT与边缘智能的新一代开发套件
人工智能·嵌入式硬件·esp32·智能家居·乐鑫科技
Rabbit_QL17 小时前
【数学基础】机器学习中的抽样:你的数据是样本,不是世界
人工智能·机器学习
金融RPA机器人丨实在智能17 小时前
深度拆解 RPA 机器人:定义、应用、价值与未来方向
人工智能·rpa·实在rpa
青主创享阁17 小时前
技术破局农业利润困局:玄晶引擎AI数字化解决方案的架构设计与落地实践
大数据·人工智能