[Agent Memory / 强化学习] MemPO源码学习笔记 ---(5)--- GRPO

Agent Memory / 强化学习 MemPO源码学习笔记 ---(5)--- GRPO

0x00 概要

现有的基于强化学习的 Memory 管理方法往往缺乏一种有效机制针对 Memory 的更新内容进行引导优化,Memory 的内容难以保证质量。

MemPO(Self-Memory Policy Optimization)使模型对 Memory 进行自管理,并引入了基于有效信息含量的 Memory-level 的优势估计,引导 Memory 保留对解决任务更有效的信息,进而提升记忆有效性。

MemPO的独特切入点:让模型把记忆写在每轮开头(),形式上像"自我对话的草稿纸",既是记忆又是思考链的一部分。这样,变成可训练的策略变量,用RL信号端到端地教会模型"什么值得记、怎么记"。RL 直接端到端优化这一行为,无需额外的记忆模块。

MemPO 的信息如下:

本篇看看GRPO的使用。

0x01 原理

1.1 现状

Agent 引入记忆机制的目的是通过移除无关信息、保留关键细节来应对智能体的长上下文问题。

原始 GRPO 基于答案正确性计算奖励,并使用轨迹级别的优势 (advantage),即同一条轨迹内所有 token共享同一个奖励。这导致对记忆生成的奖励信号稀疏、指导有限 --- 因为最终答案的正确性无法直接反映交互过程中每次 操作的质量。

MemPO设计了一种新颖的优势计算方法:在轨迹级优势之外,额外评估每一步 中记忆的信息含量,并计算一个附加的优势值,从而确保记忆在保持简洁的同时保留重要信息。

论文原文说的:"computes an additional advantage"= 除了 outcome_adv 之外,额外再算一个 advantage。 "附加的优势值" 指的就是 Memory Advantage (mem_adv)。

对应代码:A2: compute_grpo_memory_advantage () → mem_adv = (P_mem - P_full - mean) /std → 仅作用于 ... 区间

ini 复制代码
叠加方式 (A3):final_adv = outcome_adv + mem_adv
                          ↑ 原有的        ↑ "附加的"(additional)

"附加"(additional) 强调的是:这是 MemPO 在 GRPO 基础上新增的部分 --- 原始 GRPO 只有 outcome_adv, MemPO 额外加了 mem_adv来精确指导 的生成质量。

1.2 GRPO

GRPO是PPO的一个变体,区别仅在于advantage的计算方式(用组内统计替代 Critic)。GRPO 本质上是 " 用统计方法替代了 Critic网络 "--- 把一个需要学习的组件 (Critic) 换成了一个不需要学习的统计计算 (组内均值 / 标准差),代价是需要每个question 生成多条轨迹。其他所有环节 (PPO 优化框架) 不受影响。

标准PPO:

scss 复制代码
advantage = V_critic(s) - R(s)    ←     需要单独训练一个Critic网络

GRPO (Group Relative Policy Optimization):

ini 复制代码
advantage =(reward-group_mean)/ group_std  ←   不需要Critic 
其中group = 同一个question的16条rollout轨迹

GRPO 是"无Critic的PPO"------它保留了PPO 的:

  • Clipped surrogate loss
  • Importance sampling ratio
  • KL penalty to ref model
  • 多 epoch mini-batch 更新

但去掉了 Critic网络,用同组轨迹的相对排名代替 value baseline。

1.3 PPO vs GRPO

GRPO 和 PPO 的核心差异就在于 advantage 的计算方式。其余部分 (clipped loss、ratio、KL、多epoch更新) 完全相同。

  • PPO: adv = reward - V (s) ← 需要训练 Critic 来估计 V (s)
  • GRPO: adv = (score - mean) /std ← 用同组轨迹统计量替代 V (s)

PPO 和 GRPO 对比如下:

5-PPO 和 GRPO 对比

差异汇总如下:

