👁️‍🗨️视觉强化学习(VLM RL)

通过 Unsloth 使用 GRPO 和 RL 训练视觉/多模态模型!

Unsloth 现在支持带有视觉/多模态强化学习的 Qwen3-VL, Gemma 3 以及更多。由于 Unsloth 独特的 权重共享 和自定义内核,Unsloth 使得 VLM 强化学习 快 1.5–2×, 使用 90% 更少的显存,并且启用 比 FA2 配置长 15× 的上下文 长度,而不会损失准确性。此更新还引入了 Qwen 的 GSPO 算法。

Unsloth 可以在免费 Colab T4 GPU 上使用 GSPO/GRPO 训练 Qwen3-VL-8B。其他 VLM 也可行,但可能需要更大的 GPU。Gemma 需要比 T4 更新的 GPU,因为 vLLM 限制为 Bfloat16,因此我们建议在 Colab 上使用 NVIDIA L4。我们的笔记本解决涉及图像和图示的数值数学问题:

我们还将 vLLM VLM 原生集成到 Unsloth 中,因此使用 vLLM 推理时你只需在初始化模型时启用 fast_inference=True 标志即可。特别感谢 Sinoué GADarrow-up-right 提供了 第一个笔记本arrow-up-right 使得集成 VLM 强化学习更容易!

此 VLM 支持还整合了我们最新的更新,以实现更节省内存且更快的强化学习,包括我们的 待机功能,它在限制速度退化方面与其他实现相比具有独特优势。

circle-info

你只能对 fast_inference 为 vLLM 支持的 VLM 使用。有些模型,例如 Llama 3.2 Vision,因此只能在不使用 vLLM 的情况下运行,但它们仍然可以在 Unsloth 中工作。

os.environ['UNSLOTH_VLLM_STANDBY'] = '1' # 启用与 vLLM 一起的节省内存的 GRPO
model, tokenizer = FastVisionModel.from_pretrained(
    model_name = "Qwen/Qwen2.5-VL-7B-Instruct",
    max_seq_length = 16384, # 必须这么大以将图像放入上下文
    load_in_4bit = True, # LoRA 16 位时为 False
    fast_inference = True, # 启用 vLLM 快速推理
    gpu_memory_utilization = 0.8, # 内存不足时降低该值
)

同样重要的是要注意,vLLM 不支持视觉/编码器层的 LoRA,因此在加载 LoRA 适配器时将 finetune_vision_layers = False 设置为 False。 但是如果你通过 transformers/Unsloth 使用推理,你也可以训练视觉层。

# 将 LoRA 适配器添加到模型以进行参数高效的微调
model = FastVisionModel.get_peft_model(
    model,

    finetune_vision_layers     = False,# fast_inference 目前还不支持 finetune_vision_layers :(
    finetune_language_layers   = True, # 如果不微调语言层则为 False
    finetune_attention_modules = True, # 如果不微调注意力层则为 False
    finetune_mlp_modules       = True, # 如果不微调 MLP 层则为 False

    r = lora_rank, # 选择任意大于 0 的数!建议 8、16、32、64、128
    lora_alpha = lora_rank*2, # *2 可加速训练
    use_gradient_checkpointing = "unsloth", # 降低内存使用
    random_state = 3407,
)

🦋Qwen 2.5 VL 视觉强化学习的问题与怪异行为

在 Qwen 2.5 VL 的强化学习过程中,你可能会看到以下推理输出:

这被 报告arrow-up-right 在 Qwen2.5-VL-7B-Instruct 输出意外结果 “addCriterion” 中也有提及。事实上我们也看到了这个!我们尝试了非 Unsloth、bfloat16 和 float16 的机器以及其他方法,但它似乎仍然存在。例如第 165 项 即 train_dataset[165] 来自 AI4Math/MathVistaarrow-up-right 数据集如下:

然后我们得到上面的乱码输出。可以添加一个奖励函数以惩罚出现 addCriterion 的行为,或惩罚乱码输出。然而,另一种方法是让模型训练更长时间。例如大约在 60 步之后我们才看到模型通过强化学习实际学到东西:

circle-check

🏅用于减少乱码的奖励函数

为了惩罚 addCriterion 和乱码输出,我们修改了奖励函数以惩罚过多的 addCriterion 和换行符。

🏁GSPO 强化学习

此更新另外添加了 GSPO(组序列策略优化arrow-up-right)这是由阿里巴巴 Qwen 团队提出的 GRPO 变体。他们注意到 GRPO 隐式地为每个标记导致了重要性权重,尽管显式的优势并不会随每个标记缩放或改变。

这导致了 GSPO 的创建,GSPO 现在将重要性分配给序列似然而不是各个标记的个体似然。这两种算法之间的差异可以在下面看到,均来自 Qwen 和阿里巴巴的 GSPO 论文:

GRPO 算法,来源: Qwenarrow-up-right
GSPO 算法,来源: Qwenarrow-up-right

在公式 1 中,可以看出优势在该张量求和之前将每一行缩放到标记的对数概率上。本质上,尽管该缩放是赋予整个序列而非每个单独标记,但每个标记都得到了相同的缩放。下面可以看到一个简单示意图:

按行用优势缩放的 GRPO 对数概率比

公式 2 显示了每个序列的对数概率比在计算完成后被求和并取指数,只有得到的序列比随后被按行乘以优势。

按行用优势缩放的 GSPO 序列比

启用 GSPO 很简单,你只需在 GRPO 配置中设置 importance_sampling_level = "sequence" 标志即可。

总体而言,Unsloth 现在通过 VLM vLLM 快速推理既实现了 90% 的内存使用减少,又在 GRPO 和 GSPO 下实现了 1.5-2x 的速度提升!

如果你想了解更多关于强化学习的内容,请查看我们的 RL 指南:

Reinforcement Learning Guide

作者: 特别感谢 Keitharrow-up-right Dattaarrow-up-right 为本文做出的贡献!

最后更新于

这有帮助吗?