🤖 roboto_origin_03 Wiki
首页 / 训练 / RND 好奇心探索与对称性增强

在足式机器人强化学习的训练过程中,稀疏奖励与策略不对称是两个常见且相互独立的难题:Random Network Distillation (RND) 通过为智能体提供内在好奇心奖励来缓解探索困难;对称性增强 (Symmetry Enhancement) 则利用足式机器人天然的左右对称结构,在数据层面与损失层面同时约束策略输出。本文档将系统解析这两个机制在本项目中的实现原理、算法集成方式与配置实践。

Sources: rnd.py, symmetry.py, ppo.py


RND 好奇心探索机制

核心原理与数学基础

Random Network Distillation (RND) 是一种基于预测误差的内在奖励方法。系统维护两个结构相同但角色迥异的 MLP 网络:一个是固定参数的随机目标网络 (target),另一个是可训练的预测网络 (predictor)。对于给定的状态输入 s,内在奖励定义为两网络输出嵌入的 L2 距离:

$$r_{\text{intrinsic}} = | f_{\text{target}}(s) - f_{\text{predictor}}(s) |_2$$

由于目标网络随机初始化后不再更新,预测网络仅在频繁访问的状态上降低误差;而在罕见状态上,预测误差保持较高,从而自然产生探索激励。该机制在足式机器人训练中尤为重要,可帮助策略突破局部最优步态,探索更广泛的姿态空间。

Sources: rnd.py

模块架构

RND 模块通过 obs_groups["rnd_state"] 从环境的 TensorDict 观测中提取指定状态子集作为输入。该设计允许使用者灵活选择哪些观测分量参与好奇心计算(例如仅使用本体感知信息,排除高度扫描等外部感知)。模块内部包含四层核心组件:

graph TD
    A[环境观测 TensorDict] -->|get_rnd_state| B[状态拼接]
    B --> C{state_normalization?}
    C -->|True| D[EmpiricalNormalization]
    C -->|False| E[Identity]
    D --> F[Target Network<br/>frozen MLP]
    E --> F
    D --> G[Predictor Network<br/>trainable MLP]
    E --> G
    F --> H[Target Embedding]
    G --> I[Predictor Embedding]
    H --> J[L2 Distance]
    I --> J
    J --> K{reward_normalization?}
    K -->|True| L[EmpiricalDiscountedVariationNormalization]
    K -->|False| M[Identity]
    L --> N{weight_scheduler?}
    M --> N
    N -->|scale| O[最终内在奖励]

Target Network 在初始化后永久设为 eval() 模式,其参数不参与梯度回传;Predictor Network 则由独立的 Adam 优化器驱动,在 PPO 的每次参数更新阶段进行训练。输入状态归一化与奖励归一化均为可选项:状态归一化采用标准的 EmpiricalNormalization 维护运行均值与方差;奖励归一化则使用 EmpiricalDiscountedVariationNormalization,通过折扣累计奖励的标准差进行缩放,以适配非平稳的奖励分布。

Sources: rnd.py, normalization.py

与 PPO 训练循环的集成

RND 并非独立算法,而是作为辅助模块嵌入标准 PPO 训练循环。其生命周期横跨三个阶段:

环境交互阶段 (process_env_step):每次环境步进后,RND 模块根据当前观测计算内在奖励,并直接与外在奖励相加。这一合并发生在 GAE 计算之前,因此内在奖励会自然参与优势估计与回报计算。值得注意的是,update_normalization 在此阶段同步更新状态归一化器的统计量。

回报计算阶段 (compute_returns):合并后的奖励流经标准 GAE 公式,优势函数与回报值均包含了好奇心驱动的信号。

参数更新阶段 (update):对每个 mini-batch,PPO 首先提取 rnd_state 并通过已更新的状态归一器,随后计算 predictor 与 target 的 MSE 损失。RND 的梯度经由独立优化器 rnd_optimizer 回传,与策略网络梯度在 reduce_parameters 中跨 GPU 聚合。

Sources: ppo.py, ppo.py

权重调度策略

RND 的内在奖励权重支持三种调度模式,避免好奇心信号在训练后期过度干扰已收敛的策略:

调度模式 说明 适用场景
constant 始终保持初始权重 探索需求持续稳定的任务
step 在指定步数后跳变至最终值 需要阶段性降低探索的精细调参
linear 在初始步与终止步之间线性插值 平滑衰减好奇心信号,最为常用

权重的实际生效值会在 get_intrinsic_reward 中根据 update_counter(每次环境步进递增)动态计算,并且会在配置解析阶段自动乘以 env.unwrapped.step_dt 进行时间尺度缩放。

Sources: rnd.py, rnd.py, rnd.py


对称性增强机制

生物学启发与足式机器人对称性

