DPPO 策略¶
在 server 侧运行 diffusion 风格策略并与 DPPO 算法配合;流策略则可以配 DPPO 或 FPO。
本页包含:
- 内置
dppo-policy - 内置
pi0-policy(OpenPI PI0) - 用
BasePolicyGradientDiffusionPolicy实现自定义 diffusion policy,或用BasePolicyGradientFlowPolicy实现流策略
快速开始¶
DPPO 策略。
OpenPI PI0 策略(需要 checkpoint 目录)。它是流策略,可以配 eval、fpo 和
dppo。前两条是
E11
实际跑的命令,去掉了端口、日志和输出目录相关的参数。第三条用的是
E25
的算法设置,E25 用它完整跑通过。
# evaluation - no learning
plugrl-run-server pi0-policy default eval default \
--policy.name pi05_libero \
--policy.checkpoint-path /path/to/pi0_checkpoint \
--policy.device cuda
# FPO fine-tuning
plugrl-run-server pi0-policy default fpo default \
--policy.name pi05_libero \
--policy.checkpoint-path /path/to/pi0_checkpoint \
--policy.device cuda \
--algo.learning-rate 1e-5 --algo.batch-size 8 \
--algo.num-updates-per-batch 4 --algo.n-samples-per-action 4 \
--algo.buffer-size 4096 --algo.clipping-epsilon 0.05 \
--algo.global-steps 40960 --algo.save-interval 1
# DPPO fine-tuning
plugrl-run-server pi0-policy default dppo libero \
--policy.name pi05_libero \
--policy.checkpoint-path /path/to/pi0_checkpoint \
--policy.device cuda \
--algo.buffer-size 4096 --algo.batch-size 8 \
--algo.train-itrs 2 --algo.save-interval 1
验证¶
先列出已注册的策略,再看某个策略有哪些变体。
外部包策略先 import 再进入 CLI。
python -c "import my_pkg.plugrl_policies; from plugrl_server.cli import main; main()" \
my-dppo-policy default dummy default
内置:dppo-policy¶
- UID:
dppo-policy - 代码:
plugrl-server/src/plugrl_server/policy/dppo/dppo_policy.py - 依赖:server 环境里要装
dppo可选依赖。没装的话 CLI 里就没有dppo-policy。- uv:在
plugrl-server执行uv sync --extra dppo。
- uv:在
- 变体,各自配同名的
dppo变体:default和hopper:gymhopper-medium-v2walker:gymwalker2d-medium-v2cheetah:gymhalfcheetah-medium-v2square:robomimicsquare,只微调 20 个去噪步里的最后 10 个
- 加载:
plugrl_server/meta/dppo/cfg/<env_type>/<env_name>.yamlplugrl_server/meta/dppo/asset/<env_type>/<env_name>/normalization.npz--policy.checkpoint-path加载 DPPO 预训练 checkpoint(.pt),有ema权重时用ema。不给的话网络从随机初始化开始。- 观测:期望 worker 观测包含
states,并按low_dim_keys拼接。
常用参数。
--policy.env-type gym--policy.env-name hopper-medium-v2--policy.checkpoint-path /path/to/checkpoint.pt--policy.ft-denoising-steps 10:只微调去噪链最后 10 步。前面的步骤用加载进来的 网络的冻结副本跑,只有最后 10 步会被记录下来用于训练。不设则每一步都微调。square设的就是 10。--policy.critic.*
内置:pi0-policy(OpenPI)¶
- UID:
pi0-policy - 代码:
plugrl-server/src/plugrl_server/policy/openpi/openpi_policy.py - 是流策略(
BasePolicyGradientFlowPolicy),可以配eval、fpo,也可以通过libero变体配dppo。 --policy.checkpoint-path必填,目录内需要:model.safetensorsassets/(归一化统计)- 本地安装/替换步骤见:
plugrl-server/src/plugrl_server/policy/openpi/README.md。 没装 OpenPI 时 CLI 里没有pi0-policy。
常用参数。
--policy.name pi05_libero--policy.denoising-steps 5--policy.train-expert-only:只训练 action expert,视觉语言模型冻结。这是默认值;--policy.no-train-expert-only两者一起训练。--policy.default-prompt "..."
自定义 diffusion policy¶
继承 BasePolicyGradientDiffusionPolicy:
plugrl-server/src/plugrl_server/policy/base_policy_gradient_diffusion_policy.py。
基类负责 denoising 循环并填充 DiffusionRuntimeState:
runtime_state.obs是一个DiffusionObsdataclass,字段为x、t、cond。- 每个被记录的步骤写入:
action、logprob、entropy,以及obs.x、obs.t。 只记录最后num_recorded_denoising_steps步。默认就是全部步骤,除非策略覆写这个 属性,dppo-policy为了--policy.ft-denoising-steps就覆写了它。 - 最终调用
_postprocess_action,把模型观测存进obs.cond,把 value 写入runtime_state.value。
你需要实现。
- 在
__init__里设置action_dim、action_horizon和num_denoising_steps。fake_runtime_state按它们构造形状,server 也会把前两个放进 metadata 消息发给 client。 - 一个
actor模块和一个critic模块(value head)。没有 critic 时dppo会报DPPO requires a critic.,它的优化器也是从policy.actor和policy.critic建的。fpo优化的也是这两个。 prepare_observation,把 worker 观测转成数组_get_timesteps、_initialize_x、_denoising_step、_iterative_process_action、_postprocess_actionfake_diffusion_cond(用于 buffer 预分配)_get_value。它不是 abstract,但基类会把它的返回值写进runtime_state.value, 所以不实现它会在 rollout 中途报TypeError: can't assign a NoneType to a torch.FloatTensor。- 可选
build_obs_cache(缓存昂贵的条件编码)。基类每次推理调用它一次, 结果以 keyword-only 的cond_cache=传给_denoising_step, 以obs_cache=传给_get_value。
训练时 dppo 会再调用 _denoising_step,这时 x 的 batch 是 B * S(每个被记录
的步骤一条),cond 的 batch 是 B,而且不传 cond_cache。两者不一致时用
repeat_interleave 扩展 cond,dppo-policy 就是这么做的。
关键形状(来自 fake_runtime_state),其中 S = num_recorded_denoising_steps、
H = action_horizon、D = action_dim。
action、logprob、entropy、obs.x:(B, S, H, D)obs.t:(B, S)value:(B,)
最小模板。
import dataclasses
from typing import Any
import numpy as np
import torch
from plugrl_server.policy.base_policy_gradient_diffusion_policy import (
BasePolicyGradientDiffusionPolicy,
BasePolicyGradientDiffusionPolicyConfig,
TorchTree,
)
from plugrl_server.policy.registration import register_policy, register_policy_config
UID = "my-dppo-policy"
@register_policy_config(UID)
@dataclasses.dataclass
class MyDPPOPolicyConfig(BasePolicyGradientDiffusionPolicyConfig):
checkpoint_path: str | None = None
@register_policy(UID)
class MyDPPOPolicy(BasePolicyGradientDiffusionPolicy):
def __init__(self, config: MyDPPOPolicyConfig):
super().__init__(config)
self.actor = ... # torch.nn.Module
self.critic = ... # torch.nn.Module, the value head
self.action_dim = ...
self.action_horizon = ...
self.num_denoising_steps = ...
def prepare_observation(self, _obs: dict) -> dict[str, np.ndarray]:
...
def _get_timesteps(self) -> torch.Tensor:
...
def _initialize_x(self, batch_size: int) -> torch.Tensor:
...
def _denoising_step(
self,
x: torch.Tensor,
t: torch.Tensor,
cond: TorchTree,
x_next: torch.Tensor | None = None,
*,
cond_cache: Any = None,
sampling_noise_level: float | None = None,
) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
...
def _iterative_process_action(self, action: torch.Tensor) -> torch.Tensor:
return action
def _postprocess_action(self, action: torch.Tensor, obs: TorchTree) -> Any:
...
def _get_value(self, obs: TorchTree, obs_cache: Any = None) -> torch.Tensor:
...
def fake_diffusion_cond(self, batch_size: int) -> TorchTree:
...
流策略¶
base_policy_gradient_flow_policy.py 里的 BasePolicyGradientFlowPolicy 继承自
diffusion 基类,并替你实现了 _denoising_step:沿预测的速度场走一个 Euler 步。
fpo 要求策略基于它。子类需要:
- 实现
_predict_v(x, t, cond, *, cond_cache=None),返回速度,代替_denoising_step; - 在
__init__里设置dt。内置策略从t = 1走到t = 0,用dt = -1.0 / num_denoising_steps; - 实现上面清单里的其余部分。
不给采样噪声时这一步是确定性的,log-probability 为 0。dppo 会传入噪声,让这一步
变成随机的,dppo 正是这样训练流策略的。可以参考 fpo-policy 和 pi0-policy。
LeRobot 示例¶
参考 plugrl-server/examples/lerobot/lerobot_diffusion.py(UID = "lerobot-diffusion-policy")。
可复用模式。
- 把多步观测打包成一个 batched 的嵌套
dict(这就是TorchTree),基类会替你转成张量。 - 在
build_obs_cache缓存 encoder 输出。 - 用
repeat_interleave支持上面说的B * S扩展 batch。 - 确定性采样可像
Pi0Policy一样返回全 0 的logprob。 - 随机采样按分布计算
logprob/entropy,与DPPOPolicy对齐。
常见问题¶
- CLI 里没有
dppo-policy:在运行plugrl-run-server的环境里安装dppo可选依赖。 - CLI 里没有
pi0-policy,或它启动失败:按 OpenPI README 完成本地设置。 - 报
DPPO requires a critic.:在__init__里设置self.critic。 - 训练 shape 对不上:动作形状要稳定,runtime state 字段要与 buffer 对齐。
- CLI 找不到 UID:注册模块没有被 import。