scss 复制代码
┌──────────────────┬─────────────────────────────┬─────────────────────────────┐
│                  │ 标准 PPO                     │ GRPO                        │
├──────────────────┼─────────────────────────────┼─────────────────────────────┤
│ 轨迹数/question   │ 通常1条                     │ 16条(group size)            │
├──────────────────┼─────────────────────────────┼─────────────────────────────┤
│ Critic 网络       │ ✅ 需要(~7B)               │ ❌ 不需要                    │
├──────────────────┼─────────────────────────────┼─────────────────────────────┤
│ Advantage 来源    │ GAE: reward-V(s)            │ (score-mean)/std            │
├──────────────────┼─────────────────────────────┼─────────────────────────────┤
│ 额外训练步骤      │ Critic loss                  │ 无                           │
├──────────────────┼─────────────────────────────┼─────────────────────────────┤
│ 显存占用          │ actor+ref+critic             │ actor+ref                  │
├──────────────────┼─────────────────────────────┼─────────────────────────────┤
│ Advantage 精度    │ token-level(但有             │ trajectory-level          │
│                  │ estimation error)            │ (无estimation error)     │
├──────────────────┼─────────────────────────────┼─────────────────────────────┤
│ 适合场景          │ dense reward                 │ sparse/outcome reward       │
└──────────────────┴─────────────────────────────┴─────────────────────────────┘

1.4 为什么MemPO选GRPO而不是PPO+Critic

MemPO不用Critic的四个原因如下:

Critic 在多轮长序列中极难训练

标准PPO:V(s_t) 需要为序列中每个token位置预测未来累计回报,预测"未来能否答对"。

但是,MemPO的序列结构为:Round1_tokens \| Round2_tokens \| ...\| Round5_tokens。此长度可达数千token,奖励仅在最末尾(sparse reward)。

因此,Critic 面对的挑战:

  • 序列极长 → 需要巨大容量的value网络
  • 奖励极稀疏→ V(s)几乎处处为0,难以学到有意义的信号
  • 多轮工具交互→状态空间复杂,value estimation 噪声大
GRPO 比较适合 outcome-based 稀疏奖励

GRPO 用同组轨迹均值替代value baseline,比较适合trajectory-level离散奖励。

  • GRPO的假设:奖励是trajectory-level的标量 → 完美匹配EM check的{0, 1}评分。
  • 不需要学习 V(s_t):baseline = 同 question 16 条轨迹的均值 = (score - mean) / std → 零额外参数,零额外训练,无 value estimation 误差。
计算资源节约

PPO+Critic:

  • 额外一个与actor 同规模的 Critic 网络(7B 参数)
  • Critic需要额外前向+反向
  • 显存翻倍:actor(7B)+ ref(7B)+ critic(7B)=21B 参数

GRPO:

  • 仅actor(7B)+ref(7B)=14B参数
  • 省下的资源用于更多并发rollout(16条/question)
Memory Reward 的特殊性

Memory Reward 本身自带baseline(P_mem-P_full),无需Critic 估计。

ini 复制代码
mem_reward=P_mem-P_full     这本身就是一个"自带baseline"的信号

如果用 Critic,还需要为 区间单独训练 value head → 但的"好坏"取决于未来能否答对(极长时间依赖)→ Critic几乎不可能准确估计这个value。

GRPO方案:直接跨轨迹归一化mem_reward,简单有效

小结

GRPO在MemPO 场景下是更实用的选择一一稀疏奖励、长序列、多轮交互这三个特点让Critic训练极其困难,而 GRPO通过"同组相对排名"巧妙绕过了value estimation问题。

MemPO最特色的地方:在标准GRPO之上,额外为片段设计了细粒度的位置感知奖励,让梯度信号可以精确地作用于"记忆写作"行为,而不只是笼统地惩奖整条轨迹。

我们接下来仔细分析。

0x02 MemPO GRPO

2.1 阶段

GRPO算法 = Advantage 计算方式 + PPO 优化框架,因此具体可以分两个环节:

环节1:GRPO Advantage计算(无梯度)

