┌────────────────────────────────────────────────────────────────┐
│ 双策略PPO系统架构 │
└────────────────────────────────────────────────────────────────┘
│
│
┌─────────────────────┼─────────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 环境交互 │ │ 策略网络 │ │ 好奇心模块 │
│ Environment │◄──►│ Networks │◄───►│ Curiosity │
└──────────────┘ └──────────────┘ └──────────────┘
│ │ │
│ ┌────────┴────────┐ │
│ │ │ │
▼ ▼ ▼ ▼
┌──────────────┐ ┌─────────┐ ┌─────────┐ ┌──────────┐
│ 经验缓冲区 │ │主策略 │ │对手策略 │ │内在奖励 │
│ ReplayBuffer │ │π_actor │ │π_opponent│ │Intrinsic │
└──────────────┘ └─────────┘ └─────────┘ └──────────┘
│ │ │ │
└─────────────────┴───────────┴─────────────┘
│
▼
┌──────────────┐
│ 训练器 │
│ Trainer │
└──────────────┘
位置: dual_policy_ppo.py
职责: 策略和价值函数的神经网络表示
架构:
输入: 状态 s ∈ ℝ^d
│
▼
┌─────────────────┐
│ 共享特征层 │
│ (2层MLP + LN) │
└─────────────────┘
│
├────────────────┬────────────────┐
▼ ▼ │
┌────────┐ ┌────────┐ ┌────────┐
│Actor头 │ │Critic头 │ │ │
│(策略) │ │(价值) │ │ │
└────────┘ └────────┘ └────────┘
│ │ │
▼ ▼ ▼
π(a|s) V(s) (特征)
关键特性:
- 支持离散和连续动作空间
- 使用LayerNorm提升训练稳定性
- 正交初始化加速收敛
- 共享特征提取层减少参数
输出:
- 动作分布:
π(a|s)(Categorical或Normal) - 状态价值:
V(s)(标量)
位置: dual_policy_ppo.py
职责: 生成内在奖励,引导探索
架构:
状态 s_t, 动作 a_t, 下一状态 s_{t+1}
│
├────────────────────────┬────────────────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│特征编码器 │ │特征编码器 │ │ │
│ φ(s_t) │ │ φ(s_{t+1})│ │ │
└──────────┘ └──────────┘ └──────────┘
│ │ │
├────────────────────────┼────────────────────────┤
│ │ │
▼ │ ▼
┌──────────────────┐ │ ┌──────────────┐
│ 前向动力学模型 │ │ │逆向动力学模型 │
│ f: (φ(s_t), a_t)│ │ │g: (φ(s_t), │
│ → φ(s_{t+1})│ │ │ φ(s_{t+1}))│
└──────────────────┘ │ │ → a_t │
│ │ └──────────────┘
│ │ │
▼ ▼ ▼
┌──────────────────┐ ┌──────────┐ ┌──────────────┐
│ 预测误差 │ │真实特征 │ │ 动作预测 │
│ ŷ = f(φ(s), a) │ │y = φ(s') │ │ â = g(...) │
└──────────────────┘ └──────────┘ └──────────────┘
│ │ │
└────────────────────────┤ │
▼ ▼
好奇心奖励 = ||ŷ - y||² 逆向损失
关键公式:
- 前向损失:
L_forward = ||f(φ(s_t), a_t) - φ(s_{t+1})||² - 逆向损失:
L_inverse = CE(g(φ(s_t), φ(s_{t+1})), a_t) - 好奇心:
curiosity = L_forward(预测误差)
设计理念:
- 前向模型: 预测误差越大 → 状态越新奇
- 逆向模型: 学习特征空间,使得特征包含与动作相关的信息
- 特征编码: 降维,提取关键信息
位置: dual_policy_ppo.py
职责: 统一的探索-利用-稳定性框架
核心机制:
r_intrinsic = curiosity(s, a) × [1 - KL(π_actor || π_opponent)]可视化:
高好奇心 + 低KL散度 = 高内在奖励 ✓ (有价值的新奇)
高好奇心 + 高KL散度 = 低内在奖励 ✗ (危险的新奇)
低好奇心 + 低KL散度 = 低内在奖励 ✓ (已知状态)
低好奇心 + 高KL散度 = 低内在奖励 ✗ (不合理的偏离)
L_total = L_PPO + λ_intrinsic × E[r_intrinsic] - λ_KL × KL(π || π_opp)
───┬─── ─────────┬──────────────── ──────────┬──────────
│ │ │
标准PPO 探索激励 稳定性约束各项解释:
L_PPO: 标准PPO裁剪损失,优化策略性能λ_intrinsic × E[r_intrinsic]: 内在奖励的期望,鼓励探索λ_KL × KL(π || π_opp): KL散度惩罚,防止偏离对手策略过远
每隔 N 个回合:
if 性能稳定提升:
π_opponent ← π_actor # 更新对手策略
else:
保持 π_opponent 不变 # 继续使用旧锚点
条件: 连续N个回合性能单调递增
意义:
- 对手策略代表"可达到的优秀性能"
- 避免过于保守(对手策略太弱)
- 避免过于激进(对手策略过强)
位置: trainer.py
职责: 管理训练循环和环境交互
训练流程:
初始化
│
▼
┌────────────────────────────────────┐
│ 收集经验 (collect_experience) │
│ - 与环境交互 │
│ - 存储到缓冲区 │
└────────────────────────────────────┘
│
▼
┌────────────────────────────────────┐
│ 更新策略 (agent.update) │
│ - 计算内在奖励 │
│ - 计算GAE优势 │
│ - 多轮PPO更新 │
└────────────────────────────────────┘
│
▼
┌────────────────────────────────────┐
│ 评估 (evaluate) │
│ - 确定性策略评估 │
│ - 记录性能 │
└────────────────────────────────────┘
│
▼
┌────────────────────────────────────┐
│ 更新对手策略 │
│ (update_opponent_policy) │
│ - 检查性能趋势 │
│ - 决定是否更新 │
└────────────────────────────────────┘
│
▼
回到"收集经验"或结束
环境 → 状态 s_t
│
▼
主策略 π_actor
│
├─────────────┐
│ │
▼ ▼
动作 a_t 状态价值 V(s_t)
│ │
▼ │
环境执行动作 │
│ │
▼ │
(s_{t+1}, r_t, done) │
│ │
└─────┬───────┘
│
▼
存入经验缓冲区
│
▼
计算内在奖励
r_int = Curiosity × (1 - KL)
│
▼
总奖励 = r_t + λ × r_int
│
▼
计算GAE优势
│
▼
PPO策略更新
(s_t, a_t, s_{t+1})
│
├──────────────┬──────────────┐
│ │ │
▼ ▼ ▼
特征编码 好奇心计算 KL散度计算
φ(s_t), Curiosity KL(π_actor||
φ(s_{t+1}) │ π_opponent)
│ │ │
└──────────────┼──────────────┘
▼
r_int = Curiosity × (1 - KL)
| 参数 | 符号 | 默认值 | 作用 | 调优建议 |
|---|---|---|---|---|
| 内在奖励系数 | λ_intrinsic | 0.1 | 控制探索强度 | 稀疏奖励↑, 密集奖励↓ |
| KL散度系数 | λ_KL | 0.01 | 控制稳定性 | 震荡环境↑, 稳定环境↓ |
| KL散度阈值 | ε_KL | 0.3 | 内在奖励抑制点 | 需快速探索↑, 需稳定↓ |
| 对手更新间隔 | N_update | 10 | 对手策略更新频率 | 快速适应↓, 长期稳定↑ |
| 学习率 | α | 3e-4 | 优化器步长 | 大环境↓, 小环境可保持 |
| 折扣因子 | γ | 0.99 | 未来奖励权重 | 长期任务↑ (如0.995) |
| PPO裁剪 | ε_clip | 0.2 | 策略更新幅度限制 | 标准值即可 |
intrinsic_coef: 0.2 - 0.3 # 更强探索
kl_coef: 0.01
kl_threshold: 0.3 - 0.5 # 允许更大偏离intrinsic_coef: 0.03 - 0.08 # 较弱探索
kl_coef: 0.015 - 0.02 # 更强稳定约束
kl_threshold: 0.2 - 0.25 # 更严格阈值kl_coef: 0.02 - 0.03 # 显著增强稳定性
update_opponent_interval: 15 # 更长的稳定期传统方法 (加法):
r_total = r_external + λ₁ × Curiosity - λ₂ × KL
问题: 好奇心和KL约束是独立的,可能冲突
我们的方法 (乘法):
r_total = r_external + λ × [Curiosity × (1 - KL/ε)]
优势:
- 自然融合:只有"安全的新奇"才获得奖励
- 自动平衡:高KL自动抑制高好奇心
- 语义清晰:内在奖励 = 信息增益 × 安全性
双策略系统:
主策略: 探索 + 利用
对手策略: 保守锚点
优势:
- 有界探索:
KL(π_actor || π_opponent) ≤ ε保证不会偏离过远 - 动态锚点: 对手策略会更新,不会过于保守
- 单调改进: 只在性能提升时更新,保证长期进步
定理(非正式): 在合理假设下,双策略PPO收敛到局部最优策略。
关键观察:
- PPO本身有收敛保证(单调改进)
- KL约束限制了策略变化范围(有界)
- 对手策略更新机制保证长期性能不下降(单调性)
- 内在奖励随探索充分逐渐降低(收敛)
非正式推理:
性能 P(t) 随时间单调递增或稳定
⇒ 对手策略 π_opp(t) 单调改进
⇒ KL约束变紧但主策略仍能改进
⇒ 最终收敛到 π* 附近
| 方法 | 探索机制 | 稳定性机制 | 耦合方式 |
|---|---|---|---|
| 标准PPO | 熵正则 | PPO裁剪 | N/A |
| PPO + ICM | 好奇心(ICM) | PPO裁剪 | 独立(加法) |
| PPO + RND | 随机网络 | PPO裁剪 | 独立(加法) |
| TRPO变体 | 熵正则 | KL约束 | 独立 |
| 双策略PPO ⭐ | 可控好奇心 | 对手策略+KL | 协同(乘法) |
关键创新: 探索和稳定性的协同设计,而非独立模块。
- 样本效率高: 内在奖励引导高效探索
- 训练稳定: 对手策略锚定,防止崩溃
- 通用性强: 离散/连续,稀疏/密集均适用
- 可解释性: 每个组件作用明确
- 额外计算: 需要维护两个策略网络和好奇心模块
- 超参数: 引入了额外的超参数(但含义清晰)
- 内存开销: 对手策略需要额外内存
✅ 特别适合:
- 稀疏奖励环境
- 易震荡的连续控制
- 需要平衡探索和稳定的任务
- 极简单的任务(开销大于收益)
- 完全随机环境(好奇心失效)
- 资源极度受限场景
λ_intrinsic(t) = f(exploration_progress, performance)
λ_KL(t) = g(policy_variance, training_stability)π_opponents = {π₁, π₂, ..., πₖ} # 历史多个策略
KL_multi = E_i[KL(π || πᵢ)]# 快速适应新环境
θ* = MAML(θ, {task_1, ..., task_n})# 高层策略选择子目标
# 低层策略执行具体动作
r_intrinsic_high = curiosity_high(subgoal)
r_intrinsic_low = curiosity_low(action | subgoal)- PPO: Schulman et al. (2017) - Proximal Policy Optimization
- ICM: Pathak et al. (2017) - Curiosity-driven Exploration
- Trust Region: Schulman et al. (2015) - Trust Region Policy Optimization
- RND: Burda et al. (2018) - Random Network Distillation
- NGU: Badia et al. (2020) - Never Give Up
- Ape-X: Horgan et al. (2018) - Distributed Prioritized Experience Replay
本架构文档持续更新
如有疑问或建议,欢迎提Issue!