# 第11章 强化学习：让机器人通过试错学习

> 原课程: Robots That Learn, UC Berkeley CS294-291, Spring 2026
> 主讲: Jitendra Malik
> 本章基于 Lecture 7: Reinforcement Learning
> 核心参考: Sutton & Barto, *Reinforcement Learning: An Introduction*, 2nd ed. (2018);
> Haarnoja et al., "Learning to Walk via Deep RL," RSS 2019;
> OpenAI et al., "Learning Dexterous In-Hand Manipulation," IJRR 2020

---

## 一、本章概要

**核心问题**: 机器人面对连续高维动作空间、非线性动力学和部分可观测的物理环境，如何通过与环境交互、试错来学习最优行为策略？传统控制方法(第8章)依赖精确的系统动力学模型 $$\dot{\mathbf{x}} = f(\mathbf{x}, \mathbf{u})$$，而强化学习(Reinforcement Learning, RL)提供了一条根本不同的路径: 让机器人与环境反复交互，直接从原始感知输入中端到端地学习策略，无需显式建模 $$f$$。

**与前后章节的逻辑关系**: 第8章(机器人动力学与控制)建立了基于模型的控制范式(LQR, MPC)——这些方法在模型精确时表现优异，但在非结构化环境中建模误差会累积。本章引入的无模型(model-free)RL范式恰好弥补了这一缺陷。第10章(视频世界模型)构建环境的预测模型，RL策略可以在学到的世界模型中进行"想象性"训练。第14章(RMA运动控制)和第16章(灵巧操作)中的sim-to-real迁移均以本章的PPO/SAC/域随机化为方法论基础。

**本章路线图**: 从MDP的形式化定义出发，逐层构建Bellman方程→值迭代的收缩性证明→策略梯度定理的完整推导→GAE的方差-偏差权衡→PPO的裁剪代理目标→SAC的最大熵框架与重参数化，最后深入两个机器人学中的里程碑应用——四足行走(SAC+层次化控制)和五指灵巧手操作(PPO+LSTM+非对称Actor-Critic)。

**前置知识提示**: 本章假设读者已掌握基本的概率论(期望、条件概率、KL散度)、线性代数(矩阵微分)和深度学习(反向传播、MLP架构)。如果你对RL完全陌生，建议先阅读Sutton & Barto(2018)第3-6章和第13章作为入门。

在正式开始之前，值得记住Richard Sutton在"The Bitter Lesson"中的核心洞察:**利用计算能力的大规模方法最终会战胜依赖人类知识的精巧方法**。这一原则在机器人RL中体现为: 与其手工设计复杂的控制器，不如让学习算法在海量模拟交互中发现控制策略。但机器人RL也有其独特的"苦涩": 物理交互不可无限并行化，sim-to-real鸿沟意味着在模拟器中完美的策略不一定在真实世界中工作。本章正是围绕这一核心张力展开。

---

## 二、数学基础: 从MDP到SAC的完整推导

### 2.1 马尔可夫决策过程(MDP)的形式化

RL的数学语言是马尔可夫决策过程(Markov Decision Process, MDP)，定义为一个六元组:

$$\mathcal{M} = (\mathcal{S}, \mathcal{A}, P, R, \gamma, \rho_0)$$

| 符号 | 数学定义 | 机器人学中的具体实例 |
|------|---------|---------------------|
| $$\mathcal{S} \subseteq \mathbb{R}^{d_s}$$ | 状态空间 | 关节角度 $$\mathbf{q} \in \mathbb{R}^{12}$$、角速度 $$\dot{\mathbf{q}}$$、IMU读数(6维)、足底接触力(4维) → $$d_s \approx 34$$ |
| $$\mathcal{A} \subseteq \mathbb{R}^{d_a}$$ | 动作空间 | 关节力矩 $$\boldsymbol{\tau}$$ (直接力矩控制) 或目标关节角度 $$\mathbf{q}_{\text{des}}$$ (PD控制) |
| $$P: \mathcal{S} \times \mathcal{A} \to \Delta(\mathcal{S})$$ | 状态转移概率 | 物理引擎前向动力学 $$P(\mathbf{s}' \mid \mathbf{s}, \mathbf{a})$$ (确定性或加噪声) |
| $$R: \mathcal{S} \times \mathcal{A} \to \mathbb{R}$$ | 奖励函数 | $$w_v v_x - w_e \|\boldsymbol{\tau}\|^2 + w_a \cdot \mathbb{1}_{\text{alive}}$$ |
| $$\gamma \in [0, 1)$$ | 折扣因子 | 典型值 $$0.99$$ (有效时间尺度 $$\frac{1}{1-\gamma} = 100$$ 步) |
| $$\rho_0 \in \Delta(\mathcal{S})$$ | 初始状态分布 | 机器人从随机姿态复位 |

**马尔可夫性质**的形式化:

$$P(\mathbf{s}_{t+1} \mid \mathbf{s}_t, \mathbf{a}_t, \mathbf{s}_{t-1}, \mathbf{a}_{t-1}, \ldots, \mathbf{s}_0) = P(\mathbf{s}_{t+1} \mid \mathbf{s}_t, \mathbf{a}_t)$$

在真实机器人系统中，这一假设通常**不成立**。原因有三:(1) 单帧关节角度观测不包含速度信息，速度需要通过差分或滤波推断——需要历史；(2) 地面摩擦系数、负载质量、执行器温度等不能被直接观测，但严重影响动力学；(3) 传感器存在延迟与噪声。应对策略: 用LSTM/GRU将观测历史压缩为隐状态 $$\mathbf{h}_t$$，构造增广状态 $$\hat{\mathbf{s}}_t = [\mathbf{o}_t; \mathbf{h}_{t-1}]$$ 近似恢复马尔可夫性。

**轨迹与回报**: 策略 $$\pi: \mathcal{S} \to \Delta(\mathcal{A})$$ 产生轨迹 $$\tau = (\mathbf{s}_0, \mathbf{a}_0, r_0, \mathbf{s}_1, \ldots)$$，其折扣累积回报为:

$$G_t = \sum_{k=0}^{\infty} \gamma^k R(\mathbf{s}_{t+k}, \mathbf{a}_{t+k})$$

RL的核心目标: $$\pi^* = \arg\max_{\pi} J(\pi) = \arg\max_{\pi} \mathbb{E}_{\tau \sim \pi}[\sum_{t=0}^{\infty} \gamma^t R(\mathbf{s}_t, \mathbf{a}_t)]$$

### 2.2 Bellman方程与最优性的完整证明

**状态值函数** $$V^{\pi}: \mathcal{S} \to \mathbb{R}$$:

$$V^{\pi}(\mathbf{s}) = \mathbb{E}_{\pi}\left[\sum_{k=0}^{\infty} \gamma^k R(\mathbf{s}_{t+k}, \mathbf{a}_{t+k}) \;\middle\vert \; \mathbf{s}_t = \mathbf{s}\right]$$

**动作值函数** $$Q^{\pi}: \mathcal{S} \times \mathcal{A} \to \mathbb{R}$$:

$$Q^{\pi}(\mathbf{s}, \mathbf{a}) = \mathbb{E}_{\pi}\left[\sum_{k=0}^{\infty} \gamma^k R(\mathbf{s}_{t+k}, \mathbf{a}_{t+k}) \;\middle\vert \; \mathbf{s}_t = \mathbf{s}, \mathbf{a}_t = \mathbf{a}\right]$$

两者关系: $$V^{\pi}(\mathbf{s}) = \mathbb{E}_{\mathbf{a} \sim \pi(\cdot \mid \mathbf{s})}[Q^{\pi}(\mathbf{s}, \mathbf{a})]$$

#### 2.2.1 Bellman期望方程的推导

将 $$G_t = R(\mathbf{s}_t, \mathbf{a}_t) + \gamma G_{t+1}$$ 代入 $$V^{\pi}$$ 的定义:

$$\begin{aligned}
V^{\pi}(\mathbf{s}) &= \mathbb{E}_{\pi}\left[R(\mathbf{s}_t, \mathbf{a}_t) + \gamma \sum_{k=0}^{\infty} \gamma^k R(\mathbf{s}_{t+1+k}, \mathbf{a}_{t+1+k}) \;\middle\vert \; \mathbf{s}_t = \mathbf{s}\right] \\[4pt]
&= \mathbb{E}_{\mathbf{a} \sim \pi(\cdot \mid \mathbf{s})}\left[R(\mathbf{s}, \mathbf{a}) + \gamma \, \mathbb{E}_{\mathbf{s}' \sim P(\cdot \mid \mathbf{s}, \mathbf{a})}[V^{\pi}(\mathbf{s}')]\right]
\end{aligned}$$

Q函数的Bellman期望方程:

$$Q^{\pi}(\mathbf{s}, \mathbf{a}) = R(\mathbf{s}, \mathbf{a}) + \gamma \, \mathbb{E}_{\mathbf{s}' \sim P(\cdot \mid \mathbf{s}, \mathbf{a})}\left[\mathbb{E}_{\mathbf{a}' \sim \pi(\cdot \mid \mathbf{s}')}[Q^{\pi}(\mathbf{s}', \mathbf{a}')]\right]$$

**优势函数**: $$A^{\pi}(\mathbf{s}, \mathbf{a}) = Q^{\pi}(\mathbf{s}, \mathbf{a}) - V^{\pi}(\mathbf{s})$$。直接的性质: $$\mathbb{E}_{\mathbf{a} \sim \pi}[A^{\pi}(\mathbf{s}, \mathbf{a})] = 0$$ (动作的期望优势恒为零)。$$A^{\pi}(\mathbf{s}, \mathbf{a}) > 0$$ 表示该动作好于策略平均，应增加其概率；$$A^{\pi} < 0$$ 反之。优势函数构成了所有Actor-Critic方法方差削减的理论基础。

#### 2.2.2 Bellman最优性方程

定义最优值函数: $$V^*(\mathbf{s}) = \max_{\pi} V^{\pi}(\mathbf{s})$$, $$Q^*(\mathbf{s}, \mathbf{a}) = \max_{\pi} Q^{\pi}(\mathbf{s}, \mathbf{a})$$。

$$\boxed{V^*(\mathbf{s}) = \max_{\mathbf{a} \in \mathcal{A}} \left[R(\mathbf{s}, \mathbf{a}) + \gamma \, \mathbb{E}_{\mathbf{s}' \sim P(\cdot \mid \mathbf{s}, \mathbf{a})}[V^*(\mathbf{s}')]\right]}$$

$$\boxed{Q^*(\mathbf{s}, \mathbf{a}) = R(\mathbf{s}, \mathbf{a}) + \gamma \, \mathbb{E}_{\mathbf{s}' \sim P}\left[\max_{\mathbf{a}' \in \mathcal{A}} Q^*(\mathbf{s}', \mathbf{a}')\right]}$$