ini 复制代码
B4-algo: outcome_adv =(score - mean) / std     ← 纯数值运算
A2: mem_adv = (r_t-mean) / std                 ← 纯数值运算
A3: final_adv = outcome_adv + mem_adv          ← 纯加法
所有 advantage 都是detached 常数,不参与计算图

环节2:PPO Update(有梯度)

css 复制代码
for epoch in ppo_epochs:
    for mini_batch in shuffie(batch):
        new_log_prob = actor.forward(mini_batch)
                               ↑梯度计算
                               
        ratio = exp(new_log_prob - old_log_prob) 
        loss = -mean(final_adv x clip(ratio)) + KL_penalty
        
        loss.backward()   ← 反向传播 
        optimizer.step()  ← 模型优化

总结:GRPO只决定"每个token 该鼓励还是抑制、强度多大"(advantage 值),但"怎么优化模型参数"完全是PPO 的事一一一梯度计算、反向传播、模型更新都在 PPO Update 环节。

2.2 模型

MemPO 有以下几种模型

actor(策略模型):

  • 就是正在被训练的LLM(如Qwen2.5-7B)
  • 每个PPO step都会更新其参数
  • 配置:actor_rollout_ref.model.path→初始化自SFT模型
  • 既用于rollout生成,也用于PPO更新时的前向计算

ref_model(参考模型):

  • 与actor结构完全相同的 LLM,但参数冻结不更新
  • 初始化为训练开始时的actor快照(即SFT模型本身)
  • 作用:计算KL散度惩罚KL(π_actor || π_ref)
  • 防止actor偏离初始策略太远(PPO的信任域约束)

在代码中的体现:

ini 复制代码
run_train.sh 中:
    actor_rollout_ref.model.path="NewBeeKing/MemPo_Qwen2.5-SFT"
    
    actor   ← 加载这个模型,训练中不断更新
    ref     ← 加载同一个模型,训练中冻结
    rollout ← 用actor的权重做推理(通过SGLang服务)

三者在PPO loss中的角色:

ini 复制代码
ratio = exp(new_log_prob_actor - old_log_prob_actor)
               ↑当前参数              ↑本轮开始时的快照
KL_penalty = ratio_to_ref -log(ratio_to_ref)-1
       where ratio_to_ref = exp(log_prob_actor -log_prob_ref)
                                                          ↑永远不更新
loss =-adv x clip(ratio)+ KL_coef x KL_penalty 

简单来说:

  • actor = "学生,不断学习改进
  • ref_model = "老师基线", 确保学生不会偏离太远
  • old_log_prob = "上一次考试成绩", 用于计算 importance sampling ratio

2.3 优势函数

Outcome Advantage 和 Memory Advantage 两者都用 GRPO 风格的归一化方式计算 advantage,但侧重点不同。

Outcome Advantage --------- GRPO 标准流程:

  • B4-algo: compute_grpo_outcome_advantage()
  • 分组:同一 question 的 16 条轨迹
  • 归一化:adv = (score - group_mean) / group_std
  • → 这就是 GRPO 的核心---用组内相对排名替代 Critic

Memory Advantage --------- GRPO 风格但维度不同:

  • A2: compute_grpo_memory_advantage()
  • 分组:同一 question 的所有轨迹 × 所有轮次 (~48 个值)
  • 归一化:adv = (mem_reward - pool_mean) / pool_std
  • → 借鉴了 GRPO 的 "组内归一化" 思想
  • → 但池化范围更大(跨轨迹 + 跨轮次)

两者最终:

  • final_adv = outcome_adv + mem_adv → 送入同一个 PPO loss

严格来说:

  • Outcome Advantage = 标准 GRPO
  • Memory Advantage = GRPO 启发的归一化(不是 GRPO 论文中定义的,是 MemPO 的创新设计)
  • 最终优化 = PPO clipped surrogate loss(GRPO 只是 advantage 计算方式,优化器仍是 PPO)

2.4 前向传播

此点在Rollout篇也有涉及。

