ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

PLD 方法原理 - S-X

PLD 方法原理 - S-X

PLD 方法原理:让 VLA 自己发现问题、学会恢复


1. 先看结论

flowchart LRA["已有 VLA<br/>会做任务,但偶尔失败"] --> B["Probe<br/>让 VLA 先走一段"]B --> C["Learn<br/>小型残差 RL 学会纠错"]C --> D["得到成功恢复轨迹"]D --> E["Distill<br/>用普通 SFT 教回 VLA"]E --> F["更强的 VLA<br/>部署时不再需要 RL 专家"]

PLD 不是重新训练一个机器人,也不是在推理时额外挂一个 RL 控制器。它只做三件事:

  1. Probe:从基座 VLA 的真实行为出发,找到它容易失败的状态。
  2. Learn:训练一个很小的残差策略,只负责把动作修正一点点。
  3. Distill:把“遇到错误后怎么恢复”的完整行为,用 SFT 蒸馏回原来的 VLA。

2. 为什么需要 PLD

2.1 普通 SFT 的问题

VLA 通常靠人类遥操作数据做 SFT:

flowchart TDH["人类遥操作"] --> N["正常、顺利的示范"]N --> SFT["VLA SFT"]SFT --> P["模型学会正常路径"]P --> FAIL["但部署时可能走到示范里没有的错误状态"]FAIL --> BAD["没有对应的恢复动作"]

人类示范往往是:一开始就知道怎么做,所以不会故意把物体推到角落。但 VLA 部署时可能会:

正常状态 -> 动作有一点偏差 -> 物体被推歪 -> 机械臂卡住

真正缺的不是“再看一遍正常动作”,而是:

在 VLA 自己造成的错误状态里,下一步应该怎么救。

2.2 三种数据的差别

数据 优点 缺点
人类示范 质量高,动作自然 很少覆盖 VLA 自己的失败状态
纯 VLA 成功 rollout 与 VLA 分布一致 只包含 VLA 已经会的能力
纯 RL 专家轨迹 成功率高,路径漂亮 路径很窄,可能离 VLA 的行为分布很远
PLD 轨迹 既贴近 VLA,又包含恢复动作 需要额外的机器人 RL 交互

3. 核心对象:一个基座,一个小修正器

先把符号固定下来:

  • \(\pi_b\):冻结的基座 VLA。
  • \(a_b\):基座 VLA 给出的动作。
  • \(\pi_\delta\):任务专用的残差策略。
  • \(a_\delta\):残差策略给出的修正量。
  • \(\bar a\):两者相加后的最终动作。
flowchart LROBS["当前图像 + 本体状态 + 任务语言"] --> BASE["基座 VLA π_b"]BASE --> AB["基座动作 a_b"]OBS --> RES["残差策略 π_delta"]AB --> RESRES --> AD["修正量 a_delta"]AB --> SUM["相加并裁剪"]AD --> SUMSUM --> EXEC["最终动作 a_bar"]EXEC --> ROBOT["机器人执行"]

组合动作是:

\[\bar a=\operatorname{clip}\left(a_b+\xi a_\delta\right) \]

其中 \(\xi\) 是残差尺度。它限制小专家不要一开始就把 VLA 的动作改得太狠。

一个直观比喻

\(\pi_b\) 想成“知道大方向的通才”,把 \(\pi_\delta\) 想成“站在旁边的纠错教练”:

flowchart TDGEN["VLA 通才:向目标走"] --> TRY["先尝试"]TRY --> ERR["发现走偏了"]COACH["残差教练:只修正当前动作"] --> FIX["把方向掰回来"]ERR --> FIXFIX --> GOAL["继续完成任务"]

关键点:残差策略不是替代 VLA,而是站在 VLA 旁边修正它。


4. PLD 的三阶段闭环

