支持 LoRA 的 RL(HF) 算法

最后更新:06/05/2025。

我们支持在强化学习算法(如 PPO、GRPO 等)中使用 LoRA(Low-Rank Adaptation,低秩适应)。

LoRA 是一种参数效率高的微调技术,它通过将可训练的低秩矩阵注入预训练权重(通常是线性层)来实现。这可以减少内存占用和计算成本,使得在有限硬件上微调大型模型变成可能。

带来的好处包括:

  • 在有限硬件上(如 8x80G GPU)进行超大规模模型(如 70B+)的强化学习,

  • 由于内存使用减少,能够启用更大的批次大小,

  • 简化模型迁移和部署,因为只需要保存 LoRA 适配器,

  • 可与 SLoRACCoE 等技术结合,高效服务多个 LoRA 适配器

本指南介绍如何在 RL 训练中启用 LoRA 并配置相关参数。

用法指南

  1. LoRA 可在 verl.trainer.ppo.ray_trainer.RayPPOTrainer 中使用。示例通过 verl.trainer.main_ppo 入口点提供。

  2. 目前,LoRA 仅通过 huggingface peft 支持,仅限 fsdp/fsdp2 和 vllm 后端(sglang 支持即将推出)。

  • strategy=fsdpstrategy=fsdp2

  • rollout.name=vllm

  1. LoRA 的必需配置:

  • actor_rollout_ref.model.lora_rank:整型,设置为大于 0 的合理值(如:8、16、32、64)

  • actor_rollout_ref.model.lora_alpha:浮点型,LoRA 中的 alpha 项

  • actor_rollout_ref.rollout.load_format=”safetensors”:必需。这使 vLLM 能够加载基础模型。

  • actor_rollout_ref.model.target_modules:LoRA 的目标模块。通常设置为 “all-linear”。

  1. LoRA 的可选配置:

  • actor_rollout_ref.model.lora_adapter_path:字符串,指向预训练 LoRA 适配器目录的路径。

    如果提供,则加载现有适配器而不是创建新的。支持从之前保存的适配器进行多阶段训练。 目录需要包含 adapter_model.safetensorsadapter_config.json

  1. 推荐选项:

  • actor_rollout_ref.model.use_shm=True:将模型预加载到 /dev/shm 以提升模型加载速度。

  • actor_rollout_ref.rollout.layered_summon=True:这使得 actor-model 在同步 LoRA 适配器到 vLLM 时,能够按层收集 FSDP 分片,从而降低 GPU 峰值内存。如果模型非常大(70B+)或 GPU 内存有限(< 48GB),推荐使用。

最佳实践和注意事项

  1. 学习率:建议将学习率的值提高一个数量级。

  2. LoRA Rank 秩

  • 秩设置过小可能会影响收敛。

  • LoRA 秩推荐来自 @thelongestusernameofall:

    • 很小的 lora_rank 可能会导致收敛变慢或训练性能变差。建议设置 lora_rank >=32。测试显示,对于 0.5B 模型,使用 lora_rank=32 时,训练收敛速度和最终性能几乎与非 LoRA 训练相同。

    • 对于 32B 模型,使用 lora_rank=128 时,训练收敛速度和最终性能也几乎与非 LoRA 训练相同。

    • 更多全面的参考结果即将到来。

https://github.com/eric-haibin-lin/verl-community/blob/f2b80b8b26829124dd393b7a795a0640eff11644/docs/lora.jpg?raw=true
  1. 使用 8 x 80GB GPU 对 Qwen2.5-72B 模型进行 RL 训练的参考配置(如果需要,可增加 lora_rank):

data.train_batch_size=64 \
actor_rollout_ref.model.use_shm=True \
actor_rollout_ref.model.lora_rank=32 \
actor_rollout_ref.model.lora_alpha=32 \
actor_rollout_ref.model.target_modules=all-linear \
actor_rollout_ref.actor.optim.lr=3e-5 \
actor_rollout_ref.actor.fsdp_config.fsdp_size=8 \
actor_rollout_ref.actor.fsdp_config.param_offload=True \
actor_rollout_ref.actor.fsdp_config.optimizer_offload=True \
actor_rollout_ref.rollout.tensor_model_parallel_size=8 \
actor_rollout_ref.rollout.name=vllm \
actor_rollout_ref.rollout.gpu_memory_utilization=0.4 \
actor_rollout_ref.rollout.n=5 \
actor_rollout_ref.rollout.max_num_seqs=64 \
actor_rollout_ref.rollout.max_model_len=1536 \
actor_rollout_ref.rollout.max_num_batched_tokens=1536 \
actor_rollout_ref.rollout.load_format=safetensors \
actor_rollout_ref.rollout.layered_summon=True \
actor_rollout_ref.ref.fsdp_config.param_offload=True \
actor_rollout_ref.actor.ulysses_sequence_parallel_size=1 \

示例脚本

完整示例,请参考以下脚本:

  • 从零开始的 LoRA 训练:examples/grpo_trainer/run_qwen2_5-3b_gsm8k_grpo_lora.sh

  • 从适配器路径开始的 LoRA 训练:examples/grpo_trainer/run_qwen2_5-3b_gsm8k_grpo_lora_from_adapter.sh