完整训练步的 Forward Pass 计数

MemPO 相比原版GRPO 多了1次extra forward pass(步骤②),但该次同时批量处理了 full_traj 和 mem_traj,实际吞吐开销约是标准old_log_prob的1.5~2倍,是 MemPO最主要的训练额外成本。

ini 复制代码
───────────────────────────────────────────────────
① 生成阶段 (generate_sequences)
    SGLang 自回归解码,共 n=16 条轨迹
    → 本质也是 forward,但 KV cache 优化,计一次

───────────────────────────────────────────────────
②★ MemPO 专属: compute_log_prob(full_traj + mem_traj)
    agent_loop.py 
    concat = [全部 full_traj, 全部 mem_traj]
    → 一次调用,但序列数量 = 2 × B × (T-1) × n
    B=batch_size, T=轮次, n=16

───────────────────────────────────────────────────
③ compute_log_prob (old_log_prob)
    ray_trainer.py 
    → actor 计算轨迹的旧 logp (供 PPO ratio 使用)

───────────────────────────────────────────────────
④ compute_ref_log_prob (KL 约束)
    ray_trainer.py 
    → ref model 计算 logp (供 KL 惩罚使用)

───────────────────────────────────────────────────
⑤ actor update (多 epoch 反向传播)
 默认 ppo_epochs=1, 每次需要当前 logp
特色
特性 详情
是否"推理两次"? 否,1次extra forward pass,不生成新 token
实际操作 对已生成的答案 Z,用两种不同的输入上下文计算 logp
计算次数 一次 forward pass,两种输入拼成一个 batch
计算时机 rollout 完成后,advantage 计算前
目的 衡量"仅凭能否预测正确答案"的能力
对比

与原版 VeRL的对比

阶段生成 原版 VeRL GRPO MemPO
生成 ①generate ①generate
记忆奖励 ✗无 ✓②full+mem 双路 logp
旧logp ③old_log_prob ③old_log_prob
ref logp ④ref_log_prob ④ref_log_prob
更新 ⑤actor update ⑤actor update
总计 4次 forward 5次forward

每个 search_results 都是一次搜索的返回,不是多次搜索的集合。

2.5 Loss

outcome_adv 和 mem_adv 两者共同作为 PPO 的 advantage 信号,在同一个 PPO loss 中训练。

ini 复制代码
final_adv = outcome_adv + mem_adv    ← 叠加后作为 PPO 的 advantage

PPO loss = -mean( final_adv × clip(ratio, 1-ε, 1+ε) × response_mask ) + KL_coef × KL(π || π_ref)

不是两个独立的训练过程,而是: 一次前向 → 一个 loss → 一次反向传播

不同 token 接收到的 advantage 值不同:

ini 复制代码
position:    [R1 tokens] [<mem>R2 tokens</mem>] [think tokens] [<mem>R3</mem>] [answer]
final_adv:   [  +0.8  ]    [ +0.8 + 1.2 ]      [  +0.8  ]      [+0.8 - 0.5 ]   [ +0.8 ]
              ↑ 仅 outcome  ↑ outcome + mem (正)  ↑ 仅 outcome     ↑ outcome + mem (负)
输入

loss 的输入如下:

scss 复制代码
new_log_prob [bsz, seq_len]   ←  当前actor前向得到
old_log_prob [bsz, seq_len]   ←  rollout时的快照(detached)
ref_log_prob [bsz, seq_len]   ←  refmodel(冻结)
final_adv    [bsz, seq_len]   ←  outcome_adv + mem_adv
response_mask [bsz, seq_len]  ←  1 = response token,0 = prompt token
计算

计算公式为:

scss 复制代码
PPO loss = -mean( final_adv × clip(ratio, 1-ε, 1+ε) × response_mask ) + KL_coef × KL(π || π_ref)

PPO是REINFORCE的改进版:

  • 加入importance sampling ratio:ratio=π_new/π_old,允许在旧数据上多次更新
  • 加入clip约束:防止ratio偏离太大(限制单步更新幅度)
  • 加入KL penalty:防止偏离参考策略太远
  • 本质上PPO loss中的final_adv × ratio就是REINFORCE梯度的importance-weighted版本。