flowchart LRsubgraph S1["阶段 1:训练专家"]B1["冻结基座 VLA"] --> R1["每个任务训练残差策略"]endsubgraph S2["阶段 2:生成数据"]R1 --> P2["基座先走随机步数"]P2 --> R2["残差专家接管并恢复"]R2 --> D2["保存成功完整轨迹"]endsubgraph S3["阶段 3:蒸馏"]D2 --> D3["多任务数据合并"]D3 --> SFT["基座 VLA 做 SFT"]endSFT --> DEP["部署改进后的 VLA"]

训练结束后:

  • 残差策略可以丢掉。
  • critic 可以丢掉。
  • replay buffer 可以丢掉。
  • 推理只需要改进后的 VLA。

5. 阶段 1:训练残差 RL 专家

5.1 先把基座冻结

阶段 1 不更新 VLA:

flowchart TDVLA["基座 VLA π_b"] -->|"冻结参数"| FIXED["只提供动作先验"]FIXED --> ACT["a_b"]ACT --> RES["残差策略学习如何修正"]

这样做有两个好处:

  1. RL 只需要训练一个很小的网络,成本低很多。
  2. 探索失败时,不会直接破坏 VLA 原来的通用能力。

5.2 用基座成功轨迹启动 RL

稀疏奖励下,随机探索很难碰到成功。因此先让基座 VLA 自己运行,收集成功轨迹:

flowchart LRBASE["基座 VLA rollout"] --> FILTER["只保留成功回合"]FILTER --> OFF["Offline Buffer"]OFF --> CAL["初始化 critic 的价值估计"]CAL --> RL["残差 RL 更容易起步"]

论文仿真设置中,常用每个任务 50 条成功基座轨迹作为离线种子。它们不是最终的 PLD 数据,而是帮助 RL 知道“成功附近长什么样”。

5.3 残差策略如何探索

在每一个状态:

  1. VLA 给出动作 \(a_b\)
  2. 残差策略根据状态和 \(a_b\) 采样 \(a_\delta\)
  3. 环境真正执行 \(\bar a\)
  4. 根据最终成功或失败更新 critic 和残差策略。
flowchart LROBS["状态 s"] --> VLA["π_b"]VLA --> AB["a_b"]OBS --> PI["π_delta"]AB --> PIPI --> AD["a_delta"]AB --> ADD["a_b + ξ a_delta"]AD --> ADDADD --> ENV["环境"]ENV --> R["奖励 r = 0 或 1"]ENV --> NEXT["下一状态 s_next"]R --> Q["critic Q"]NEXT --> QQ --> PI

5.4 为什么需要两个 replay buffer

flowchart TDOFF["Offline Buffer<br/>基座成功经验"] --> HALF1["采样一半"]ON["Online Buffer<br/>残差在线探索经验"] --> HALF2["采样一半"]HALF1 --> BATCH["混合 batch"]HALF2 --> BATCHBATCH --> CRITIC["更新 critic"]BATCH --> ACTOR["更新残差 actor"]
  • 只用 online:早期大多失败,成功信号太少。
  • 只用 offline:策略不会离开原来的成功路径。
  • 两者各取一半:既保留成功锚点,又允许探索新状态。

5.5 RL 只需要理解三条损失

论文使用离策略 actor-critic / SAC 思路。直观上:

Critic:给动作打分

下一步动作仍由“基座 + 残差”构成:

\[y=r+\gamma(1-done)Q_{target}(s',\bar a') \]

critic 让当前估计靠近这个目标:

\[\mathcal L_Q=\left(Q(s,\bar a)-y\right)^2 \]

实际实现使用两个 \(Q\),取较小者,减少过高估计。

Actor:寻找高价值修正

\[\mathcal L_{actor} =\mathbb E\left[\beta\log\pi_\delta(a_\delta\mid s,a_b)-Q(s,\bar a)\right] \]

第一项保留探索,第二项鼓励高成功概率动作。

Cal-QL:让 critic 先保守