四足及双足机器人具有显著的左右镜像对称 (bilateral symmetry) 结构:左侧肢体与右侧肢体的运动学链呈镜像关系,对应的关节角度、角速度及力矩在坐标变换下遵循确定的符号翻转规则。利用这一先验,可以在不增加环境交互成本的前提下,将单条轨迹扩展为多条几何等价轨迹,同时约束策略在镜像观测下输出镜像动作,从而提升样本效率并抑制不对称步态。

Sources: atom01.py

两种工作模式

本项目中的对称性增强以配置驱动的方式在 PPO 中实现,提供两个互补的开关:

数据增强 (use_data_augmentation):在每次参数更新的 mini-batch 生成后,调用 data_augmentation_func 将原始观测与动作沿批次维度与镜像副本拼接,批次大小翻倍。对应地,优势估计、回报值、旧策略对数概率等标量亦通过 repeat 操作同步扩展。该模式直接增加了每个 epoch 的有效样本量。

镜像损失 (use_mirror_loss):要求策略网络在镜像观测上的确定性输出(act_inference 的 mean action),与原始观测输出的镜像变换结果一致。损失函数采用 MSE:

$$\mathcal{L}_{\text{symmetry}} = \text{MSE}\left( \mu(\text{mirror}(o)),\ \text{mirror}(\mu(o)) \right)$$

use_data_augmentation=True 时,系统复用已增强的批次计算镜像损失,避免重复调用变换函数;否则会在损失计算前单独执行一次观测增强。即使 use_mirror_loss=False,系统依然会计算并记录该损失值用于日志分析。

Sources: ppo.py, ppo.py

模式对比与选型建议

维度 数据增强 (use_data_augmentation) 镜像损失 (use_mirror_loss)
作用位置 Mini-batch 生成阶段 损失计算阶段
网络影响 Actor 与 Critic 均看到更多样本 仅约束 Actor 的均值输出
梯度来源 来自 PPO 标准目标函数 来自显式对称性正则项
与 RNN 兼容性 ❌ 不支持循环策略 ❌ 不支持循环策略
推荐系数 无需额外系数 mirror_loss_coeff 通常设为 0.2

两种模式可以单独启用,也可以同时启用。对于 ATOM01 的平坦地形训练,项目中通常同时开启以增强策略的泛化性与对称性。

Sources: ppo.py, atom01_agent_cfg.py

ATOM01 对称变换实现

对称变换是任务相关的,因为不同机器人的观测排列、关节顺序与符号约定各不相同。项目为 ATOM01 提供了两套实现,分别服务于 Direct RLManager-based AMP 环境。

Direct RL 实现 (robolab/tasks/direct/base/agents/atom01_agent_cfg.py) 采用基于索引的硬编码映射,通过预计算的 mirror_indicesmirror_signs 对 policy 观测、critic 观测和动作执行原地置换与符号翻转。由于 direct 环境的观测通常包含历史帧堆叠,函数通过 offset 循环扩展索引以覆盖所有历史步。

Manager-based AMP 实现 (robolab/tasks/manager_based/amp/mdp/symmetry/atom01.py) 则采用更语义化的分块变换。以 policy 观测为例,左右镜像变换涉及以下分量:

动作空间的变换同样遵循 _switch_joints_left_right 的约定,确保策略输出的力矩/位置指令在镜像后对应正确的肢体。

Sources: atom01_agent_cfg.py, atom01.py, atom01.py


联合训练架构与数据流

当 RND 与对称性增强同时启用时,PPO 的训练循环呈现如下数据流。该图展示了从环境交互到参数更新的完整路径,突出两个增强模块的介入点:

sequenceDiagram
    participant Env as 环境 (VecEnv)
    participant PPO as PPO 算法
    participant RND as RND 模块
    participant Sym as 对称性增强
    participant Pol as Actor-Critic 策略

    loop 每步环境交互
        Pol->>PPO: act(obs)
        PPO->>Env: step(actions)
        Env->>PPO: obs, rewards, dones, extras
        PPO->>RND: update_normalization(obs)
        RND->>PPO: intrinsic_rewards
        PPO->>PPO: rewards += intrinsic_rewards
        PPO->>PPO: storage.add_transition(...)
    end

    PPO->>Pol: evaluate(last_obs)
    PPO->>PPO: compute_returns (GAE)

    loop num_learning_epochs × num_mini_batches
        PPO->>PPO: 生成 mini-batch
        alt use_data_augmentation
            PPO->>Sym: data_augmentation_func(obs, actions)
            Sym->>PPO: obs_aug, actions_aug (batch×2)
            PPO->>PPO: 重复 advantages/returns/old_log_prob
        end

        PPO->>Pol: act(obs_batch) → log_prob, entropy
        PPO->>Pol: evaluate(obs_batch) → values
        PPO->>PPO: surrogate_loss + value_loss - entropy

        alt use_mirror_loss
            PPO->>Pol: act_inference(obs_aug)
            PPO->>Sym: mirror(mean_actions_original)
            PPO->>PPO: MSE(mean_actions_mirrored, mirror(mean_actions_original))
            PPO->>PPO: loss += mirror_loss_coeff × symmetry_loss
        end

        alt rnd enabled
            PPO->>RND: predictor(rnd_state), target(rnd_state)
            PPO->>PPO: MSE(predictor_embedding, target_embedding)
        end

        PPO->>PPO: optimizer.zero_grad(); loss.backward()
        PPO->>PPO: rnd_optimizer.zero_grad(); rnd_loss.backward()
        PPO->>PPO: clip_grad_norm + step()
    end