ini 复制代码
# Importance Sampling Ratio
ratio = exp(new_log_prob - old_log_prob)

# Clipped Surrogate
surr1 = ratio × final_adv
surr2 = clip(ratio,1-e,1+e) × final_adv
policy_loss = -mean( min(surr1, surr2) × response_mask )

# KL Penalty (low-variance estimator)
ratio_ref = exp(new_log_prob - ref_log_prob) 
kl = ratio_ref-log(ratio_ref)-1
kl_loss = KL_coef × mean(kl × response_mask)

# Total
total_loss = policy_loss + kl_loss 

最终的 total_loss 是一个标量(scalar),但中间步骤涉及张量运算,即total_loss 是标量。中间的 ratio、advantage等是bsz,seq_len张量,通过mean()操作压缩为标量。total_loss.backward()从该标量反传梯度到所有模型参数,唯一有梯度的量是new_log_prob(当前actor前向计算得到)。

我们接下来看看几个具体细节。

ratio

PPO loss中的ratio是importance sampling比率,配合clip防止单步更新过大:

  • ratio > 1:当前策略比生成时,更倾向选择这些token
  • ratio < 1:当前策略比生成时,更不倾向选择这些token
  • ratio = 1:没变化
Importance sampling

Importance sampling 允许用一个分布(旧策略 π_old)采的样本来估计另一个分布(新策略 π_new)下的期望:

css 复制代码
E_π_new[f(x)] = E_π_old[f(x) × π_new(x) / π_old(x)]

PPO需要它是因为rollout在旧策略下生成,但要更新到新策略。ratio=π_new/π_old就是importance weight,纠正了分布不匹配。clip限制ratio范围是为了防止weight太大导致高方差。

张量形状

各步骤的形状如下:

scss 复制代码
  new_log_prob     [bsz, seq_len]    ← 张量(每个token一个log概率)
  old_log_prob     [bsz, seq_len]    ← 张量
  ratio            [bsz, seq_len]    ← 张量(逐token计算)
  final_adv        [bsz, seq_len]    ← 张量(逐token不同值)
  surr1            [bsz, seq_len]    ← 张量
  surr2            [bsz, seq_len]    ← 张量
  min(surr1,surr2) [bsz, seq_len]    ← 张量
  response_mask    [bsz, seq_len]    ← 张量(0/1)
  
  policy_loss = -mean(min(...) × mask)  ← 标量 ✓  (对所有元素求平均)
  kl_loss = KL_coef × mean(...)         ← 标量 ✓
  total_loss = policy_loss + kl_loss    ← 标量 ✓

total_loss.backward() ← 从这个标量反传梯度到所有参数

关键:mean()操作将[bsz,seq_len]的张量压缩为标量,然后.backward()从该标量计算梯度。

MemPO的特殊之处

Loss公式本身没有修改,特殊性全在final_adv的构造上:

ini 复制代码
标准 GRPO:
    final_adv[i, :] = outcome_adv_i   ← 全序列同一个值

MemPO:
    final_adv[i, :] = outcome_adv_i + mem_adv[i, :]
                                        ↑ 仅 <mem> 区间非零

效果:同一条轨迹内,不同 token 的 advantage 值不同:

xml 复制代码
token类型            advantage 值            梯度效果
─────────────────────────────────────────────────────────
<mem>...</mem>      outcome + mem_adv_t      双重驱动(可正可负)
<think>内容          outcome                  仅结果驱动
<search>query       outcome                  仅结果驱动
<answer>内容         outcome                  仅结果驱动
prompt tokens       masked out (=0)          无梯度

这就是 MemPO 的全部创新点在 loss 层面的体现------通过让 token 接收额外的 memory quality 信号,实现对记忆摘要能力的精准优化,而不影响其他 token 的学习。