它的作用可以用一句话理解:对数据里没见过的动作,不要盲目给高分。 这比死记一个复杂公式更重要。

5.6 阶段 1 伪代码

函数 Learn(task, base_policy):冻结 base_policy# 用基座成功经验启动offline_buffer = 收集 base_policy 的成功轨迹online_buffer = 空用 Cal-QL 初始化 critic随机初始化 residual_policy重复训练:如果还在 warmup:action = base_policy(观测)否则:base_action = base_policy(观测)delta = residual_policy(观测, base_action)action = clip(base_action + ξ * delta)next_obs, reward, done = 环境执行(action)online_buffer.加入(观测, action, reward, next_obs, done)# 每个 batch 一半来自成功离线池,一半来自在线池batch = mix_sample(offline_buffer, online_buffer, ratio=1:1)更新 critic 的 TD 损失更新 residual_policy 的 SAC 损失软更新 target critic返回 residual_policy

到这里得到的是“某一个任务的纠错专家”,不是最终部署模型。


6. 阶段 2:让专家生成真正有用的数据

6.1 纯专家为什么还不够

如果每一局都从初始状态直接让专家完成,轨迹通常非常整齐:

flowchart TDE["纯 RL 专家"] --> GOOD["成功率高"]E --> NARROW["但总是走同一条窄路径"]NARROW --> MISS["看不到基座常见的失败状态"]MISS --> BAD["蒸馏后仍不会处理这些失败"]

6.2 Base policy probing:先让基座走一段

每一局随机采样一个接管时刻 \(T_{base}\)

\[T_{base}\sim[0,\alpha T] \]

执行规则:

\[a_t= \begin{cases} a_{b,t}, & t<T_{base}\\ a_{b,t}+a_{\delta,t}, & t\ge T_{base} \end{cases} \]

flowchart LRS0["初始状态"] --> B1["基座动作"]B1 --> B2["基座动作"]B2 --> X["随机接管点"]X --> R1["基座动作 + 残差修正"]R1 --> R2["继续恢复"]R2 --> OK["成功"]

这里的“随机”不是给机器人加完全无意义的噪声,而是随机决定让基座先走多久。因此,探索集中在基座实际会到达的状态附近。

6.3 成功轨迹怎么保存

flowchart TDTRAJ["完整混合轨迹"] --> CHECK{"最终成功?"}CHECK -->|"是"| KEEP["保存:基座前缀 + 恢复后缀"]CHECK -->|"否"| DROP["丢弃"]KEEP --> DATA["PLD 数据集"]

注意:阶段 2 保存的动作是最终执行动作,即:

  • 前缀保存 \(a_b\)
  • 后缀保存 \(a_b+a_\delta\)
  • 不保存“只有残差”的伪动作。

6.4 为什么这批数据更适合训练 VLA

flowchart LRBASEDIST["基座部署时会遇到的状态"] --> PROBE["基座 probing"]PROBE --> FAILSTATE["暴露错误状态"]FAILSTATE --> RECOVER["专家给出恢复动作"]RECOVER --> PLD["成功 PLD 轨迹"]PLD --> SFT["VLA 学会在错误状态恢复"]

PLD 同时满足两件事:

  1. 状态像基座:VLA 微调后不容易偏离原来的通用分布。
  2. 动作比基座好:错误状态里有成功恢复标签。

6.5 一个具体例子:方块被推到角落

flowchart LRA["方块在中间"] -->|"VLA 伸偏"| B["碰到方块"]B -->|"VLA 继续执行"| C["方块被推到角落"]C -->|"残差专家接管"| D["先把方块拨回可抓位置"]D --> E["重新对齐夹爪"]E --> F["抓起并完成任务"]

普通人类示范往往没有 \(C\rightarrow D\);PLD 的价值就在这里。

6.6 阶段 2 伪代码