一旦获得 $$Q^*$$，最优策略为: $$\pi^*(\mathbf{s}) = \arg\max_{\mathbf{a}} Q^*(\mathbf{s}, \mathbf{a})$$

**策略改进定理(Policy Improvement Theorem)**: 设 $$\pi, \pi'$$ 为确定性策略。若对所有 $$\mathbf{s}$$ 有 $$Q^{\pi}(\mathbf{s}, \pi'(\mathbf{s})) \geq V^{\pi}(\mathbf{s})$$，则 $$\pi'$$ 至少与 $$\pi$$ 一样好: $$V^{\pi'}(\mathbf{s}) \geq V^{\pi}(\mathbf{s}), \forall \mathbf{s}$$。若至少一个状态上式严格成立，则 $$\pi'$$ 严格优于 $$\pi$$。

**证明**: 反复展开Bellman方程:

$$\begin{aligned}
V^{\pi}(\mathbf{s}) &\leq Q^{\pi}(\mathbf{s}, \pi'(\mathbf{s})) \\
&= R(\mathbf{s}, \pi'(\mathbf{s})) + \gamma \mathbb{E}_{\mathbf{s}' \sim P}[V^{\pi}(\mathbf{s}')] \\
&\leq R(\mathbf{s}, \pi'(\mathbf{s})) + \gamma \mathbb{E}_{\mathbf{s}' \sim P}[Q^{\pi}(\mathbf{s}', \pi'(\mathbf{s}'))] \\
&= R(\mathbf{s}, \pi'(\mathbf{s})) + \gamma \mathbb{E}_{\mathbf{s}' \sim P}[R(\mathbf{s}', \pi'(\mathbf{s}')) + \gamma \mathbb{E}_{\mathbf{s}''}[V^{\pi}(\mathbf{s}'')]] \\
&\leq \ldots \quad (\text{无限展开}) \quad \leq V^{\pi'}(\mathbf{s})
\end{aligned}$$

$$\blacksquare$$

#### 2.2.3 Bellman最优算子的收缩性 — Banach不动点定理证明

定义Bellman最优算子 $$\mathcal{T}^*: \mathbb{R}^{\vert \mathcal{S}\vert } \to \mathbb{R}^{\vert \mathcal{S}\vert }$$:

$$(\mathcal{T}^* V)(\mathbf{s}) = \max_{\mathbf{a} \in \mathcal{A}} \left[R(\mathbf{s}, \mathbf{a}) + \gamma \sum_{\mathbf{s}' \in \mathcal{S}} P(\mathbf{s}' \mid \mathbf{s}, \mathbf{a}) V(\mathbf{s}')\right]$$

**定理(Bellman算子的 $$\gamma$$-收缩性)**: $$\|\mathcal{T}^* V_1 - \mathcal{T}^* V_2\|_{\infty} \leq \gamma \|V_1 - V_2\|_{\infty}$$

**证明**:

$$\begin{aligned}
\|(\mathcal{T}^* V_1) - (\mathcal{T}^* V_2)\|_{\infty}
&= \max_{\mathbf{s}} \left\vert  \max_{\mathbf{a}} [R(\mathbf{s}, \mathbf{a}) + \gamma \sum_{\mathbf{s}'} P(\mathbf{s}'\vert \mathbf{s}, \mathbf{a}) V_1(\mathbf{s}')] - \max_{\mathbf{a}} [R(\mathbf{s}, \mathbf{a}) + \gamma \sum_{\mathbf{s}'} P(\mathbf{s}'\vert \mathbf{s}, \mathbf{a}) V_2(\mathbf{s}')] \right\vert 
\end{aligned}$$

利用 $$\vert \max_a f(a) - \max_a g(a)\vert  \leq \max_a \vert f(a) - g(a)\vert $$ (max算子的非扩张性):

$$\begin{aligned}
\|(\mathcal{T}^* V_1) - (\mathcal{T}^* V_2)\|_{\infty}
&\leq \max_{\mathbf{s}, \mathbf{a}} \left\vert  \gamma \sum_{\mathbf{s}'} P(\mathbf{s}'\vert \mathbf{s}, \mathbf{a}) (V_1(\mathbf{s}') - V_2(\mathbf{s}')) \right\vert  \\
&\leq \gamma \max_{\mathbf{s}, \mathbf{a}} \sum_{\mathbf{s}'} P(\mathbf{s}'\vert \mathbf{s}, \mathbf{a}) \cdot \max_{\mathbf{s}''} \vert V_1(\mathbf{s}'') - V_2(\mathbf{s}'')\vert  \\
&= \gamma \max_{\mathbf{s}, \mathbf{a}} \sum_{\mathbf{s}'} P(\mathbf{s}'\vert \mathbf{s}, \mathbf{a}) \cdot \|V_1 - V_2\|_{\infty} \\
&= \gamma \|V_1 - V_2\|_{\infty}
\end{aligned}$$

最后一步成立是因为 $$\sum_{\mathbf{s}'} P(\mathbf{s}'\vert \mathbf{s}, \mathbf{a}) = 1$$。$$\blacksquare$$

由**Banach不动点定理**: 完备度量空间上的收缩映射存在唯一不动点。因此 $$\mathcal{T}^*$$ 有唯一不动点，且恰好是 $$V^*$$: $$\mathcal{T}^* V^* = V^*$$。值迭代 $$V_{k+1} \leftarrow \mathcal{T}^* V_k$$ 从任意初始 $$V_0$$ 出发以线性速率收敛:

$$\|V_k - V^*\|_{\infty} \leq \gamma^k \|V_0 - V^*\|_{\infty}$$

**机器人学含义**: 在连续状态空间中，函数近似(神经网络)替代了精确值函数表格。深度RL丢失了精确收敛保证，但换取了在高维连续空间中的可行解能力——这是"利用计算的苦涩教训"在RL中的具体体现。

### 2.3 策略梯度定理的完整证明

策略梯度方法直接对期望回报做梯度上升。这是处理连续动作空间的自然选择——$$\arg\max_{\mathbf{a}} Q$$ 无法在 $$\mathbb{R}^{d_a}$$ 上枚举。

**定理(Policy Gradient Theorem)** [Sutton et al., 1999]:

$$\boxed{\nabla_{\boldsymbol{\theta}} J(\boldsymbol{\theta}) = \mathbb{E}_{\pi_{\boldsymbol{\theta}}}\left[\sum_{t=0}^{\infty} \nabla_{\boldsymbol{\theta}} \log \pi_{\boldsymbol{\theta}}(\mathbf{a}_t \mid \mathbf{s}_t) \cdot \Psi_t\right]}$$

其中 $$\Psi_t$$ 可为以下任一形式(均给出无偏梯度估计; 以优势函数 $$\Psi_t = A^{\pi}(\mathbf{s}_t, \mathbf{a}_t)$$ 方差最小):
- 总回报: $$\Psi_t = G_t$$ (REINFORCE, Williams 1992)
- Q值: $$\Psi_t = Q^{\pi}(\mathbf{s}_t, \mathbf{a}_t)$$
- 优势函数: $$\Psi_t = A^{\pi}(\mathbf{s}_t, \mathbf{a}_t)$$ (最小方差)

**完整证明(5步)**:

**步骤1 — 轨迹概率分解**。轨迹 $$\tau = (\mathbf{s}_0, \mathbf{a}_0, \ldots, \mathbf{s}_T)$$ 的概率密度:

$$p_{\boldsymbol{\theta}}(\tau) = \rho_0(\mathbf{s}_0) \prod_{t=0}^{T-1} \pi_{\boldsymbol{\theta}}(\mathbf{a}_t \mid \mathbf{s}_t) \cdot P(\mathbf{s}_{t+1} \mid \mathbf{s}_t, \mathbf{a}_t)$$

关键洞察: 环境转移 $$P$$ 和初始分布 $$\rho_0$$ 与策略参数 $$\boldsymbol{\theta}$$ **无关**。

**步骤2 — 对数导数技巧**。利用 $$\nabla_{\boldsymbol{\theta}} p_{\boldsymbol{\theta}}(\tau) = p_{\boldsymbol{\theta}}(\tau) \nabla_{\boldsymbol{\theta}} \log p_{\boldsymbol{\theta}}(\tau)$$:

$$\begin{aligned}
\nabla_{\boldsymbol{\theta}} J(\boldsymbol{\theta}) &= \nabla_{\boldsymbol{\theta}} \mathbb{E}_{\tau \sim p_{\boldsymbol{\theta}}}[R(\tau)] = \nabla_{\boldsymbol{\theta}} \int R(\tau) p_{\boldsymbol{\theta}}(\tau) d\tau \\
&= \int R(\tau) \nabla_{\boldsymbol{\theta}} p_{\boldsymbol{\theta}}(\tau) d\tau \quad (\text{积分与梯度交换}) \\
&= \int R(\tau) p_{\boldsymbol{\theta}}(\tau) \nabla_{\boldsymbol{\theta}} \log p_{\boldsymbol{\theta}}(\tau) d\tau \\
&= \mathbb{E}_{\tau \sim p_{\boldsymbol{\theta}}}\left[R(\tau) \nabla_{\boldsymbol{\theta}} \log p_{\boldsymbol{\theta}}(\tau)\right]
\end{aligned}$$

**步骤3 — 环境动力学与策略解耦(策略梯度定理的精髓)**:

$$\begin{aligned}
\log p_{\boldsymbol{\theta}}(\tau) &= \log \rho_0(\mathbf{s}_0) + \sum_{t=0}^{T-1} \left[\log \pi_{\boldsymbol{\theta}}(\mathbf{a}_t \mid \mathbf{s}_t) + \log P(\mathbf{s}_{t+1} \mid \mathbf{s}_t, \mathbf{a}_t)\right] \\
\nabla_{\boldsymbol{\theta}} \log p_{\boldsymbol{\theta}}(\tau) &= \sum_{t=0}^{T-1} \nabla_{\boldsymbol{\theta}} \log \pi_{\boldsymbol{\theta}}(\mathbf{a}_t \mid \mathbf{s}_t) + 0 + 0
\end{aligned}$$

$$\rho_0$$ 和 $$P$$ 不含 $$\boldsymbol{\theta}$$，梯度为零——**策略梯度定理不需要环境动力学模型**。这就是model-free RL的数学基础。

**步骤4 — 因果性与baseline减除**。时刻 $$t$$ 的动作不影响之前的奖励:

$$\nabla_{\boldsymbol{\theta}} J(\boldsymbol{\theta}) = \mathbb{E}_{\tau \sim p_{\boldsymbol{\theta}}}\left[\sum_{t=0}^{T-1} \nabla_{\boldsymbol{\theta}} \log \pi_{\boldsymbol{\theta}}(\mathbf{a}_t \mid \mathbf{s}_t) \cdot G_t\right]$$

Baseline $$b(\mathbf{s}_t)$$ 不引入偏差:

$$\mathbb{E}_{\mathbf{a}_t \sim \pi_{\boldsymbol{\theta}}}\left[\nabla_{\boldsymbol{\theta}} \log \pi_{\boldsymbol{\theta}}(\mathbf{a}_t \mid \mathbf{s}_t) \cdot b(\mathbf{s}_t)\right] = b(\mathbf{s}_t) \nabla_{\boldsymbol{\theta}} \underbrace{\mathbb{E}_{\mathbf{a}_t}[1]}_{=1} = 0$$

**步骤5 — 最终形式**。用 $$Q^{\pi}$$ 替代 $$G_t$$ 的期望，用 $$V^{\pi}$$ 作为最优baseline:

$$\boxed{\nabla_{\boldsymbol{\theta}} J(\boldsymbol{\theta}) = \mathbb{E}_{\pi_{\boldsymbol{\theta}}}\left[\sum_{t=0}^{\infty} \nabla_{\boldsymbol{\theta}} \log \pi_{\boldsymbol{\theta}}(\mathbf{a}_t \mid \mathbf{s}_t) \cdot A^{\pi}(\mathbf{s}_t, \mathbf{a}_t)\right]}$$

$$\blacksquare$$

**从REINFORCE到Actor-Critic的演进逻辑**:
- **REINFORCE**(Williams, 1992): $$\Psi_t = G_t$$。致命缺陷: $$G_t$$ 方差极高($$O(T^2)$$量级)。在机器人学中意味着需数百万次真实交互。
- **带baseline的REINFORCE**: 减除 $$V(\mathbf{s}_t)$$，方差大幅降低但仍需完整轨迹。
- **Actor-Critic**: 用TD学习在线估计 $$V_{\boldsymbol{\phi}}(\mathbf{s})$$，构造 $$\hat{A}_t = R_t + \gamma V_{\boldsymbol{\phi}}(\mathbf{s}_{t+1}) - V_{\boldsymbol{\phi}}(\mathbf{s}_t)$$。可在线更新，TD估计引入偏差但大幅削减方差。

### 2.4 广义优势估计(GAE)的完整推导

GAE(Schulman et al., 2016)是当代策略梯度方法中最重要的方差削减技术。核心思想: 在偏差和方差之间用参数 $$\lambda$$ 做连续的、可微调的折衷。

**定义(TD误差)**: $$\delta_t^V = R_t + \gamma V(\mathbf{s}_{t+1}) - V(\mathbf{s}_t)$$

**k-步优势估计**: $$\hat{A}_t^{(k)} = \sum_{l=0}^{k-1} \gamma^l \delta_{t+l}^V$$

性质: $$k=1$$ → 单步TD(低方差、高偏差)；$$k \to \infty$$ → 蒙特卡洛(无偏、高方差)。

**GAE的关键洞察**: 不选固定 $$k$$，而对所有可能 $$k$$ 按指数衰减权重 $$\lambda^{k-1}$$ 加权组合:

$$\boxed{\hat{A}_t^{\text{GAE}(\gamma, \lambda)} = (1 - \lambda)\sum_{k=1}^{\infty} \lambda^{k-1} \hat{A}_t^{(k)} = \sum_{l=0}^{\infty} (\gamma \lambda)^l \delta_{t+l}^V}$$

**推导(交换求和次序)**:

$$\begin{aligned}
\hat{A}_t^{\text{GAE}} &= (1 - \lambda) \sum_{k=1}^{\infty} \lambda^{k-1} \sum_{l=0}^{k-1} \gamma^l \delta_{t+l}^V \\
&= (1 - \lambda) \sum_{l=0}^{\infty} \gamma^l \delta_{t+l}^V \underbrace{\sum_{k=l+1}^{\infty} \lambda^{k-1}}_{\text{几何级数: } \frac{\lambda^l}{1-\lambda}} \quad (\text{交换求和次序}) \\
&= \sum_{l=0}^{\infty} (\gamma \lambda)^l \delta_{t+l}^V
\end{aligned}$$

**参数 $$\lambda$$ 的物理含义**:

| $$\lambda$$ | 等效行为 | 方差 | 偏差 | 适用场景 |
|-----------|---------|------|------|---------|
| $$\lambda = 0$$ | 1-步TD | 最低 | 最高 | 环境高度随机 |
| $$\lambda = 0.95$$ | 约20步有效窗口 | 低 | 低 | **机器人学推荐** |
| $$\lambda = 1$$ | MC(无折扣) | 最高 | 无偏 | 环境完全确定性 |

机器人学典型值 $$\lambda \in [0.92, 0.97]$$。有效时间窗口约 $$\frac{1}{1-\gamma\lambda} \approx 10\text{-}30$$ 步(假设 $$\gamma=0.99$$)，恰好覆盖步态周期的相位转换时间尺度。

**GAE的递推计算**: 从后向前，每步仅需一次乘法和加法:

$$\hat{A}_t^{\text{GAE}} = \delta_t^V + \gamma \lambda (1 - d_t) \hat{A}_{t+1}^{\text{GAE}}$$

其中 $$d_t$$ 是终止标志。

**GAE与TD($$\lambda$$)的统一**: $$G_t^{\lambda} = V(\mathbf{s}_t) + \hat{A}_t^{\text{GAE}}$$。$$\lambda=0$$ 给出TD(0)目标，$$\lambda=1$$ 给出MC回报。GAE将所有介于其间的可能性无缝统一。

### 2.5 PPO: 信任区域策略优化的实用化

PPO(Schulman et al., 2017)是机器人学中应用最广泛的on-policy RL算法。其前身TRPO通过KL散度约束限制策略更新幅度——但需要共轭梯度。PPO用一个巧妙的**裁剪**(clipping)机制实现几乎相同的效果。

**重要性采样比率**: $$r_t(\boldsymbol{\theta}) = \frac{\pi_{\boldsymbol{\theta}}(\mathbf{a}_t \mid \mathbf{s}_t)}{\pi_{\boldsymbol{\theta}_{\text{old}}}(\mathbf{a}_t \mid \mathbf{s}_t)}$$

**PPO的裁剪代理目标**:

$$\boxed{L^{\text{CLIP}}(\boldsymbol{\theta}) = \mathbb{E}_t\left[\min\left(r_t(\boldsymbol{\theta}) \hat{A}_t,\; \text{clip}(r_t(\boldsymbol{\theta}), 1 - \epsilon, 1 + \epsilon) \hat{A}_t\right)\right]}$$

**clip机制的工作原理**:

**Case 1: $$\hat{A}_t > 0$$**(该动作好于预期)。$$L = \min(r_t, 1+\epsilon) \hat{A}_t$$。当 $$r_t > 1+\epsilon$$ 时梯度为零——防止过于激进地增加已不错的动作概率。

**Case 2: $$\hat{A}_t < 0$$**(该动作差于预期)。$$L$$ 等价于 $$\max(r_t, 1-\epsilon) \hat{A}_t$$。当 $$r_t < 1-\epsilon$$ 时梯度为零——防止过于激进地惩罚已不太可能被选择的动作。

**PPO的完整损失函数**:

$$L^{\text{PPO}}(\boldsymbol{\theta}, \boldsymbol{\phi}) = \mathbb{E}_t\left[L^{\text{CLIP}}(\boldsymbol{\theta}) - c_1 L^{\text{VF}}(\boldsymbol{\phi}) + c_2 S[\pi_{\boldsymbol{\theta}}](\mathbf{s}_t)\right]$$

其中 $$L^{\text{VF}} = (V_{\boldsymbol{\phi}}(\mathbf{s}_t) - V_t^{\text{targ}})^2$$ 是价值函数损失，$$S$$ 是策略熵奖励。典型超参数: $$\epsilon=0.2$$, $$c_1=0.5$$, $$c_2=0.01$$。

**连续动作空间的策略参数化**: 动作空间 $$\mathbf{a} \in \mathbb{R}^{d_a}$$。标准做法是对角高斯分布:

$$\pi_{\boldsymbol{\theta}}(\mathbf{a} \mid \mathbf{s}) = \mathcal{N}\left(\boldsymbol{\mu}_{\boldsymbol{\theta}}(\mathbf{s}),\; \text{diag}(\boldsymbol{\sigma}_{\boldsymbol{\theta}}^2(\mathbf{s}))\right)$$

Actor网络输出 $$\boldsymbol{\mu}_{\boldsymbol{\theta}} \in \mathbb{R}^{d_a}$$ 和 $$\log \boldsymbol{\sigma}_{\boldsymbol{\theta}} \in \mathbb{R}^{d_a}$$ (对数形式保证正定性)。动作采样通过重参数化: $$\mathbf{a} = \boldsymbol{\mu}_{\boldsymbol{\theta}}(\mathbf{s}) + \boldsymbol{\sigma}_{\boldsymbol{\theta}}(\mathbf{s}) \odot \boldsymbol{\epsilon}$$, $$\boldsymbol{\epsilon} \sim \mathcal{N}(\mathbf{0}, \mathbf{I}_{d_a})$$。

对数概率: $$\log \pi_{\boldsymbol{\theta}}(\mathbf{a} \mid \mathbf{s}) = -\frac{d_a}{2} \log(2\pi) - \frac{1}{2} \sum_{i=1}^{d_a} [\frac{(a_i - \mu_i)^2}{\sigma_i^2} + 2\log \sigma_i]$$

### 2.6 SAC: 最大熵强化学习 — 机器人RL的标准范式

SAC(Haarnoja et al., 2018)是为连续动作空间设计的off-policy算法，已成为机器人RL的事实标准。核心创新: 将**熵正则化**植入RL目标函数。

#### 2.6.1 最大熵目标与Soft Bellman方程

**最大熵RL目标**:

$$\boxed{J_{\text{SAC}}(\pi) = \sum_{t=0}^{\infty} \mathbb{E}_{(\mathbf{s}_t, \mathbf{a}_t) \sim \rho_{\pi}}\left[R(\mathbf{s}_t, \mathbf{a}_t) + \alpha \, \mathcal{H}(\pi(\cdot \mid \mathbf{s}_t))\right]}$$

其中 $$\mathcal{H}(\pi(\cdot \mid \mathbf{s})) = -\mathbb{E}_{\mathbf{a} \sim \pi}[\log \pi(\mathbf{a} \mid \mathbf{s})]$$ 是策略熵。$$\alpha > 0$$ 控制探索与利用平衡: $$\alpha \to 0$$ 退化回标准RL；$$\alpha \to \infty$$ 退化为均匀随机策略。

**最大熵框架的三大优势**:

1. **自然探索**: 熵项鼓励策略保持随机性，防止过早收敛到次优确定性策略。在多模态奖励地形(如多条步态都能稳定行走)中尤为重要。
2. **鲁棒性**: 最大熵策略更"圆滑"，对sim-to-real迁移中的模型误差更宽容。
3. **样本效率**: Off-policy replay buffer使样本效率远超on-policy算法(10x-100x差距)，对机器人学意义深远。

**Soft值函数**: 从最大熵目标定义Soft Q和Soft V:

$$Q_{\text{soft}}^{\pi}(\mathbf{s}, \mathbf{a}) = R(\mathbf{s}, \mathbf{a}) + \gamma \mathbb{E}_{\mathbf{s}' \sim P}\left[V_{\text{soft}}^{\pi}(\mathbf{s}')\right]$$

$$V_{\text{soft}}^{\pi}(\mathbf{s}) = \mathbb{E}_{\mathbf{a} \sim \pi}\left[Q_{\text{soft}}^{\pi}(\mathbf{s}, \mathbf{a}) - \alpha \log \pi(\mathbf{a} \mid \mathbf{s})\right]$$

合并得到**Soft Bellman方程**:

$$\boxed{Q_{\text{soft}}^{\pi}(\mathbf{s}, \mathbf{a}) = R(\mathbf{s}, \mathbf{a}) + \gamma \mathbb{E}_{\mathbf{s}' \sim P,\, \mathbf{a}' \sim \pi}\left[Q_{\text{soft}}^{\pi}(\mathbf{s}', \mathbf{a}') - \alpha \log \pi(\mathbf{a}' \mid \mathbf{s}')\right]}$$

与标准Bellman方程的唯一差异: 每步奖励扣除了 $$\alpha \log \pi$$——高熵动作被"征税"，低熵动作获"补贴"。

#### 2.6.2 SAC重参数化技巧 — 机器人学视角

策略更新需计算 $$\nabla_{\boldsymbol{\theta}} \mathbb{E}_{\mathbf{a} \sim \pi_{\boldsymbol{\theta}}}[Q(\mathbf{s}, \mathbf{a}) - \alpha \log \pi_{\boldsymbol{\theta}}(\mathbf{a} \mid \mathbf{s})]$$。直接用对数导数技巧(§2.3)会产生高方差——因为动作 $$\mathbf{a}$$ 的采样随机性被注入梯度。

**重参数化技巧**将采样与网络参数解耦:

$$\boxed{\mathbf{a} = f_{\boldsymbol{\theta}}(\boldsymbol{\epsilon}; \mathbf{s}) = \boldsymbol{\mu}_{\boldsymbol{\theta}}(\mathbf{s}) + \boldsymbol{\sigma}_{\boldsymbol{\theta}}(\mathbf{s}) \odot \boldsymbol{\epsilon}, \quad \boldsymbol{\epsilon} \sim \mathcal{N}(\mathbf{0}, \mathbf{I})}$$

现在 $$\boldsymbol{\theta}$$ 仅出现在确定性函数 $$f_{\boldsymbol{\theta}}$$ 中。策略目标函数:

$$J_{\pi}(\boldsymbol{\theta}) = \mathbb{E}_{\mathbf{s} \sim \mathcal{D},\, \boldsymbol{\epsilon} \sim \mathcal{N}}\left[\alpha \log \pi_{\boldsymbol{\theta}}(f_{\boldsymbol{\theta}}(\boldsymbol{\epsilon}; \mathbf{s}) \mid \mathbf{s}) - Q_{\boldsymbol{\psi}}(\mathbf{s}, f_{\boldsymbol{\theta}}(\boldsymbol{\epsilon}; \mathbf{s}))\right]$$

通过链式法则求梯度:

$$\boxed{\nabla_{\boldsymbol{\theta}} J_{\pi} = \mathbb{E}_{\mathbf{s}, \boldsymbol{\epsilon}}\left[\nabla_{\mathbf{a}} (\alpha \log \pi_{\boldsymbol{\theta}} - Q_{\boldsymbol{\psi}}) \big\vert _{\mathbf{a} = f_{\boldsymbol{\theta}}(\boldsymbol{\epsilon}; \mathbf{s})} \cdot \nabla_{\boldsymbol{\theta}} f_{\boldsymbol{\theta}}(\boldsymbol{\epsilon}; \mathbf{s}) + \alpha \nabla_{\boldsymbol{\theta}} \log \pi_{\boldsymbol{\theta}}\right]}$$

第一项通过 $$\nabla_{\mathbf{a}} Q$$ 反向传播(利用Q网络的信息丰富的梯度)，第二项是熵对 $$\boldsymbol{\theta}$$ 的直接梯度。

**重参数化为何方差更小?** 标准策略梯度的方差来自 $$\log \pi_{\boldsymbol{\theta}}$$ 梯度和 $$Q$$ 值两个随机变量之积。重参数化将 $$\nabla_{\mathbf{a}} Q$$ 带入计算——$$\nabla_{\mathbf{a}} Q$$ 在接近贪心动作时趋于零，提供自然方差衰减。对高维动作空间(如Shadow Hand的24维)，方差削减效果是质变式的。

**tanh压缩**: 机器人动作通常有界($$a_i \in [-1, 1]$$，关节限位)。SAC用tanh压缩:

$$\mathbf{a} = \tanh(\boldsymbol{\mu}_{\boldsymbol{\theta}}(\mathbf{s}) + \boldsymbol{\sigma}_{\boldsymbol{\theta}}(\mathbf{s}) \odot \boldsymbol{\epsilon})$$

对数概率通过变量变换修正:

$$\log \pi(\mathbf{a} \mid \mathbf{s}) = \log \mathcal{N}(\mathbf{u} \mid \boldsymbol{\mu}, \boldsymbol{\sigma}^2) - \sum_{i=1}^{d_a} \log(1 - \tanh^2(u_i))$$

其中 $$\mathbf{u} \sim \mathcal{N}(\boldsymbol{\mu}, \boldsymbol{\sigma}^2)$$ 是tanh之前的pre-activation。第二项是 $$\tanh$$ 的雅可比行列式对数。

#### 2.6.3 SAC算法完整流程

**双Q网络(Clipped Double-Q)**: 两组独立Q网络 $$Q_{\boldsymbol{\psi}_1}, Q_{\boldsymbol{\psi}_2}$$ 及其目标网络。取最小值抑制overestimation bias(Fujimoto et al., 2018): $$\min_{j=1,2} Q_{\bar{\boldsymbol{\psi}}_j}(\mathbf{s}', \mathbf{a}')$$

**Critic更新**: 最小化Soft Bellman残差:

$$J_Q(\boldsymbol{\psi}_j) = \mathbb{E}_{(\mathbf{s}, \mathbf{a}, r, \mathbf{s}', d) \sim \mathcal{D}}\left[(Q_{\boldsymbol{\psi}_j}(\mathbf{s}, \mathbf{a}) - y)^2\right]$$

目标值: $$y = r + \gamma (1 - d)(\min_{j=1,2} Q_{\bar{\boldsymbol{\psi}}_j}(\mathbf{s}', \mathbf{a}') - \alpha \log \pi_{\boldsymbol{\theta}}(\mathbf{a}' \mid \mathbf{s}'))$$, $$\mathbf{a}' \sim \pi_{\boldsymbol{\theta}}(\cdot \mid \mathbf{s}')$$

**Actor更新**(重参数化): $$J_{\pi}(\boldsymbol{\theta}) = \mathbb{E}_{\mathbf{s} \sim \mathcal{D}, \boldsymbol{\epsilon}}\left[\alpha \log \pi_{\boldsymbol{\theta}}(f_{\boldsymbol{\theta}}(\boldsymbol{\epsilon}; \mathbf{s}) \mid \mathbf{s}) - \min_{j} Q_{\boldsymbol{\psi}_j}(\mathbf{s}, f_{\boldsymbol{\theta}}(\boldsymbol{\epsilon}; \mathbf{s}))\right]$$

**自动温度调节**: $$J(\alpha) = \mathbb{E}_{\mathbf{a} \sim \pi_{\boldsymbol{\theta}}}[-\alpha \log \pi_{\boldsymbol{\theta}}(\mathbf{a} \mid \mathbf{s}) - \alpha \bar{\mathcal{H}}]$$, 目标熵 $$\bar{\mathcal{H}} = -\dim(\mathcal{A})$$

**目标网络软更新**: $$\bar{\boldsymbol{\psi}}_j \leftarrow \tau \boldsymbol{\psi}_j + (1 - \tau)\bar{\boldsymbol{\psi}}_j$$, $$\tau \ll 1$$ (典型值 $$0.005$$)

#### 2.6.4 SAC vs PPO: 机器人学中的选择指南

| 维度 | SAC | PPO |
|------|-----|-----|
| 数据来源 | Off-policy(replay buffer) | On-policy(当前策略) |
| 样本效率 | **高**(可重用历史数据) | 低(每次更新后丢弃) |
| 训练稳定性 | 中等(对超参数敏感) | **高**(clip机制提供天然稳定性) |
| 并行化 | 独立环境并行 | **同步环境并行** |
| 熵处理 | 目标函数内置(最大熵) | 附加熵奖励项 |
| 适用场景 | 仿真中长期训练; 样本效率关键 | 大规模并行仿真(Isaac Gym) |
| 典型训练步数 | $$10^5 - 10^6$$ | $$10^6 - 10^8$$ |

### 2.7 Sim-to-Real迁移: 从仿真到真实世界

机器人RL的根本矛盾: 训练需海量交互($$10^6 - 10^9$$步)，而真实硬件每步都有时间和磨损成本。Sim-to-Real将训练放在仿真器中进行。

**Sim-to-Real鸿沟的形式化**: $$\mathcal{L}_{\text{SR}}(\pi) = J_{\text{real}}(\pi) - J_{\text{sim}}(\pi)$$。根源: $$P_{\text{sim}} \neq P_{\text{real}}$$ 且 $$\Omega_{\text{sim}} \neq \Omega_{\text{real}}$$

#### 2.7.1 域随机化(Domain Randomization, DR)

训练期间随机化仿真参数 $$\xi \sim p(\xi)$$，迫使策略对参数变化鲁棒:

$$J_{\text{DR}}(\pi) = \mathbb{E}_{\xi \sim p(\xi)}\left[\mathbb{E}_{\tau \sim \pi, \mathcal{M}_\xi}\left[\sum_{t} R_t\right]\right]$$

**Episode-level vs Step-level**: Episode-level(每episode采样一次)优于Step-level(每步重采样)，因为: (a)真实世界参数保持固定；(b)Step-level产生非物理的参数波动；(c)Episode-level迫使策略从历史中隐式辨识参数——训练出内嵌于策略中的"系统辨识器"。

**OpenAI灵巧手的DR参数空间**:

| 参数 | 随机化范围 | 物理含义 |
|------|-----------|---------|
| 手指摩擦系数 | $$\mathcal{U}[0.5, 1.5]$$ | 不同表面状况 |
| 物体质量 | 名义值 $$\times [0.7, 1.3]$$ | 未知物体 |
| 关节阻尼 | 名义值 $$\times [0.5, 1.5]$$ | 温度变化/磨损 |
| 物体尺寸 | $$\pm 5\%$$ | 制造公差 |
| 外力扰动 | 随机脉冲 | 意外碰撞 |
| 执行器延迟 | $$[0, 20]$$ ms | 通信延迟 |
| 观测噪声 | $$\mathcal{N}(0, \sigma_{\text{obs}}^2)$$ | 传感器噪声 |

#### 2.7.2 系统辨识(System Identification)

DR的局限: 真实参数可能不在随机化范围内。SysID用少量真实数据校准仿真器:

$$\hat{\xi} = \arg\min_{\xi} \sum_{(\mathbf{s}_t^{\text{real}}, \mathbf{a}_t^{\text{real}}, \mathbf{s}_{t+1}^{\text{real}})} \|\mathbf{s}_{t+1}^{\text{real}} - f_{\text{sim}}(\mathbf{s}_t^{\text{real}}, \mathbf{a}_t^{\text{real}}; \xi)\|^2$$

SysID缩小所需DR范围，两者协同使用效果最佳。

#### 2.7.3 域适应(Domain Adaptation)

学习映射 $$\Phi: \mathcal{S}_{\text{sim}} \to \mathcal{S}_{\text{real}}$$，使仿真策略可应用于真实观测。对视觉观测(图像)的域适应最为有效——将仿真渲染图像"风格迁移"到真实相机的色彩/纹理分布。

---

## 三、关键案例分析

### 3.1 Haarnoja et al.(RSS 2019): 通过深度RL学习四足行走

**问题设定**: 四足机器人Minitaur(8自由度，每条腿2个直接驱动电机)在平面上稳定行走，仅使用本体感觉(关节编码器 + IMU, 无外部视觉)。动作空间为8维关节位置PD控制目标。

**方法论核心 — SAC + 层次化PD控制**:

**奖励函数设计**是核心工程贡献:

$$R_t = \underbrace{w_v \cdot \min(v_x, v_x^{\text{des}})}_{\text{前进速度}} + \underbrace{w_a \cdot \mathbb{1}_{\text{alive}}}_{\text{存活奖励}} - \underbrace{w_e \cdot \sum_i \vert \tau_i \dot{q}_i\vert }_{\text{能量消耗}} - \underbrace{w_q \cdot \|\mathbf{q} - \mathbf{q}_{\text{nom}}\|_2^2}_{\text{姿态正则化}}$$

每个子项的物理含义:
- **速度项**: $$\min$$ 裁剪防止"跑过头再急刹车"的reward hacking
- **存活项**: 防止"立刻摔倒"被视为正策略(因为摔倒终止episode可能被错误地视为"好的"以避免后续能量惩罚)
- **能量项**: 关节功率的总和，鼓励利用被动动力学的节能步态
- **姿态项**: 惩罚偏离直立姿态，防止采用"拖行"策略

**层次化控制架构**: 策略输出关节位置目标 $$\mathbf{q}_{\text{des}}$$(100Hz)，底层PD控制器1kHz跟踪:

$$\boldsymbol{\tau} = K_p(\mathbf{q}_{\text{des}} - \mathbf{q}) - K_d \dot{\mathbf{q}}$$

这种分层的优势: (a)策略从直接力控制降级为目标位置选择；(b)PD控制器提供平滑执行器行为，稳定训练；(c)与真实电机驱动器的位置控制接口直接兼容。

**SAC的行走定制**: (1) 状态堆叠最近3帧以推断速度；(2) 策略均值裁剪到关节限位；(3) 双Q + 自动温度调节。

**训练与结果**: MuJoCo仿真, 8并行环境, 约200万步(~2小时)收敛, 速度跟踪误差约0.1m/s。SAC比DDPG收敛快约2x且步态更自然。简单域随机化(地面摩擦)后zero-shot迁移成功。

### 3.2 OpenAI et al.(IJRR 2020): 通过RL学习灵巧手中操作

**问题设定**: Shadow Dexterous Hand(24自由度五指仿人灵巧手)在手掌内旋转物体到达目标姿态。训练完全在MuJoCo仿真中进行，zero-shot迁移到真实硬件。

**方法论核心 — PPO + LSTM + 非对称Actor-Critic + 域随机化**:

**非对称Actor-Critic**是该工作的**核心架构洞见**:

- **Actor** $$\pi_{\boldsymbol{\theta}}(\mathbf{a}_t \mid \mathbf{o}_t, \mathbf{h}_{t-1})$$: 仅接收可获取的观测——关节位置($$\mathbb{R}^{24}$$)、指尖触觉(~$$\mathbb{R}^{60}$$)、带噪声的物体姿态估计($$\mathbb{R}^7$$)
- **Critic** $$V_{\boldsymbol{\phi}}(\mathbf{s}_t)$$: 接收**完整仿真状态**——Actor可见信息 + 精确物体位姿/速度 + 接触力/力矩 + 关节力矩真值

**非对称架构的有效性原理**:
1. Critic享有特权信息 → 极为精确的优势估计 → 低方差梯度信号
2. Actor被迫从部分观测中提取隐含状态 → 隐式学习状态估计器
3. 零冗余部署: 推理时仅需Actor网络
4. 本质上是通过RL进行**表示学习**——无需标注状态真值

**LSTM的角色**: 将过去约50步的观测压缩为隐状态 $$\mathbf{h}_t$$，使策略能够: (1)通过时序差分估计物体速度；(2)从接触模式推断被遮挡的物体位姿；(3)捕获滚动接触动力学；(4)建模肌腱驱动的滞后效应。

**训练配置与结果**: 6144并行CPU核心, ~50小时。PPO: lr=$$3\times10^{-4}$$, batch=98304, $$\gamma=0.998$$, $$\lambda=0.95$$, $$\epsilon=0.2$$。手掌内旋转zero-shot迁移成功率~90%。失败主要来自仿真未建模的物理效应(静摩擦、柔性接触、肌腱滞后)。

**工程教训**: 非对称Actor-Critic已成为sim-to-real迁移的标配(RMA, ANYmal等均采用)；Episode-level随机化优于Step-level；大规模并行化使on-policy PPO与off-policy SAC可在样本效率层面竞争。

---

## 四、算法与代码实现

本节给出机器人RL中三个核心组件的完整PyTorch实现。所有代码带逐行中文注释，标注公式出处和工程考量。

### 4.1 PPO for Continuous Control(连续控制的PPO)

```python
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.distributions import Normal
import numpy as np


class GaussianActor(nn.Module):
    """连续动作空间的对角高斯策略网络(Actor)

    输出: μ_θ(s) ∈ R^{d_a} 和 log σ_θ ∈ R^{d_a}
    对应 §2.5: π_θ(a|s) = N(μ_θ(s), diag(σ_θ²(s)))

    架构: 2层MLP (hidden=256) 是机器人RL的经验标配。
    本体感觉状态(关节角度/IMU)用2层已足够。
    """
    def __init__(self, obs_dim, act_dim, hidden_dim=256):
        super().__init__()
        # 共享特征提取层
        self.net = nn.Sequential(
            nn.Linear(obs_dim, hidden_dim), nn.ReLU(),
            nn.Linear(hidden_dim, hidden_dim), nn.ReLU(),
        )
        self.mean_head = nn.Linear(hidden_dim, act_dim)
        # 对数标准差: 可学习参数 (状态无关)
        # init log_std=0 → std=1.0 → 初始探索范围约 [-1, 1]
        self.log_std = nn.Parameter(torch.zeros(act_dim))

    def forward(self, obs):
        """前向传播: 输入状态, 输出高斯分布参数"""
        h = self.net(obs)
        mean = self.mean_head(h)
        # clamp 防止 exp(log_std) 数值爆炸
        # exp(-20) ≈ 2e-9, exp(2) ≈ 7.4
        std = torch.exp(self.log_std.clamp(-20, 2))
        return mean, std

    def sample(self, obs):
        """重参数化采样 + 对数概率计算

        对应 §2.5: a = μ + σ ⊙ ε, ε ~ N(0, I)
        """
        mean, std = self.forward(obs)
        dist = Normal(mean, std)
        action = dist.rsample()  # 重参数化 — 梯度流过采样
        # sum(dim=-1): 独立高斯假设, 多维log_prob = 各维之和
        log_prob = dist.log_prob(action).sum(dim=-1)
        return action, log_prob

    def evaluate(self, obs, action):
        """评估给定动作的对数概率 (用于PPO的 ratio = π_new/π_old)"""
        mean, std = self.forward(obs)
        dist = Normal(mean, std)
        log_prob = dist.log_prob(action).sum(dim=-1)
        entropy = dist.entropy().sum(dim=-1)
        return log_prob, entropy


class ValueCritic(nn.Module):
    """V(s) 状态值函数网络(Critic)

    输出: 标量 V_φ(s) ∈ R
    对应 Bellman 方程: V^π(s) = E_a[R(s,a) + γ V^π(s')]
    """
    def __init__(self, obs_dim, hidden_dim=256):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(obs_dim, hidden_dim), nn.ReLU(),
            nn.Linear(hidden_dim, hidden_dim), nn.ReLU(),
            nn.Linear(hidden_dim, 1),
        )

    def forward(self, obs):
        return self.net(obs).squeeze(-1)  # [B,1] → [B]


def compute_gae(rewards, values, dones, gamma=0.99, lam=0.95):
    """广义优势估计(GAE)的向量化实现

    对应 §2.4: A_t^GAE = Σ_{l=0}^{∞} (γλ)^l δ_{t+l}^V

    递推形式: A_t = δ_t + γλ(1-d_t)A_{t+1}
    其中 δ_t = r_t + γ V(s_{t+1})(1-d_t) - V(s_t)

    Args:
        rewards: [T]          奖励序列
        values:  [T+1]        价值估计, values[-1] 是 bootstrap value
        dones:   [T]          终止标志 (1.0=terminal, 0.0=not)
        gamma:   折扣因子
        lam:     GAE-λ 参数 (机器人学典型值: 0.95)

    Returns:
        advantages: [T]       优势估计 A_t^GAE
        returns:    [T]       TD(λ) 回报目标 G_t^λ = A_t + V(s_t)
    """
    T = len(rewards)
    advantages = torch.zeros(T)
    gae = 0.0

    # 反向遍历 (从 T-1 到 0)
    for t in reversed(range(T)):
        # TD误差: δ_t = r_t + γ V(s_{t+1}) - V(s_t)
        delta = (rewards[t]
                 + gamma * values[t + 1] * (1.0 - dones[t])
                 - values[t])
        # GAE递推: gae_t = δ_t + γλ(1-d_t) gae_{t+1}
        gae = delta + gamma * lam * (1.0 - dones[t]) * gae
        advantages[t] = gae

    # TD(λ) 回报目标: G_t^λ = A_t^GAE + V(s_t)
    returns = advantages + values[:-1]
    return advantages, returns


def ppo_update(actor, critic, actor_optim, critic_optim,
               obs_batch, act_batch, adv_batch, ret_batch,
               old_log_prob_batch, clip_eps=0.2, value_coef=0.5,
               entropy_coef=0.01, n_epochs=10, batch_size=64):
    """PPO 多轮更新 — mini-batch SGD + PPO clipping

    对应 §2.5:
    L^PPO = L^CLIP(θ) - c1 * L^VF(φ) + c2 * S[π_θ]
    其中 L^CLIP(θ) = min(r_t(θ) Â_t, clip(r_t(θ), 1-ε, 1+ε) Â_t)
    """
    # === 优势归一化 — 降低方差的关键工程技巧 ===
    adv_batch = (adv_batch - adv_batch.mean()) / (adv_batch.std() + 1e-8)

    dataset = torch.utils.data.TensorDataset(
        obs_batch, act_batch, adv_batch, ret_batch, old_log_prob_batch
    )
    loader = torch.utils.data.DataLoader(dataset, batch_size=batch_size,
                                          shuffle=True)

    for _ in range(n_epochs):
        for obs, act, adv, ret, old_logp in loader:

            # === Critic 更新: L^VF(φ) = MSE(V_φ(s), G_t^λ) ===
            value_pred = critic(obs)
            value_loss = F.mse_loss(value_pred, ret)

            critic_optim.zero_grad()
            value_loss.backward()
            critic_optim.step()

            # === Actor 更新: PPO clipped surrogate objective ===
            log_prob, entropy = actor.evaluate(obs, act)
            ratio = torch.exp(log_prob - old_logp)  # r_t(θ) = π_new/π_old

            # PPO clipped objective
            surr1 = ratio * adv
            surr2 = torch.clamp(ratio, 1.0 - clip_eps, 1.0 + clip_eps) * adv
            actor_loss = -torch.min(surr1, surr2).mean()

            # 完整PPO损失: L^CLIP - c2 * entropy
            loss = actor_loss - entropy_coef * entropy

            actor_optim.zero_grad()
            loss.backward()
            actor_optim.step()
```

### 4.2 SAC for Locomotion(面向机器人运动的SAC)

```python
import copy
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.distributions import Normal
import numpy as np


class SoftQNetwork(nn.Module):
    """Soft Q-function Q_ψ(s, a)

    对应 §2.6.2 Soft Bellman 方程

    输入: [obs, act] 拼接 (d_s + d_a 维)
    输出: 标量 Q 值
    """
    def __init__(self, obs_dim, act_dim, hidden_dim=256):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(obs_dim + act_dim, hidden_dim), nn.ReLU(),
            nn.Linear(hidden_dim, hidden_dim), nn.ReLU(),
            nn.Linear(hidden_dim, 1),
        )

    def forward(self, obs, act):
        return self.net(torch.cat([obs, act], dim=-1)).squeeze(-1)


class TanhGaussianActor(nn.Module):
    """带 tanh 压缩的高斯策略网络(SAC Actor)

    对应 §2.6.2:
    a = tanh(μ_θ(s) + σ_θ(s) ⊙ ε), ε ~ N(0, I)

    tanh 压缩确保 a_i ∈ (-1, 1), 契合关节限位。
    """
    LOG_STD_MIN = -20   # exp(-20) ≈ 2e-9
    LOG_STD_MAX = 2     # exp(2) ≈ 7.4

    def __init__(self, obs_dim, act_dim, hidden_dim=256):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(obs_dim, hidden_dim), nn.ReLU(),
            nn.Linear(hidden_dim, hidden_dim), nn.ReLU(),
        )
        self.mean_head = nn.Linear(hidden_dim, act_dim)
        self.log_std_head = nn.Linear(hidden_dim, act_dim)

    def forward(self, obs):
        h = self.net(obs)
        mean = self.mean_head(h)
        log_std = self.log_std_head(h)
        log_std = torch.clamp(log_std, self.LOG_STD_MIN, self.LOG_STD_MAX)
        std = torch.exp(log_std)
        return mean, std, log_std

    def sample(self, obs):
        """重参数化采样 + tanh 压缩 + 对数概率修正

        返回: (action, log_prob)
        """
        mean, std, log_std = self.forward(obs)
        dist = Normal(mean, std)
        u = dist.rsample()          # u ~ N(μ, σ²), 无界
        action = torch.tanh(u)      # a = tanh(u), a ∈ (-1, 1)

        # 对数概率的变量变换修正 (§2.6.2):
        # log π(a|s) = log p(u) - Σ_i log(1 - tanh²(u_i))
        log_prob_u = dist.log_prob(u).sum(dim=-1)
        # 数值稳定实现: 2*(log(2) - u - softplus(-2u))
        log_prob = log_prob_u - (
            2.0 * (np.log(2.0) - u - F.softplus(-2.0 * u))
        ).sum(dim=-1)

        return action, log_prob


class SACAgent:
    """SAC (Soft Actor-Critic) — 连续控制的标准 off-policy RL 算法

    架构 (对应 §2.6.3 完整流程):
      - Actor π_θ:     TanhGaussianActor (重参数化高斯策略)
      - Critic Q_ψ1, Q_ψ2: SoftQNetwork (双 Q, Clipped Double-Q)
      - Target Q_ψ̄1, Q_ψ̄2: EMA 目标网络
      - 自动温度调节 α: log_α 作为可学习参数

    Args:
        obs_dim:         观测维度 d_s
        act_dim:         动作维度 d_a
        lr:              学习率 (典型值 3e-4)
        gamma:           折扣因子 γ
        tau:             目标网络软更新系数 (典型值 0.005)
        alpha:           初始温度 (若自动调节则为初始值)
        target_entropy:  目标熵 H̄ (默认 -act_dim)
    """
    def __init__(self, obs_dim, act_dim, lr=3e-4, gamma=0.99,
                 tau=0.005, alpha=0.2, target_entropy=None):
        self.actor = TanhGaussianActor(obs_dim, act_dim)
        self.q1 = SoftQNetwork(obs_dim, act_dim)
        self.q2 = SoftQNetwork(obs_dim, act_dim)

        # 目标网络: deep copy 初始参数, 冻结 requires_grad
        self.q1_target = copy.deepcopy(self.q1)
        self.q2_target = copy.deepcopy(self.q2)
        for p in self.q1_target.parameters():
            p.requires_grad = False
        for p in self.q2_target.parameters():
            p.requires_grad = False

        self.actor_optim = torch.optim.Adam(self.actor.parameters(), lr=lr)
        self.q1_optim = torch.optim.Adam(self.q1.parameters(), lr=lr)
        self.q2_optim = torch.optim.Adam(self.q2.parameters(), lr=lr)

        self.gamma = gamma
        self.tau = tau

        # 自动温度调节 (Haarnoja et al., 2019)
        if target_entropy is None:
            target_entropy = -act_dim
        self.target_entropy = target_entropy
        self.log_alpha = nn.Parameter(torch.tensor(np.log(alpha)))
        self.alpha_optim = torch.optim.Adam([self.log_alpha], lr=lr)

    @property
    def alpha(self):
        """exp(log_α) 保证 α > 0"""
        return self.log_alpha.exp().item()

    def update(self, replay_buffer, batch_size=256):
        """SAC 单步更新 (off-policy: 从 replay buffer 采样)

        对应 §2.6.3 算法流程:
        1. Critic 更新 (Soft Bellman residual)
        2. Actor 更新 (重参数化梯度)
        3. 温度 α 自动调节
        4. 目标网络 EMA 软更新
        """
        obs, act, reward, next_obs, done = replay_buffer.sample(batch_size)

        # ============================================================
        # Step 1: Critic 更新 — Soft Bellman Residual
        # J_Q(ψ_j) = E[(Q_ψ_j(s,a) - y)²]
        # y = r + γ(1-d)(min_j Q_ψ̄_j(s',a') - α log π_θ(a'|s'))
        # ============================================================
        with torch.no_grad():
            next_act, next_log_prob = self.actor.sample(next_obs)
            # Clipped Double-Q: 取 min 抑制 overestimation
            q1_next = self.q1_target(next_obs, next_act)
            q2_next = self.q2_target(next_obs, next_act)
            q_next = torch.min(q1_next, q2_next) - self.alpha * next_log_prob
            # (1-done): episode 终止时不 bootstrap
            q_target = reward + self.gamma * (1.0 - done) * q_next

        q1_loss = F.mse_loss(self.q1(obs, act), q_target)
        q2_loss = F.mse_loss(self.q2(obs, act), q_target)

        self.q1_optim.zero_grad(); q1_loss.backward(); self.q1_optim.step()
        self.q2_optim.zero_grad(); q2_loss.backward(); self.q2_optim.step()

        # ============================================================
        # Step 2: Actor 更新 — 重参数化梯度 (§2.6.2)
        # J_π(θ) = E[α log π_θ(f_θ(ε;s)|s) - min_j Q_ψ_j(s, f_θ(ε;s))]
        # ============================================================
        new_act, new_log_prob = self.actor.sample(obs)
        q1_new = self.q1(obs, new_act)
        q2_new = self.q2(obs, new_act)
        q_new = torch.min(q1_new, q2_new)
        actor_loss = (self.alpha * new_log_prob - q_new).mean()

        self.actor_optim.zero_grad(); actor_loss.backward()
        self.actor_optim.step()

        # ============================================================
        # Step 3: 自动温度调节 (Haarnoja et al., 2019)
        # J(α) = E[-α log π(a|s) - α H̄]
        # ============================================================
        alpha_loss = -(self.log_alpha.exp() *
                       (new_log_prob + self.target_entropy).detach()).mean()
        self.alpha_optim.zero_grad(); alpha_loss.backward()
        self.alpha_optim.step()

        # ============================================================
        # Step 4: 目标网络 EMA 软更新: θ̄ ← τ·θ + (1-τ)·θ̄
        # ============================================================
        with torch.no_grad():
            for tp, p in zip(self.q1_target.parameters(),
                             self.q1.parameters()):
                tp.data.copy_(self.tau * p.data + (1 - self.tau) * tp.data)
            for tp, p in zip(self.q2_target.parameters(),
                             self.q2.parameters()):
                tp.data.copy_(self.tau * p.data + (1 - self.tau) * tp.data)
```

### 4.3 Domain Randomization Wrapper(域随机化包装器)

```python
from typing import Dict, Tuple, Any
import numpy as np


class DomainRandomizationEnv:
    """域随机化环境包装器 — 每次 reset 随机采样物理参数

    实现 DR 训练范式 (§2.7.1):
      J_DR(π) = E_{ξ~p(ξ)}[E_{τ~π, M_ξ}[Σ R_t]]

    关键技术: Episode-level 随机化
      - 每个 episode 采样一次参数 ξ, 全程固定
      - 迫使策略从观测历史中隐式辨识环境参数

    为何不采用 Step-level:
      1. 真实世界参数不每步变化
      2. Step-level 产生非物理参数波动 → 误导性训练信号
      3. Episode-level 诱导隐式系统辨识能力
    """
    def __init__(self, env, randomization_config: Dict[str, Any]):
        """
        Args:
            env: 基础仿真环境 (Gym/Gymnasium 兼容)
            randomization_config: 随机化参数空间字典, 格式:
                {
                    'friction':    [0.5, 1.5],     # [low, high] 均匀分布
                    'mass_scale':  [0.7, 1.3],      # 质量缩放
                    'damping':     [0.5, 1.5],      # 阻尼缩放
                    'action_delay': [0, 20],         # 延迟 (ms)
                    'obs_noise':   0.001,            # 固定值(不随机化)
                }
        """
        self.env = env
        self.config = randomization_config
        self.current_params: Dict[str, float] = {}

    def _sample_params(self) -> Dict[str, float]:
        """从配置空间中独立采样一组物理参数"""
        params = {}
        for param_name, param_range in self.config.items():
            if isinstance(param_range, (list, tuple)):
                low, high = param_range
                params[param_name] = np.random.uniform(low, high)
            elif isinstance(param_range, (int, float)):
                params[param_name] = param_range  # 固定值
        return params

    def reset(self) -> np.ndarray:
        """重置环境 + 采样新参数 (Episode-level DR)"""
        self.current_params = self._sample_params()
        for param_name, value in self.current_params.items():
            self._apply_param(param_name, value)
        return self.env.reset()

    def step(self, action: np.ndarray) -> Tuple[np.ndarray, float, bool, Dict]:
        """执行动作"""
        return self.env.step(action)

    def _apply_param(self, param_name: str, value: float):
        """将采样参数应用到仿真环境 (MuJoCo 风格伪实现)"""
        if param_name == 'friction':
            self.env.set_geom_friction(value)
        elif param_name == 'mass_scale':
            self.env.set_body_mass_scale(value)
        elif param_name == 'damping':
            self.env.set_joint_damping(value)
        elif param_name == 'action_delay':
            self.env.set_action_delay(value)
        elif param_name == 'obs_noise':
            self.env.set_observation_noise(value)

    def get_current_params(self) -> Dict[str, float]:
        """返回当前 episode 的物理参数 (用于日志和分析)"""
        return self.current_params.copy()
```

---

## 五、核心Takeaway与延伸阅读

### 5.1 核心洞察

**洞察 1: Bellman方程是RL的第一性原理，所有无模型RL算法都是其不同的实现方式**。Bellman最优算子 $$\mathcal{T}^*$$ 的 $$\gamma$$-收缩性赋予值迭代收敛保证(Banach不动点定理)；策略梯度定理本质上是在连续动作空间中通过采样近似求解 $$\max_{\mathbf{a}} Q$$；SAC的Soft Bellman方程将熵嵌入值函数定义，使探索-利用平衡成为优化目标的一部分而非外挂技巧。

**洞察 2: 方差-偏差权衡贯穿RL全程 — GAE的 $$\lambda$$ 参数是机器人RL中最重要的"压缩旋钮"**。$$\lambda=0$$ 退化为单步TD(高偏差、低方差)；$$\lambda=1$$ 退化为MC(无偏、高方差)。机器人学典型值 $$\lambda \approx 0.95$$ 提供的有效时间窗口($$\frac{1}{1-\gamma\lambda} \approx 10\text{-}30$$步)恰好覆盖步态周期和操作原语的自然时间尺度——这是物理世界的时间常数与算法设计的对齐。

**洞察 3: 最大熵框架(SAC)是机器人RL的标准范式 — 不是因为它理论优雅，而是因为它解决了sim-to-real中的实际问题**。熵正则化的三大效应——自然探索、策略鲁棒性、off-policy样本效率——每一项都直接回应了机器人RL的核心痛感。SAC的重参数化技巧利用 $$\nabla_{\mathbf{a}} Q$$ 的信息丰富梯度信号，大幅降低策略梯度方差——对高自由度(Shadow Hand的24维)是质变式的改进。

**洞察 4: 非对称Actor-Critic + LSTM + 域随机化是sim-to-real迁移的成熟配方**。OpenAI灵巧手工作的四件套具有一般性: (1)训练时Critic享有特权仿真状态产生低方差优势估计；(2)Actor仅接收部署时可获取的观测，被迫隐式学习状态估计；(3)LSTM将时序上下文压缩为隐状态，近似恢复马尔可夫性；(4)Episode-level域随机化注入分布鲁棒性约束。这一范式已扩散到RMA(四足行走)、ANYmal、无人机导航等一系列系统。

**洞察 5: 奖励函数设计是机器人RL中最重要也最"非数学"的超参数**。与Atari(天然得分)和围棋(胜负明确)不同，行走/操作的奖励必须由工程师精心设计。好的奖励函数编码**任务的几何/物理约束**——"$$v_x$$ 接近 $$v_{\text{des}}$$"而非"到达终点"；"姿态接近直立"而非"不摔倒"。逐项惩罚(能量、抖动、极限位置)防止reward hacking。奖励设计是一门介于物理、几何和心理学之间的技艺。

### 5.2 开放问题与研究方向

1. **奖励规范(Reward Specification)**: 能否从自然语言指令或专家演示中自动推断奖励函数？Inverse RL和Preference-based RL(Christiano et al., 2017)是两条主线。

2. **安全探索(Safe Exploration)**: 如何保证RL探索阶段不发生灾难性行为？约束MDP(CMDP)、控制屏障函数(CBF)、以及基于MPC的安全滤波器都是活跃方向。

3. **世界模型 + RL**: Dreamer系列(Hafner et al., 2019-2023)在学到的动力学模型中"想象"训练。这能解决样本效率问题吗？还是世界模型的累积误差使其在高精度操作中不可靠？

4. **多任务与元RL**: 能否训练一个策略同时完成行走、奔跑、跳跃？多任务RL面临灾难性遗忘、任务推断和奖励尺度平衡等困难。

5. **大规模并行仿真**: Isaac Gym将并行环境推到数万级别——是否会使得on-policy PPO的样本效率劣势变得无关紧要？

### 5.3 推荐延伸阅读

| 文献 | 关键贡献 | 与本章的关联 |
|------|---------|------------|
| Sutton & Barto (2018), Ch.3-6, 13 | RL完整理论体系 | 值函数、TD学习、策略梯度的标准参考 |
| Schulman et al. (2016), "GAE" | 广义优势估计 | GAE完整推导、$$\lambda$$ 消融实验 |
| Schulman et al. (2017), "PPO" | 裁剪代理目标函数 | PPO vs TRPO对比、大规模分布式实验 |
| Haarnoja et al. (2018), "SAC" | 最大熵off-policy AC | SAC理论基础、与DDPG/TD3的对比 |
| Haarnoja et al. (2019), "SAC v2" | 自动温度调节 | 使SAC成为"无调参"算法 |
| Andrychowicz et al. (2020), IJRR | OpenAI灵巧手完整版 | 非对称AC、DR全面分析 |
| Tobin et al. (2017), "Domain Randomization" | DR开创性工作 | DR原理、首个策略迁移验证 |
| Peng et al. (2018), "Dynamics Randomization" | DR系统化实验 | 4项任务的DR消融研究 |
| Hafner et al. (2023), "DreamerV3" | 世界模型 + RL | 隐动力学中训练策略 |
| Kumar et al. (2021), "RMA" | 快速运动适应 | 非对称AC在四足行走的应用(第14章) |

---

## 六、练习与思考

### 基础练习

**习题1(MDP建模与Bellman手动计算)**:
考虑3x3 GridWorld。状态 $$s \in \{0, 1, \ldots, 8\}$$。动作 $$\mathcal{A} = \{\text{上}, \text{下}, \text{左}, \text{右}\}$$，确定性转移但碰壁则留在原地。状态8是目标(到达奖励+10并终止)，状态4是陷阱(进入奖励-10并终止)，其余每步 $$R=-1$$。取 $$\gamma=0.9$$。

(a) 写出该MDP的完整六元组。假设 $$\rho_0$$ 均匀分布在所有非终止状态。

(b) 用值迭代手动计算 $$V^*(s)$$ 对所有9个状态(至少3轮迭代)。

(c) 验证 $$V^*$$ 是 $$\mathcal{T}^*$$ 的不动点: 从你得到的 $$V^*$$ 出发，手算 $$\mathcal{T}^* V^*$$ 验证相等。

(d) 分析: 为什么深度RL无法在连续高维空间中做值迭代？你的答案应涉及维数灾难和函数近似的必要性。

**习题2(策略梯度定理的工程验证)**:
用PyTorch实现REINFORCE算法在CartPole-v1上的训练。要求:

(a) 不查阅教学代码，根据 §2.3 的策略梯度定理独立推导实现。

(b) 实现两个版本: (i)无baseline($$\Psi_t = G_t$$)；(ii)带baseline $$V_{\boldsymbol{\phi}}(\mathbf{s})$$。

(c) 每个版本运行10个随机种子，绘制: (i)episode回报学习曲线；(ii)梯度范数 $$\|\nabla_{\boldsymbol{\theta}} J\|_2$$ 的变化。分析baseline对梯度方差的削减效果。

(d) 证明: 若 $$V_{\boldsymbol{\phi}} = V^{\pi}$$(完美价值函数)，则带baseline的梯度估计是无偏且方差最小的(提示: §2.3步骤4)。

**习题3(GAE参数扫描)**:
在连续控制环境(如Pendulum-v1或HalfCheetah-v2)中用PPO训练，固定所有其他超参数，仅改变 $$\lambda \in \{0, 0.5, 0.8, 0.9, 0.95, 0.99, 1.0\}$$。

(a) 绘制平均回报 vs 环境步数的曲线。

(b) 测量达到80%最终性能所需的训练步数 vs $$\lambda$$。

(c) 讨论: $$\lambda=0$$(纯TD)和 $$\lambda=1$$(纯MC)在训练初期和后期的表现差异。与GAE的"方差-偏差"理论是否一致？

(d) 在什么情况下 $$\lambda=1$$ 可能优于 $$\lambda=0.95$$？(提示: 考虑环境随机性非常小的场景)

### 进阶练习

**习题4(SAC的实现与重参数化分析)**:
基于 §4.2 的SACAgent框架，在HalfCheetah-v2上从零实现完整SAC训练。要求:

(a) 自己实现Replay Buffer。

(b) 训练10万步后，对同一状态重复采样1000次动作(不同 $$\boldsymbol{\epsilon}$$)。绘制动作分布直方图，验证策略保持了有意义的熵(分布不是delta函数)。

(c) 比较: (i)重参数化技巧的actor更新；(ii)对数导数技巧的actor更新。量化两者的actor_loss方差。

(d) 验证Clipped Double-Q是否缓解Q值过估计: 每隔1000步记录 $$Q_{\boldsymbol{\psi}_1}, Q_{\boldsymbol{\psi}_2}$$ 和实际MC回报，绘制三者趋势图。

**习题5(SAC vs PPO系统对比)**:
在MuJoCo机器人任务(推荐Ant-v2或Humanoid-v2)上系统对比SAC和PPO:

(a) **样本效率**: 横轴交互步数，纵轴平均回报。标注两算法达到相同性能阈值所需步数比。

(b) **壁钟时间**: 记录实际计算时间，讨论off-policy的replay buffer开销和on-policy的rollout同步开销如何影响wall-time效率。

(c) **超参数敏感性**: 学习率 $$\{10^{-4}, 3\times10^{-4}, 10^{-3}\}$$ 和网络宽度 $$\{64, 128, 256, 512\}$$ 的网格搜索，绘制性能热力图。

(d) 基于实验结果，为以下场景推荐算法: (i)单GPU, 10并行环境；(ii)8-GPU, 4096并行环境；(iii)真实机器人在线学习。

**习题6(域随机化消融实验)**:
在四足行走仿真(推荐MuJoCo的Ant或Minitaur)中用PPO训练，进行DR消融研究:

(a) **Baseline**: 无DR(固定参数)。

(b) **单参数消融**: 逐一添加随机化(地面摩擦、负载质量、关节阻尼、执行器延迟、观测噪声)，测量zero-shot鲁棒性影响。

(c) **鲁棒性评估**: 对每个策略在100个"外推"参数集(参数在训练范围的1.2倍之外)上评估，记录平均存活步数。

(d) 哪个参数对sim-to-real迁移最关键？是否所有参数都产生正向鲁棒性收益？

(e) 将结果与 §2.7.1 的DR形式化 $$J_{\text{DR}}$$ 联系。$$p(\xi)$$ 的支撑集选择如何影响分布内和分布外泛化？讨论"随机化范围越大越好"是否成立。

### 开放研究问题

**习题7(奖励函数设计的几何方法)**:
四足机器人需学习"安静行走"——最小化足地接触冲击噪声。

(a) 提出至少三种不同的奖励设计方案。写出每个方案的数学表达式。

(b) 对每个方案，分析可能的**reward hacking**行为。例如: 机器人选择不移动，或采用低频蹦跳步态。

(c) 提出两种缓解reward hacking的策略，分析各自优劣: (i)多目标加权奖励；(ii)约束RL(硬约束而非软惩罚)。

(d) 讨论: 在极端情况下，奖励工程是否等价于"用先验知识设计控制器"？如果是，RL在机器人学中的独特价值在哪里？

**习题8(域随机化的理论基础与局限)**:
域随机化隐含假设真实环境参数 $$\xi^*$$ 在随机化分布 $$p(\xi)$$ 的支撑集内。

(a) 用概率论严格陈述这一假设。若 $$\xi^* \notin \text{supp}(p)$$，给出最坏情况下 $$J_{\text{real}}(\pi) - J_{\text{sim}}(\pi)$$ 的下界。

(b) **结构性失配**(structural mismatch): DR只能随机化仿真器已有模型的参数，但无法弥补仿真器根本不建模的物理效应(柔性接触、静摩擦、肌腱滞后)。试证: 存在一类真实物理现象，DR无法通过任何 $$p(\xi)$$ 来补偿。

(c) 系统辨识(SysID, §2.7.2)和域随机化(DR, §2.7.1)如何互补？设计将两者结合的训练方案。

(d) 若有一个"完美"物理模拟器，RL是否还需策略学习？还是可直接做开环最优控制？讨论Sim-to-Real的根本哲学。

---

> **上一章**: [第10章 视频世界模型](../chapters/ch10_视频世界模型.md)
>
> **下一章**: [第12章 行为克隆](../chapters/ch12_行为克隆.md)
>
> *提示: 第12章将介绍行为克隆(Behavioral Cloning)——从专家演示中直接学习策略。与本章的RL不同，行为克隆不需要奖励函数，但面临分布偏移的根本挑战。两章共同构成了机器人技能获取的两大范式：试错学习(RL)与演示学习(IL)。*


---

<!-- chapter-nav -->
<div style="display:flex; justify-content:space-between; align-items:center; padding:1em 0;">
  <div><a href="ch10_视频世界模型.md">← 第10章 视频世界模型</a></div>
  <div><a href="index.md">↑ 目录</a></div>
  <div><a href="ch12_行为克隆.md">第12章 行为克隆 →</a></div>
</div>