为什么不用两个独立loss分别优化?

MemPO 的训练,本质上是一个 PPO 算法 + 一个复合 advantage:

  • GRPO (Group Relative Policy Optimization) 负责计算 outcome_adv
  • Memory reward 机制负责计算 mem_adv
  • 两者加和后送入标准 PPO clipped surrogate loss

并没有分别训练两个 objective, 也没有分步交替优化 --- --- --- 就是一个统一的梯度更新。

如此设计的原因有三:

梯度冲突问题

如果两个loss独立:

ini 复制代码
loss_outcome = -outcome_adv × log π(token) 
loss_memory = -mem_adv × log π(mem_token)

以场景3(答错+好mem)为例:

scss 复制代码
loss_outcome 想让<mem>token概率 ↓ (因为整条轨迹答错了)
loss_memory  想让<mem>token概率 ↑ (因为摘要写得好)

梯度冲突:两个loss对token可能方向相反 → 两个梯度方向相反 → 训练不稳定、震荡。

叠加方案直接解决:(-0.8) + (+1.2) = +0.4,产出一个明确的净方向。

PPO的clip 机制需要统一advantage

PPO clip的含义:限制每步更新幅度

如果拆成两个loss分别clip:每个loss各允许幅度的更新,叠加后实际更新了2ε→超出信任域

统一后只clip一次:final_adv = outcome + mem → clip一次 → 总更新在ε内

实现极简+计算高效

统一方案:1次前向,1次反向,1次参数更新 → 实现极简+计算高效 → 无需调两个1oss的权重系数

ini 复制代码
final_adv = outcome_adv + mem_adv  ←   1行加法

独立方案:→2次前向,2次反向,2次参数更新(或需要梯度累积) → 还需要调两个loss的权重系数 →实际上调权重系数 ≈ 调mem_adv的相对幅度(本质相同)

总结:叠加 advantage 本质上等价于带权重的多目标优化,但更稳定、更高效、且天然兼容PPO的clip约束

2.6 梯度

我们来看看整个训练过程中哪些计算有梯度、哪些没有。

✗ 无梯度(detached/frozen):

java 复制代码
✗ 无梯度(detached/frozen):
  - Rollout 生成 token                     → SGLang 推理,不保留计算图
  - A1 compute_log_prob (mem_reward)      → detached,仅算数值
  - B2 compute_score (outcome_reward)     → 纯字符串匹配,无张量
  - B4-algo outcome_adv                   → 纯数值运算
  - A2 mem_adv                            → 纯数值运算
  - A3 final_adv = outcome + mem          → 常数张量
  - old_log_prob                          → detached 快照
  - ref_log_prob                          → 冻结模型

☑ 有梯度(唯一来源):

scss 复制代码
☑ 有梯度(唯一来源):
  PPO Update 中:
  new_log_prob = actor.forward(response_ids)    ← 当前 actor 前向
                 ↑ 这是唯一参与计算图的量

  ratio = exp(new_log_prob - old_log_prob)      ← 梯度流经 new_log_prob
  loss = -mean(final_adv × clip(ratio) × mask)  ← 标量
   + KL_coef x f(new_log_prob, ref_log_prob)
   
  loss.backward() 
  ↓ 梯度方向:
  loss → ratio → new_log_prob → actor 参数 (weights, biases, embeddings) 
  optimizer.step() →更新actor 所有参数

因此:

整个 MemPO 的梯度就是∂loss/∂θ_actor(PPO Update 中 new_log_prob 对 actor 参数的梯度),通过 new_log_prob这一个计算图节点反传到模型参数。

所有advantage、reward、ref/old log_prob 都只是常数系数,决定梯度的"方向和大小",但不贡献梯度本身。

2.7 KL约束

直觉含义

KL约束是防止模型为了刷分而"跑偏"一确保更新后的策略不会偏离起点太远。

直觉类比