复合损失函数

在一次参数更新迭代中,总损失由以下四项线性叠加而成:

$$\mathcal{L}{\text{total}} = \mathcal{L}{\text{surrogate}} + c_{\text{value}} \mathcal{L}{\text{value}} - c{\text{entropy}} \mathcal{H} + c_{\text{mirror}} \mathcal{L}_{\text{symmetry}}$$

RND 的预测器拥有独立的优化器,不直接参与上述总损失,而是通过 rnd_loss 单独优化:

$$\mathcal{L}{\text{RND}} = \text{MSE}\left( f{\text{predictor}}(s_{\text{rnd}}),\ f_{\text{target}}(s_{\text{rnd}}) \right)$$

在分布式多卡训练中,策略梯度与 RND 梯度会在 reduce_parameters 中拼接为单一张量,通过 all_reduce 聚合后再写回各参数,确保所有 GPU 的参数更新一致性。

Sources: ppo.py, ppo.py, ppo.py


配置指南与最佳实践

RND 配置示例

RND 通过 algorithm 配置中的 rnd_cfg 字段启用。以下为一个适用于 ATOM01 粗糙地形训练的参考配置:

from isaaclab_rl.rsl_rl import RslRlRndCfg

algorithm = RslRlPpoAlgorithmCfg(
    # ... 其他 PPO 参数 ...
    rnd_cfg=RslRlRndCfg(
        num_outputs=64,                    # 嵌入维度
        predictor_hidden_dims=[256, 128],  # 预测网络隐层
        target_hidden_dims=[256, 128],     # 目标网络隐层
        activation="elu",
        weight=1.0,                        # 内在奖励初始权重(会自动乘以 step_dt)
        state_normalization=True,
        reward_normalization=True,
        learning_rate=1e-3,                # RND 独立优化器学习率
        weight_schedule={
            "mode": "linear",
            "initial_step": 0,
            "final_step": 5000,
            "final_value": 0.1
        }
    )
)

观测组配置:启用 RND 时,obs_groups 必须包含 "rnd_state" 键,用于指定参与 RND 计算的观测分量。resolve_rnd_config 会在 runner 初始化时自动统计该组观测的总维度并写入配置。

Sources: rnd.py, on_policy_runner.py

对称性配置示例

对称性配置同样位于 algorithm 字段下,需提供一个可调用对象作为数据增强函数:

from isaaclab_rl.rsl_rl import RslRlSymmetryCfg
from robolab.tasks.direct.base.agents.atom01_agent_cfg import data_augmentation_func

algorithm = RslRlPpoAlgorithmCfg(
    # ... 其他 PPO 参数 ...
    symmetry_cfg=RslRlSymmetryCfg(
        use_data_augmentation=True,
        use_mirror_loss=True,
        mirror_loss_coeff=0.2,
        data_augmentation_func=data_augmentation_func
    )
)

若通过字符串方式引用跨模块的函数,可利用 resolve_callable 支持的 "module.path:function_name" 格式,例如: data_augmentation_func="robolab.tasks.manager_based.amp.mdp.symmetry.atom01:compute_symmetric_states"

Sources: symmetry.py, ppo.py, utils.py

关键超参数建议

参数 推荐值 说明
rnd_cfg.weight 0.5 ~ 2.0 需与环境外在奖励的量级匹配,过大将导致策略只追求新奇状态
rnd_cfg.predictor_hidden_dims [256, 128][512, 256] 容量应足够拟合目标网络,但不宜超过策略网络
mirror_loss_coeff 0.1 ~ 0.3 过高会过度约束策略灵活性,抑制必要的非对称调整
num_outputs (RND) 32 ~ 128 嵌入维度过低会丢失状态区分度,过高增加计算开销
weight_schedule.final_step 总迭代数的 10% ~ 50% 好奇心信号应在策略基本掌握运动技能后逐步衰减

保存与恢复

OnPolicyRunner 在保存模型时会自动将 RND 的 state_dictrnd_optimizer_state_dict 写入检查点;加载时亦会自动恢复。对称性增强本身不引入额外可训练参数,因此无需单独保存。

Sources: on_policy_runner.py


与其他模块的关系

RND 与对称性增强均通过配置开关独立启用,二者互不干扰,但共享相同的 PPO 训练循环。理解它们与周边模块的协作关系有助于进行系统性调试: