> For the complete documentation index, see [llms.txt](https://unsloth.ai/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://unsloth.ai/docs/zh/kuai-su-kai-shi/reinforcement-learning-rl-guide/vision-reinforcement-learning-vlm-rl.md).

# 视觉强化学习（VLM RL）

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

Unsloth 现在支持视觉/多模态 RL，搭配 [Qwen3-VL](/docs/zh/mo-xing/tutorials/qwen3-how-to-run-and-fine-tune/qwen3-vl-how-to-run-and-fine-tune.md), [Gemma 3](/docs/zh/mo-xing/tutorials/gemma-3-how-to-run-and-fine-tune.md) 以及更多。由于 Unsloth 独特的 [权重共享](/docs/zh/kuai-su-kai-shi/reinforcement-learning-rl-guide.md#what-unsloth-offers-for-rl) 以及自定义内核，Unsloth 让 VLM RL **快 1.5–2 倍，** 使用 **显存占用减少 90%**，并支持 **长 15 倍的上下文** 长度比 FA2 配置更长，且没有精度损失。此更新还引入了 Qwen 的 [GSPO](#gspo-rl) 算法。

Unsloth 可以在免费的 Colab T4 GPU 上使用 GSPO/GRPO 训练 Qwen3-VL-8B。其他 VLM 也可以使用，但可能需要更大的 GPU。Gemma 需要比 T4 更新的 GPU，因为 vLLM [仅限制为 Bfloat16](/docs/zh/mo-xing/tutorials/gemma-3-how-to-run-and-fine-tune.md#unsloth-fine-tuning-fixes)，因此我们建议在 Colab 上使用 NVIDIA L4。我们的笔记本可解决涉及图像和图表的数值数学问题：

* **Qwen-3 VL-8B** (vLLM 推理)**:** [Colab](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Qwen3_VL_\(8B\)-Vision-GRPO.ipynb)
* **Qwen-2.5 VL-7B** (vLLM 推理)**:** [Colab](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Qwen2_5_7B_VL_GRPO.ipynb) •[ Kaggle](https://www.kaggle.com/notebooks/welcome?src=https://github.com/unslothai/notebooks/blob/main/nb/Kaggle-Qwen2_5_7B_VL_GRPO.ipynb\&accelerator=nvidiaTeslaT4)
* **Gemma-3-4B** (Unsloth 推理)： [Colab](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Gemma3_\(4B\)-Vision-GRPO.ipynb)

我们还已将 vLLM VLM 集成原生加入 Unsloth，因此要使用 vLLM 推理，你只需启用 `fast_inference=True` 标志，在初始化模型时启用。特别感谢 [Sinoué GAD](https://github.com/unslothai/unsloth/pull/2752) 提供了 [第一个笔记本](https://github.com/GAD-cell/vlm-grpo/blob/main/examples/VLM_GRPO_basic_example.ipynb) ，使得集成 VLM RL 更加容易！

此 VLM 支持还集成了我们最新的更新，使 RL 更节省内存且更快，包括我们的 [待机功能](/docs/zh/kuai-su-kai-shi/reinforcement-learning-rl-guide/memory-efficient-rl.md#unsloth-standby)，与其他实现相比，它独特地限制了速度下降。

{% hint style="info" %}
你只能使用 `fast_inference` 用于 vLLM 支持的 VLM。一些模型，如 Llama 3.2 Vision，因此只能在不使用 vLLM 的情况下运行，但它们仍可在 Unsloth 中正常工作。
{% endhint %}

```python
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，因此请设置 `finetune_vision_layers = False` 在加载 LoRA 适配器时。\
不过，如果你使用 transformers/Unsloth 进行推理，你也可以训练视觉层。

```python
# 将 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,
)
```

## :butterfly:Qwen 2.5 VL 视觉 RL 问题与怪癖

在 Qwen 2.5 VL 的 RL 过程中，你可能会看到如下推理输出：

{% code overflow="wrap" %}

```
 addCriterion
 <tool_call>\n addCriterion\n\n addCriterion\n\n addCriterion\n\n addCriterion\n\n addCriterion\n\n addCriterion\n\n addCriterion\n\n addCriterion\n\n addCriterion\n\n addCriterion\n\n\n addCriterion\n\n 自动生成\n\n addCriterion\n\n addCriterion\n\n addCriterion\n\n addCriterion\n\n addCriterion\n\n addCriterion\n\n addCriterion\n\n addCriterion\n\n\n addCriterion\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
```

{% endcode %}

这曾是 [被报告](https://github.com/QwenLM/Qwen2.5-VL/issues/759) 在 Qwen2.5-VL-7B-Instruct 的输出中也被报告为意外结果“addCriterion”。事实上我们也看到了这个问题！我们尝试了非 Unsloth、bfloat16 和 float16 机器以及其他方法，但它似乎仍然存在。例如第 165 项，即 `train_dataset[165]` 来自 [AI4Math/MathVista](https://huggingface.co/datasets/AI4Math/MathVista) 数据集如下：

{% code overflow="wrap" %}

```
图示为赛车手驾驶赛车与赛道墙壁相撞时所走路径的俯视图。碰撞前一刻，他以速度 $v_i=70 \mathrm{~m} / \mathrm{s}$ 沿与墙壁成 $30^{\circ}$ 的直线运动。碰撞后，他以速度 $v_f=50 \mathrm{~m} / \mathrm{s}$ 沿与墙壁成 $10^{\circ}$ 的直线运动。他的质量 $m$ 为 $80 \mathrm{~kg}$。碰撞持续 $14 \mathrm{~ms}$。碰撞过程中作用在驾驶员身上的平均力大小是多少？
```

{% endcode %}

<figure><img src="https://2657992854-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2Fgit-blob-61a659529171fcc10ed6398a15912b21d6b1a076%2FUntitled.png?alt=media" alt="" width="128"><figcaption></figcaption></figure>

然后我们就得到了上面的乱码输出。可以添加一个奖励函数来惩罚添加 addCriterion，或者惩罚乱码输出。不过，另一种方法是让它训练更久。比如，大约要到 60 步之后，我们才看到模型真正通过 RL 学到东西：

<figure><img src="https://2657992854-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2Fgit-blob-5f34f66f0ac6508fd28343b16592c59b889ec5ca%2Fimage.webp?alt=media" alt=""><figcaption></figcaption></figure>

{% hint style="success" %}
强制 `<|assistant|>` 在生成过程中这样做会按预期减少这些乱码结果，因为这是一个 Instruct 模型；不过，最好还是添加奖励函数来惩罚不良生成，如下一节所述。
{% endhint %}

## :medal:用于减少乱码的奖励函数

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

```python
def formatting_reward_func(completions,**kwargs):
    import re
    thinking_pattern = f'{REASONING_START}(.*?){REASONING_END}'
    answer_pattern = f'{SOLUTION_START}(.*?){SOLUTION_END}'

    scores = []
    for completion in completions:
        score = 0
        thinking_matches = re.findall(thinking_pattern, completion, re.DOTALL)
        answer_matches = re.findall(answer_pattern, completion, re.DOTALL)
        if len(thinking_matches) == 1:
            score += 1.0
        if len(answer_matches) == 1:
            score += 1.0

        # 修复 addCriterion 问题
        # 参见 https://docs.unsloth.ai/new/vision-reinforcement-learning-vlm-rl#qwen-2.5-vl-vision-rl-issues-and-quirks
        # 对过多的 addCriterion 和换行符进行惩罚
        if len(completion) != 0:
            removal = completion.replace("addCriterion", "").replace("\n", "")
            if (len(completion)-len(removal))/len(completion) >= 0.5:
                score -= 2.0

        scores.append(score)
    return scores
```

## :checkered\_flag:GSPO 强化学习

此更新还加入了 GSPO（[组序列策略优化](https://arxiv.org/abs/2507.18071)），这是阿里巴巴 Qwen 团队提出的 GRPO 变体。他们注意到，GRPO 会隐式地为每个 token 产生重要性权重，尽管显式的优势并不会随每个 token 缩放或变化。

这促成了 GSPO 的诞生，它现在将重要性分配给序列似然，而不是各个 token 的单独似然。这两种算法的差异如下所示，均来自 Qwen 和阿里巴巴的 GSPO 论文：

<figure><img src="https://2657992854-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2Fgit-blob-45d743dd5dcd590626777ce09cfab61808aa8c24%2Fimage.png?alt=media" alt="" width="563"><figcaption><p>GRPO 算法，来源： <a href="https://arxiv.org/abs/2507.18071">Qwen</a></p></figcaption></figure>

<figure><img src="https://2657992854-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2Fgit-blob-ee755850cbe17482ce240dde227d55c62e9a3e64%2Fimage.png?alt=media" alt="" width="563"><figcaption><p>GSPO 算法，来源： <a href="https://arxiv.org/abs/2507.18071">Qwen</a></p></figcaption></figure>

在公式 1 中可以看出，优势会在该张量求和之前将每一行缩放到 token 的 logprob 中。本质上，尽管该缩放是针对整个序列而不是每个单独 token 给出的，但每个 token 得到的缩放都是相同的。下方可见一个简单示意图：

<figure><img src="https://2657992854-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2Fgit-blob-b3c944808a15dde0a7ff45782f9f074993304bf1%2FCopy%20of%20GSPO%20diagram%20(1).jpg?alt=media" alt="" width="286"><figcaption><p>GRPO Logprob 比率按行由优势缩放</p></figcaption></figure>

公式 2 表明，在计算出 Logprob 比率后，每个序列的 logprob 比率会先求和并指数化，而只有得到的序列比率会再按行乘以优势。

<figure><img src="https://2657992854-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2Fgit-blob-62fc5b50921e79cce155d2794201c9b96faf941e%2FGSPO%20diagram%20(1).jpg?alt=media" alt="" width="313"><figcaption><p>GSPO 序列比率按行由优势缩放</p></figcaption></figure>

启用 GSPO 很简单，你只需要设置 `importance_sampling_level = "sequence"` 在 GRPO 配置中的该标志。

```python
training_args = GRPOConfig(
    output_dir = "vlm-grpo-unsloth",
    per_device_train_batch_size = 8,
    gradient_accumulation_steps = 4,
    learning_rate = 5e-6,
    adam_beta1 = 0.9,
    adam_beta2 = 0.99,
    weight_decay = 0.1,
    warmup_ratio = 0.1,
    lr_scheduler_type = "cosine",
    optim = "adamw_8bit",
    # beta = 0.00,
    epsilon = 3e-4,
    epsilon_high = 4e-4,
    num_generations = 8,    
    max_prompt_length = 1024,
    max_completion_length = 1024,
    log_completions = False,
    max_grad_norm = 0.1,
    temperature = 0.9,
    # report_to = "none", # 如果你想记录到 Weights & Biases，则设为 "wandb"
    num_train_epochs = 2, # 用于快速测试运行，完整训练时增大
    report_to = "none"
    
    # GSPO 如下：
    importance_sampling_level = "sequence",
    
    # Dr GRPO / GAPO 等
    loss_type = "dr_grpo",
)
```

总体而言，Unsloth 现在结合 VLM vLLM 快速推理，不仅可将内存使用减少 90%，还能在 GRPO 和 GSPO 下实现 1.5–2 倍更快的速度！

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

[Reinforcement Learning](/docs/zh/kuai-su-kai-shi/reinforcement-learning-rl-guide.md)

***作者：** 非常感谢* [*Keith*](https://www.linkedin.com/in/keith-truongcao-7bb84a23b/) *和* [*Datta*](https://www.linkedin.com/in/datta0/) *对本文的贡献！*


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://unsloth.ai/docs/zh/kuai-su-kai-shi/reinforcement-learning-rl-guide/vision-reinforcement-learning-vlm-rl.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