函数 ProbeAndCollect(base_policy, residual_policy):dataset = 空重复若干回合:重置环境T_base = 随机采样 [0, α*T] 中的一个步数trajectory = 空对每个时间步 t:base_action = base_policy(观测)如果 t < T_base:action = base_action否则:delta = residual_policy(观测, base_action)action = clip(base_action + ξ * delta)trajectory.记录(观测, 任务语言, action)执行动作并得到新观测如果成功:dataset.保存(trajectory)  # 保存完整轨迹结束本回合如果失败或超时:丢弃 trajectory结束本回合返回 dataset

7. 阶段 3:把恢复能力教回 VLA

7.1 数据长什么样

最终只需要普通的行为克隆样本:

\[(\text{图像},\text{本体状态},\text{语言指令},\text{实际执行动作}) \]

flowchart LRD1["任务 1 的 PLD 成功轨迹"] --> ALL["多任务 PLD 数据集"]D2["任务 2 的 PLD 成功轨迹"] --> ALLDN["任务 N 的 PLD 成功轨迹"] --> ALLALL --> INPUT["观测 + 语言"]ALL --> LABEL["实际执行动作"]INPUT --> VLA["原来的 VLA"]LABEL --> VLAVLA --> NEW["蒸馏后的 VLA"]

7.2 不需要发明新的 SFT loss

PLD 不规定 tokenizer,也不规定动作头。它只把数据交给基座原来的训练接口:

  • 连续动作头:继续用连续动作回归或流匹配损失。
  • 自回归动作头:继续用动作 token 的交叉熵。

核心等式只有一句:

\[\mathcal L_{PLD}=\mathcal L_{base\ VLA}(\mathcal D^{PLD}) \]

也就是说,PLD 创新在数据怎么来,不在 token 怎么定义。

7.3 蒸馏时学的不是残差

flowchart TDPREFIX["基座前缀"] --> LAB1["标签 = a_b"]RECOVERY["专家恢复后缀"] --> LAB2["标签 = a_b + a_delta"]LAB1 --> BC["统一做 SFT"]LAB2 --> BCBC --> VLA["VLA 自己学会输出恢复后的动作"]

VLA 不会被训练成“预测 \(a_\delta\)”。它直接学习完整的最终动作。这样部署时就不需要再运行残差网络。

7.4 阶段 3 伪代码

函数 Distill(base_policy, pld_dataset):对 pld_dataset 中的每条样本:输入 = 图像 + 状态 + 语言指令标签 = 机器人当时真正执行的动作使用 base_policy 原来的 SFT 训练方式可用 LoRA 降低微调成本返回更新后的 base_policy

8. 训练完成后如何推理

flowchart LROBS["新图像 + 状态 + 语言"] --> VLA["改进后的 VLA"]VLA --> ACT["预测动作或动作块"]ACT --> CTRL["控制器执行"]CTRL --> OBS2["读取新观测"]OBS2 --> VLA

推理阶段没有:

  • 残差 actor;
  • critic;
  • replay buffer;
  • 训练用奖励模型。

因此 PLD 对使用者的最终体验很简单:还是调用原来的 VLA,只是它在失败状态下更会恢复。


9. PLD 为什么有效

9.1 它解决了三个错位

flowchart TDP1["RL 太难起步"] --> S1["基座成功数据 + 保守 critic 初始化"]P2["专家轨迹太窄"] --> S2["让基座先走,再由专家恢复"]P3["直接改大 VLA 太贵"] --> S3["只训练小残差,最后普通 SFT"]S1 --> OUT["高成功率 + 更贴近部署 + 训练成本较低"]S2 --> OUTS3 --> OUT

9.2 和三种简单方案相比

方案 它教 VLA 什么 它缺什么
只用人类数据 正常情况下怎么做 错误状态的恢复
只用基座成功数据 VLA 已经会的路径 新能力和纠错动作
只用纯 RL 专家 一条很漂亮的专家路径 基座真实错误分布
PLD 基座会遇到什么问题,以及如何成功恢复 需要机器人交互和成功检测

9.3 最核心的因果链

flowchart LRA["基座先走"] --> B["进入基座常见错误状态"]B --> C["残差 RL 找到恢复动作"]C --> D["形成成功完整轨迹"]D --> E["SFT 学到恢复动作"]E --> F["下一次基座少失败或会自救"]

10. 论文结果:只看这几个数字

实验 基线 使用 PLD 后
LIBERO,\(\pi_0\) 平均成功率 93.4% 97.2%
LIBERO,OpenVLA 平均成功率 91.8% 99.2%
SimplerEnv 平均成功率 71.8% 96.6%
真实方块抓取,PLD 数据 - 30/30
真实方块抓取,纯 RL 专家数据 - 16/30
真实方块抓取,人类数据 - 10/30

这些结果支持的不是“残差专家可以替代 VLA”,而是:

用残差专家生成的数据,能比单纯的人类示范或纯专家 rollout 更适合改进通用 VLA。


11. 只保留必要的实现要点

残差 RL

项目 论文常用设置
offline / online 采样比例 1 : 1
batch size 256
折扣因子 \(\gamma\) 0.99
warmup episodes 100
残差尺度 \(\xi\) LIBERO 约 0.5;SimplerEnv 约 0.1
critic 两个 Clipped Double \(Q\)
critic 初始化 Cal-QL

数据采集

  • 每个任务训练一个残差专家。
  • 随机选择基座前缀长度 \(T_{base}\)
  • 成功才保存完整轨迹。
  • 失败轨迹用于 RL 探索,但不作为论文主 SFT 数据。

SFT

  • 多任务轨迹合并后再训练通用 VLA。
  • 标签是最终执行动作,不是残差动作。
  • 使用基座原来的动作头损失。
  • 论文采用 LoRA rank 32、8 张 L40 GPU。

12. 这个方法不是什么

不是直接 RL 微调大 VLA

大 VLA 在阶段 1 和阶段 2 都冻结。RL 只训练小型残差策略。

不是给 VLA 加一个永久外挂

残差策略只负责采数据。SFT 完成后,部署只需要一个 VLA。

不是随机给动作加噪声

PLD 的探索是“基座动作 + 学到的残差”,残差由 critic 引导,并且受到 \(\xi\) 限制。

不是把所有失败轨迹直接拿去 SFT

论文主方案保留的是能够最终完成任务的混合轨迹。失败轨迹主要帮助 RL 学习。

不是从零开始就完全无人监督

它仍需要一个已有一定能力的基座 VLA。真实实验也先用人类数据让基座达到可工作的水平。


13. 限制和现实边界

flowchart TDL1["基座完全不会做任务"] --> B1["很难收集成功离线种子"]L2["没有可靠成功检测"] --> B2["RL 和 SFT 数据都会被污染"]L3["探测时间过长"] --> B3["进入不可恢复状态"]L4["任务数量很多"] --> B4["每任务专家与奖励仍有成本"]L5["无限重复飞轮"] --> B5["论文尚未证明不会遗忘或退化"]

所以 PLD 更适合这样的场景:

  • 已有一个“基本会做,但不够稳”的 VLA;
  • 可以自动判断成功或失败;
  • 允许机器人进行一定量的在线交互;
  • 希望减少新增遥操作,而不是完全取消所有人工启动数据。

14. 一页纸总结

flowchart TDROOT["PLD"] --> Q1["问题:示范没有覆盖 VLA 自己的失败"]ROOT --> Q2["做法:冻结 VLA,训练小残差"]ROOT --> Q3["采数:VLA 前缀 + 残差恢复"]ROOT --> Q4["训练:完整成功轨迹做 SFT"]ROOT --> Q5["部署:只留下改进后的 VLA"]

最后再用一句话复述:

PLD 让 VLA 先犯自己会犯的错,再让小型 RL 专家把它救回来,最后把“如何自救”教回 VLA。

返回列表