想象一个学生(actor)在刷题提分:

  • 没有约束:可能发现某种"作弊"捷径(如固定输出某个高频答案)→分数暂时上升,但能力退化
  • KL约束:"你可以改进,但不能变得和原来的自己(ref)差别太大" →保持泛化能力的同时逐步提升
数学直觉

KL(π_actor || π_ref)衡量两个分布的"距离":

  • = 0:actor和ref完全一样(没学到任何东西)
  • 很大:actor和ref差别巨大(可能过度优化/rewardhacking)

在loss中:

csharp 复制代码
total_loss = policy_loss + KL_coef x KL

policy_loss想让模型"往高reward方向走" → 拉离ref 

KL_penalty想让模型"别离ref太远" → 拉回ref

两者对抗 → 模型在"提升"和"稳定"之间找到平衡

在MemPO中的实际作用

KL penalty约束actor不偏离ref model(SFT起点)太远。

没有KL penalty时可能出现的问题:

  • 模型学会写一种固定模板的(高mem_reward但无实际信息 / reward hacking)
  • 模型对所有问题都搜同一个query(碰巧某些场景有效)
  • 输出多样性崩溃(所有16条轨迹趋同)
  • 训练不稳定

KL penalty 确保:→ 模型的输出分布保持多样性 → 每步更新幅度有限,训练稳定 → 不会出现reward hacking

实现

配置kl_loss_type = low_var_kl,使用 k3估计量(Schulman 2020):

ini 复制代码
# 普通KL(k1,有偏梯度): 
kl ≈ log π_ref - log π_new

# Low-variance KL estimator
# 代码中用的不是直接的 KL,而是 low-variance 近似:
    # low_var_kl(k3,无偏梯度):
    kl = ratio_ref - log(ratio_ref) - 1
    where ratio_ref = exp(new_log_prob - ref_log_prob) = π_actor / π_ref

    当 ratio_ref = 1 (完全一样): kl = 1 - 0 - 1 = 0 ✅
    当 ratio_ref > 1 (actor概率更高): kl > 0
    当 ratio_ref < 1 (actor概率更低): kl > 0
    → 任何偏离都被惩罚,是一个"弹簧力"把 actor 拉回 ref

为什么用 k3? k3比 k1方差更低,训练更稳定,尤其适合多轮 agent 场景(轨迹长、方差本来就大)。

几个估计器比较如下:

估计器 公式 性质
k1 无偏,方差大,可负
k2 有偏,恒正
k3 () 无偏 + 恒正 + 低方差(Schulman)
low_var_kl 同k3,再做clamp(-10, 10)数值保护 同k3 + 防爆

TransFormer-封面

0xFF 参考

本文使用 markdown.com.cn 排版

相关推荐
美狐美颜SDK开放平台2 小时前
直播APP开发实战:从摄像头调用到视频美颜sdk集成
android·人工智能·计算机视觉·音视频·直播美颜sdk
镜象科技3 小时前
抑郁情绪数字化干预:从“隐蔽的信号“到“看得见的路径“
人工智能
素男3 小时前
对上的,和没对上的——两篇之间那条链
人工智能·agent·self-becoming·ai长期记忆·ai自我介绍
richard_yuu3 小时前
动态规划:强化学习的「数学基础」,从 MDP 到值迭代
深度学习·神经网络·算法·yolo·机器学习·动态规划
niuTaylor3 小时前
飞腾 FT-2000/4 Ubuntu 内存卡 / NVMe SSD 系统制作完整指南
linux·服务器·人工智能·驱动开发·单片机
搞科研的小刘选手3 小时前
【计算机方向 | IEEE出版 | 杭州站】第七届机器学习与计算机应用国际学术会议(ICMLCA 2026)
机器学习·学术会议·计算机应用·会议推荐·浙江工业大学
pusheng20253 小时前
马年市场快报 | 阿尔及利亚政府推进2200万台家用CO报警器安装计划
大数据·人工智能
mmmmath_33 小时前
LeetCode.225.用队列实现栈
算法
Elaine3363 小时前
数据结构与算法-程序
数据结构·python·算法·计算机基础·编程基础