风险敏感规划:当"平均最优"不够,如何度量并优化尾部风险(CVaR)¶
Part-U 不确定性规划方向 · 第六章(U5) 性质:⚪ 跨方向共享。本章是 Part-U 五安全谱的收官——尾部风险维。
前置自测¶
开始前,请先回答以下 5 题。答不出 ≥ 2 题,建议先回到指向的前置章节补齐。
- 机会约束(chance constraint)是什么? 它对"碰撞"这件事约束的是什么量?如果把允许失败概率 \(\delta\) 调到 0,会发生什么?(→ U3 机会约束规划)
- VaR(Value-at-Risk,风险价值)和分位数是什么关系? "95% VaR = 100"这句话的含义是什么?(→ 本章 §U5.1,或概率统计基础)
- 线性规划(LP)和二次规划(QP)的标准形式是什么? "引入辅助变量把 \(\max(0, x)\) 这种非光滑项线性化"是怎么做的?(→ Part 0 凸优化基础)
- 控制障碍函数(CBF)如何保证安全? \(h(x)\ge 0\) 定义什么,\(\dot h + \alpha h \ge 0\) 这个条件保证什么?(→ U2 鲁棒规划与安全滤波 §U2.5)
- 标准强化学习里,\(Q(s,a)\) 是什么的期望? 如果不取期望、而是保留"回报的整个分布",你能多知道什么?(→ RL 基础,软依赖)
这 5 题对应本章五块前置:机会约束(U3,CVaR 的直接前身)、VaR/分位数(理解 CVaR 的基线)、LP/QP(CVaR 可算化的工具)、CBF(CVaR-CBF 的基础)、RL 期望(理解分布式 RL 的动机)。第 1、4 题尤其关键——本章会反复用到"CVaR 是机会约束的公理化升级"和"把 CVaR 嵌进 CBF/MPC"。
本章目标¶
学完本章,你应该能够:
- 陈述 Artzner 一致性风险测度的四条公理(单调性、平移不变性、正齐次性、次可加性),并解释**次可加性为什么排除了 VaR**、为什么这对机器人安全至关重要。
- 推导 Rockafellar–Uryasev 的 CVaR 变分公式 \(\mathrm{CVaR}_\alpha(X)=\min_z\{z+\frac{1}{1-\alpha}\mathbb{E}[(X-z)_+]\}\),并把它**样本化成一个线性规划**。
- 解释 静态 CVaR 的时间不一致问题——为什么它不能直接塞进动态规划——以及 Ruszczyński 嵌套 CVaR 如何用"逐步施加一步条件 CVaR"修复它。
- 建立 分布式 RL(C51 / QR-DQN / IQN)与 CVaR 的精确关系,特别是 IQN 的 \(\tau\) 重采样如何实现 CVaR 及任意畸变风险度量。
- 说明 Majumdar–Pavone 机器人风险公理的核心论点——为什么"期望 + 碰撞概率"这种常见做法不满足公理、会诱发不合理行为。
- 实现 CVaR 的 LP 计算、把 CVaR 约束嵌入 MPC 的 QP、以及一个能在线调风险偏好的 IQN,并能在 2D 机器人导航上验证 CVaR 比机会约束更好地控制尾部。
- 判断 一个机器人安全问题该用机会约束还是 CVaR、该选什么 \(\alpha\)、什么时候需要比 CVaR 更灵活的畸变风险度量。
本章知识导航¶
本章主线一句话:在"期望最优"和"最坏情况"这两个极端之间,用一个公理化、可调(\(\alpha\))、可微的中间地带,度量并优化尾部风险。
知识结构(五个核心 + 落地):
风险敏感规划 = 优化"尾部"而非"平均"
│
┌─────────────────┼─────────────────┐
度量什么 怎么算 怎么用
(公理化) (可算化) (落地)
│ │ │
§U5.1 四公理 §U5.2 CVaR LP §U5.5 CVaR-CBF/MPC
(Artzner+ (Rockafellar- (把 CVaR 嵌进
机器人六公理) Uryasev → LP) 安全滤波/MPC)
│ │
│ §U5.3 时间一致性
│ (静态 CVaR 不一致
│ → 嵌套 CVaR)
│ │
└──── §U5.4 分布式 RL ────┘
(C51/QR-DQN/IQN:
学整个回报分布 →
天然暴露任意风险测度)
阅读路径: - 想建立直觉:§U5.1(为什么需要公理)→ §U5.2(CVaR 长什么样、怎么算)→ §U5.5(怎么用)。 - 做理论 / 写论文:全章顺序读,重点 §U5.1(公理 + 表示定理)、§U5.3(时间一致性,最易踩坑)。 - 做 RL / 世界模型:§U5.2(CVaR 定义)→ §U5.4(分布式 RL 与 CVaR 的精确关系,与你的方向交界最深)。 - 速查:直接看本章末的核心公式速查 + 符号速查 + 方法选型决策指南。
难度分布:§U5.1 ⭐⭐⭐、§U5.2 ⭐⭐⭐、§U5.3 ⭐⭐⭐⭐、§U5.4 ⭐⭐⭐⭐、§U5.5 ⭐⭐⭐。
每节解决一个递进的问题,连起来是"度量 → 算 → 递推 → 学 → 用"的完整链条:
| 节 | 一句话问题 | 一句话答案 |
|---|---|---|
| §U5.1 | 什么样的风险度量才"讲道理"?为什么不能用 VaR? | Artzner 四公理;VaR 违反次可加(合并制造风险),CVaR 满足全部公理 |
| §U5.2 | CVaR 怎么算、怎么不破坏优化的凸性? | Rockafellar–Uryasev 变分公式 → 辅助变量 → 线性规划,保凸 |
| §U5.3 | 多步序贯决策怎么用 CVaR?为什么不能直接塞进 DP? | 静态 CVaR 时间不一致;嵌套 CVaR 逐步施加、恢复 Bellman |
| §U5.4 | 怎么数据驱动地学风险敏感策略? | 分布式 RL 学整个回报分布,风险态度后置成对分位函数的重加权 |
| §U5.5 | 怎么把 CVaR 落到真实的安全工具上? | CVaR-CBF / CVaR-MPC,在 Part-U 安全谱上换"安全条件的写法" |
一条贯穿全章的暗线:风险态度(用什么度量、\(\alpha\) 取多少)是决策的一个独立、可量化、可调的维度——不该被默认为"风险中性(期望)"。从正向规划(§U5.1–§U5.5)到逆向学习(进阶十的风险敏感 IRL),这条暗线反复出现。
前置知识桥接¶
本章建立在 Part-U 前几章和一些公共基础之上。这里用几行重新激活它们,你不必翻回去也能跟上。
回顾 U3(机会约束规划):机会约束把安全写成 \(\Pr(\text{违反约束})\le\delta\)——允许小概率失败、换取可行性。我们在那里用它把"硬约束"松弛成"概率约束",并讨论了它的近似谱(从 Boole 界到 SAA)。本章的出发点正是机会约束的一个软肋:它只看"失败的概率有没有超过 \(\delta\)",完全不管"一旦失败、有多惨"。CVaR 正是来补这一刀的——它看的是尾部的**平均严重程度**。这条"CC 看分位点、CVaR 看尾部平均"的对比会贯穿全章。
回顾 U2(CBF 安全滤波):控制障碍函数用 \(h(x)\ge 0\) 定义安全集,用 \(\dot h+\alpha h\ge 0\)(离散版 \(h(x_{t+1})\ge(1-\alpha)h(x_t)\))保证状态永远留在安全集里(前向不变性)。我们在那里用它做"安全滤波器"——把任意标称控制投影到安全的控制集合。本章 §U5.5 会把这个 \(h(x)\ge 0\) 升级:当 \(x\) 受随机扰动时,不再要求"所有扰动下都安全"(太保守),而是要求"尾部最坏 \(\alpha\) 的平均仍安全"——即 \(\mathrm{CVaR}_\alpha[h]\ge 0\)。
回顾凸优化(Part 0):线性规划 LP 和二次规划 QP 是带线性 / 二次目标 + 线性约束的凸问题,有成熟高效求解器。关键技巧——非光滑的 \(\max(0,x)=(x)_+\) 可以引入辅助变量 \(u\ge 0,\ u\ge x\) 线性化(最小化时 \(u\) 会被压到 \(\max(0,x)\))。这个技巧是 §U5.2 把 CVaR 变成 LP 的全部秘密。
软依赖 RL(PPO/SAC、\(Q=\mathbb{E}[\text{回报}]\)):标准 RL 里,动作价值 \(Q(s,a)\) 是"从状态 \(s\) 执行动作 \(a\)、之后按策略走到底"的**折扣回报的期望**——\(Q(s,a)=\mathbb{E}[\sum_t\gamma^t r_t]\)。智能体据此决策(选 \(Q\) 最大的动作)或改进策略(actor-critic)。关键词是那个**期望** \(\mathbb{E}\)——标准 RL 在定义价值时就把回报的随机性平均掉了,只留一个均值。§U5.4 的分布式 RL 会把这个 \(Q=\mathbb{E}[Z]\) 改成学**整个回报分布** \(Z(s,a)\)——有了整个分布,就能算它的任意风险测度(均值、CVaR、任意畸变),而不只是均值。这正是本章和 RL 交界最深的地方。没有 RL 背景也能读懂 §U5.4 的思想(学分布而非均值),只是代码细节需要一点 PyTorch。
如果跳过本章会怎样¶
两个具体场景,说明缺了"尾部风险"这一维会出什么事:
- 场景一(被罕见灾难拖垮的"平均最优"):你给配送机器人做路径规划,目标是最小化**期望**耗时。有一条路平均最快,但有 3% 的概率撞上一个会卡住机器人 2 小时的死角。期望目标会算:"3% × 2 小时的尾部 ≈ 平摊到平均里只多几分钟,仍是最快"——于是选了它,然后每 33 次就有一次灾难性卡死。期望把罕见的大灾难"平均掉"了。风险敏感目标(CVaR)会盯住这条路最坏 5% 的平均耗时,直接否决它。这正是 §U5.1 要讲的"为什么期望不够"。
-
场景二(机会约束的"达标即停"陷阱):你用机会约束做避障,要求 \(\Pr(\text{碰撞})\le 5\%\)。方案 A 的碰撞概率 4.9%,但一旦碰撞是低速轻碰;方案 B 的碰撞概率也是 4.9%,但一旦碰撞是高速重创。机会约束认为两者**一样好**(都达标 4.9%<5%)——它对"碰撞有多严重"完全失明。CVaR 会看尾部的平均代价,明确区分 A 和 B。这正是 §U5.2/§U5.5 要解决的。
-
场景三(多步规划的"朝令夕改"):你给机器人做多步风险规划,想"最小化整条任务的最坏 5% 总代价"。你在起点算出一个最优计划,机器人开始执行;走了一步、观察到环境的某个随机结果后,你按同样的准则重新算——结果新计划和旧计划冲突,机器人在"执行旧计划"和"听从新计划"之间反复横跳,行为抖动甚至绕圈。这不是 bug,是"静态 CVaR 时间不一致"的必然后果(§U5.3)——而如果你根本不知道静态 vs 嵌套 CVaR 的区别,你会百思不得其解。
一句话:缺了风险敏感这一维,你的机器人要么被期望"平均掉"的罕见灾难反复打击,要么在机会约束的"达标即停"里对灾难的严重程度视而不见,要么在多步规划里因时间不一致而朝令夕改。
预计阅读时间¶
- 精读(推导 + 跑通全部代码 + 做练习):18–25 小时,建议分 2 周。
- 速读(读正文 + 看代码不跑,建立完整理解):4–5 小时。
- 速查(查某个公式 / 概念 / 选型):直接跳本章末的速查表与决策指南,10–20 分钟。
§U5.1 Artzner 四公理:什么样的"风险度量"才算合理 ⭐⭐⭐¶
动机:你需要把"一个随机代价"压成"一个数"¶
机器人在不确定环境里做决策,每个方案的后果不是一个确定的数,而是一个**随机变量**——比如"这条路径的耗时"是一个分布(大多数时候 10 分钟,偶尔因堵塞 30 分钟),"这个动作的代价"也是一个分布(通常安全,偶尔碰撞)。要在方案之间排序、要写进优化目标,你必须把这个随机变量**压成一个标量**——这个"从随机代价到实数"的映射,就叫**风险度量(risk measure)** \(\rho\)。这个"压成一个标量"的操作看似平凡,其实是整个风险敏感规划的起点——你**怎么**压(用什么 \(\rho\)),就编码了你**怎么**看待不确定性下的好坏。用期望压,你只在乎平均;用 CVaR 压,你额外在乎尾部。本节要回答的就是:在所有可能的"压法"里,哪些是"讲道理"的、哪些会误导机器人。
最自然的选择是**期望** \(\rho(Z)=\mathbb{E}[Z]\)。但期望有个致命问题(前置场景一):它把罕见的大灾难"平均掉"了。一条路 97% 概率 10 分钟、3% 概率 120 分钟,期望只有 \(0.97\times10+0.03\times120\approx13.3\) 分钟,看起来很好——可那 3% 的两小时卡死会反复发生。期望对尾部不敏感。
第二个候选是 VaR(Value-at-Risk,风险价值)。\(\mathrm{VaR}_\alpha(Z)\) 是代价分布的 \(\alpha\) 分位数——"有 \(\alpha\) 的把握,代价不超过这个值"。比如 \(\mathrm{VaR}_{0.95}=100\) 表示"95% 的情况下代价 \(\le 100\)"。VaR 关注了尾部的位置,金融界用了几十年。但 VaR 也有它自己的致命问题——而且这个问题不是"调一调就好"的,是**结构性**的。
那么,到底什么样的 \(\rho\) 才算一个"讲道理"的风险度量?这正是 Artzner 等人 1999 年那篇里程碑论文要回答的——他们不直接造一个度量,而是**先立公理**:列出任何一个理性的风险度量都应该满足的基本性质,满足这些性质的就叫**一致性风险测度(coherent risk measure)**。这是一种典型的公理化思路:与其争论"哪个度量最好",不如先约定"好的度量必须满足哪些性质",再看谁满足、谁违反。
约定:本章统一把 \(Z\)(或 \(X\)、\(L\))当作**代价 / 损失**,越大越坏(耗时越长、碰撞越重)。这与金融文献常把 \(X\) 当"收益、越大越好"相反——读金融来源时要注意符号方向。本章所有公理、CVaR 公式都按"代价越大越坏"陈述,与机器人直觉一致。
反面:如果用一个"不讲道理"的度量会怎样¶
先看不立公理、随手挑度量的后果,你就懂了为什么需要公理。
假设你用 VaR 做风险度量,且场景是:机器人要同时执行两个子任务 A 和 B,各自有一个"小概率大代价"的失败模式(比如 A 有 4% 概率损失 100,B 有 4% 概率损失 100,两者独立)。你分别评估:\(\mathrm{VaR}_{0.95}(A)\) 和 \(\mathrm{VaR}_{0.95}(B)\)——因为各自的失败概率 4% < 5%,95% 分位数落在"不失败"那一侧,所以 \(\mathrm{VaR}_{0.95}(A)=\mathrm{VaR}_{0.95}(B)=0\)(小代价)。看起来两个任务风险都是 0。
但合起来呢?两个独立的 4% 失败事件,至少一个失败的概率是 \(1-0.96^2\approx7.8\% > 5\%\)——于是"联合代价"的 95% 分位数落进了失败区,\(\mathrm{VaR}_{0.95}(A+B)\) 可能高达 100(甚至两个都失败时 200)。于是出现了荒谬的结论:
把两个任务合起来,VaR 反而暴涨。 这违反了一个最基本的直觉——"分散化 / 合并不应该凭空制造风险"。如果你的风险度量会因为"把两件事放一起评估"就给出比"分别评估之和"更高的风险,它会诱导机器人做出反直觉的决策:宁愿把任务拆开单独做(即使物理上没有任何理由),只为了在度量上显得"风险更低"。这种度量是不能信的。这个反例正是 Artzner 论文里指出的 VaR 的核心缺陷,也是"次可加性"公理要排除的情形。
把这个反例用数字钉实(已实跑核对):取 \(A,B\) 各以 4% 概率损失 100、否则 0,相互独立。\(\Pr(A>0)=4\%<5\%\),所以 \(\mathrm{VaR}_{0.95}(A)=0\),同理 \(\mathrm{VaR}_{0.95}(B)=0\),两者之和为 0。但 \(A+B\) 的分布是:以 \(0.96^2=92.16\%\) 概率为 0、以 \(2\times0.04\times0.96=7.68\%\) 概率为 100、以 \(0.0016\) 概率为 200。于是 \(\Pr(A+B>0)=7.84\%>5\%\),\(\mathrm{VaR}_{0.95}(A+B)=100>0\)——合并后 VaR 从 0 暴涨到 100,次可加性被彻底违反。而对同样的 \(A,B\) 算 CVaR(用下一节的 Rockafellar–Uryasev 公式,对原子稳健):\(\mathrm{CVaR}_{0.95}(A)=\mathrm{CVaR}_{0.95}(B)=\frac{0.04\times100}{0.05}=80\),\(\mathrm{CVaR}_{0.95}(A+B)=\frac{0.0016\times200+0.0484\times100}{0.05}=103.2\le160\)——CVaR 的次可加性成立。(注意:算 CVaR\((A+B)\) 时不能用"对 \(\ge\)VaR 的样本取平均"的朴素估计,那样会因原子算错,必须用 §U5.2 的 RU 公式——这个坑下一节细讲。)
理论:四条公理及其机器人含义¶
Artzner、Delbaen、Eber、Heath 在 Coherent Measures of Risk(Mathematical Finance 9(3):203–228, 1999)里提出:一个风险度量 \(\rho\)(从代价随机变量到实数)若满足以下四条公理,就称为**一致性的(coherent)**。下面逐条给出数学陈述和机器人语境的解读(代价越大越坏)。
A1 单调性(Monotonicity):若 \(Z\le Z'\) 逐样本成立(\(Z\) 在每种情况下都不比 \(Z'\) 差),则 \(\rho(Z)\le\rho(Z')\)。 - 机器人含义:如果方案一在**所有**可能情况下代价都不高于方案二,那它的风险评估也不该更高。一个严格更优的方案不应被判为"更危险"。这是最基本的合理性——度量不能颠倒明摆着的优劣。
A2 平移不变性(Translation invariance / Cash invariance):对任意确定常数 \(c\),\(\rho(Z+c)=\rho(Z)+c\)。 - 机器人含义:如果给所有情况都加上一个确定的代价增量 \(c\)(比如每条路都多收 \(c\) 的固定过路费),那风险评估就正好增加 \(c\)。确定性的代价直接、线性地反映到风险里,不被放大或缩小。这条还有一个漂亮的解读:\(\rho(Z)\) 可理解为"为了让 \(Z\) 变得可接受,需要预留多少确定性的安全裕量"——加确定代价 \(c\),需要的裕量正好也加 \(c\)。
A3 正齐次性(Positive homogeneity):对任意 \(\beta\ge 0\),\(\rho(\beta Z)=\beta\rho(Z)\)。 - 机器人含义:风险随规模等比缩放。如果把代价单位从"米"换成"厘米"(乘 100),或把任务规模放大 \(\beta\) 倍,风险评估就等比放大 \(\beta\) 倍。度量不依赖于你用什么单位来记代价。(注:正齐次性在金融里有争议——它忽略了"规模本身带来的流动性风险",但在机器人代价度量里通常合理。后面 Majumdar–Pavone 的讨论会松动这一条。)
A4 次可加性(Subadditivity):\(\rho(Z+Z')\le\rho(Z)+\rho(Z')\)。 - 机器人含义:这是四条里最深刻、也是排除 VaR 的那一条。它说**合并不会凭空制造风险**——两个子任务联合后的风险,不超过各自风险之和。Artzner 用一句话概括它:"a merger does not create extra risk"(合并不产生额外风险)。它正面编码了"分散化 / 冗余的价值":把鸡蛋分到多个篮子里(或给系统加冗余),联合风险只会 \(\le\) 各自之和,绝不会更高。上面 VaR 反例里"合起来风险暴涨"正是违反了这一条。
把四条公理放在**同一个机器人例子**上走一遍,体会它们如何协同。设一个仓库 AGV 的"延误代价"随机变量 \(Z\)(单位:分钟,越大越坏):
- A1 单调性的作用:若改进路径后,新路径在每种交通情况下延误都 \(\le\) 旧路径,那风险度量必须判新路径风险 \(\le\) 旧路径。否则度量会阻止明摆着的改进——AGV 会拒绝一条严格更好的路,荒谬。
- A2 平移不变性的作用:若全程多加一道固定 5 分钟的安检(确定性增量),风险评估正好 +5。这让"确定成本"和"风险"在同一单位下可加——你可以说"这条路的风险等价于 \(\rho(Z)\) 分钟的确定延误",安检加 5 分钟,等价延误也加 5 分钟。
- A3 正齐次性的作用:若把延误从"分钟"换算成"秒"(×60),风险评估也 ×60。度量不依赖单位——否则换个单位风险排序就变,无法在不同 AGV / 不同度量单位间比较。
- A4 次可加性的作用:AGV 要连续完成两段配送 \(Z_1,Z_2\)。次可加保证 \(\rho(Z_1+Z_2)\le\rho(Z_1)+\rho(Z_2)\)——把两段一起评估的风险,不超过分别评估之和。这鼓励"整体规划"而非"把任务拆散只为在度量上显得风险低"(VaR 恰恰会因违反它而诱导拆散,前面反例)。
四条合起来,AGV 的风险度量才"讲道理":不颠倒改进(A1)、与确定成本同尺度可加(A2)、不依赖单位(A3)、鼓励整体规划(A4)。期望满足全部四条(它是最简单的一致性度量),但期望的问题不在公理、在它把尾部平均掉——CVaR 既满足全部四条、又盯住尾部,这才是它的价值。
A3 + A4 合起来又叫**次可加 + 正齐次 = 次可线性(sublinear),并能推出**凸性:\(\rho(\lambda Z+(1-\lambda)Z')\le\lambda\rho(Z)+(1-\lambda)\rho(Z')\)。凸性对优化至关重要——它保证"把风险写进目标 / 约束后,问题仍是凸的、可高效全局求解"。这条性质在 §U5.2 把 CVaR 嵌进 MPC 时会直接兑现。
为什么 VaR 违反 A4、而 CVaR 满足全部四条¶
VaR 的问题:\(\mathrm{VaR}_\alpha\) 只是一个**分位点**——它只告诉你"尾部从哪里开始"(\(\alpha\) 分位数的位置),完全不管"尾部里面有多惨"。正因为它只是一个分位数,重尾 / 多峰分布下两个独立损失之和的分位数可能突然跳进失败区,导致 \(\mathrm{VaR}(Z+Z')>\mathrm{VaR}(Z)+\mathrm{VaR}(Z')\)(上面的反例)。Artzner 等人在论文里正是指出基于分位数的方法不满足次可加,并提出了修复这一缺陷的方法——即引入一致性的度量。所以 VaR 不是"调参能救"的,它结构上就缺次可加性。
先把三个候选度量摆在一起对照,看清各自看见和看不见什么:
| 度量 | 看什么 | 看不见什么 | 满足一致性公理 | 凸 |
|---|---|---|---|---|
| 期望 \(\mathbb{E}[Z]\) | 平均 | 尾部(罕见大灾难被平均掉) | 是(但对尾部失明) | 是 |
| VaR\(_\alpha\) | 尾部从哪开始(分位点) | 尾部内部多惨 | 否(违反次可加) | 否 |
| CVaR\(_\alpha\) | 尾部的平均严重程度 | (尾部内更极端的个别点,但看了平均) | 是(全部四条) | 是 |
这张表一眼看出为什么 CVaR 胜出:期望对尾部失明、VaR 既对尾部内部失明又不满足公理(且非凸难优化),只有 CVaR 既看尾部严重程度、又满足全部公理、又凸(可优化)。
CVaR 的解法:CVaR(Conditional Value-at-Risk,条件风险价值,也叫 Expected Shortfall、Mean Excess Loss、Tail VaR)不看分位点,而看**分位点以上整个尾部的平均**:
直觉:\(\mathrm{CVaR}_{0.95}\) = "最坏 5% 情况的平均代价"。它不只关心尾部从哪开始,还把整个尾部积分平均了。正是这个"对尾部积分取平均"的操作带来了光滑性,进而保证了次可加性——尾部平均是一个关于分布的凸、光滑的泛函,合并两个损失时不会出现 VaR 那种分位点突跳。可以证明 CVaR 满足全部四条公理,是一致性风险测度。这就是为什么风险敏感规划的主力是 CVaR 而非 VaR。
对比性思维:VaR 看"门槛在哪",CVaR 看"门槛后面有多惨"——一字之差,公理性质天壤之别。把损失分布想成一条尾巴:VaR 是"尾巴从哪个 \(x\) 坐标开始"的那个**点**;CVaR 是"那条尾巴覆盖的区域的平均高度"。两个机器人方案可能有完全相同的 VaR(尾巴起点一样),但一个尾巴又细又短(轻微超支)、另一个又粗又长(灾难性超支)——VaR 说它们一样危险,CVaR 一眼看出后者差得多(前置场景二)。这个区别在数学上的后果是决定性的:看"点"的 VaR 会因分位点突跳而违反次可加(合并制造风险),看"尾部平均"的 CVaR 因积分光滑而满足全部公理。记住这句"VaR 看门槛、CVaR 看门槛后的平均",你就抓住了本章前两节的全部直觉。
机器人特有的两条公理:Majumdar–Pavone 的扩展¶
Artzner 的四公理来自金融。机器人的序贯决策有额外的结构,Majumdar 和 Pavone 在 How Should a Robot Assess Risk? Towards an Axiomatic Theory of Risk in Robotics(ISRR 2017, arXiv:1710.11040)里论证:机器人的风险度量还应再满足两条公理。他们给出表示定理,精确刻画了满足这些公理的度量类(称为畸变风险度量 distortion risk metrics),并讨论了机器人中常用风险度量的陷阱。
A5 共单调可加性(Comonotone additivity):若 \(Z\) 和 \(Z'\) 共单调(completely positively correlated,总是同涨同跌,本质是同一个底层随机源的两个单调函数),则 \(\rho(Z+Z')=\rho(Z)+\rho(Z')\)(取等号,不打折)。 - 机器人含义:次可加性(A4)奖励分散化,但分散化的前提是"风险不完全相关"。如果两个代价完全正相关(比如同一个传感器故障同时拖垮两个子系统),它们之间**没有真正的分散化**——此时联合风险就应该正好等于各自之和,不该获得虚假的"分散化折扣"。A5 堵住了这个漏洞:只对真正不相关的风险给次可加的好处,对共单调的风险不打折。
用一个具体例子体会 A5 为什么重要:设机器人有两个子系统的延误代价 \(Z_1,Z_2\),都由**同一个**电池电压随机源驱动——电压低时两个子系统同时变慢(\(Z_1,Z_2\) 完全正相关、共单调)。一个只满足 A1–A4 的次可加度量会给 \(\rho(Z_1+Z_2)<\rho(Z_1)+\rho(Z_2)\)(打了分散化折扣),仿佛把两个子系统放一起降低了风险。但这是**虚假的**——它们由同一个源驱动,根本没有分散化(电压一低两个一起坏)。A5 强制 \(\rho(Z_1+Z_2)=\rho(Z_1)+\rho(Z_2)\)(不打折),如实反映"没有真正分散化"。CVaR 满足 A5——对共单调的代价,它的尾部恰好同时发生,CVaR 取等号。这对机器人冗余设计有直接含义:两个共用同一故障源的"冗余"模块,不应被风险度量当成真正的冗余——A5 保证度量不会被这种假冗余骗到,从而避免工程师据此做出"以为有冗余、其实没有"的危险设计。
A6 律不变性(Law invariance):若 \(Z\) 和 \(Z'\) 同分布,则 \(\rho(Z)=\rho(Z')\)。 - 机器人含义:风险只取决于代价的**概率分布**,而不取决于"这个代价具体来自哪个物理事件"。两个分布完全相同的代价,风险评估必须相同。这是个很自然的要求——它也意味着风险度量可以**只从数据(样本分布)估计**,不需要知道底层物理机制。这条对"用蒙特卡洛样本估风险"(§U5.2)是隐含的前提。
表示定理(Kusuoka / Föllmer–Schied 一脉):一个深刻的结果是,满足 A1–A6 的风险度量恰好是**畸变风险度量(distortion risk metric)**,可写成对分位函数的一个加权积分:
其中 \(F_Z^{-1}\) 是代价 \(Z\) 的分位函数(逆 CDF),\(g:[0,1]\to[0,1]\) 是一个单调递增的**畸变函数(distortion function)**,\(g(0)=0,g(1)=1\)。直觉:畸变函数 \(g\) 重新分配了各个分位数的权重——风险中性(期望)对应 \(g(\tau)=\tau\)(每个分位数等权),而风险厌恶则把更多权重压到高分位(坏)的尾部。
这个表示定理为什么深刻?它把"无穷多种可能的风险度量"收缩成了一个**可参数化的家族**——任何满足六公理的度量,都由一个畸变函数 \(g\)(一条 \([0,1]\to[0,1]\) 的单调曲线)唯一决定。这意味着:选风险度量 = 选一条畸变曲线。你不再面对"无数种压法"的茫然,而是面对一个有清晰结构的选择空间(畸变函数的形状)。这也是为什么 §U5.4 的 IQN 如此强大——它学到了完整的分位函数 \(F_Z^{-1}\),于是"应用任意畸变 \(g\)"只是对分位函数的一次加权积分,任意一致性风险测度都能即时算出。表示定理在理论上统一了一致性风险测度,IQN 在算法上把这个统一变成了可操作的旋钮。
CVaR 是这个大类里的一个特例:取 \(g(\tau)=\min\!\left(\frac{\tau}{\alpha},1\right)\)(这里用一种约定;不同文献因"代价 vs 收益"方向和 \(\alpha\) 的定义会有等价的变体)——这个 \(g\) 在 \(\tau<\alpha\) 时权重为 0、在 \(\tau\ge\alpha\) 的尾部均匀加权,正好对应"只平均最坏 \((1-\alpha)\) 尾部"。换个 \(g\),你就得到别的风险度量。把几个常见的畸变函数 \(g\)(或等价的权重 \(\mathrm{d}g\))摆在一起,看它们如何对应不同的风险态度:
| 畸变(权重如何分配到分位) | 对应的风险度量 | 风险态度 |
|---|---|---|
| \(g(\tau)=\tau\)(每个分位等权) | 期望 \(\mathbb{E}[Z]\) | 风险中性 |
| \(g\) 在尾部 \([\alpha,1]\) 均匀加权、其余为 0(阶跃) | CVaR\(_\alpha\) | 只均匀关注最坏 \((1-\alpha)\) 尾部 |
| \(g\) 平滑地给越坏的分位越高权重(递增的权重谱 \(\phi\)) | 谱风险测度 | 对越坏的分位越担忧(比 CVaR 平滑) |
| 全部权重压到最坏那一个分位(\(g\) 在 \(\tau=1\) 跳到 1) | 最坏情况 \(\mathrm{ess\,sup}\,Z\) | 极端保守(= 鲁棒) |
这张表把抽象的"畸变函数 \(g\)"变具体了:风险态度的本质,就是你如何给不同坏程度的分位分配权重。期望一视同仁(等权);CVaR 把权重均匀压到尾部(尾部内还是一视同仁);谱风险更精细(尾部内也按坏的程度递增加权);最坏情况把所有权重压到唯一最坏点。\(\alpha\)(CVaR)或 \(\phi\)(谱风险)就是调节这个权重分配的旋钮。这也预告了 §U5.4——IQN 学到整个分位函数后,"换一个 \(g\)"就是"换一种 \(\tau\) 的重加权方式",于是任意畸变风险度量都能即时算出。这个表示定理是 §U5.4 的理论根基——分布式 RL(IQN)学到了整个分位函数 \(F_Z^{-1}\),于是**换一个畸变函数 \(g\),就能即时算出任意畸变风险度量**,CVaR 只是其中最常用的一个。
本质洞察:公理化把"选哪个风险度量"从主观偏好变成了数学必然。一开始你可能觉得"用期望还是 VaR 还是 CVaR"是个见仁见智的工程口味问题。但 Artzner 和 Majumdar–Pavone 的工作揭示:一旦你写下几条"任何理性风险度量都该满足"的公理,候选集就被极大地收窄了——VaR 直接出局(违反次可加),而满足全部公理的恰好是畸变风险度量这一大类,CVaR 是其中结构最简单、最常用的代表。这就是公理化方法的威力:它不靠"我觉得 CVaR 更好"的主观论证,而是用"你想要这几条性质 ⟹ 你只能在这个类里选"的逻辑必然性来指导选择。对机器人安全工程师,这意味着选风险度量有了**可辩护的理论依据**,而非拍脑袋——当你向同事或审查者解释"为什么用 CVaR 不用碰撞概率"时,公理就是你的论据。
⚠️ 本节常见陷阱¶
💡 概念误区:以为 VaR 只是"没 CVaR 那么好",调高 \(\alpha\) 就能补救 - 现象 / 后果:继续用 VaR 做风险约束,以为把 \(\alpha\) 从 0.95 调到 0.99 就更安全、更合理了。 - 根本原因:VaR 的缺陷是**结构性的**(违反次可加性),不是"尾部看得不够远"。无论 \(\alpha\) 多高,VaR 始终只是一个分位点,对尾部内部的严重程度完全失明,且合并风险时仍可能暴涨。调 \(\alpha\) 改变的是"尾巴从哪开始看",改变不了"只看一个点、不看尾部平均"这个根本盲区。 - 正确做法:要看尾部严重程度、要满足公理,就用 CVaR(或更一般的畸变风险度量)。VaR 适合"只关心达标概率、不关心严重程度"的场合,但那种场合本质就是机会约束(U3),不如直接用机会约束。
💡 概念误区:把代价方向搞反,套用金融文献的公理符号 - 现象 / 后果:直接抄金融教材的单调性"\(X\ge Y\Rightarrow\rho(X)\le\rho(Y)\)"(因为金融里 \(X\) 是收益、越大越好),用到机器人代价上,导致风险排序整个颠倒。 - 根本原因:金融文献多以 \(X\) 为**收益**(越大越好),机器人语境以 \(Z\) 为**代价**(越大越坏),两者的单调性方向、平移不变的符号都相反。混用会让"更坏的方案"被算成"更低风险"。 - 正确做法:固定一个约定并贯穿全程。本章统一用"代价越大越坏",单调性是 \(Z\le Z'\Rightarrow\rho(Z)\le\rho(Z')\)。读任何来源前,先确认它的 \(X\) 是代价还是收益,再翻译公理方向。
🧠 思维陷阱:以为"满足公理"就等于"适合你的任务" - 现象 / 后果:知道 CVaR 是一致性的,就无脑对所有问题都用 CVaR,不考虑任务是否真的需要风险厌恶、\(\alpha\) 该取多少。 - 根本原因:公理保证的是"度量本身讲道理"(不会颠倒优劣、不会凭空造风险),但**不**保证"这个风险态度适合你的任务"。一个探索型机器人可能根本不该风险厌恶(过度保守会一事无成);\(\alpha\) 取多高也取决于你对尾部的容忍度和样本量(§U5.5 思考题)。 - 正确做法:先判断任务是否真的在乎尾部(安全攸关 → 是;纯探索 / 可重试 → 未必),再选风险态度和 \(\alpha\)。公理是"度量合格的必要条件",不是"用它就对"的充分条件。
练习¶
- [A 型·VaR 次可加性反例] 用 NumPy 构造两个独立的离散损失变量 \(A,B\)(各以 4% 概率取 100、否则取 0)。采样 \(10^5\) 次,数值估计 \(\mathrm{VaR}_{0.95}(A)\)、\(\mathrm{VaR}_{0.95}(B)\)、\(\mathrm{VaR}_{0.95}(A+B)\),验证 \(\mathrm{VaR}_{0.95}(A+B) > \mathrm{VaR}_{0.95}(A)+\mathrm{VaR}_{0.95}(B)\)(次可加性被违反)。再对同样的 \(A,B\) 算 CVaR,验证 CVaR 的次可加性成立(\(\le\))。
- [B 型·Artzner 论文精读] 精读 Artzner 等 1999 的 Section 2(四公理定义)和 Section 4(VaR 反例 + 一致性度量的引入)。用中文写一份 1–2 页总结,对四条公理**逐条**给出一个机器人场景的具体例子,说明"违反这条公理会诱发什么不合理的机器人行为"。
- [思考题] Majumdar–Pavone 用共单调可加性(A5)堵住"虚假分散化折扣"的漏洞。请设计一个具体的机器人场景:两个子系统的失败代价**完全正相关**(共单调),说明如果用一个只满足 A1–A4、不满足 A5 的度量,会错误地给这个系统打出"低于真实风险"的评估,从而诱导工程师做出危险的冗余设计决策。
§U5.2 Rockafellar–Uryasev:把 CVaR 变成一个线性规划 ⭐⭐⭐¶
动机:CVaR 的定义里藏着一个"先算 VaR"的难题¶
§U5.1 给了 CVaR 的直觉形式 \(\mathrm{CVaR}_\alpha(Z)=\mathbb{E}[Z\mid Z\ge\mathrm{VaR}_\alpha(Z)]\)。这个式子虽然直观,但有个工程上的麻烦:它**依赖于先知道 \(\mathrm{VaR}_\alpha\)**(你得先算出分位点,才能对超过它的部分取平均)。而 \(\mathrm{VaR}_\alpha\) 是分位数,分位数关于决策变量是**非凸、非光滑**的——如果你想"优化一个决策 \(\theta\) 使 CVaR 最小",这个"先算分位数"的依赖会让优化问题变得很难处理。
更糟的是,在机器人优化里我们要的不是"给定分布算 CVaR",而是"把 CVaR 写进优化目标或约束"——比如"在 CVaR(碰撞代价) \(\le\) 阈值的约束下规划轨迹"。如果 CVaR 的计算本身就要嵌套一个求分位数的子问题,整个优化就没法用标准的凸优化求解器解。
举个具体的机器人例子体会这个困难:你要为无人机规划一条轨迹(决策变量是控制序列 \(\theta\)),目标是"在风扰下,碰撞代价的 CVaR\(_{0.95}\) 最小"。如果按 CVaR 的定义"先算 VaR、再对超过 VaR 的部分平均",那么每当优化器试一个新的 \(\theta\),碰撞代价的分布就变(不同轨迹遇到不同的风扰后果),VaR(那个分位点)也跟着变——VaR 作为 \(\theta\) 的函数是**非光滑**的(在样本点处有拐折)、**非凸**的。于是优化器看到的是一个"内层嵌着非凸非光滑子问题"的双层结构,梯度法在拐折处卡住、全局最优无保证、求解器直接罢工。这正是"按定义算 CVaR"在优化里走不通的根本原因——也是 Rockafellar–Uryasev 公式的价值所在:它把这个双层非凸结构,化成了单层凸优化。
Rockafellar 和 Uryasev 在 Optimization of Conditional Value-at-Risk(Journal of Risk 2(3):21–42, 2000)里给出了一个漂亮得令人意外的解法:他们找到一个**辅助变量**形式,把 CVaR 写成一个**对辅助变量求最小**的表达式——而且这个表达式是**凸**的,能直接样本化成**线性规划**。这个技术能同时算出 VaR 并优化 CVaR,可以与解析或场景方法结合、在大规模问题上高效求解。这是 CVaR 从"理论上好"走向"工程上能用"的关键一步。
反面:如果硬按定义算 CVaR 会怎样¶
假设你不知道 Rockafellar–Uryasev 公式,硬按定义把 CVaR 嵌进优化。你的优化问题会长这样(最小化决策 \(\theta\) 的 CVaR):
这里 \(\mathrm{VaR}_\alpha(L(\theta,\omega))\) 本身是 \(\theta\) 的一个复杂函数(\(\theta\) 一变,损失分布变,分位数也变)。于是你面对的是一个**双层优化**:外层优化 \(\theta\),内层每次都要重新求分位数。分位数函数不光滑(在样本点处有拐折)、不凸,梯度法容易卡住,全局最优无保证。更别说"条件期望 \(\mathbb{E}[\cdot\mid\cdot]\)"里的条件集合 \(\{L\ge\mathrm{VaR}\}\) 也随 \(\theta\) 跳变。这条路在工程上基本走不通——这正是为什么需要一个不依赖"先算 VaR"的等价形式。
补一个直觉,为什么分位数(VaR)对决策变量非凸:分位数是"排第 \(\alpha N\) 位的那个样本值",当 \(\theta\) 连续变化时,哪个样本排在第 \(\alpha N\) 位会**突然跳变**(一个样本超过另一个时,排序换位)——于是 VaR 作为 \(\theta\) 的函数是分段的、在换位处有拐折,既不光滑也不凸。而 CVaR 是"尾部的平均",平均是对一段样本求和,\(\theta\) 变化时这个和平滑地变(个别样本换位对平均的影响是连续的),所以 CVaR 光滑且凸。这就是 VaR 和 CVaR 在优化性质上天壤之别的根源——一个看"排第几位的那个点"(排序突跳),一个看"那一段的平均"(平滑)。Rockafellar–Uryasev 公式的魔力,正是把"先排序找分位点"这个非凸操作,替换成了一个对辅助变量 \(z\) 的凸最小化。
理论:Rockafellar–Uryasev 变分公式¶
核心结论:CVaR 可以写成对一个**辅助标量 \(z\)** 求最小:
其中 \((X-z)_+=\max(0,X-z)\) 是"超过 \(z\) 的部分"。这个式子的神奇之处:右边不需要预先知道 VaR,\(z\) 只是一个自由的辅助变量,让你对它取最小即可;而**取到最小的那个 \(z^*\) 恰好就是 \(\mathrm{VaR}_\alpha\)**,最小值恰好就是 \(\mathrm{CVaR}_\alpha\)。换句话说,这个变分公式"顺带"把 VaR 也算出来了。
为什么这个公式成立?看一阶条件。 把右边的目标记为 \(F(z)=z+\frac{1}{1-\alpha}\mathbb{E}[(X-z)_+]\)。对 \(z\) 求导(利用 \(\frac{\mathrm{d}}{\mathrm{d}z}\mathbb{E}[(X-z)_+]=-\Pr(X>z)\),因为 \(z\) 增大一点,超过 \(z\) 的样本各减少同样一点,期望减少的速率正是"有多大比例的样本超过 \(z\)"):
令导数为 0:\(\Pr(X>z)=1-\alpha\),即 \(\Pr(X\le z)=\alpha\)——这正是 \(\alpha\) 分位数的定义,所以 \(z^*=\mathrm{VaR}_\alpha\)。把 \(z^*\) 代回 \(F\),经整理(\(\mathbb{E}[(X-z^*)_+]=\Pr(X>z^*)\cdot\mathbb{E}[X-z^*\mid X>z^*]=(1-\alpha)\mathbb{E}[X-\mathrm{VaR}_\alpha\mid X\ge\mathrm{VaR}_\alpha]\)):
得证。\(F(z)\) 是凸的(\((X-z)_+\) 对 \(z\) 凸,期望保凸,加线性项 \(z\) 仍凸),所以"令导数为 0"找到的就是全局最小。
一个验证细节:上面的导数推导假设分布连续。当分布有原子(离散点,比如机器人"碰 / 不碰"的二值代价)时,\(F(z)\) 在原子处有拐折、导数不连续,但 \(F\) 仍是凸的、最小值仍等于 CVaR——只是"用 \(\mathbb{E}[X\mid X\ge\mathrm{VaR}]\) 这个条件期望形式"在原子处会偏离真实 CVaR。这个细节很重要:对有原子的分布,应当用变分公式(或下面的 LP)来算 CVaR,而不是用"对超过 VaR 的样本取平均"的朴素估计——后者在原子处会算错(本节练习会让你亲眼看到这个偏差)。
从公式到线性规划:样本平均近似(SAA)¶
变分公式里的期望 \(\mathbb{E}[(X-z)_+]\) 在实际中用**样本平均近似(Sample Average Approximation, SAA)**——你有 \(N\) 个损失样本 \(\{x_1,\dots,x_N\}\)(来自蒙特卡洛、历史数据或仿真),用样本均值代替期望:
现在用前置桥接里的标准技巧处理非光滑的 \((x_i-z)_+\):引入辅助变量 \(u_i\ge 0\),约束 \(u_i\ge x_i-z\)。在最小化目标里,每个 \(u_i\) 会被自动压到它的下界 \(\max(0,x_i-z)=(x_i-z)_+\)(因为目标想让 \(u_i\) 尽量小,而约束不让它低于 \(x_i-z\) 和 0)。于是 CVaR 计算变成一个标准**线性规划**:
这是个有 \(N+1\) 个变量、\(2N\) 个线性约束的 LP,任何 LP 求解器秒解。
为什么辅助变量 \(u_i\) 会"自动"等于 \((x_i-z)_+\)(值得想清楚):这是辅助变量技巧的精髓。约束只说 \(u_i\ge x_i-z\) 且 \(u_i\ge0\)——它给了 \(u_i\) 两个下界,但没说 \(u_i\) 等于什么。关键在目标函数:目标是**最小化** \(\sum u_i\)(系数为正),所以优化器会把每个 \(u_i\) 尽量往小压。能压到多小?压到两个下界里较大的那个,即 \(u_i=\max(x_i-z, 0)=(x_i-z)_+\)。若 \(x_i>z\)(样本超过 \(z\)),\(u_i\) 被压到 \(x_i-z\);若 \(x_i\le z\),\(u_i\) 被压到 0。于是在最优解处 \(\sum u_i=\sum(x_i-z)_+\),正好是变分公式里的那一项——这就是为什么这个 LP 等价于变分公式。记住这个模式:要把 \(\max(0,\text{表达式})\) 放进最小化问题,就引入一个辅助变量、给它"\(\ge\) 表达式"和"\(\ge0\)"两个下界,最小化会自动把它压到 \(\max\)。这个技巧在凸优化里反复出现(不只 CVaR),是把非光滑 \((\cdot)_+\) 线性化的标准手法。
关键的工程红利:如果损失是决策变量 \(\theta\) 的函数 \(x_i=L(\theta,\omega_i)\),且 \(L\) 对 \(\theta\) 凸,那么约束 \(u_i\ge L(\theta,\omega_i)-z\) 关于 \((\theta,z,u)\) 仍是凸的,整个"优化 \(\theta\) 使 CVaR 最小"的问题保持凸!这意味着你可以把 CVaR 直接写进一个更大的凸优化(比如 MPC 的 QP),而不破坏凸性——这正是 §U5.5 把 CVaR 嵌进 MPC 的基础。这个"辅助变量 + 线性约束"的小技巧,是 CVaR 能进入实时机器人优化的全部秘密。
数值验证:公式、LP 与尾部敏感性¶
下面的数值都已实跑核对。先验证变分公式确实在 \(z^*=\mathrm{VaR}\) 取到最小、最小值等于 CVaR(标准正态,\(\alpha=0.95\)):取一组 20 万样本,对 \(F(z)=z+\frac{1}{1-\alpha}\overline{(x-z)_+}\) 做一维搜索,最优 \(z^*\approx 1.642\),恰好等于经验 VaR\(_{0.95}\approx 1.642\);最小值 \(\approx 2.059\),恰好等于经验 CVaR\(_{0.95}\approx 2.059\)。变分公式得到验证。
再看 SAA-LP:对 2000 个标准正态样本解上面的 LP,LP 最优值 \(\approx 2.084\)(即 CVaR),\(z^*\approx 1.673\)(即 VaR),与直接的经验估计一致。LP 形式可用。
最能体现"CVaR 比 VaR 对尾部敏感"的是重尾对比。取标准正态和标准化的学生 \(t\) 分布(自由度 3,归一到单位方差),都算 \(\alpha=0.95\):
| 分布 | VaR\(_{0.95}\) | CVaR\(_{0.95}\) | CVaR/VaR |
|---|---|---|---|
| 正态 | 1.640 | 2.059 | 1.26 |
| \(t\)(df=3,重尾) | 1.365 | 2.248 | 1.65 |
注意一个反直觉的现象:重尾 \(t\) 分布的 VaR 反而更小(1.365 < 1.640)——因为它更集中在中间,95% 分位点更靠内。但它的 CVaR 明显更大(2.248 > 2.059),CVaR/VaR 比值从正态的 1.26 跳到 1.65。这说明:只看 VaR,你会误判重尾分布"更安全"(分位点更小);CVaR 看穿了它肥厚的尾巴。为什么会这样?重尾 \(t\) 分布把概率质量"两极分化"——大部分挤在中间(所以中间更尖、95% 分位点更靠内、VaR 更小),少部分甩到很远的尾巴(所以尾部更肥)。VaR 只看"95% 分位点在哪",被那个更靠内的分位点骗了,以为安全;CVaR 看"超过分位点的整个尾部的平均",把那条甩得很远的肥尾巴算了进去,于是更大。这个机理对机器人很关键:很多真实扰动(突发碰撞力、传感器偶发大误差)正是这种"平时很集中、偶尔甩很远"的重尾——VaR 会被它们的"平时集中"骗到,CVaR 才捕捉到"偶尔甩很远"的危险。对机器人,重尾恰恰对应"偶发但极端的灾难"(罕见的高速碰撞、突发的传感器全失效)——这正是 VaR 失明、CVaR 警觉的地方。
CVaR 随 \(\alpha\) 怎么变(再补一组直觉数字):固定标准正态,看 CVaR\(_\alpha\) 随 \(\alpha\) 升高如何变化——\(\alpha=0.9\) 时 CVaR\(\approx1.75\)、\(\alpha=0.95\) 时 \(\approx2.06\)、\(\alpha=0.99\) 时 \(\approx2.67\)。\(\alpha\) 越接近 1,CVaR 看的尾部越窄越极端、值越大(越保守)。这印证了 \(\alpha\) 是一个直观的"保守程度"旋钮:调高它,机器人对越来越极端的尾部设防。但同时(呼应后面的陷阱)\(\alpha\) 越高、落在尾部的样本越少(\(\alpha=0.99\) 时 \(N\) 个样本只有约 \(0.01N\) 个在尾部),估计越不稳——这是 \(\alpha\) 不能盲目调高的统计代价。
另一个视角:CVaR 的对偶表示与"最坏分布平均"¶
Rockafellar–Uryasev 的变分公式是 CVaR 的**原始(primal)**形式。CVaR 还有一个同样深刻的**对偶(dual)**形式,能从另一个角度解释它为什么是一致性的——而这正好把 §U5.1 的公理和 §U5.2 的可算化连起来。
一致性风险测度有一个一般的对偶表示:任何一致性风险测度都可写成"在一组备选概率测度上取最坏期望"——
其中 \(\mathcal{Q}\) 是一族概率测度(一个凸集)。直觉:一致性风险 = "对一族可能的概率情景,取最坏那个情景下的期望"。这正是一致性公理的对偶面孔——次可加 + 正齐次(次可线性)的泛函,按凸分析的对偶,必然能写成"在某个凸集上取上确界"。
对 CVaR,这个备选测度族 \(\mathcal{Q}\) 有极清晰的形式:所有"密度不超过 \(\frac{1}{1-\alpha}\) 倍原测度"的概率测度。也就是说,\(\mathrm{CVaR}_\alpha(X)=\max\{\mathbb{E}_Q[X]: 0\le\frac{\mathrm{d}Q}{\mathrm{d}P}\le\frac{1}{1-\alpha}\}\)——你可以把概率质量任意搬动,但任何一点的密度最多放大到原来的 \(\frac{1}{1-\alpha}\) 倍。要让 \(\mathbb{E}_Q[X]\) 最大(最坏),最优的 \(Q\) 就是把全部"可放大额度"都压到 \(X\) 最大(最坏)的那 \(1-\alpha\) 尾部上——于是 \(\mathbb{E}_Q[X]\) 恰好就是"最坏 \(1-\alpha\) 尾部的平均",即 CVaR。对偶和原始在这里完美对上。
这个对偶视角不只是漂亮——它是**分布鲁棒优化(DRO)**和 §U5.5 的分布鲁棒 MPC(DR-MPC)的桥梁:把"对一族分布取最坏"这个思想推广(让 \(\mathcal{Q}\) 是"离名义分布不超过某距离的所有分布"),就得到分布鲁棒的 CVaR——在分布本身都不确定时仍能给出尾部保证。
多视角理解:CVaR 有三张等价的面孔——尾部平均、变分最小、最坏分布期望。同一个 CVaR,可以从三个角度看,每个角度服务于不同目的:(1) 尾部平均 \(\mathbb{E}[X\mid X\ge\mathrm{VaR}]\)(§U5.1)——最直观,用于解释"它度量什么";(2) 变分最小 \(\min_z\{z+\frac{1}{1-\alpha}\mathbb{E}[(X-z)_+]\}\)(§U5.2 原始)——最可算,用于嵌进 LP/QP 优化;(3) 最坏分布期望 \(\max_{Q\in\mathcal{Q}}\mathbb{E}_Q[X]\)(对偶)——最深刻,用于解释"为什么一致"并通向分布鲁棒。像 / 不像:三者数值完全相等(是同一个量),但"可操作性"不同——讲直觉用 (1)、写优化用 (2)、做理论 / 鲁棒推广用 (3)。一个成熟的从业者会根据手头任务在三张面孔间自由切换:要给同事解释就说"最坏 5% 的平均",要写进 MPC 就用变分形式,要推广到分布不确定就用对偶形式。理解"同一对象的多重表示各有所长",是从"会用 CVaR"到"精通 CVaR"的关键一步。
⚠️ 本节常见陷阱¶
💡 编程陷阱:对有原子(离散值)的损失,用
mean(x[x >= VaR])估 CVaR - 现象 / 后果:对二值代价(碰 / 不碰)或离散损失算 CVaR,用"对超过 VaR 的样本取平均",得到的值系统性偏离真实 CVaR——而且可能让你误判次可加性。例如两个独立的"4% 概率损失 100"的变量 \(A,B\),用这种朴素估计算出 CVaR\((A+B)\approx 102\)、却把 CVaR\((A)+\)CVaR\((B)\) 算成 \(\approx 8\),看上去次可加性被违反——这是估计器的错,不是 CVaR 的错。 - 根本原因:当分布在 VaR 处有原子(一团样本恰好等于分位点),"\(\ge\) VaR 的样本"的占比不等于 \(1-\alpha\),朴素平均既没取够也没取对那 \(1-\alpha\) 尾部。 - 正确做法:用 Rockafellar–Uryasev 公式 \(z+\frac{1}{1-\alpha}\overline{(x-z)_+}\)(\(z=\) 分位数)或直接解 SAA-LP——它们对原子稳健。用 RU 重算上面的例子,CVaR\((A)=\)CVaR\((B)=80\)、CVaR\((A+B)=103.2\le 160\),次可加性正确成立。 - 自检方法:对一个已知解析 CVaR 的离散分布(如上面的 \(A\),理论 CVaR\(_{0.95}=4/0.05=80\))测试你的估计器,对不上就说明踩了原子的坑。💡 概念误区:把辅助变量 \(z\) 当成一个需要单独调的超参数 - 现象 / 后果:在 CVaR-LP 里把 \(z\) 固定成某个猜的值(比如手动设成"大概的 VaR"),而不是让优化器去优化它。 - 根本原因:误解了变分公式——\(z\) 不是超参数,是**被优化掉的内部变量**,优化器会自动把它解到 \(\mathrm{VaR}_\alpha\)。固定它会破坏"min over \(z\)",算出的不是 CVaR 而是一个上界(因为 \(F(z)\ge F(z^*)=\)CVaR 对任意 \(z\) 成立)。 - 正确做法:始终把 \(z\) 作为决策变量交给 LP/QP 求解器。它的最优值会自己浮现为 VaR,你不用、也不该手动设它。
🧠 思维陷阱:以为 SAA 样本越少越省事,少量样本也能可靠估极端尾部 - 现象 / 后果:用很少的样本(如 \(N=50\))估 CVaR\(_{0.99}\),得到的估计方差极大、每次跑都跳,却以为"差不多对"。 - 根本原因:\(\alpha\) 越接近 1,CVaR 依赖的尾部样本越少——\(N\) 个样本里只有约 \((1-\alpha)N\) 个落在尾部(\(\alpha=0.99,N=50\) 时尾部只有约 0.5 个样本!),少到无法可靠估计。这是估计极端尾部的固有困难(呼应 §U5.1 思维陷阱的"α 越高越需要更多样本")。 - 正确做法:\(\alpha\) 越高,\(N\) 要越大(经验上让 \((1-\alpha)N\) 至少几十到上百)。样本实在有限时,要么降低 \(\alpha\)(看没那么极端的尾部)、要么用参数化 / 重要性采样补尾部样本,别盲目相信小样本的极端尾部估计。
练习¶
- [A 型·CVaR LP] 用 Python(CVXPY 或纯 NumPy + SciPy
linprog)实现 Rockafellar–Uryasev 的 CVaR-LP:给定 1000 个损失样本,解 LP 算 CVaR\(_{0.95}\)。分别对(a)标准正态样本、(b)重尾的标准化 \(t\)(df=3)样本,对比 CVaR 与 VaR 的差异,复现"重尾下 CVaR/VaR 比值显著更大"的现象。再验证你的 LP 解出的 \(z^*\) 确实等于经验 VaR。 - [A 型·原子分布的 CVaR 估计] 构造一个离散损失(4% 概率取 100,否则取 0)。分别用(a)朴素估计
mean(x[x>=VaR])、(b)Rockafellar–Uryasev 公式 / LP,算 CVaR\(_{0.95}\)。对比两者,验证朴素估计偏离理论值 80、而 RU 公式 / LP 给出正确的 80。写一句话解释为什么朴素估计在这里出错。 - [思考题] 变分公式 \(\mathrm{CVaR}_\alpha(X)=\min_z\{z+\frac{1}{1-\alpha}\mathbb{E}[(X-z)_+]\}\) 把"先算分位数再取尾部平均"这个非凸的两步操作,变成了一个凸的一步最小化。请解释:这个转化为什么对"把 CVaR 写进 MPC 的优化目标"如此关键?如果没有它、直接在 MPC 里嵌"对超过 VaR 的代价取平均",会破坏 MPC 优化问题的什么性质、导致什么后果?
§U5.3 时间不一致与嵌套 CVaR:为什么静态 CVaR 塞不进动态规划 ⭐⭐⭐⭐¶
动机:单步 CVaR 好用,多步 CVaR 却会"自己打自己脸"¶
§U5.2 教会了我们在**一次性决策**里用 CVaR——给定一个损失分布,算它的 CVaR、把它写进一个 LP/QP。但机器人的决策是**序贯**的:走一步、观察、再走一步……一直到任务结束。我们关心的往往是整条轨迹的**累积代价** \(L=c_0+\gamma c_1+\gamma^2 c_2+\cdots\) 的尾部风险。
最自然的想法是:把整条轨迹的累积代价当成一个随机变量 \(L\),直接最小化它的 CVaR:\(\min_\pi\mathrm{CVaR}_\alpha(L)\)。这叫**静态 CVaR**(static / nested-free CVaR)——在 \(t=0\) 时刻,盯着"从头到尾的总代价分布"的尾部。听起来很合理。
为什么"听起来合理"却有陷阱?先看它在**单步**为什么没问题:单步决策只在 \(t=0\) 做一次、之后不再有信息更新和重新决策,所以"在 \(t=0\) 盯住代价分布的尾部"就是全部,没有"后续重新评估"的机会去和它矛盾。陷阱恰恰出在**多步**——多步意味着你会走一步、获得新信息(观察到环境的某个随机结果)、然后**站在新的信息上重新决策**。问题是:\(t=0\) 时你对"全程总代价的最坏 \(1-\alpha\) 尾部"的定义,和走到 \(t=1\)、获得新信息后对"剩余轨迹的最坏 \(1-\alpha\) 尾部"的定义,可能指向完全不同的情形。当这两个"尾部"不一致时,\(t=0\) 的最优计划和 \(t=1\) 的重新最优就会打架——这就是时间不一致。
但这里埋着一个深刻的陷阱:静态 CVaR 是时间不一致的(time-inconsistent)。意思是——你在 \(t=0\) 时刻按"最小化整条轨迹 CVaR"定下的最优策略,走到 \(t=1\)、获得新信息后,如果重新按同样的准则做一次最优决策,会得到一个**和原计划不一致**的策略。换句话说,你昨天的最优计划,今天的你会想推翻。这对动态规划是致命的——DP 的整个机器(Bellman 方程、值迭代)都建立在"时间一致"之上:DP 假设"未来的最优子策略"可以独立求解、再拼回整体最优(最优性原理)。时间不一致直接摧毁了这个前提。
这一节要讲清楚两件事:(1) 静态 CVaR 为什么时间不一致、为什么这让它塞不进 DP;(2) Ruszczyński 的**嵌套 CVaR(nested / Markov risk measure)**如何用"换一种施加风险的方式"修复时间一致性,让 risk-averse 的 Bellman 方程重新成立。
反面:硬把静态 CVaR 当 DP 目标会怎样¶
设想一个两步导航:\(t=0\) 选第一步动作,\(t=1\) 观察到环境(比如前方是否结冰)后选第二步动作。你在 \(t=0\) 用静态 CVaR 规划:枚举所有"\(t=0\) 动作 + \(t=1\) 应变策略"的组合,算每个组合下"总代价"分布的 CVaR\(_{0.95}\),选 CVaR 最小的那套完整计划。假设算出来的最优计划是:"\(t=0\) 走左,若 \(t=1\) 观察到结冰则减速、否则正常"。
现在时间推进到 \(t=1\),你真的观察到了"结冰"。手里的计划说"减速"。但如果此刻的你**重新**用静态 CVaR 做一次决策——只不过现在的"整条轨迹"是从 \(t=1\) 算起的剩余轨迹——你会发现:\(t=0\) 那个"95% 尾部"是针对**全程总代价**定义的,而走到 \(t=1\) 并观察到结冰后,"哪些情况算最坏 5%"这件事被重新洗牌了。在 \(t=0\) 看来属于尾部的某些情形,现在可能已经不在 \(t=1\) 视角的尾部里(因为"结冰"这个分支本身可能就是当初尾部的一部分,条件在它上面之后,尾部的构成完全变了)。于是 \(t=1\) 的你重新优化,可能得出"应该正常速度"而不是"减速"——和 \(t=0\) 的计划冲突。
后果很具体:你的机器人要么死板地执行一个它此刻已经不认同的旧计划(承诺执行 \(t=0\) 的策略),要么每步都推翻重来(每步重新优化静态 CVaR)——而后者会导致行为抖动、甚至在某些构造下绕圈子。 更糟的是,因为没有时间一致性,你**无法用 Bellman 方程递推**地求解——没法把"\(t=1\) 之后的最优"当成一个可复用的子问题,因为它依赖于"\(t=0\) 时刻对全程尾部的定义",而这个定义随时间漂移。整个动态规划的高效递推结构垮掉了。这正是静态 CVaR 不能直接进 DP 的根本原因。
理论:嵌套 CVaR 与 risk-averse Bellman 方程¶
Ruszczyński 在 Risk-averse dynamic programming for Markov decision processes(Mathematical Programming 125:235–261, 2010)里给出的修复思路,本质是**换一种"施加风险"的方式**:不在 \(t=0\) 对"全程总代价"施加一次 CVaR,而是**在每一步都施加一次"一步条件 CVaR",层层嵌套**。
形式上,把目标从静态的 \(\mathrm{CVaR}_\alpha(c_0+\gamma c_1+\gamma^2 c_2+\cdots)\) 换成**嵌套**形式:
其中 \(\mathrm{CVaR}_\alpha^{s_t}\) 表示"在状态 \(s_t\) 处、对下一步的随机性施加的一步条件 CVaR"。直觉对比:静态 CVaR 是"站在起点,对整条路的总代价的尾部担忧一次";嵌套 CVaR 是"每走到一个状态,都对'紧接着的下一步会通向什么'的尾部担忧一次,然后把这种逐步的担忧层层复合起来"。
这个换法为什么修复了时间一致性? 因为嵌套形式天然是**递归**的——它的结构本身就长成 Bellman 方程的样子。定义 risk-averse 值函数 \(V(s)\),它满足:
其中 \(s'\) 是从 \((s,a)\) 转移到的(随机的)下一状态,\(\mathrm{CVaR}_\alpha^{s}[\cdot]\) 是对这个随机 \(s'\) 取的一步条件 CVaR。这就是 risk-averse Bellman 方程——它和标准 Bellman 方程长得几乎一样,唯一的改动是把"对下一状态取期望 \(\mathbb{E}_{s'}[V(s')]\)"换成"对下一状态取一步 CVaR \(\mathrm{CVaR}_\alpha^{s}[V(s')]\)",其余(\(\min_a\)、即时代价 \(c\)、折扣 \(\gamma\)、递归结构)完全不变。直觉上,标准 Bellman 假设"下一状态按其概率平均",risk-averse Bellman 则悲观地假设"下一状态偏向最坏 \(1-\alpha\) 尾部"。正因为这个改动只动了"如何聚合下一状态的随机性"、没动递归结构,求解机器(值迭代、策略迭代)几乎原样可用——这是嵌套形式相比静态形式的核心工程优势(实现四会把这"只改一行"落成可运行代码)。
Ruszczyński 证明了这个嵌套构造的三个关键性质:
- 时间一致性自动成立:嵌套 CVaR 定义的偏好是时间一致的——\(t=0\) 定的最优策略,\(t=1\) 重新优化仍然认同。因为每一步只对"下一步"施加风险、风险的施加不依赖于"全程尾部"这种会漂移的全局量。
- risk-averse Bellman 方程成立:上面的递归方程有唯一解,且最优策略可由它导出——DP 的最优性原理在嵌套风险下恢复了。
- 值迭代 / 策略迭代收敛:一步 CVaR 算子(像期望算子一样)是一个**压缩映射**(CVaR 满足单调性 + 平移不变,正好保证 Bellman 算子是 \(\gamma\)-压缩),所以值迭代、策略迭代照常收敛到唯一最优——你熟悉的 MDP 求解机器几乎原样可用,只是把期望换成一步 CVaR。
实际怎么算这个一步 CVaR(工程细节):risk-averse 值迭代每次更新 \(V(s)=\min_a\{c+\gamma\,\mathrm{CVaR}_\alpha^s[V(s')]\}\),核心是对"下一状态值 \(V(s')\) 的随机分布"算一步 CVaR。怎么算?下一状态 \(s'\) 按转移概率 \(P(s'\mid s,a)\) 分布,\(V(s')\) 是一组带概率的值——这正是一个离散随机变量,用 §U5.2 的工具算它的 CVaR 即可:要么直接用 Rockafellar–Uryasev 公式(对这组带概率的值,\(z=\) 其 \(\alpha\) 分位、再算 \(z+\frac{1}{1-\alpha}\mathbb{E}[(V(s')-z)_+]\)),要么解一个小 LP(变量是 \(z\) 和每个后继的辅助 \(u\))。实现四就是前一种做法的直接落地。所以 risk-averse VI 的每次迭代,本质是"对每个 \((s,a)\) 解一个一步 CVaR 子问题"——子问题很小(变量数 = 后继状态数),但要解 \(|S|\times|A|\) 次。这也是进阶四列的开放问题之一:"嵌套 CVaR Bellman 每步要解一个一步 CVaR,大规模问题如何高效求解这一嵌套"——状态多时这 \(|S|\times|A|\) 个小 LP 的总开销不可忽视,是 nested-CVaR 求解的实际瓶颈。
和静态 CVaR 求解的对比:静态 CVaR 没有这种"每步一个小子问题"的递推结构——它要在整条轨迹空间上优化(或把 VaR 阈值 \(z\) 增广进状态,变成一个更大的 MDP)。所以嵌套虽然每步要解小 LP,但它有递推结构(可用 VI/PI、可并行各状态的子问题);静态没有干净的递推,求解往往更难。这从求解角度再次印证"几乎总用嵌套"。
对比性思维:静态 CVaR 是"一次性对全程担忧",嵌套 CVaR 是"每步对下一步担忧再复合"——前者时间不一致、塞不进 DP,后者时间一致、Bellman 照常。打个比方:静态 CVaR 像一个人在出发前对"整趟旅程会不会很糟"焦虑一次,定下全程计划——可一旦上路、信息更新,他对"什么算糟"的判断变了,旧计划就不认了(时间不一致)。嵌套 CVaR 像一个人每到一个路口,只对"下一段路会通向多糟"谨慎一次,然后一路这样谨慎下去——这种"逐步、局部"的谨慎天然可以递推(每个路口的决策只依赖当前状态),所以 Bellman 方程成立。代价是两者度量的**不是同一个东西**:静态 CVaR 精确控制"全程总代价的尾部",嵌套 CVaR 控制的是"逐步复合的风险",后者通常更保守(每步都担忧、担忧会累积),且没有"全程总代价 CVaR \(\le\) 某值"这样干净的整体解释。选哪个,是"要可处理的 DP(嵌套)"还是"要精确的全程尾部语义(静态)"之间的权衡。
本质洞察:时间一致性不是 CVaR 的毛病,而是"在序贯决策里如何施加风险"的根本张力。一个初学者容易以为"静态 CVaR 时间不一致"是 CVaR 这个度量有缺陷。其实不然——问题出在**把一个'对整条随机轨迹的一次性风险评估'硬塞进'逐步展开的序贯决策'这个错配上。任何"对全程总量施加一次的非线性风险泛函"(不只是 CVaR)都会面临时间不一致,因为"全程尾部"的定义会随信息更新而漂移。Ruszczyński 的洞察是:要让风险与 DP 兼容,就必须把风险的施加也"序贯化"——每步施加一点、层层复合,让风险泛函的结构和决策的递归结构对齐。这呼应了一个更普遍的原理(U4 也出现过):**当你想用动态规划求解时,目标函数的结构必须和'逐步递推'相容——期望天然相容(线性、可分解),而非线性风险泛函必须改造成嵌套形式才相容。理解这一点,你就明白了为什么风险敏感 RL(§U5.4)里"动态 / iterated CVaR"和"静态 CVaR"是两个不同的东西,以及为什么它们在理论上不一致。
静态 vs 嵌套:一个必须记住的区分¶
这个区分会直接影响 §U5.4 对分布式 RL 的理解,值得单列出来:
| 静态 CVaR(static) | 嵌套 CVaR(nested / Markov) | |
|---|---|---|
| 施加方式 | 对全程总代价 \(\sum\gamma^t c_t\) 施加**一次** CVaR | 每步施加**一步条件** CVaR,层层嵌套 |
| 语义 | "全程总代价最坏 \((1-\alpha)\) 的平均" | "逐步复合的风险",无干净的全程解释 |
| 时间一致性 | ✗ 不一致(尾部定义随信息漂移) | ✓ 一致(每步只看下一步) |
| 能否用 Bellman/DP | ✗ 不能直接递推 | ✓ risk-averse Bellman 成立,VI/PI 收敛 |
| 保守程度 | 相对不那么保守(只担忧全程总量) | 通常更保守(每步担忧 + 累积) |
| 求解 | 需特殊处理(如增广状态、轨迹空间优化) | 像标准 MDP,把期望换成一步 CVaR |
用实现六的两步例子把这个区别钉成数字:那个例子里 \(t=0\) 的静态 CVaR 计划(A 分支选 \(A_2\))与 \(t=1\) 重优化(选 \(A_1\))冲突,而嵌套 CVaR 的 \(t=0\) 计划(\(V\)(A)\(=\min(1,1.6)=1\),选 \(A_1\))与 \(t=1\) 一致。一个"翻车"、一个"一致",差别就在"风险施加的方式"——静态对全程总量施加一次(尾部定义会随信息漂移),嵌套每步施加(只看当前状态往后,不漂移)。
实践含义:如果你要用 DP / 动态规划 / RL 的递推机器求解多步风险敏感问题,几乎总是用嵌套 CVaR(它和 Bellman 兼容)。如果你坚持要"全程总代价 CVaR"的精确语义(某些安全认证场景),就得接受静态 CVaR 的不可递推性、用别的手段(如把 VaR 阈值 \(z\) 增广进状态、在整条轨迹空间上优化)。两者不可混为一谈——这也是文献里常见的混淆源。
嵌套 CVaR 的保守性从哪来、有多大(直觉量化):嵌套 CVaR"通常更保守"不是含糊其辞,有具体来源。每一步施加一次 CVaR\(_\alpha\),相当于每步都"假设接下来会落到最坏 \(1-\alpha\) 尾部"——而一条 \(H\) 步的轨迹,这种"每步都担忧尾部"会**沿轨迹复合**。粗略地说,静态 CVaR 担忧"全程总代价落到最坏 \(1-\alpha\) 尾部"(一次性、对总量),嵌套 CVaR 担忧"第 1 步坏、且第 2 步也坏、且……"层层叠加——后者对应的"等效全程置信水平"比 \(\alpha\) 更极端。\(H\) 越长、\(\alpha\) 越接近 1,复合越显著,嵌套比静态保守越多。这解释了 §U5.3 思维陷阱里"逐步累积的保守"——它是嵌套结构的数学必然,不是 bug。工程含义:长时域 + 高 \(\alpha\) 的嵌套 CVaR 可能保守到机器人寸步难行,此时要么缩短施加 CVaR 的步长(不必每步都施加)、要么降低每步的 \(\alpha\),在"时间一致"和"不过度保守"之间找平衡。
一个两步数值走查:亲眼看到时间不一致¶
抽象地说"静态 CVaR 时间不一致"不够直观。用一个最小的两步例子把它算出来(数值已实跑核对)。
设定:\(t=1\) 时有两个分支——分支 A(概率 0.9,"常态")和分支 B(概率 0.1,"灾难",代价确定为 50)。在分支 A,\(t=1\) 再二选一动作 \(\{A_1, A_2\}\):
- \(A_1\):确定代价 1;
- \(A_2\):0.5 概率代价 0、0.5 概率代价 1.6(期望 0.8,比 \(A_1\) 低,但有个 1.6 的小尾巴)。
我们用 \(\alpha=0.9\)(CVaR 看最坏 10%)。
\(t=0\) 用静态 CVaR\(_{0.9}\)(对全程总代价)规划:全程最坏 10% 几乎全部来自分支 B(代价 50,概率 0.1 正好就是那最坏的 10%)——所以无论分支 A 里选 \(A_1\) 还是 \(A_2\),全程 CVaR\(_{0.9}\) 都是 50(A 分支的代价根本进不了全程最坏 10% 的视野)。既然 CVaR 一样,静态最优就按期望 tie-break:\(A_2\) 的全程期望(5.72)略低于 \(A_1\)(5.90),于是 \(t=0\) 的静态 CVaR 最优在分支 A 选 \(A_2\)。
走到 \(t=1\)、观察到"分支 A"(90% 会发生),重新用静态 CVaR\(_{0.9}\) 优化剩余:现在条件在 A 内,A 就是全部世界,CVaR\(_{0.9}\) 只看 A 内的最坏 10%。算一下:\(A_1\) 在 A 内的 CVaR\(_{0.9}=1\)(确定值),\(A_2\) 在 A 内的 CVaR\(_{0.9}=1.6\)(它那个 1.6 的尾巴正好是 A 内最坏 10%)。于是 \(t=1\) 重优化会选 \(A_1\)(\(1 < 1.6\))。
冲突出现了:\(t=0\) 的计划在分支 A 选 \(A_2\),但 \(t=1\) 真到了分支 A 却想选 \(A_1\)——昨天的最优计划,今天的你想推翻。根源:\(t=0\) 的静态 CVaR 只盯"全程最坏 10%",而那 10% 全被分支 B 占据,分支 A 根本不在它的尾部视野里,于是它对 A 内的选择"漫不经心"(只按期望 tie-break);而 \(t=1\) 站进分支 A,A 就是它的全部,A 内那个 1.6 的尾巴突然变成了它必须认真对待的"最坏 10%"。信息更新("已知在 A")让"什么算尾部"彻底变了——这就是时间不一致的机制。
改用嵌套 CVaR\(_{0.9}\):每步施加一步条件 CVaR。\(t=1\) 在分支 A 内对剩余施加 CVaR(A 内最坏 10%),\(t=0\) 算 \(V\)(A) 时用的就是"A 内的一步条件 CVaR 最优"——即 \(\min(\mathrm{CVaR}^A(A_1),\mathrm{CVaR}^A(A_2))=\min(1,1.6)=1\)(选 \(A_1\))。于是 \(t=0\) 规划 A 分支时用的就是 \(A_1\),与 \(t=1\) 真到 A 时的选择**必然一致**。嵌套 CVaR 的"每步只看当前状态往后"天然消除了"全程尾部随信息漂移"的问题,时间一致性自动成立。本节练习一会让你把这个走查完整复现成代码。
⚠️ 本节常见陷阱¶
💡 概念误区:以为"静态 CVaR"和"嵌套 CVaR"在多步问题里是同一个东西 - 现象 / 后果:在论文 / 代码里看到"CVaR-MDP"或"CVaR-RL",默认它就是"最小化全程总代价的 CVaR",结果对不上别人的结论 / 实现。 - 根本原因:多步设定下两者是**不同的目标**——静态 CVaR 对全程总量施加一次、时间不一致;嵌套 CVaR 每步施加、时间一致。它们的最优策略、保守程度、可解性都不同。 - 正确做法:读到任何多步 CVaR 工作,先确认它用的是静态还是嵌套(看它能不能写出 Bellman 方程——能就是嵌套)。自己实现时明确选择并说明,别默认。
🧠 思维陷阱:以为时间不一致"只是理论洁癖",工程上无所谓 - 现象 / 后果:明知静态 CVaR 时间不一致,仍每步重新优化静态 CVaR 当作没事,结果机器人行为抖动、计划反复推翻、甚至在闭环里绕圈。 - 根本原因:时间不一致有**真实的闭环后果**——每步重优化会给出互相矛盾的计划,叠加执行就是抖动 / 振荡 / 次优。这不是洁癖,是会让机器人实际跑歪的工程问题。 - 正确做法:序贯闭环里要么用嵌套 CVaR(时间一致、可放心每步重规划),要么用静态 CVaR 但**承诺执行**整条规划(不中途重优化)并配合增广状态正确求解。别"用静态 CVaR 的目标 + 每步重优化的执行"这种自相矛盾的组合。
💡 概念误区:以为一步 CVaR 算子不是压缩映射、嵌套 CVaR 的 VI 不保证收敛 - 现象 / 后果:担心把期望换成 CVaR 后值迭代发散,于是不敢用 risk-averse Bellman,退回纯期望。 - 根本原因:一步 CVaR 算子继承了 CVaR 的单调性(A1)和平移不变性(A2),这两条正好保证 Bellman 算子是 \(\gamma\)-压缩映射(和期望算子同理)——所以值迭代、策略迭代照常收敛到唯一不动点。Ruszczyński 证明了这一点。 - 正确做法:放心用 risk-averse 值迭代 / 策略迭代。把标准 MDP 求解器里的"对下一状态取期望"替换成"取一步 CVaR"即可,收敛性有保证。
练习¶
- [A 型·两步时间不一致演示] 构造一个最简两步 MDP(\(t=0\) 一个二选一动作,\(t=1\) 观察到一个二值随机事件后再二选一,叶子有明确代价)。(a)用静态 CVaR\(_{0.5}\)(对全程总代价)算 \(t=0\) 的最优完整计划;(b)模拟"走到 \(t=1\)、观察到事件后,重新用静态 CVaR\(_{0.5}\) 优化剩余决策",验证它与 (a) 的计划冲突(时间不一致)。(c)改用嵌套 CVaR\(_{0.5}\),验证 \(t=0\) 计划与 \(t=1\) 重优化一致。
- [A 型·risk-averse 值迭代] 在一个小的格子世界 MDP(带随机转移)上实现 risk-averse 值迭代:把标准 VI 里的 \(\mathbb{E}[V(s')]\) 换成一步 \(\mathrm{CVaR}_\alpha[V(s')]\)(用 §U5.2 的 LP 或变分公式算一步 CVaR)。对比 \(\alpha\to 0\)(风险中性,退化回标准 VI)和 \(\alpha=0.9\)(风险厌恶)下学到的策略差异,验证风险厌恶的策略更避开高方差路径。验证 VI 收敛。
- [思考题] Ruszczyński 嵌套 CVaR 时间一致但"通常更保守"。请解释这个保守性是从哪里来的(提示:每步都施加一次 CVaR,担忧会沿轨迹累积)。在什么样的机器人任务里,这种"逐步累积的保守"是合理的、甚至是想要的?在什么任务里它会过度保守、反而有害?
§U5.4 分布式强化学习与 CVaR 的精确关系 ⭐⭐⭐⭐¶
动机:标准 RL 把分布"平均"掉了,正好丢掉了算风险所需的信息¶
回顾软依赖里的标准 RL:它学的是动作价值 \(Q(s,a)=\mathbb{E}[Z(s,a)]\),其中 \(Z(s,a)\) 是"从 \((s,a)\) 出发、按策略走下去的随机折扣回报"。注意这里有个**期望** \(\mathbb{E}[\cdot]\)——标准 RL 在学习的第一步就把回报的整个分布**压成了一个均值**。
这正好和本章的需求冲突。我们想要的是回报(或代价)分布的**尾部**信息(CVaR),但标准 RL 从一开始就把分布平均掉、只留均值——尾部信息在学习过程中就丢失了。你拿到一个训练好的 \(Q\) 函数,它只告诉你"平均回报多少",没法反推出"最坏 5% 情况回报多少"。要算 CVaR,你需要的是**整个分布**,而不只是它的均值。
分布式强化学习(Distributional RL) 的核心思想正是:不要在学习时就把分布平均掉,而是**学整个回报分布 \(Z(s,a)\) 本身**。一旦你手里有了完整的回报分布,算它的任何风险测度(均值、VaR、CVaR、任意畸变风险度量)都只是对这个分布做一次后处理。这就把"风险敏感"和"价值学习"解耦了:先学到完整分布,再按需施加任意风险态度。这也是本章和 RL 方向交界最深的地方——分布式 RL 天然就是风险敏感决策的载体。
反面:只有均值 \(Q\),你无法做任何风险敏感决策¶
假设你只有标准 RL 训出的 \(Q(s,a)=\mathbb{E}[Z(s,a)]\)。现在想让机器人风险厌恶——在两个动作里选"最坏情况不那么糟"的那个。你做不到:两个动作可能有完全相同的 \(Q\)(相同均值),但一个回报分布又窄又稳、另一个又宽又有灾难性尾部。均值 \(Q\) 对这个差异完全失明(正是 §U5.1 期望盲区的 RL 版)。
你可能想"那我额外学一个方差呢"?方差也不够——方差是对称的,它同等惩罚"好的意外"和"坏的意外",而风险厌恶只该担忧坏尾部。而且均值 + 方差仍不能精确给出 CVaR(除非分布恰好是正态)。根本问题是:任何对分布的低阶矩概括(均值、方差)都丢失了尾部的精确形状,而 CVaR 要的恰恰是尾部的精确形状。唯一的出路是保留(近似)整个分布——这正是分布式 RL 做的。
一个具体例子说明"均值 + 方差"为何不够:两个动作的回报分布都是均值 0、方差 1,但动作 A 是正态(对称、薄尾),动作 B 是"95% 概率小赢、5% 概率巨亏"的偏态分布(同样均值方差,但有一个灾难性的下尾)。均值 + 方差对 A 和 B 给出完全相同的描述——它们看不出 B 那个 5% 的巨亏尾巴。而 CVaR\(_{0.95}\) 会明确告诉你 B 的下尾比 A 差得多。对机器人,B 这种"平时不错、偶尔灾难"的偏态回报恰恰最危险(也最常见——很多机器人故障就是低频高危的),而它正是均值方差的盲区、CVaR 的强项。这就是为什么风险敏感非要保留整个分布不可:灾难往往藏在低阶矩看不见的尾部形状里。
理论:三种回报分布的表示 + 各自如何给出 CVaR¶
分布式 RL 起源于 Bellemare、Dabney、Munos 的 A Distributional Perspective on Reinforcement Learning(ICML 2017,提出 C51),后续 QR-DQN、IQN 不断改进分布的表示方式。它们的共同点是用**分布式 Bellman 方程**学回报分布 \(Z(s,a)\),区别在于用什么参数化来表示这个分布。下面逐个看三种表示,以及每种如何算 CVaR。
C51(Categorical, 51 atoms)——Bellemare–Dabney–Munos, ICML 2017。把回报分布表示成一个**固定支撑的分类分布**:预先选定 51 个固定的"价值原子" \(\{z_1,\dots,z_{51}\}\)(均匀铺在一个预设的回报范围 \([V_{\min},V_{\max}]\) 上),网络输出每个原子的概率 \(\{p_i(s,a)\}\)。回报分布就近似成"在这 51 个点上的离散分布"。学习时用投影后的分布式 Bellman 更新 + 交叉熵损失。 - 如何算 CVaR:有了 \(\{(z_i,p_i)\}\),把原子按 \(z_i\) 排序,从最坏一端累积概率到 \(\alpha\)(或 \(1-\alpha\),看代价 / 回报方向),对落入尾部的原子按概率加权平均,就是 CVaR。 - 局限:支撑固定——你得**预先猜对回报范围** \([V_{\min},V_{\max}]\),猜错了(回报超出范围)就被截断,且 51 个固定点的分辨率有限(论文指出它为了保均值会高估方差)。
QR-DQN(Quantile Regression)——Dabney–Rowland–Bellemare–Munos, AAAI 2018。反过来:不固定支撑、固定概率。学 \(N\) 个**分位数** \(\{q_1,\dots,q_N\}\),其中 \(q_i=F_Z^{-1}\!\big(\frac{i-0.5}{N}\big)\)(第 \(\frac{i-0.5}{N}\) 分位点的回报值)。即把分布表示成"\(N\) 个等概率的 Dirac,位置由分位数回归学出"。用分位数回归损失(pinball loss)训练,自动调整分位位置以最小化与 Bellman 目标的 1-Wasserstein 距离。 - 如何算 CVaR:分位数表示算 CVaR 极其自然——CVaR 就是尾部分位数的平均。要 \(\mathrm{CVaR}\) 关注最坏 \(\beta\) 比例,就对落在那 \(\beta\) 尾部的 \(\beta N\) 个 \(q_i\) 取平均。 - 改进:支撑自适应(分位位置是学出来的,不用预设范围),分辨率比 C51 更灵活。
IQN(Implicit Quantile Networks)——Dabney–Ostrovski–Silver–Munos, ICML 2018(arXiv:1806.06923, PMLR 80:1096–1105)。再进一步:不学固定的 \(N\) 个分位数,而是学**整个分位函数** \(\psi(s,a,\tau)\)——一个把分位水平 \(\tau\in[0,1]\) 映射到回报值的连续网络。训练时**采样** \(\tau\sim U(0,1)\),用分位数回归损失拟合。这样 \(\psi(s,a,\cdot)\) 隐式地表示了任意精度的回报分布(采样越多越精)。 - 如何算 CVaR——这是 IQN 最漂亮的地方:要算下尾 CVaR(关注最坏 / 最低回报的 \(\alpha\) 比例),只需把 \(\tau\) 的采样从 \(U(0,1)\) 改成 \(U(0,\alpha)\),再对 \(\psi(s,a,\tau)\) 取平均。因为 \(\frac{1}{\alpha}\int_0^\alpha F_Z^{-1}(\tau)\,\mathrm{d}\tau\) 正是下尾 CVaR 的定义(分位函数在 \([0,\alpha]\) 上的平均 = 最坏 \(\alpha\) 尾部的平均)。更一般地,IQN 通过对 \(\tau\) 做**非均匀重采样 / 加权**(即施加一个畸变函数 \(\beta(\tau)\)),可以实现**任意畸变风险度量**(呼应 §U5.1 的表示定理)——CVaR 只是"把 \(\tau\) 压到 \([0,\alpha]\)"这一种特例。论文正是用这种"通过策略畸变函数得到风险敏感策略"的方式,研究了风险敏感策略在 Atari 上的行为。
把三种表示并排对照,看清它们的取舍:
| C51 | QR-DQN | IQN | |
|---|---|---|---|
| 固定什么 | 支撑(原子位置) | 概率(等概率) | 都不固定(连续分位函数) |
| 学什么 | 各原子的概率 | \(N\) 个分位的位置 | 整个分位函数 \(\psi(s,a,\tau)\) |
| 损失 | 投影 + 交叉熵 | 分位数回归(pinball) | 分位数回归(采样 \(\tau\)) |
| 要投影步吗 | 要(Bellman 变换错位支撑) | 不要(位置自适应) | 不要 |
| 算 CVaR 怎么做 | 原子排序累积尾部 | 尾部分位取平均 | 改 \(\tau\) 采样区间到 \([0,\alpha]\) |
| 支撑范围 | 须预设 \([V_{\min},V_{\max}]\) | 自适应 | 自适应、任意精度 |
| 表达灵活性 | 低(固定网格) | 中 | 高(连续) |
一句话:表达灵活性 C51 < QR-DQN < IQN,算 CVaR 的自然程度也递增(C51 要排序累积、QR-DQN 取尾部分位、IQN 只改采样区间)。这张表是后面"三种画法"多视角理解的结构化版本。
数值验证(已实跑,标准正态回报,关注最坏 \(\alpha=0.1\) 尾部):用排序样本作分位函数,在 \(\tau\sim U(0,0.1)\) 上取分位函数均值得到 \(-1.754\),与直接的经验下尾平均 \(\mathbb{E}[Z\mid Z\le\mathrm{VaR}_{0.1}]=-1.755\) 吻合。三种风险态度的对比也很清晰:
| \(\tau\) 采样区间 | 风险态度 | 贪心选取的分位平均值 |
|---|---|---|
| \(U(0,1)\) | 风险中性(= 期望) | \(+0.000\) |
| \(U(0,0.1)\) | 极度风险厌恶(CVaR\(_{0.1}\) 下尾) | \(-1.753\) |
| \(U(0.9,1)\) | 风险偏好(只看最好 10%) | \(+1.757\) |
风险厌恶的贪心策略盯住低分位(保守、避开坏尾),风险偏好盯住高分位(冒进、博好尾),风险中性回到均值 0。同一个学好的 \(\psi(s,a,\tau)\),只换 \(\tau\) 的采样区间,就在风险中性 / 厌恶 / 偏好之间自由切换——不用重新训练。这是 IQN 作为风险敏感决策载体的核心优势。
一个关键的理论警告:动态 CVaR ≠ 静态 CVaR¶
这里必须接上 §U5.3 的区分,否则会犯一个微妙但严重的错误。当你用分布式 RL(如 IQN)做"每步都按 CVaR 贪心选动作"时,你得到的**不是**静态 CVaR 最优(最小化全程总回报的 CVaR),而是一种**动态 / 迭代 CVaR(dynamic / iterated CVaR)——每步局部施加 CVaR、沿轨迹复合,这更接近 §U5.3 的嵌套 CVaR,而**与静态 CVaR 最优化在理论上不一致(Lim & Malik, 2022 等指出了这一点)。
直觉:IQN 学的是"从当前 \((s,a)\) 出发的回报分布",对它按 CVaR 贪心,是在每一步对"未来回报分布的尾部"施加一次 CVaR——这是逐步施加,正是嵌套 / 动态 CVaR 的味道,而非"站在起点对全程总回报施加一次"的静态 CVaR。所以:用分布式 RL 的逐步 CVaR 贪心得到的策略,不能解释成'最小化了全程总代价的 CVaR'。如果你的任务真的要静态 CVaR 的语义,分布式 RL 的朴素 CVaR 贪心给不了,需要额外手段(如把 VaR 阈值增广进状态)。
本质洞察:分布式 RL 把"学价值"和"选风险态度"解耦了——先学全分布,风险态度只是事后的一次重加权。标准 RL 在学习时就焊死了风险态度(隐含地选了"风险中性 = 期望"),想换风险态度得改目标重训。分布式 RL 的范式转变在于:学习阶段保留完整的回报分布(不预设任何风险态度),风险态度推迟到决策阶段、表现为对分布的一次后处理(重加权 / 重采样)。IQN 把这个解耦做到极致——同一个分位函数网络 \(\psi(s,a,\tau)\),配 \(U(0,1)\) 是风险中性、配 \(U(0,\alpha)\) 是 CVaR 厌恶、配任意畸变 \(\beta(\tau)\) 是任意风险测度,全部不用重训。这就是为什么"分布式 RL 与 CVaR 的交界最深":不是 CVaR 用了分布式 RL,而是分布式 RL 天然把风险态度变成了一个可即时调节的旋钮。但务必记住上面的警告——这个旋钮调出的是动态 / 迭代 CVaR,不是静态 CVaR,两者理论上不一致(§U5.3)。
多视角理解:C51 / QR-DQN / IQN 是同一件事(学回报分布)的三种"画分布"方式。把"表示一个分布"想象成画它的图像:C51 是**固定 x 轴刻度、画 y 轴高度**(固定 51 个回报值,学每个的概率)——像直方图;QR-DQN 是**固定 y 轴刻度、画 x 轴位置**(固定 N 个等概率,学每个的回报位置)——像画 N 条等高的竖线、位置可动;IQN 是**学整条曲线**(学 \(\tau\mapsto\) 回报值的连续映射)——像直接画出逆 CDF 曲线本身。像 / 不像:三者都在表示同一个回报分布、都用分布式 Bellman 更新、都能算 CVaR;但表示的灵活性递增(C51 支撑固定 → QR-DQN 支撑自适应 → IQN 连续任意精度),算 CVaR 的自然程度也递增(C51 要排序累积、QR-DQN 取尾部分位平均、IQN 只需改 \(\tau\) 采样区间)。理解这个"三种画法"的递进,你就理解了分布式 RL 这条线的演化逻辑:一步步让"回报分布"被表示得更灵活、让"施加任意风险测度"更自然。
分布式 RL 为什么能学:分布式 Bellman 算子是压缩¶
分布式 RL 看似在做一件更难的事(学整个分布而非一个数),凭什么能保证学得到、学得收敛?答案和标准 RL 同源——分布式 Bellman 算子也是一个压缩映射,只是度量的不是值的距离,而是**分布之间的距离**。
标准 RL 的 Bellman 算子 \(\mathcal{T}Q(s,a)=\mathbb{E}[r]+\gamma\mathbb{E}[Q(s',a')]\) 在 \(L_\infty\) 范数下是 \(\gamma\)-压缩,所以值迭代收敛。分布式 RL 的**分布式 Bellman 算子**把这个搬到分布上:\(\mathcal{T}Z(s,a)\stackrel{D}{=}r+\gamma Z(s',a')\)(\(\stackrel{D}{=}\) 表示分布相等)——下一步回报分布 = 即时奖励 + 折扣后的后继回报分布。Bellemare 等证明:这个算子在 \(p\)-Wasserstein 距离(衡量两个分布的"搬运距离")的某种上确界度量下是 \(\gamma\)-压缩。于是"反复施加分布式 Bellman 算子"会收敛到唯一的不动点——真实的回报分布。
不同算法对应不同的"如何表示分布 + 在什么度量下投影": - C51 在 KL 散度下用交叉熵拟合(但要先把 Bellman 目标投影回固定支撑,这个投影步是 C51 的技术核心); - QR-DQN 用分位数回归损失,最小化 1-Wasserstein 距离(分位数表示天然匹配 Wasserstein); - IQN 同样用分位数回归,但对连续 \(\tau\) 采样,隐式拟合整个分位函数。
这解释了三者的技术差异为什么主要在"分布的表示 + 投影 / 损失"上——它们共享"分布式 Bellman 压缩"这个收敛性根基,区别只在如何参数化分布、用什么度量去逼近不动点。
多视角理解:分布式 Bellman 和标准 Bellman 是同一个递归,只是"携带的东西"从一个数变成一个分布。标准 Bellman 递归携带"期望回报"这一个数,压缩性在数的距离(\(L_\infty\))下成立;分布式 Bellman 递归携带"整个回报分布",压缩性在分布的距离(Wasserstein)下成立。像 / 不像:递归结构完全一样(都是"即时 + 折扣后继"),都靠压缩性保证收敛;区别是携带的信息量——标准版把分布压成均值后再递归(信息有损),分布式版直接对分布递归(信息无损)。理解这个平行,你就明白分布式 RL 不是"另起炉灶的新方法",而是"把同一个 Bellman 递归升级到携带完整分布"——它继承了 RL 全部的收敛理论(只是换了度量空间),又多保留了算风险所需的尾部信息。这也是为什么 §U5.4 说分布式 RL 是风险敏感决策"天然的载体":它在不牺牲 RL 收敛性的前提下,把风险态度所需的分布信息一路保留到了决策阶段。
C51 的投影步:固定支撑带来的麻烦与解法¶
三种表示里,C51 的"固定支撑"埋了一个技术难点值得讲清——它正好解释了为什么后来要发展 QR-DQN/IQN。分布式 Bellman 更新 \(\mathcal{T}Z\stackrel{D}{=}r+\gamma Z(s',a')\) 里有个 \(r+\gamma(\cdot)\) 的变换:即时奖励 \(r\) 平移、折扣 \(\gamma\) 收缩。问题来了——C51 的原子位置 \(\{z_i\}\) 是**预先固定**的,但 \(r+\gamma z_i\) 这些变换后的位置**几乎不可能正好落在原来的固定原子上**(平移 + 收缩后错位了)。于是 Bellman 目标分布的支撑和你的固定支撑对不齐,没法直接比较 / 更新。
C51 的解法是**投影步 \(\Phi\):把变换后错位的目标分布,按"质量守恒"重新分配回固定原子上——一个落在 \(z_i\) 和 \(z_{i+1}\) 之间的目标质量,按线性插值的比例分给这两个相邻原子。投影完成后,目标分布回到固定支撑上,才能用交叉熵损失和当前分布比较。这个投影是 C51 的技术核心,也是它的**累赘——它引入了额外的偏差(投影本身是近似),且论文指出 C51 为了保住均值会**高估方差**。
这正是 QR-DQN 的直接动机:QR-DQN 反过来固定概率、让位置自适应(分位数),于是 Bellman 变换 \(r+\gamma q_i\) 后的位置**仍是合法的分位值**(分位数对单调变换封闭),根本不需要投影步。IQN 更进一步让整个分位函数连续。所以三者的演化逻辑可以一句话概括:C51 固定支撑 → 要投影(累赘 + 偏差);QR-DQN 固定概率 → 免投影(位置自适应);IQN 连续分位 → 任意精度。理解 C51 投影步的麻烦,你就懂了为什么"固定支撑"是 C51 的原罪、为什么后续都往"自适应支撑"走。
对比性思维:C51 要投影、QR-DQN 免投影,差别全在"固定支撑 vs 固定概率"这个表示选择。C51 把分布画成"固定 x 刻度、动 y 高度"(固定原子位置、学概率),于是 Bellman 变换错位了支撑、必须投影回去(累赘 + 高估方差);QR-DQN 画成"固定 y 刻度、动 x 位置"(固定等概率、学分位位置),Bellman 变换后位置仍合法、免投影。像 / 不像:都用分布式 Bellman、都逼近回报分布;但表示选择决定了"要不要投影"这个关键工程后果——固定支撑被变换打乱、固定概率不被打乱。这是一个深刻的设计教训:表示的选择会一路传导到算法的简洁性——选错表示(固定支撑),就得用投影这种额外步骤去弥补;选对表示(固定概率 / 连续分位),算法自然干净。这也是为什么分布式 RL 这条线越往后(QR→IQN)表示越灵活、算法越简洁。
风险敏感在哪一步起作用:贪心、策略改进与连续控制¶
前面讲了 IQN 怎么算 CVaR,但风险态度具体在 RL 的哪一步注入?这决定了它能用在什么算法上。
值方法里——在贪心步注入。DQN 类方法(含 C51/QR-DQN/IQN)通过 \(\arg\max_a\) 选动作。风险敏感就是把这个 \(\arg\max\) 的依据从"期望 \(\mathbb{E}[Z(s,a)]\)"换成"畸变期望"(如 CVaR):\(a^\star=\arg\max_a\,\rho_\beta[Z(s,a)]\)。对 IQN,\(\rho_\beta\) 就是"对 \(\beta\) 重加权的 \(\tau\) 采样后取均值"。注意:换贪心依据**不改变训练**(分位函数照常学完整分布),只改变部署时怎么用——这就是"风险态度后置"的技术含义。
策略梯度 / actor-critic 里——在评论家注入。SAC、PPO 这类连续控制方法没有 \(\arg\max\),而是用一个 critic 评估动作、actor 据此改进。风险敏感版(如 Distributional SAC / DSAC)让 critic 学回报分布、用畸变期望(CVaR)作为 actor 改进的信号——actor 朝"提高 CVaR"而非"提高期望"的方向更新。这把风险敏感从离散动作(DQN 系)推广到了连续控制(机器人更常用)。具体地(详见进阶二十一):标准 SAC 的 critic 学 \(Q=\mathbb{E}[Z]\)、actor 最大化它;DSAC 的 critic 学整个分布 \(Z(s,a)\)、actor 改成最大化 \(\mathrm{CVaR}_\alpha[Z]\)。这对机器人尤其重要——双足、四足、机械臂的控制都是连续力矩,用不了 DQN 的离散贪心,分布式 actor-critic 是把 CVaR 带进这些连续控制系统的主要途径。
一个关键的微妙处——风险敏感与探索的张力。风险厌恶的贪心会避开"高方差"的动作,但 RL 训练早期恰恰需要探索高方差动作来学习。如果训练时就用强风险厌恶贪心,可能探索不足、学不到好策略。常见做法:训练时风险中性(充分探索)、部署时才切风险厌恶(IQN 的后置特性正好支持这一点——同一个学好的分位函数,部署时改 \(\tau\) 采样即可),或用 Risk-Conditioned 策略(进阶四)把 \(\alpha\) 作为输入、训练时见过各种 \(\alpha\)。
对比性思维:风险态度注入的位置——值方法在"贪心步"、策略方法在"评论家",但本质都是"把期望换成畸变期望"。DQN 系在 \(\arg\max_a\) 处把 \(\mathbb{E}[Z]\) 换成 \(\rho_\beta[Z]\);actor-critic 在 critic 评估处做同样替换、让 actor 朝畸变期望改进。像 / 不像:注入的代码位置不同(一个在动作选择、一个在策略梯度信号),但数学操作完全一样——都是"用畸变期望代替期望作为决策 / 改进依据"。这个统一视角告诉你:要给任何一个 RL 算法加风险敏感,就找到它"用期望做决策"的那一步,把期望换成畸变期望(CVaR),其余不动。而分布式 RL 的价值就在于它**提供了那个被替换进去的完整分布**——没有分布式 RL 学到的 \(Z(s,a)\),你根本没有"畸变期望"可算。
⚠️ 本节常见陷阱¶
💡 概念误区:以为对分布式 RL 学到的分布按 CVaR 贪心,就得到了静态 CVaR 最优策略 - 现象 / 后果:用 IQN 每步按 CVaR\(_\alpha\) 选动作,然后声称 / 以为"我的策略最小化了整条轨迹总代价的 CVaR"。 - 根本原因:逐步对"未来回报分布"施加 CVaR 是**动态 / 迭代 CVaR**(接近嵌套 CVaR,§U5.3),与静态 CVaR(对全程总量施加一次)理论上不一致(Lim & Malik 2022)。两者的最优策略不同。 - 正确做法:明确你要的是哪种。要动态 / 嵌套语义(多数实时控制场景够用)→ 分布式 RL 的逐步 CVaR 贪心可以。要静态全程 CVaR 语义 → 需额外手段(VaR 阈值增广进状态等),分布式 RL 朴素贪心给不了。
💡 编程陷阱:在 C51 里把回报范围 \([V_{\min},V_{\max}]\) 设得太窄 - 现象 / 后果:C51 训练时回报分布被截断在预设范围边界,尾部概率全堆在边界原子上,算出的 CVaR 严重失真(尾部被"压扁"在边界)。 - 根本原因:C51 用**固定支撑**——超出 \([V_{\min},V_{\max}]\) 的回报无法表示,被投影到边界。范围设窄了,恰恰是 CVaR 关心的极端尾部被截断。 - 正确做法:C51 要保守地设宽回报范围(覆盖可能的极端回报),或干脆用支撑自适应的 QR-DQN / IQN(不用预设范围,分位位置自己学)。算 CVaR 这种尾部敏感的量时尤其要警惕 C51 的范围设置。
🧠 思维陷阱:以为学方差(或均值 + 方差)就能代替学整个分布做风险敏感 - 现象 / 后果:为省事不学完整分布,只额外学一个方差,用均值 − \(k\cdot\) 标准差当"风险敏感价值"。 - 根本原因:方差是**对称**的,同等惩罚好尾和坏尾,而风险厌恶只该担忧坏尾;且均值 + 方差只在分布是正态时才能定出 CVaR,非正态(尤其重尾、多峰)下给不出正确尾部。机器人灾难往往恰是非正态的重尾事件。 - 正确做法:要精确的尾部风险(CVaR / 畸变测度),就得保留(近似)整个分布——用分布式 RL。均值 − \(k\sigma\) 只在分布近正态时是 CVaR 的粗糙代理,对重尾灾难不可靠。
练习¶
- [A 型·IQN 风险态度切换] 用 PyTorch 实现一个小 IQN(分位函数网络 \(\psi(s,a,\tau)\)),在 CartPole 或 MountainCar 上训练到收敛。训练完成后,不重新训练,仅改变贪心时 \(\tau\) 的采样区间——\(U(0,1)\)(风险中性)、\(U(0,0.1)\)(CVaR\(_{0.1}\) 极度风险厌恶)、\(U(0.9,1)\)(风险偏好)——对比三种策略在带随机扰动的环境里的行为差异(风险厌恶应更保守、更少触发失败)。
- [A 型·三种表示算 CVaR] 给定一个已知的回报分布(如混合高斯),分别用(a)C51 式固定原子、(b)QR-DQN 式分位数、(c)IQN 式 \(\tau\sim U(0,\alpha)\) 采样,三种方法估计它的 CVaR\(_{0.1}\)。对比三者的精度与对参数(原子数 / 分位数 / 采样数)的敏感性,验证 IQN 的 \(\tau\sim U(0,\alpha)\) 估计与解析下尾 CVaR 吻合。
- [思考题] IQN 可以通过对 \(\tau\) 施加任意畸变函数 \(\beta(\tau)\) 实现任意畸变风险度量。请设计一个具体的机器人导航场景,其中**单纯的 CVaR 不够用**——你需要一个比"只平均最坏 \(\alpha\) 尾部"更精细的风险态度(比如同时对中等坏和极端坏赋予不同的、非阶跃的权重)。说明你会选什么形状的畸变函数 \(\beta(\tau)\)、为什么,以及它如何用 IQN 的 \(\tau\) 重采样实现。
§U5.5 CVaR-CBF 与 CVaR-MPC:把尾部风险嵌进安全滤波与模型预测控制 ⭐⭐⭐¶
动机:确定性的安全条件,遇到随机扰动就不够用了¶
前面三节把 CVaR"度量什么"(§U5.1 公理)、"怎么算"(§U5.2 LP)、"多步怎么办"(§U5.3 嵌套)讲清楚了。这一节是落地——把 CVaR 嵌进机器人实际用的两个安全工具:控制障碍函数(CBF)安全滤波**和**模型预测控制(MPC)。
回顾 U2 的 CBF:用 \(h(x)\ge 0\) 定义安全集(\(h\) 是到障碍的距离之类的"安全裕量函数"),用条件 \(\dot h+\alpha h\ge 0\)(离散版 \(h(x_{t+1})\ge(1-\alpha)h(x_t)\))保证状态永远留在安全集里。这套在**确定性**系统上很漂亮。但真实机器人有随机扰动——状态转移是 \(x_{t+1}=f(x_t,u_t)+w_t\),\(w_t\) 是随机的(风、打滑、传感噪声)。此时 \(h(x_{t+1})\) 本身成了随机变量,"\(h(x_{t+1})\ge 0\)"不再是一个确定的条件,而是一个随机事件。
那该要求什么?有几个层次的选择,正好对应 Part-U 的安全谱: - 要求所有扰动下都安全(\(h\ge 0\) 对最坏的 \(w\) 也成立):这是 U2 的鲁棒做法,最保守——如果扰动无界(高斯尾巴拖到无穷),根本不可行。 - 要求高概率安全(\(\Pr(h(x_{t+1})\ge 0)\ge 1-\delta\)):这是 U3 的机会约束做法,看违反概率——但它对"违反时有多惨"失明(§U5.1 场景二)。 - 要求尾部平均安全(\(\mathrm{CVaR}_\alpha[-h(x_{t+1})]\le 0\),即最坏 \(\alpha\) 尾部的平均仍安全):这是本节的 CVaR 做法——既不像鲁棒那样要求最坏情况(可行性好),又比机会约束多看了"违反的严重程度"(公理化、对尾部敏感)。
CVaR-CBF 正是把 CBF 的安全条件从"确定性的 \(h\ge 0\)"升级为"CVaR 意义下的 \(h\ge 0\)"。
把这三个层次(外加最弱的"期望"层次)摆成一张表,对照它们在随机扰动 \(x_{t+1}=f(x_t,u_t)+w_t\) 下要求什么、保守程度、可行性:
| 安全条件层次 | 要求 | 保守程度 | 可行性(无界扰动下) | 对应 Part-U |
|---|---|---|---|---|
| 期望安全 | \(\mathbb{E}[h(x_{t+1})]\ge0\) | 最弱 | 好 | (最松,对尾部失明) |
| 机会约束安全 | \(\Pr(h(x_{t+1})\ge0)\ge1-\delta\) | 弱 | 好 | U3 |
| CVaR 安全 | \(\mathrm{CVaR}_\alpha[-h(x_{t+1})]\le0\) | 中 | 可行 | U5(本章) |
| 最坏情况安全 | \(\forall w:\ h(x_{t+1})\ge0\) | 最强 | 无界扰动下**不可行** | U2 鲁棒 |
这张表把 §U5.5 的核心选择讲清了:期望安全只管平均(一阵风就推过界);机会约束管概率(但对违反多严重失明);最坏情况管所有扰动(无界扰动下无解);CVaR 安全管尾部的平均严重程度,既可行又对尾部敏感,正好卡在机会约束和最坏情况之间。这也是为什么 CVaR-CBF/MPC 在"鲁棒太保守/不可行、机会约束又看不见严重程度"时是理想的中间选择。
反面:在随机系统上硬用确定性 CBF 会怎样¶
设想一个轮式机器人沿墙走,标称控制器想贴着墙走以抄近路,CBF 负责不让它撞墙。如果你忽略扰动、用确定性 CBF:它会算"按标称动力学 \(f(x,u)\),下一步 \(h(x_{t+1})\ge 0\) 吗",只要标称预测不撞就放行。但真实有侧风扰动 \(w_t\)——标称预测"刚好不撞"(\(h=0.01\))时,一阵侧风就把它推过去撞了。确定性 CBF 对扰动完全没有裕量,它保证的是"标称轨迹安全",不是"真实带扰轨迹安全"。
反过来,如果你为了对付扰动,用"最坏情况"鲁棒 CBF——要求对**所有**可能的 \(w\)(包括高斯分布拖到 \(\pm\infty\) 的尾巴)都 \(h\ge 0\)——那机器人会被吓得离墙远远的、甚至发现"没有任何控制能保证对无界扰动绝对安全"而宣告无解。这就是鲁棒做法在无界随机扰动下的可行性灾难。
CVaR-CBF 走中间:不要求对最坏的(无界尾巴)安全,而要求"最坏 \(\alpha\) 尾部的平均"安全——这是一个**有界、可行、又对尾部敏感**的条件,正好卡在"确定性太冒险"和"鲁棒太保守"之间。
理论:CVaR-CBF 与 CVaR-MPC¶
CVaR-CBF(Ahmadi–Xiong–Ames, 2021)。Ahmadi、Xiong、Ames 在 Risk-averse control via CVaR barrier functions: application to bipedal robot locomotion(IEEE Control Systems Letters / L-CSS 6:878–883, 2021)里提出:把 CBF 的前向不变条件用 CVaR 表述。直觉上,把确定性的"安全裕量不减太多"条件
升级为对随机的下一步裕量施加 CVaR:要求"裕量损失"的尾部平均受控,即(记 \(\rho_\alpha\) 为 CVaR 风险算子,作用在随机的 \(h(x_{t+1})\) 上)
含义:不要求每次裕量都不掉太多(确定性),也不要求最坏扰动下不掉太多(鲁棒),而要求"裕量下降的最坏 \(\alpha\) 尾部的平均"不超标——即"尾部最坏情况下平均而言,机器人仍待在安全集内"。这个条件可以用 §U5.2 的 Rockafellar–Uryasev 辅助变量形式写成凸约束,嵌进控制器的 QP 里(CBF 安全滤波本就是个 QP:把标称控制投影到满足 CBF 约束的最近控制)。论文在 Cassie 双足机器人上验证了它——双足行走对扰动极其敏感(一推就可能摔),CVaR-CBF 让它在随机扰动下保持风险厌恶的安全裕量。
为什么双足行走是 CVaR-CBF 的理想试验场?双足机器人的安全(不摔倒)对扰动极其敏感——它的支撑多边形小、重心高,一个不大的推力或地面不平就可能让它越过"可恢复"的边界摔倒。在这种系统上,三种安全条件的差异被放大得很清楚:确定性 CBF 只保证"标称(无扰动)下不摔",但真实地面总有扰动,标称安全的步态一遇扰动就可能摔(裕量没留余地);最坏情况鲁棒 CBF 要求"对所有可能的推力都不摔"——但推力理论上无界(可以很大),要求对无界推力绝对不摔,机器人只能用极其保守的小步、慢速,甚至发现无解;CVaR-CBF 则要求"裕量损失的最坏 \(\alpha\) 尾部平均受控"——它对常见的中小扰动留足裕量、对极罕见的巨大推力不强求(那种推力下摔倒是可接受的,因为强求会让正常行走都不可能)。这恰好匹配双足行走的现实需求:要对绝大多数扰动稳健,但不为了应对"几乎不会发生的巨推"而牺牲正常步态。这就是为什么 CVaR-CBF 在 Cassie 这类对扰动敏感、又不能过度保守的系统上特别有价值。
CVaR-MPC。同样的思路用到 MPC:MPC 在每个控制周期解一个有限时域最优控制问题(最小化未来 \(H\) 步的代价 + 满足约束)。把其中的约束 / 代价用 CVaR 表述,就是 CVaR-MPC。具体地,对每个预测步、对随机扰动采 \(N\) 个样本(场景),用 §U5.2 的 SAA-LP 形式把"碰撞代价的 CVaR \(\le\) 阈值"写成辅助变量 + 线性约束,加进 MPC 的 QP。因为(§U5.2)CVaR-LP 保凸,只要原 MPC 是凸 QP、加 CVaR 约束后仍是凸 QP,可实时求解。这条线还包括分布鲁棒的变体(DR-MPC,Dixit–Burdick 等),在分布本身不确定时用分布鲁棒 CVaR。
与 U2/U3 的统一:CVaR-CBF / CVaR-MPC 把 Part-U 的安全谱在"安全滤波 / MPC"这个统一框架里串起来了——同一个 CBF/MPC 骨架,安全条件取"确定性 \(h\ge0\)"是 U2 标称、取"\(\Pr(h\ge0)\ge1-\delta\)"是 U3 机会约束、取"\(\mathrm{CVaR}_\alpha[-h]\le0\)"是本章 CVaR、取"对最坏扰动 \(h\ge0\)"是 U2 鲁棒。换一个安全条件的写法,就在安全谱上滑动。这正是 U0 五安全谱"同一主干、不同范式"的工程化身。
C++ 生态的空白:一个真实的原创机会¶
这里值得对学习者明确指出一个现状:CVaR-MPC 的 C++ 实现生态几乎空白。CVaR 的 LP/QP 形式在 Python(CVXPY、scipy)里很容易写,但要上实时机器人(kHz 控制回路),需要 C++ 的高效实现——把 Rockafellar–Uryasev 辅助变量嵌进 acados / OSQP 这类实时 QP 求解器、把 IQN 学到的分位函数用 ONNX / TorchScript 导出到 C++ 做在线 CVaR 贪心。这块目前缺少成熟的开源库。对想做开源贡献的学习者,这是一个**真实、具体、有显著教育和影响力价值的方向**——不是造轮子,是填一块真实的空白。本章后续(下一段完成时)的"从 Python 到 C++ 部署"会展开 acados + 辅助变量、IQN 分位函数 ONNX 导出的具体路径。
本质洞察:CVaR-CBF/MPC 不是新算法,而是给 U2/U3 的安全骨架换了一个"风险态度旋钮"。CBF 安全滤波和 MPC 的骨架(把标称控制投影到安全集 / 滚动优化)是 U2 就建好的。CVaR-CBF/MPC 的贡献不在骨架,而在**安全条件的写法**——把"\(h\ge0\)"这个安全判据替换成 CVaR 形式。这个替换之所以可行且优雅,全靠 §U5.2 的 Rockafellar–Uryasev:它把 CVaR 写成凸的辅助变量形式,于是"CVaR 安全条件"和原来的"确定性安全条件"一样,都是 QP 里的凸约束,不破坏可解性。所以掌握 CVaR-CBF/MPC 的关键不是学新优化技巧,而是理解"安全条件可以是确定性 / 概率 / 尾部平均 / 最坏情况的不同写法,它们在同一个 QP 框架里可互换"——这个"安全条件可替换"的视角,把 Part-U 的整条安全谱统一成了"换约束写法"这一件事。
CVaR-MPC 的 QP 长什么样:把辅助变量摊开¶
把 §U5.2 的 Rockafellar–Uryasev 辅助变量真正嵌进 MPC 的 QP,看清它的结构。一个带 CVaR 安全约束的 MPC,在每个控制周期解这样一个优化(记预测时域 \(H\)、决策是控制序列 \(u_{0:H-1}\)、对扰动采 \(N\) 条场景 \(\{\omega^{(j)}\}_{j=1}^N\)):
逐块解读:目标是标准 MPC 的跟踪 + 控制代价(凸二次)。约束第一行是标称动力学。关键是后两行——它们就是 §U5.2 的 CVaR-LP 形式:\(z\) 是那个自动解到 VaR 的辅助标量,\(v_j\) 是每条场景的辅助变量(被压到 \((c^{(j)}-z)_+\)),第三行那个不等式说"碰撞代价的 CVaR\(_\alpha\le\kappa\)"。其中 \(c_{\text{collision}}(x_{0:H}^{(j)})\) 是第 \(j\) 条扰动场景下整条预测轨迹的碰撞代价(注意是**整条轨迹**的,呼应 §U5.5 编程陷阱"采整条轨迹场景")。
为什么这是个可实时求解的 QP:目标二次凸、动力学约束(线性化后)线性、CVaR 那几行全是线性的(辅助变量的功劳)——所以整体是凸 QP,OSQP / acados 这类求解器能在毫秒级解出。下表看 CVaR-MPC 的 QP 规模随场景数 \(N\) 和时域 \(H\) 怎么变(相比标称 MPC 多出来的部分):
| 量 | 标称 MPC | CVaR-MPC | 增量 |
|---|---|---|---|
| 决策变量 | \(\sim H\cdot n_u\)(控制序列) | \(+1+N\)(辅助 \(z\) 和 \(v_j\)) | 随 \(N\) 线性 |
| CVaR 相关约束 | 0 | \(N+1\) 行(\(v_j\ge\ldots\) 和 CVaR \(\le\kappa\)) | 随 \(N\) 线性 |
| 凸性 | 凸 QP | 仍凸 QP | 不破坏 |
| 实时性 | 毫秒级 | 毫秒级(\(N\) 适中时) | \(N\) 太大会变慢 |
关键观察:CVaR 带来的额外规模**只随场景数 \(N\) 线性增长**(\(1+N\) 个变量、\(N+1\) 行约束),且**不破坏凸性**。所以实时场景下控制 \(N\)(几十到一两百)就能兼顾尾部估计精度和求解速度——这是 CVaR-MPC 能上实时的关键。把 \(\alpha\to0\)(不看尾部)这套退化回标称 MPC,把 CVaR 约束换成 \(\Pr\) 约束就是机会约束 MPC——同一个 QP 骨架,换那几行约束就在安全谱上滑动(§U5.5 主线)。这就是"把 CVaR 嵌进 MPC"的全部具体内容:不是什么复杂的新机器,就是在原 MPC 的 QP 里多加一个标量 \(z\)、\(N\) 个 \(v_j\)、和 \(N+1\) 行线性约束。
CVaR-CBF 的安全条件用一个具体 \(h\) 走一遍¶
把 CVaR-CBF 的抽象条件落到一个具体的安全裕量函数上。设机器人沿墙走,\(h(x)=d(x)-d_{\min}\) 是"到墙的距离减去最小允许距离"(\(h\ge0\) 即安全)。确定性 CBF 要求 \(h(x_{t+1})\ge(1-\alpha_{\text{cbf}})h(x_t)\)——裕量每步最多按比例 \((1-\alpha_{\text{cbf}})\) 衰减。
随机扰动下 \(x_{t+1}=f(x_t,u_t)+w_t\),\(h(x_{t+1})\) 是随机的。CVaR-CBF 把上面的确定性条件改成对"裕量损失"\(\Delta h=h(x_t)-h(x_{t+1})\) 施加 CVaR:要求 \(\mathrm{CVaR}_\alpha(\Delta h)\le\alpha_{\text{cbf}}\,h(x_t)\)(裕量损失的尾部平均不超过允许的衰减量)。展开成可优化的形式——对扰动采 \(N\) 个样本 \(\{w^{(j)}\}\),用 Rockafellar–Uryasev 辅助变量:
直觉对比三种写法在这个具体 \(h\) 上的差异:确定性 CBF 只看标称 \(w=0\) 时的 \(h(x_{t+1})\)(一阵侧风就被推过界);最坏情况鲁棒 CBF 要求对所有 \(w\)(含无界尾巴)都 \(h\ge0\)(侧风无界时无解);CVaR-CBF 要求"裕量损失的最坏 \(\alpha\) 尾部平均"受控——它给侧风留了尾部裕量,又不要求对无界侧风绝对安全。安全滤波器把标称控制 \(u_{\text{nom}}\) 投影到满足这个 CVaR 约束的最近 \(u\),就是一个小 QP(目标 \(\min\|u-u_{\text{nom}}\|^2\) + 上面的线性 CVaR 约束)。这就是 §U5.5 主线"安全条件可替换"在 CBF 上的具体兑现——同一个投影 QP,把约束行从确定性换成 CVaR 形式即可。
当分布本身也不确定:分布鲁棒 CVaR(DR-MPC)¶
前面的 CVaR-MPC 假设我们能从一个**已知**的扰动分布采样(混合高斯等)。但真实机器人常面临更深一层的不确定:扰动的分布本身也不确定 / 估不准(环境变了、传感器漂移、仿真到现实的差距)。此时按一个错的名义分布算 CVaR,尾部保证可能落空。
分布鲁棒 CVaR(Distributionally Robust CVaR) 来补这一刀(Dixit–Burdick 等的 DR-MPC 是机器人上的代表)。思路:不对单一名义分布算 CVaR,而是对"离名义分布不超过某距离的**一族**分布"取最坏的 CVaR——
其中 \(\mathcal{B}(P_0,\epsilon)\) 是以名义分布 \(P_0\) 为中心、半径 \(\epsilon\) 的分布球(常用 Wasserstein 距离或矩约束定义)。这正好接上 §U5.2 那个对偶视角——CVaR 本身已是"在一族测度上取最坏期望",分布鲁棒 CVaR 是把那个测度族再扩大(容纳分布估计误差)。\(\epsilon=0\)(完全信任名义分布)退回普通 CVaR;\(\epsilon\) 越大越保守(容忍越大的分布误差)。
工程上,某些分布球(如 Wasserstein 球、矩约束)下的 DR-CVaR 仍可化成凸优化(SOCP / SDP 或带额外对偶变量的 LP),从而嵌进 MPC——只是约束比普通 CVaR-MPC 多一层"对分布不确定的对偶"。这给机器人多了一层防护:不仅对"已知分布的尾部"鲁棒,还对"分布估计本身的误差"鲁棒。
本质洞察:CVaR、机会约束、鲁棒、分布鲁棒,是"对不确定性嵌套地担忧"的层层加码。把全章的安全范式按"担忧的层次"排:机会约束担忧"会不会出事"(概率);CVaR 担忧"出事有多严重"(尾部均值);鲁棒担忧"最坏情况"(\(\alpha\to1\));分布鲁棒再担忧"我对分布的估计本身错了怎么办"(分布球)。每一层都在前一层之外多套一层担忧,对应多一层对偶 / 约束。这揭示了一个统一图景:所谓"安全范式的选择",本质是决定"你要对不确定性嵌套地担忧到第几层"——担忧越多层越保守、越鲁棒,但也越保守(性能代价越大)、越需要更多信息和计算。CVaR 在这个嵌套里是承上启下的一层(比机会约束多担忧严重程度、比鲁棒少担忧到最坏),而 §U5.2 的对偶表示正是把这些层次统一起来的数学语言(都是"在某个测度族上取最坏期望",族越大越保守)。理解这个嵌套结构,你就有了在 Part-U 整条安全谱上为任意任务定位的统一框架。
⚠️ 本节常见陷阱¶
💡 概念误区:把 CVaR-CBF 里的两个 \(\alpha\) 搞混 - 现象 / 后果:CVaR-CBF 里有两个不同的 \(\alpha\)——CBF 的类 K 函数系数 \(\alpha_{\text{cbf}}\)(控制安全裕量恢复速度,U2 的)和 CVaR 的尾部水平 \(\alpha\)(控制看多深的尾部,本章的)。混用 / 写成同一个会导致调参混乱、行为莫名其妙。 - 根本原因:两个 \(\alpha\) 管的是完全不同的事——一个是 CBF 的不变性速率、一个是风险的尾部深度,恰好都习惯用字母 \(\alpha\)。 - 正确做法:明确区分、用不同记号(如 CBF 用 \(\gamma_{\text{cbf}}\) 或 \(\alpha_{\text{cbf}}\)、CVaR 用 \(\alpha\))。理解它们独立可调:\(\alpha_{\text{cbf}}\) 调"撞墙前多早开始减速"、CVaR 的 \(\alpha\) 调"对多极端的扰动尾部设防"。
💡 编程陷阱:CVaR-MPC 里对每个预测步独立采样扰动场景,破坏时间相关性 - 现象 / 后果:在 MPC 的 \(H\) 步预测里,每步各自独立采 \(N\) 个扰动样本,算出的 CVaR 约束行为异常 / 过于乐观。 - 根本原因:扰动沿时间往往相关(持续的侧风、系统性偏差),且 CVaR 关心的是"整条预测轨迹的尾部代价"。每步独立采样既丢了时间相关性,又把"轨迹级的尾部"错误地拆成了"逐步的尾部"(这又回到了 §U5.3 静态 vs 嵌套的区分——要想清楚你约束的是哪个)。 - 正确做法:采**整条轨迹的扰动序列样本**(\(N\) 条完整的 \(w_{0:H}\) 序列,保留时间相关结构),在轨迹级别算 CVaR;并明确你要的是轨迹总代价的 CVaR(静态)还是逐步 CVaR(嵌套),按 §U5.3 选对应形式。
🧠 思维陷阱:以为 CVaR 安全条件能提供和鲁棒方法一样的"硬保证" - 现象 / 后果:用 CVaR-CBF 后就当机器人"绝对安全"了,像鲁棒方法那样信任它。 - 根本原因:CVaR 控制的是**尾部的平均**,不是**最坏情况的绝对界**。\(\mathrm{CVaR}_\alpha[-h]\le0\) 保证"最坏 \(\alpha\) 尾部平均而言安全",但尾部内部仍可能有个别更极端的违反(CVaR 是尾部均值,均值达标不代表无一例外)。它给的是风险意义的保证,不是 U2 鲁棒那种"对所有扰动都安全"的硬保证。 - 正确做法:清楚 CVaR 保证的语义边界——它在"鲁棒太保守 / 不可行"时提供了可行且对尾部敏感的中间方案,但若任务要求绝对硬安全(且扰动有界),仍需 U2 的鲁棒方法。按任务的安全等级在安全谱上选(U0 五安全谱)。
练习¶
- [A 型·CVaR-MPC vs 机会约束 MPC] 对一个 2D 点机器人 + 混合高斯扰动(模拟"偶发大扰动"的重尾),实现 CVaR-MPC:把"碰撞代价的 CVaR\(_{0.9}\le\) 阈值"用 Rockafellar–Uryasev 辅助变量嵌进 MPC 的 QP。再实现一个机会约束 MPC(\(\Pr(\text{碰撞})\le0.1\))作对比。蒙特卡洛跑两者,验证 CVaR-MPC 更好地控制了尾部碰撞代价(机会约束达标但偶发重创,CVaR 把尾部均值压住)。
- [A 型·CVaR-CBF 安全滤波] 实现一个 1D / 2D 的 CVaR-CBF 安全滤波器:给定一个会贴边走的标称控制器和随机扰动,把"裕量损失的 CVaR\(_\alpha\le(1-\alpha_{\text{cbf}})h\)"约束嵌进投影 QP。对比确定性 CBF(无扰动裕量,会被扰动推出界)和 CVaR-CBF(留尾部裕量)在带扰动闭环下的安全率。
- [思考题] CVaR-CBF/MPC 把 Part-U 的安全谱统一成"换安全条件的写法"。请对一个具体的四足机器人巡检任务,论证你会在什么地形 / 任务阶段用哪种安全条件:确定性(U2 标称)、机会约束(U3)、CVaR(本章)、还是最坏情况鲁棒(U2 鲁棒)?给出你的判断依据(提示:扰动是否有界、违反的严重程度、对可行性的要求、是否安全攸关)。
完整实现精读:从公式到可运行代码¶
前面把 CVaR 的理论讲透了,这里给出十个可运行、已数值核对的 Python 实现,把全章核心落成代码——从"算 CVaR"(实现一至二)到"切换风险态度"(实现三)、从"风险敏感动态规划"(实现四、六)到"用 CVaR 塑造决策"(实现五、九、十),再到"看穿重尾的微妙"(实现八)和"平均-尾部权衡"(实现七)。每个实现都标注了它对应正文的哪一节、验证了什么结论。所有数值都实跑核对过——本章不放任何未经验证的数字。建议对照正文逐个跑一遍,亲手感受"理论 → 可运行代码 → 真实机器人"这条路。其中实现一至三在同一会话里连续运行(实现二、三复用实现一开头的 import numpy as np、rng 和 cvar_ru),实现四起各自独立自包含;最后两段 C++ 部署代码是展示集成思路的骨架(需 acados / PyTorch 环境),其余皆可直接运行。
实现一:CVaR 的三种算法(朴素 / Rockafellar–Uryasev / LP)¶
先实现 §U5.2 的三种算 CVaR 的方式,并亲眼看到朴素估计在原子分布上的坑。
import numpy as np
from scipy.optimize import linprog
def cvar_naive(losses, alpha):
"""朴素估计: 对 >= VaR 的样本取平均。对【有原子的分布】不稳健(会算错)。"""
var = np.quantile(losses, alpha)
tail = losses[losses >= var]
return tail.mean() if len(tail) else var
def cvar_ru(losses, alpha):
"""Rockafellar-Uryasev 变分公式: z + mean((x-z)+)/(1-alpha), 取 z=VaR。
这是 §U5.2 的核心公式, 对原子分布稳健。"""
z = np.quantile(losses, alpha) # z* = VaR_alpha
return z + np.mean(np.maximum(losses - z, 0.0)) / (1.0 - alpha)
def cvar_lp(losses, alpha):
"""SAA-LP 形式(§U5.2): min z + 1/((1-a)N) Σu_i s.t. u_i>=x_i-z, u_i>=0。
返回 (CVaR, z*)。展示如何把 CVaR 写成标准线性规划。"""
n = len(losses)
c = np.concatenate([[1.0], np.full(n, 1.0 / ((1 - alpha) * n))]) # 目标系数
A_ub = np.zeros((n, 1 + n)); b_ub = np.zeros(n)
for i in range(n): # u_i >= x_i - z → -z - u_i <= -x_i
A_ub[i, 0] = -1.0; A_ub[i, 1 + i] = -1.0; b_ub[i] = -losses[i]
bounds = [(None, None)] + [(0, None)] * n # z 自由, u_i >= 0
res = linprog(c, A_ub=A_ub, b_ub=b_ub, bounds=bounds, method='highs')
return res.fun, res.x[0]
# 验证(数值已核对): 原子分布——4% 概率损失 100, 否则 0。理论 CVaR_0.95 = 4/0.05 = 80
rng = np.random.default_rng(42)
atom = (rng.random(100_000) < 0.04) * 100.0
print(f"朴素估计 = {cvar_naive(atom, 0.95):.2f} # ≈4, 严重偏离理论80 —— 踩了原子坑!")
print(f"RU 公式 = {cvar_ru(atom, 0.95):.2f} # ≈81, 正确(≈80)")
# 输出: 朴素 4.05 / RU 80.94 —— 朴素估计在原子处彻底算错
逐块对应 §U5.2:cvar_ru 是变分公式的直接实现——取 \(z=\mathrm{VaR}\)(分位数),算 \(z+\frac{1}{1-\alpha}\overline{(x-z)_+}\);cvar_lp 是把它样本化成 LP(辅助变量 \(u_i\)、线性约束)。验证最关键的一点:朴素估计在原子分布上给出 4.05,而理论 CVaR\(_{0.95}=80\)——因为这个分布在 VaR 处有原子(一大团样本恰好等于分位点),"\(\ge\) VaR 的样本取平均"取错了尾部。RU 公式给出 80.94,正确。这就是 §U5.2 编程陷阱说的"对原子分布必须用 RU / LP,不能用朴素平均"的活例。
实现二:CVaR 的尾部敏感性(正态 vs 重尾 t)¶
复现 §U5.2 的核心现象——CVaR 看穿重尾,而 VaR 会被骗。
# 正态 vs 标准化学生 t(df=3, 重尾), 都归一到单位方差, 比较 VaR 与 CVaR
xn = rng.standard_normal(200_000)
xt = rng.standard_t(3, 200_000) / np.sqrt(3.0) # t(3) 标准化到单位方差
for name, x in [("正态", xn), ("t(df=3)", xt)]:
var = np.quantile(x, 0.95)
cvar = cvar_ru(x, 0.95)
print(f"{name:8s}: VaR={var:.3f} CVaR={cvar:.3f} CVaR/VaR={cvar/var:.2f}")
# 输出:
# 正态 : VaR=1.648 CVaR=2.071 CVaR/VaR=1.26
# t(df=3) : VaR=1.354 CVaR=2.241 CVaR/VaR=1.66
# 反直觉: 重尾 t 的 VaR 反而更小(1.35<1.65), 但 CVaR 明显更大(2.24>2.07)!
逐块对应 §U5.2:注意那个反直觉结果——重尾 \(t\) 分布的 VaR 更小(更集中在中间,95% 分位点更靠内),但 CVaR 更大(尾巴更肥)。CVaR/VaR 比值从正态的 1.26 跳到 \(t\) 的 1.66。这量化地证明:只看 VaR 会误判重尾分布"更安全",CVaR 看穿了它的肥尾。对机器人,重尾对应偶发极端灾难(罕见高速碰撞、突发全失效)——这正是要用 CVaR 不用 VaR 的实战理由。
实现三:IQN 的风险态度切换(同一分位函数,改 τ 采样区间)¶
把 §U5.4 的核心——"同一个学好的分位函数,只换 \(\tau\) 采样区间就切换风险态度"——用一个最小例子落地。这里不训练完整 IQN(那需要环境交互),而是用一个已知的回报分布的分位函数,演示 \(\tau\) 重采样的机制。
# 用排序样本模拟一个学好的分位函数 F^{-1}(tau)(实际 IQN 里这是网络 psi(s,a,tau))
Z = np.sort(rng.standard_normal(200_000)) # 回报分布(越大越好)
def Finv(tau):
"""分位函数: 给定分位水平 tau, 返回回报值。IQN 里这是神经网络 psi(s,a,tau)。"""
idx = np.clip((np.asarray(tau) * len(Z)).astype(int), 0, len(Z) - 1)
return Z[idx]
# 同一个 Finv, 只改 tau 的采样区间, 就在三种风险态度间切换(§U5.4 的关键)
print("=== 同一分位函数, 改 τ 采样区间 = 切换风险态度 ===")
for lo, hi, name in [(0, 1, "风险中性 U(0,1)"),
(0, 0.1, "风险厌恶 U(0,0.1) = CVaR_0.1 下尾"),
(0.9, 1.0, "风险偏好 U(0.9,1)")]:
greedy_value = Finv(rng.uniform(lo, hi, 100_000)).mean()
print(f" {name:34s}: 贪心值 = {greedy_value:+.3f}")
# 输出:
# 风险中性 U(0,1) : 贪心值 = +0.006 (≈均值0)
# 风险厌恶 U(0,0.1) = CVaR_0.1 下尾 : 贪心值 = -1.746 (盯最坏10%)
# 风险偏好 U(0.9,1) : 贪心值 = +1.761 (盯最好10%)
# 核对: U(0,0.1) 采样均值 应 = 经验下尾 CVaR
print(f"核对: U(0,0.1)均值={Finv(rng.uniform(0,0.1,100_000)).mean():.3f}"
f" ≈ 经验下尾平均={Z[:int(0.1*len(Z))].mean():.3f}")
# 输出: 核对: U(0,0.1)均值=-1.748 ≈ 经验下尾平均=-1.746
逐块对应 §U5.4:Finv 模拟 IQN 学到的分位函数 \(\psi(s,a,\tau)\)(真实 IQN 里它是个神经网络,这里用排序样本代替以聚焦机制)。三个循环只改 \(\tau\) 的采样区间:\(U(0,1)\) 覆盖全分布给出均值(风险中性 \(+0.006\approx0\))、\(U(0,0.1)\) 只采下尾给出 CVaR\(_{0.1}\)(风险厌恶 \(-1.746\))、\(U(0.9,1)\) 只采上尾(风险偏好 \(+1.761\))。最后一行核对:\(\tau\sim U(0,0.1)\) 的采样均值 \(-1.748\) 确实等于经验下尾平均 \(-1.746\)——印证了 §U5.4 的"\(\frac{1}{\alpha}\int_0^\alpha F^{-1}(\tau)\mathrm{d}\tau\) = 下尾 CVaR"。全程没有重新训练,只换采样区间——这就是 IQN 把风险态度变成"事后旋钮"的全部秘密。
实现四:risk-averse 值迭代(同一 MDP,风险态度切换策略)¶
把 §U5.3 的 risk-averse Bellman 落成可运行代码——在一个小 MDP 上做值迭代,只把"对下一状态取期望"换成"取一步 CVaR",看风险态度如何切换最优策略。
import numpy as np
def cvar_next(values, probs, alpha):
"""一步 CVaR: 对随机下一步的 (代价+gamma*V) 值取 CVaR_alpha。
代价越大越坏, 看最坏 (1-alpha) 尾部的平均。alpha=0 退化为期望。"""
order = np.argsort(-values) # 从最坏(最大代价)排序
v, p = values[order], probs[order]
tail = 1.0 - alpha
acc, acc_val = 0.0, 0.0
for vi, pi in zip(v, p): # 从最坏往里累积到 tail 比例
take = min(pi, tail - acc)
if take <= 1e-12: break
acc_val += vi * take; acc += take
if acc >= tail - 1e-12: break
return acc_val / tail if tail > 0 else v[0]
# 小 MDP: 0->1->2(目标). 两个动作: safe(稳)/risk(险)
# risk 期望代价更低(诱人), 但有 5% 概率撞上灾难代价 20
nS, gamma = 3, 0.95
trans = { # trans[s][a] = [(s', prob, cost), ...]
0: {'safe': [(1, 1.0, 2.0)], 'risk': [(1, 0.95, 0.5), (0, 0.05, 20.0)]},
1: {'safe': [(2, 1.0, 2.0)], 'risk': [(2, 0.95, 0.5), (1, 0.05, 20.0)]},
2: {'safe': [(2, 1.0, 0.0)], 'risk': [(2, 1.0, 0.0)]}, # 吸收(目标)
}
def risk_averse_vi(alpha, iters=400):
V = np.zeros(nS)
for _ in range(iters): # 值迭代
Vnew = np.zeros(nS)
for s in [0, 1]:
q = {}
for a in ['safe', 'risk']:
o = trans[s][a]
sp = np.array([x[0] for x in o]); pr = np.array([x[1] for x in o]); c = np.array([x[2] for x in o])
future = c + gamma * V[sp] # 随机量: 即时代价 + 折扣后继值
# === 关键一行: 期望 换成 一步 CVaR (§U5.3 risk-averse Bellman) ===
q[a] = float(np.sum(pr * future)) if alpha <= 1e-9 else cvar_next(future, pr, alpha)
Vnew[s] = min(q.values()) # 最小化代价
V = Vnew
return V
for alpha, name in [(0.0, "风险中性 α=0 "), (0.8, "风险厌恶 α=0.8"), (0.95, "强厌恶 α=0.95")]:
V = risk_averse_vi(alpha)
# 导出 s0 的最优动作
s, q = 0, {}
for a in ['safe', 'risk']:
o = trans[s][a]; sp=np.array([x[0] for x in o]);pr=np.array([x[1] for x in o]);c=np.array([x[2] for x in o])
fut = c + gamma*V[sp]; q[a] = float(np.sum(pr*fut)) if alpha<=1e-9 else cvar_next(fut,pr,alpha)
print(f"{name}: V={np.round(V,3)} s0 最优动作 = {min(q, key=q.get)}")
# 输出:
# 风险中性 α=0 : V=[3.016 1.549 0. ] s0 最优动作 = risk (期望代价低, 选险)
# 风险厌恶 α=0.8: V=[3.9 2. 0. ] s0 最优动作 = safe (避开灾难尾部, 选稳)
# 强厌恶 α=0.95: V=[3.9 2. 0. ] s0 最优动作 = safe
逐块对应 §U5.3:整个值迭代和标准 VI 一模一样,唯一的改动是那一行注释标出的——把"对下一状态取期望 \(\sum p_i\cdot\text{future}_i\)"换成"取一步 CVaR cvar_next(future, pr, alpha)"。验证结果正是 §U5.3 的核心:风险中性(\(\alpha=0\),退化回标准 VI)选"险"(它期望代价更低,\(0.95\times0.5+0.05\times20=1.475<2.0\)),但 CVaR 风险厌恶(\(\alpha=0.8/0.95\))切换到"稳"——因为它盯住了"险"那 5% 概率的灾难代价 20,宁可多花确定的代价也要避开尾部。这就是 risk-averse Bellman 的实际效果:同一个 MDP、同一套值迭代代码,只调 \(\alpha\),就让机器人从"赌期望"变成"避尾部"。而且因为 CVaR 满足单调性 + 平移不变(§U5.3),这个值迭代和标准 VI 一样收敛(这里迭代 400 次已稳定)。
实现五:CVaR 约束 vs 机会约束(重尾扰动下的尾部控制对比)¶
把累积项目的核心实验落成代码——在重尾扰动下,对比机会约束和 CVaR 约束选出的避障决策,亲眼看到"碰撞概率打平、尾部严重程度拉开"。
import numpy as np
rng = np.random.default_rng(0)
# 单步避障决策: 选横向偏移 u>=0 (越大越安全但越绕路)。
# 机器人位置 = u + w, w 是重尾扰动(混合高斯: 90% 小扰动, 10% 大扰动)。
def sample_disturbance(n):
big = rng.random(n) < 0.10 # 10% 概率大扰动 -> 重尾
return np.where(big, rng.normal(0, 2.0, n), rng.normal(0, 0.3, n))
d_safe = 1.0
def collision_cost(u, w): # 越往障碍侧越危险, 二次惩罚
return np.maximum(0.0, -(u + w) - d_safe) ** 2
def detour_cost(u): # 绕路代价
return 0.3 * u ** 2
N = 200_000
w = sample_disturbance(N)
us = np.linspace(0, 4, 81)
delta = 0.1; alpha = 1 - delta # 机会约束 P(碰撞)<=0.1; CVaR_0.9
stats = {}
for u in us:
cc = collision_cost(u, w)
p_coll = np.mean(cc > 1e-9) # 碰撞概率
z = np.quantile(cc, alpha) # RU 算 CVaR_0.9(碰撞代价)
cvar = z + np.mean(np.maximum(cc - z, 0)) / (1 - alpha)
stats[u] = (p_coll, cvar, detour_cost(u))
# (A) 机会约束: 在 P(碰撞)<=delta 的 u 里选绕路最小
u_cc = min([(u, v) for u, v in stats.items() if v[0] <= delta], key=lambda kv: kv[1][2])[0]
# (B) CVaR 约束: 在 CVaR(碰撞代价)<=kappa 的 u 里选绕路最小
kappa = 0.5
u_cvar = min([(u, v) for u, v in stats.items() if v[1] <= kappa], key=lambda kv: kv[1][2])[0]
print(f"机会约束选 u={u_cc:.2f}: P(碰撞)={stats[u_cc][0]:.3f} CVaR碰撞代价={stats[u_cc][1]:.3f} 绕路={stats[u_cc][2]:.3f}")
print(f"CVaR约束选 u={u_cvar:.2f}: P(碰撞)={stats[u_cvar][0]:.3f} CVaR碰撞代价={stats[u_cvar][1]:.3f} 绕路={stats[u_cvar][2]:.3f}")
# 输出:
# 机会约束选 u=0.00: P(碰撞)=0.032 CVaR碰撞代价=0.867 绕路=0.000
# CVaR约束选 u=0.60: P(碰撞)=0.022 CVaR碰撞代价=0.479 绕路=0.108
逐块对应 §U5.5 + 累积项目:扰动是重尾混合高斯(90% 小 + 10% 大),正是 CVaR 大显身手的场景。机会约束只要求 \(\Pr(\text{碰撞})\le0.1\)——它发现 \(u=0\)(完全不绕路)就已达标(碰撞概率 3.2%),于是选了它,但留下很高的尾部碰撞代价 0.867(一旦碰上那 10% 大扰动,撞得很重)。CVaR 约束要求"碰撞代价的 CVaR\(_{0.9}\le0.5\)"——它必须绕路到 \(u=0.60\) 才能把尾部代价压到 0.479,代价是多走了一点(绕路 0.108)。两者碰撞概率接近(3.2% vs 2.2%,都达标),但尾部严重程度差了近一倍——这就是 §U5.1 场景二、§U5.5 主线的活例:机会约束对"碰撞有多重"失明,CVaR 直接压住了尾部的平均严重程度。把这个单步决策换成 MPC 的滚动 QP(§U5.5 的 QP 结构)、扰动场景换成整条轨迹,就是累积项目的完整实验。
实现六:两步时间不一致(静态 CVaR 翻车、嵌套 CVaR 一致)¶
把 §U5.3 的两步走查落成可运行代码——亲手算出"静态 CVaR 的 \(t=0\) 计划与 \(t=1\) 重优化冲突,而嵌套 CVaR 一致"。
import numpy as np
def cvar_discrete(vals, probs, alpha):
"""离散分布的 CVaR_alpha (代价越大越坏, 看最坏 (1-alpha) 尾部的平均)。
对原子稳健——按概率精确累积尾部, 不依赖样本。"""
vals = np.asarray(vals, float); probs = np.asarray(probs, float)
order = np.argsort(-vals) # 从最坏(最大)排
v, p = vals[order], probs[order]
tail = 1 - alpha
acc, acc_v = 0.0, 0.0
for vi, pi in zip(v, p):
take = min(pi, tail - acc) # 这一档贡献多少尾部质量
if take <= 1e-12: break
acc_v += vi * take; acc += take
if acc >= tail - 1e-12: break
return acc_v / tail if tail > 0 else v[0]
# 两步问题: t=1 有分支 A(prob 0.9, 常态) 和 B(prob 0.1, 灾难, 代价 50)。
# 分支 A 内 t=1 再选 A1 / A2:
A1 = ([1.0], [1.0]) # A1: 确定代价 1
A2 = ([0.0, 1.6], [0.5, 0.5]) # A2: 期望 0.8(更低), 但有 1.6 的尾巴
B = ([50.0], [1.0]) # B: 灾难分支, 确定代价 50
pA, pB = 0.9, 0.1
alpha = 0.9 # CVaR 看最坏 10%
def full_dist(aA): # 给定 A 分支选 aA, 构造全程总代价分布
av, ap = (A1 if aA == 'A1' else A2)
vals = list(av) + [B[0][0]]
probs = [pA * p for p in ap] + [pB]
return vals, probs
# === t=0: 静态 CVaR(对全程总代价) ===
print("t=0 静态 CVaR_0.9(全程):")
for aA in ['A1', 'A2']:
v, p = full_dist(aA)
c = cvar_discrete(v, p, alpha); m = float(np.sum(np.array(v) * np.array(p)))
print(f" A 选 {aA}: 全程CVaR={c:.2f}, 全程期望={m:.3f}")
# 两者全程CVaR都=50(最坏10%全来自B), 按期望tie-break -> 选 A2(期望5.72<5.90)
# === t=1: 已到分支 A, 重优化(条件CVaR只看A内) ===
cA1 = cvar_discrete(*A1, alpha); cA2 = cvar_discrete(*A2, alpha)
print(f"t=1 在A内重优化: A1的CVaR_0.9={cA1:.2f}, A2的CVaR_0.9={cA2:.2f} -> 选 {'A1' if cA1<cA2 else 'A2'}")
print(f" => t=0计划A选A2, t=1重优化选{'A1' if cA1<cA2 else 'A2'}: 冲突! (静态CVaR时间不一致)")
# === 嵌套 CVaR: t=0 算 V(A) 用 A内一步条件CVaR最优 ===
V_A = min(cA1, cA2) # = min(1, 1.6) = 1, 即选 A1
print(f"嵌套CVaR: t=0算V(A)=min(CVaR(A1),CVaR(A2))={V_A:.1f} -> A选A1, 与t=1一致 (时间一致)")
# 输出:
# t=0 静态 CVaR_0.9(全程):
# A 选 A1: 全程CVaR=50.00, 全程期望=5.900
# A 选 A2: 全程CVaR=50.00, 全程期望=5.720
# t=1 在A内重优化: A1的CVaR_0.9=1.00, A2的CVaR_0.9=1.60 -> 选 A1
# => t=0计划A选A2, t=1重优化选A1: 冲突! (静态CVaR时间不一致)
# 嵌套CVaR: t=0算V(A)=min(CVaR(A1),CVaR(A2))=1.0 -> A选A1, 与t=1一致 (时间一致)
逐块对应 §U5.3:cvar_discrete 用按概率精确累积尾部的方式算 CVaR(对原子稳健,呼应 §U5.2)。核心结论一目了然:\(t=0\) 站在起点看全程,最坏 10% 全被灾难分支 B 占据,所以 A 内选 \(A_1\) 还是 \(A_2\) 对全程 CVaR(都是 50)毫无影响——静态最优只好按期望 tie-break,选了期望更低的 \(A_2\)。但 \(t=1\) 真到了分支 A(90% 会发生),A 就是全部世界,A 内那个 1.6 的尾巴成了必须正视的最坏 10%,于是重优化选 \(A_1\)。\(t=0\) 选 \(A_2\)、\(t=1\) 选 \(A_1\),计划自相矛盾——这就是静态 CVaR 时间不一致的根源:信息更新让"什么算尾部"漂移了。最后一段验证嵌套 CVaR:\(t=0\) 算 \(V\)(A) 时用的就是"A 内一步条件 CVaR 最优"\(=\min(1,1.6)=1\)(即 \(A_1\)),与 \(t=1\) 必然一致。这把 §U5.3 最抽象的论证变成了五行就能复现的数字。
实现七:均值–CVaR 有效前沿(看"平均 vs 尾部"的权衡)¶
把进阶专题六的均值–CVaR 权衡落成代码——扫描混合权重,画出"平均表现 vs 尾部风险"的 Pareto 前沿,看纯均值最优和纯 CVaR 最优如何分处两端。
import numpy as np
rng = np.random.default_rng(0)
def cvar_ru(losses, alpha):
z = np.quantile(losses, alpha)
return z + np.mean(np.maximum(losses - z, 0)) / (1 - alpha)
# 两条候选路径的延误代价分布(机器人路径选择):
N = 200_000
p1 = np.where(rng.random(N) < 0.1, rng.normal(30, 5, N), rng.normal(8, 1, N)) # 快但重尾(偶发大延误)
p2 = rng.normal(15, 2, N) # 慢但稳
alpha = 0.9
# 扫混合权重 theta: 代价 = theta*p1 + (1-theta)*p2, 看 均值 vs CVaR 的权衡
print(f"{'theta':>6} {'均值':>8} {'CVaR_0.9':>10}")
frontier = []
for theta in np.linspace(0, 1, 11):
mix = theta * p1 + (1 - theta) * p2
m, c = mix.mean(), cvar_ru(mix, alpha)
frontier.append((theta, m, c)); print(f"{theta:6.1f} {m:8.3f} {c:10.3f}")
best_mean = min(frontier, key=lambda x: x[1]) # 纯均值最优
best_cvar = min(frontier, key=lambda x: x[2]) # 纯 CVaR 最优
print(f"\n纯均值最优: theta={best_mean[0]:.1f} (均值{best_mean[1]:.2f}, 但 CVaR={best_mean[2]:.2f})")
print(f"纯CVaR最优: theta={best_cvar[0]:.1f} (CVaR={best_cvar[2]:.2f}, 但均值{best_cvar[1]:.2f})")
# 输出(节选):
# theta=0.0: 均值15.00 CVaR_0.9=18.51 (全走稳路 p2)
# theta=1.0: 均值10.21 CVaR_0.9=30.03 (全走快路 p1, 均值最低但尾部最差)
# 纯均值最优: theta=1.0 (均值10.21, 但 CVaR=30.03)
# 纯CVaR最优: theta=0.1 (CVaR=18.00, 但均值14.52)
逐块对应进阶六:扫描 \(\theta\)(两条路径的混合权重),每个 \(\theta\) 给出一个"(均值, CVaR)"点,连起来就是均值–CVaR 有效前沿。结果清楚显示权衡:纯均值最优在 \(\theta=1.0\)(全走快路,平均延误最低 10.21,但尾部 CVaR 高达 30——那 10% 概率的大延误把尾部拖得很惨);纯 CVaR 最优在 \(\theta=0.1\)(几乎全走稳路,CVaR 压到 18,但平均延误升到 14.5)。两个最优分处前沿两端,中间的 \(\theta\) 是各种"平均 vs 尾部"的折中。这正是进阶六说的:纯最小化 CVaR(\(\theta=0.1\))会得到一个为压尾部而牺牲平均表现的保守解,而均值–CVaR 权衡(用 \(\lambda\) 在前沿上选点)让你按任务需求平衡——这也是为什么实践中几乎总用均值–CVaR 加权目标而非纯 CVaR。把这个一维 \(\theta\) 扫描换成高维决策 + 凸优化(均值和 CVaR 都凸,§U5.2),就能高效扫出完整前沿。
实现八:α 扫描——重尾的"危险"只在高 α 才暴露¶
实现二在单个 \(\alpha=0.95\) 比了正态 vs 重尾。这里扫描 \(\alpha\),揭示一个更深的现象:重尾的危险程度强烈依赖你看多深的尾部。
import numpy as np
rng = np.random.default_rng(0)
def cvar_ru(x, a):
z = np.quantile(x, a); return z + np.mean(np.maximum(x - z, 0)) / (1 - a)
xn = np.sort(rng.standard_normal(1_000_000)) # 正态
xt = rng.standard_t(3, 1_000_000) / np.sqrt(3.0) # 重尾 t(df=3), 标准化到单位方差
print(f"{'alpha':>6}{'VaR_正态':>9}{'CVaR_正态':>10}{'VaR_t':>8}{'CVaR_t':>9}")
for a in [0.90, 0.95, 0.99, 0.995]:
print(f"{a:6.3f}{np.quantile(xn,a):9.3f}{cvar_ru(xn,a):10.3f}"
f"{np.quantile(xt,a):8.3f}{cvar_ru(xt,a):9.3f}")
# 输出:
# alpha VaR_正态 CVaR_正态 VaR_t CVaR_t
# 0.900 1.282 1.757 0.943 1.682 <- 浅尾部: t 的 CVaR 反而更低!
# 0.950 1.647 2.065 1.358 2.242 <- t 开始超过正态
# 0.990 2.331 2.665 2.625 4.076 <- 深尾部: t 的 CVaR 暴涨(4.08 vs 2.67)
# 0.995 2.571 2.891 3.379 5.209 <- 更深: 差距更大(5.21 vs 2.89)
逐块解读:这张表揭示一个反直觉但重要的现象——重尾分布的"危险"只在高 \(\alpha\)(深尾部)才暴露。\(\alpha=0.90\) 时,\(t(3)\) 的 CVaR(1.68)甚至**低于**正态(1.76)——因为浅尾部还没探到 \(t\) 那肥厚的尾巴,\(t\) 更集中的中部反而显得"安全"。但 \(\alpha\) 一旦调高到 0.99、0.995,\(t\) 的 CVaR(4.08、5.21)就**远超**正态(2.67、2.89),差距随 \(\alpha\) 拉大。这给一个深刻的工程教训:如果你的扰动是重尾的(很多真实机器人扰动都是),用低 \(\alpha\) 的 CVaR 会严重低估危险——你得用足够高的 \(\alpha\) 才能探到那条肥尾巴。这也再次印证 §U5.1:VaR 和浅尾 CVaR 都可能被重尾欺骗,只有看得够深的 CVaR 才看穿它。结合实现二(单点对比)和本实现(\(\alpha\) 扫描),你就完整理解了"CVaR 看穿重尾"这件事的微妙之处——看穿的前提是 \(\alpha\) 够高。
实现九:CVaR 作为约束嵌进优化(不只是计算,而是塑造决策)¶
前面的实现都在"算"CVaR。这里展示 CVaR 真正的工程用法——把它作为**约束**嵌进一个优化,让它塑造决策。场景:在三条候选路径上分配权重(混合策略),最小化期望损失,但要求混合损失的 CVaR 不超过阈值。
import numpy as np
from scipy.optimize import linprog
rng = np.random.default_rng(1)
K, N, alpha = 3, 2000, 0.9
L = np.zeros((N, K)) # 三条路径的损失样本
L[:, 0] = np.where(rng.random(N) < 0.1, rng.normal(30, 5, N), rng.normal(5, 1, N)) # 快但重尾
L[:, 1] = rng.normal(12, 2, N) # 中
L[:, 2] = rng.normal(16, 1.5, N) # 慢但稳
meanL = L.mean(axis=0)
# 决策变量: [w_0,w_1,w_2, z, u_1..u_N]; 混合损失第 i 样本 = sum_k w_k L[i,k]
# 目标: min 期望损失 = sum_k w_k * mean(L[:,k]) (z,u 不进目标)
# 约束: CVaR_0.9(混合) <= kappa, 即 z + 1/((1-a)N) sum u_i <= kappa, u_i >= mix_i - z, u_i>=0
# sum w = 1, w >= 0
def solve_cvar_constrained(kappa):
nv = K + 1 + N
c = np.zeros(nv); c[:K] = meanL # 目标: 最小化期望损失
A_ub, b_ub = [], []
row = np.zeros(nv); row[K] = 1.0; row[K+1:] = 1.0/((1-alpha)*N) # CVaR <= kappa
A_ub.append(row); b_ub.append(kappa)
for i in range(N): # u_i >= mix_i - z
row = np.zeros(nv); row[:K] = L[i, :]; row[K] = -1.0; row[K+1+i] = -1.0
A_ub.append(row); b_ub.append(0.0)
A_eq = [np.concatenate([np.ones(K), np.zeros(1+N)])]; b_eq = [1.0] # sum w = 1
bounds = [(0, None)]*K + [(None, None)] + [(0, None)]*N
return linprog(c, A_ub=np.array(A_ub), b_ub=np.array(b_ub),
A_eq=np.array(A_eq), b_eq=b_eq, bounds=bounds, method='highs')
for k in range(K): # 先看各路径单独的期望与 CVaR
z = np.quantile(L[:, k], alpha); cv = z + np.mean(np.maximum(L[:, k]-z, 0))/(1-alpha)
print(f"路径{k}: 期望={meanL[k]:.2f}, CVaR_0.9={cv:.2f}")
for kappa in [20, 15]: # 收紧 CVaR 约束, 看权重如何转移
res = solve_cvar_constrained(kappa)
w = res.x[:K]
print(f"kappa={kappa}: 最优权重={np.round(w,3)}, 期望损失={meanL@w:.3f}")
# 输出:
# 路径0: 期望=7.39, CVaR_0.9=29.12 <- 期望最低但尾部最危险(重尾)
# 路径1: 期望=11.96, CVaR_0.9=15.39
# 路径2: 期望=15.98, CVaR_0.9=18.57
# kappa=20: 最优权重=[0.462 0.538 0. ], 期望损失=9.848 <- 还能用不少路径0
# kappa=15: 最优权重=[0.104 0.896 0. ], 期望损失=11.486 <- 收紧后被迫远离路径0
逐块对应 §U5.2 + §U5.5:这是 CVaR 从"计算"走向"塑造决策"的关键一步。纯最小化期望会全压路径 0(期望最低 7.39),但它 CVaR 高达 29——那 10% 的重尾会带来灾难。加上 CVaR 约束后,优化器**主动**把权重从危险的路径 0 转移到稳的路径 1:\(\kappa=20\) 时还能用 46% 的路径 0(期望 9.85),\(\kappa=15\) 收紧后只敢用 10%(期望升到 11.49)。这就是 CVaR 约束的作用——它不改变"算法骨架"(还是个 LP),却用尾部风险约束塑造了最优决策,强迫它在"期望低"和"尾部稳"之间权衡。注意整个问题仍是 LP(CVaR 约束靠辅助变量 \(z,u_i\) 保持线性,§U5.2),所以可高效求解、可嵌进更大的 MPC(§U5.5)。这把前面"算 CVaR"的代码升级成了"用 CVaR 约束做决策"——正是 CVaR-MPC 的核心机制。
实现十:CVaR-CBF 安全滤波(确定性 CBF 在扰动下翻车)¶
最后落到 §U5.5 的 CVaR-CBF——演示确定性 CBF 在随机扰动下为何不够、CVaR-CBF 如何留出尾部裕量。
import numpy as np
rng = np.random.default_rng(2)
# 1D 机器人贴墙走: 位置 x>=0 安全(撞墙=x<0)。标称控制想贴边走(省路), 扰动 w 推它。
def disturbance(n): # 重尾扰动: 15% 概率大扰动
return np.where(rng.random(n) < 0.15, rng.normal(0, 0.15, n), rng.normal(0, 0.03, n))
def collision_cost(x, w): # 撞墙(x+w<0)的二次惩罚
return np.maximum(0.0, -(x + w)) ** 2
N = 200_000
# 确定性 CBF: 只看标称(w=0)下安全, 允许贴到 x=0.05; CVaR-CBF: 留尾部裕量, 退到 x=0.35
for label, x_target in [("确定性 CBF (贴边 x=0.05)", 0.05), ("CVaR-CBF (保守 x=0.35)", 0.35)]:
w = disturbance(N); pos = x_target + w
p_hit = np.mean(pos < 0.0) # 撞墙率
cc = collision_cost(x_target, w)
z = np.quantile(cc, 0.9); cvar = z + np.mean(np.maximum(cc - z, 0)) / 0.1 # 碰撞代价 CVaR_0.9
print(f"{label}: 撞墙率={p_hit:.3f}, 碰撞代价 CVaR_0.9={cvar:.4f}")
# 输出:
# 确定性 CBF (贴边 x=0.05): 撞墙率=0.095, 碰撞代价 CVaR_0.9=0.0098 <- 9.5% 撞墙!
# CVaR-CBF (保守 x=0.35): 撞墙率=0.001, 碰撞代价 CVaR_0.9=0.0001 <- 0.1%, 留了裕量
逐块对应 §U5.5:确定性 CBF 只保证"标称(无扰动)下安全"——它允许机器人贴边走到 \(x=0.05\)(标称下不撞)。但真实有重尾扰动,那 15% 的大扰动一推,机器人就越界——撞墙率高达 9.5%。CVaR-CBF 要求"裕量损失的尾部平均受控",于是它让机器人退到 \(x=0.35\)(留出应对扰动的尾部裕量),撞墙率降到 0.1%、碰撞代价 CVaR 也降两个量级。这就是 §U5.5 的核心:确定性 CBF 对扰动留零裕量(标称安全≠真实安全),CVaR-CBF 按尾部风险留出恰当裕量——既不像确定性那样冒险,也不像最坏情况鲁棒那样为无界扰动退到无穷远。把这个一步安全滤波换成滚动的 CVaR-MPC(§U5.5 的 QP),就是真实机器人上的风险敏感安全滤波器。
> 本质洞察:十个实现串起了本章的核心闭环。实现一(CVaR 三算法)把 §U5.1–§U5.2 的"度量 + 可算化"落地,并暴露原子坑;实现二(尾部敏感性)量化了 §U5.1 的"CVaR 看穿重尾、VaR 失明";实现三(IQN τ 重采样)把 §U5.4 的"学全分布、风险态度后置"做成可运行的旋钮;实现四(risk-averse 值迭代)把 §U5.3 的 risk-averse Bellman 落成"只改一行就让策略避开尾部"的演示;实现五(CVaR vs 机会约束)量化了 §U5.5 的"碰撞概率打平、尾部严重程度拉开";实现六(两步时间不一致)把 §U5.3 最抽象的"静态翻车、嵌套一致"算成了五行数字;实现七(均值–CVaR 前沿)把进阶六的"平均 vs 尾部"权衡画成了 Pareto 前沿;实现八(α 扫描)揭示"重尾的危险只在高 α 才暴露";实现九(CVaR 作为约束)把 CVaR 从"计算"升级到"塑造决策";实现十(CVaR-CBF 安全滤波)展示确定性 CBF 在扰动下 9.5% 撞墙、CVaR-CBF 留尾部裕量降到 0.1%。十个实现合起来演示了风险敏感规划的完整思路:用公理化的 CVaR 度量尾部(而非期望 / VaR)→ 用 Rockafellar–Uryasev 把它变成可算的凸形式 → 用嵌套 CVaR 让它与动态规划兼容 → 在分布式 RL 里把风险态度解耦成对分位函数的一次重加权。把实现一的 CVaR-LP 嵌进 MPC 的 QP(§U5.5)、把实现三的 IQN 分位函数导出到 C++(从 Python 到 C++ 部署那一节),就是从这些教学代码通向真实机器人部署的两条路。¶
进阶专题¶
正文给了五个核心和落地,这里对几个值得深入的点展开——既加深主线,也是研究 / 工程会真正碰到的细节。
进阶专题一:指数效用与 LEQG——风险敏感的"史前史" ⭐⭐⭐¶
CVaR 不是风险敏感的起点。早在 1972 年,Howard 和 Matheson 在 Risk-Sensitive Markov Decision Processes(Management Science 18(7):356–369, 1972)就开创了风险敏感 MDP,用的是**指数效用(exponential utility):不优化期望回报 \(\mathbb{E}[Y]\),而优化"确定性等价(certain equivalent)"——把回报先过一个指数效用函数 \(U(Y)=\frac{1}{\gamma}(1-e^{-\gamma Y})\)(或等价的 \(e^{\gamma Y}\) 形式)再取期望。其中 \(\gamma\) 是**风险敏感系数:\(\gamma>0\) 风险厌恶、\(\gamma<0\) 风险偏好、\(\gamma\to0\) 退回风险中性(期望)。
这个准则的数学魅力在于:对线性高斯系统 + 二次代价,它有闭式解——这就是 LEQG(Linear-Exponential-Quadratic-Gaussian)控制,是经典 LQG 的风险敏感推广(Jacobson 1973、Whittle 等发展)。指数效用还有一个漂亮性质:它通过泰勒展开自然地把"均值 − \(\frac{\gamma}{2}\) 方差"作为一阶近似,即**风险敏感系数 \(\gamma\) 直接调节"对方差的厌恶程度"**。Howard–Matheson 用值迭代(有限时域)和策略迭代(无限时域)求解,并证明了求解机器的可用性。
为什么后来转向 CVaR? 指数效用有两个软肋:(1) \(\gamma\) 不直观——你很难说清"\(\gamma=0.3\)"对应什么具体的风险态度,没有"最坏 5% 的平均"这种可解释的语义;(2) 它通过指数**同时**惩罚整个分布的形状,而非聚焦尾部——它对"好的意外"和"坏的意外"的处理不像 CVaR 那样只盯坏尾。CVaR 的崛起正是因为它把"\(\gamma\) 不直观"换成了"\(\alpha\) 直观可解释(最坏 \(1-\alpha\) 的平均)",并满足 §U5.1 的一致性公理(指数效用不是一致性风险测度)。
用数字看指数效用如何区分方差(已实跑核对):取两个方案,A 的代价 \(\sim N(10,1^2)\)、B 的代价 \(\sim N(10,4^2)\)——同均值、B 方差大。风险中性(只看均值)认为两者无差别(都是 10)。但指数效用的确定性等价 \(\mathrm{CE}=\frac{1}{\gamma}\log\mathbb{E}[e^{\gamma Z}]\)(\(Z\) 代价、\(\gamma>0\) 风险厌恶)能区分它们:\(\gamma=0.1\) 时 CE(A)\(=10.05\)、CE(B)\(=10.80\);\(\gamma=0.3\) 时 CE(A)\(=10.15\)、CE(B)\(=12.40\);\(\gamma=0.5\) 时 CE(A)\(=10.25\)、CE(B)\(=13.98\)——\(\gamma\) 越大,B 的高方差被惩罚得越狠,风险厌恶者越坚定地选 A。而且确定性等价的泰勒一阶近似 \(\mathrm{CE}\approx\text{均值}+\frac{\gamma}{2}\text{方差}\) 对得很准(\(\gamma=0.3\) 时近似给 12.41,精确 12.40)——这直观显示了 \(\gamma\) 就是"对方差的厌恶系数"。但也正是这个例子暴露了指数效用的软肋:它惩罚的是**方差**(对称,同等惩罚好坏两侧的波动),而 CVaR 只惩罚坏尾——对"偶发大灾难但平时很稳"的重尾分布,指数效用不如 CVaR 聚焦。
本质洞察:风险敏感的历史是"从不直观的旋钮走向可解释、可公理化的度量"。指数效用的 \(\gamma\) 像一个没有刻度的旋钮——能调风险态度,但你说不清调到哪意味着什么。CVaR 的 \(\alpha\) 是有刻度的旋钮——\(\alpha=0.95\) 明确就是"盯最坏 5% 的平均"。这条从 LEQG(1972)到 CVaR(2000)再到分布式 RL(2017)的主线,本质是风险度量不断变得**更可解释、更可公理化辩护、更与优化 / 学习机器兼容**。理解这条史前史,你就明白 CVaR 不是凭空出现的"最优解",而是几十年里"如何度量风险"这个问题逐步逼近"既理论自洽又工程可用"的产物——这也提醒你:CVaR 也未必是终点(§U5.4 的畸变风险度量、谱风险测度就是更一般的后继)。
进阶专题二:机会约束 vs CVaR——为什么 CVaR 是 CC 的"公理化升级" ⭐⭐⭐¶
本章开篇说 CVaR 是机会约束(U3)的公理化升级。这里把两者的精确关系摆清楚,这是理解何时用哪个的关键。
机会约束(CC):\(\Pr(L>0)\le\delta\)——约束"损失为正(违反安全)的概率"不超过 \(\delta\)。它本质上约束的是 VaR:\(\Pr(L>0)\le\delta\) 等价于 \(\mathrm{VaR}_{1-\delta}(L)\le0\)(\(1-\delta\) 分位数不为正)。所以机会约束 = VaR 约束,继承了 VaR 的全部毛病(§U5.1):只看分位点、对尾部严重程度失明、不满足次可加。
CVaR 约束:\(\mathrm{CVaR}_{1-\delta}(L)\le0\)——约束"最坏 \(\delta\) 尾部的平均损失"不为正。因为 \(\mathrm{CVaR}\ge\mathrm{VaR}\) 恒成立(尾部平均 \(\ge\) 尾部起点),所以 CVaR 约束比机会约束更强:\(\mathrm{CVaR}_{1-\delta}(L)\le0\Rightarrow\mathrm{VaR}_{1-\delta}(L)\le0\Rightarrow\Pr(L>0)\le\delta\)。满足 CVaR 约束的一定满足对应的机会约束,反之不然。
精确关系:CVaR 约束是机会约束的一个**凸的、保守的、对尾部敏感的替代**。它的三个好处正好对应 CC 的三个痛点: - CC 非凸(VaR 非凸)→ CVaR 凸(§U5.2)→ 可高效优化; - CC 对尾部严重程度失明 → CVaR 看尾部平均 → 区分"轻微违反"和"灾难违反"(§U5.1 场景二); - CC 不满足次可加 → CVaR 一致性 → 合并不制造虚假风险(§U5.1)。
对比性思维:机会约束问"出事的概率",CVaR 问"出事的概率 + 出多大事"——CVaR 多管了"严重程度"这一维。一个安全工程师用机会约束时,只能设"碰撞概率 ≤ 5%"——但这对"碰一下"和"撞毁"一视同仁。换成 CVaR 约束"碰撞代价的 CVaR\(_{0.95}\) ≤ 阈值",就同时管住了概率(尾部从哪开始)和严重程度(尾部平均多惨)。代价是 CVaR 约束更保守(更强、可能牺牲一点性能 / 可行域),且需要损失的分布信息(不只是违反概率)。选哪个:只关心"达标率"、违反后果都差不多 → 机会约束够用且约束更松;违反后果差异大、安全攸关 → CVaR(U0 安全谱上 CVaR 比 CC 更靠保守端)。这也精确回答了本章开篇"CVaR 是 CC 公理化升级"的含义——升级的是"从只看概率到兼看严重程度 + 凸 + 一致性"。
进阶专题三:Safe RL 生态与精读路线 ⭐⭐¶
想动手做风险敏感 / 安全 RL,有一套相对成熟的开源生态。按"先理解、再上手"的顺序梳理。
- OmniSafe(
PKU-Alignment/omnisafe,Apache-2.0,Python):Safe RL 的统一框架,集成 CPO、PPO-Lagrangian、CVaR-CMDP 等 16+ 算法。精读重点:理解 CMDP(约束 MDP)vs CVaR-CMDP 的算法差异——前者约束期望代价(\(\mathbb{E}[\text{cost}]\le d\)),后者约束代价的 CVaR(尾部敏感)。这正好对应本章"期望 vs 尾部"的主线在 Safe RL 里的体现。 - Safety-Gymnasium(
PKU-Alignment/safety-gymnasium,MIT,Python):CMDP 接口 + Gymnasium 兼容的安全 RL 环境。精读重点:如何定义 cost 函数和安全约束——理解 Safe RL 把"安全"形式化为"代价 + 约束"的工程接口。 - Bellemare–Dabney–Rowland《Distributional Reinforcement Learning》(MIT Press, 2023):分布式 RL 的权威教材。精读重点:第 5 章(Quantile Regression,QR-DQN 的理论)和第 8 章(Risk-Sensitive RL,把分布式 RL 接到风险测度)——这是 §U5.4 的理论底座。
- CVXPY(Python):凸优化建模库。精读重点:用它写 CVaR 的 LP/SOCP 约束(§U5.2),亲手感受"辅助变量 + 线性约束"如何保凸。
- acados + CasADi(C++/Python):实时 MPC 求解器。精读重点:如何在 acados 的 OCP 里嵌入 CVaR 约束(手动线性化 + Rockafellar–Uryasev 辅助变量)——这是 §U5.5 提到的 CVaR-MPC 走向实时 C++ 的关键工具,也是 C++ 生态空白处最值得动手的地方。
精读路线建议:想理解理论 → 先读《Distributional RL》第 5、8 章 + 本章 §U5.1–§U5.4;想动手 Safe RL → 跑 OmniSafe 的 CVaR-CMDP + Safety-Gymnasium 环境;想做 CVaR-MPC → 用 CVXPY 原型验证(§U5.2 实现一)再用 acados 上实时。
进阶专题四:前沿与开放问题 ⭐⭐⭐⭐¶
风险敏感规划仍是活跃领域,几条值得关注的前沿(截至本文知识范围):
- Risk-Conditioned 策略(如 Risk-Conditioned DSAC, Choi 等 2021–2024):把风险水平 \(\alpha\) 作为策略网络的**输入**,训练一个能在运行时按指定 \(\alpha\) 调风险偏好的策略——不用为每个风险态度重训。这把 §U5.4 IQN "事后调 \(\tau\)" 的思想进一步做进策略本身。
- CVaR RL 的样本复杂度(如 OCE reductions, Wang 等 arXiv 2024):给出了某些设定(exogenous block MDP)下 CVaR RL 的首个样本复杂度保证——风险敏感 RL 的理论基础正在补齐。
- 谱风险测度的分布式 RL(Static Spectral Risk for DRL 等,2025 前后):把分布式 RL 从 CVaR 推广到更一般的谱风险 / 畸变风险度量,并处理"静态 vs 动态"一致性(呼应 §U5.3、§U5.4 的核心警告)。
开放问题(也是本章反复指出的原创机会): - C++ 高效 CVaR-MPC:如何把 Rockafellar–Uryasev 辅助变量高效嵌进 acados/OSQP 的实时 QP,做到 kHz 控制回路?这块 C++ 生态几乎空白。 - IQN 分位函数的 C++ 在线部署:如何把训练好的 IQN 分位函数用 ONNX / TorchScript 导出到 C++,做在线 CVaR 贪心? - 嵌套 CVaR Bellman 的高效数值求解:§U5.3 的 risk-averse Bellman 每步要解一个一步 CVaR(一个小 LP),大规模问题如何高效求解这一嵌套?
> 这些问题没有定论,适合作研究切入点。共同主题是"把理论上漂亮的风险敏感方法,做成实时机器人能用的高效实现"——理论(CVaR LP、分布式 RL)已相当成熟,缺的是 C++ 实时落地这一环。这正是 §U5.5 强调"C++ 生态空白 = 真实原创机会"的具体清单。¶
进阶专题五:CVaR 与机会约束在安全谱上的位置 ⭐⭐⭐¶
把本章放回 U0 的五安全谱,能看清 CVaR 到底站在哪。五安全谱按"对不确定性的态度从最保守到最灵活"排:
| 谱位 | 范式 | 对不确定性的处理 | 数学对象 | 何时用 |
|---|---|---|---|---|
| 最保守 | U2 鲁棒 | 对**所有**扰动(含最坏)都安全 | tube / 最坏情况界 | 扰动有界、安全攸关、可接受保守 |
| ↓ | U5 CVaR | 对**最坏 \(\alpha\) 尾部的平均**安全 | CVaR(尾部均值) | 扰动可能无界、要兼顾尾部严重程度与可行性 |
| ↓ | U3 机会约束 | 对**高概率**(\(1-\delta\))安全 | VaR / 违反概率 | 只关心达标率、违反后果差不多 |
| 灵活 | U4 POMDP | 处理**感知端**不确定(状态看不清) | belief(分布) | 状态部分可观测 |
| 交互端 | U1 分支 | 处理**他者意图**不确定 | 加权分支树 | 多智能体交互 |
注意 CVaR 在谱上正好卡在鲁棒和机会约束之间——比机会约束保守(看尾部平均而非只看分位点),比鲁棒灵活(看尾部平均而非最坏情况,可行性更好)。而 U4/U1 处理的是**正交**的不确定性维度(感知端 / 交互端),与 U2/U3/U5 的动力学端不确定性可叠加——这也是为什么本章末尾说"风险敏感的信念空间规划"(U4 belief + U5 CVaR)是两维的结合。
本质洞察:CVaR 不是要取代机会约束或鲁棒,而是在安全谱上填了一个"既看严重程度又可行"的中间位置。很多人争论"该用机会约束还是鲁棒",仿佛只有两极。CVaR 揭示这是个连续谱——鲁棒(对所有扰动安全,\(\alpha\to1\) 的极限)和机会约束(只看分位点)之间,有一整段"看尾部多深的平均"的中间地带,由 \(\alpha\) 连续调节。\(\alpha\to1\) 时 CVaR 趋向最坏情况(鲁棒),\(\alpha\) 适中时它是一个可行且对尾部敏感的折中。所以选风险范式不是"二选一",而是"在谱上选一个点"——CVaR 给了你这个连续旋钮。这把 Part-U 的几种安全范式统一成了"对尾部担忧到什么程度"的谱系,而非互斥的方法。
进阶专题六:均值–CVaR 权衡——风险敏感的"有效前沿" ⭐⭐⭐¶
纯粹最小化 CVaR 会得到一个极度保守的策略(只盯尾部、不管平均表现)——这往往过头了。实践中更常见的是**均值–CVaR 权衡**:同时考虑期望和尾部风险,
其中 \(\lambda\ge0\) 是风险厌恶权重。\(\lambda=0\) 是纯期望(风险中性),\(\lambda\to\infty\) 趋向纯 CVaR(极度保守),中间是权衡。扫描 \(\lambda\) 会得到一条**有效前沿(efficient frontier)**——每个 \(\lambda\) 对应一个"期望 vs 尾部风险"的最优权衡点,连起来是一条 Pareto 前沿(要更低的尾部风险,就得牺牲一点期望表现)。
这和 Markowitz 的均值–方差有效前沿是同一个思想,只是把"方差"换成了"CVaR"——而 CVaR 比方差好在:它只惩罚坏尾(方差对称惩罚好坏两侧)、且满足一致性公理(§U5.1)。因为均值和 CVaR 都凸(§U5.2),它们的加权和仍凸,整条前沿可以用凸优化高效扫出来。
对比性思维:均值–CVaR 前沿 vs 纯 CVaR 最小化——前者给一族权衡解、后者给一个极端解。纯最小化 CVaR 像"只问最坏情况、不计代价",得到单个极度保守的策略;均值–CVaR 前沿像"在保守和进取之间给你一整条可选的谱",由 \(\lambda\) 调节。像 / 不像:都用 CVaR 度量尾部、都是凸优化;区别是纯 CVaR 给一个点(可能过度保守、平均表现很差),均值–CVaR 给一条 Pareto 前沿(让你按任务在"平均好"和"尾部稳"之间选)。工程上几乎总是用后者——纯 CVaR 最小化的解往往保守到没有实用价值(为了压尾部牺牲了全部平均表现)。这也呼应了 §U5.1 的"满足公理 ≠ 适合任务":CVaR 是好度量,但怎么用(纯最小化还是权衡)仍需工程判断。
进阶专题七:CVaR 之外的一致性风险测度 ⭐⭐⭐⭐¶
CVaR 是最常用的一致性风险测度,但不是唯一的。§U5.1 的表示定理说满足六公理的是整个畸变风险度量类——CVaR 只是 \(g(\tau)=\min(\tau/\alpha,1)\) 这一个畸变。其他重要成员:
- 谱风险测度(spectral risk measure):\(\rho_\phi(X)=\int_0^1 \phi(\tau)F^{-1}(\tau)\mathrm{d}\tau\),其中 \(\phi\) 是一个递增的权重函数("风险谱")。CVaR 是 \(\phi\) 为"尾部均匀、其余为 0"的阶跃特例。一般的 \(\phi\) 可以平滑地对越坏的分位赋越高权重——比 CVaR 的"一刀切尾部"更精细。它们都是一致性的。
- 熵风险测度 / 熵 VaR(entropic risk / EVaR):基于指数效用(进阶一)的 \(\frac{1}{\gamma}\log\mathbb{E}[e^{\gamma X}]\) 是凸的(凸风险测度),但**不是正齐次的**(不满足 A3),所以严格说不是一致性的(是更广的"凸风险测度")。EVaR 是它的一个一致性化变体,且是 CVaR 的一个上界。它的好处是有闭式、可微,适合某些优化。
- **均值–半方差、CVaR 的组合**等:实践中常组合多个度量。
具体看谱风险如何比 CVaR 更精细:CVaR\(_\alpha\) 的权重在尾部 \([\alpha,1]\) 是**均匀**的(尾部内每个分位等权),相当于"对最坏 5% 一视同仁"。但有时你想对"最坏 1%"比"最坏 5% 里相对没那么坏的部分"更担忧——谱风险用一个**递增**的权重 \(\phi(\tau)\) 实现这一点:比如 \(\phi\) 在 \(\tau=1\)(最坏)附近陡增,就对极端尾部赋更高权重。极端情形 \(\phi\) 全压到 \(\tau=1\) 就退化成最坏情况。所以谱风险是"CVaR(尾部均匀)和最坏情况(只看最坏点)之间的连续谱",由权重函数 \(\phi\) 的形状调节——比 CVaR 单一的 \(\alpha\) 旋钮更灵活,代价是 \(\phi\) 不如 \(\alpha\) 直观、且失去了"最坏 \(\alpha\) 的平均"这个干净解释。
为什么仍以 CVaR 为主?因为 CVaR 兼具:一致性(满足公理)、可解释性("最坏 \(\alpha\) 的平均")、可算化(RU 的 LP,§U5.2)、和分布式 RL 的天然兼容(IQN 的 \(\tau\) 采样,§U5.4)。其他度量或缺可解释性(谱风险的 \(\phi\) 不如 \(\alpha\) 直观)、或缺一致性(熵风险非正齐次)、或缺简单的 LP 形式。CVaR 是"够好且够简单"的甜点。
本质洞察:CVaR 的流行不是因为它"最好",而是因为它在多个维度上都"够好"——一致、可解释、可算、与 RL 兼容。如果只看某个单一维度,总有比 CVaR 更优的度量:要更精细的尾部加权,谱风险更灵活;要闭式可微,熵风险更方便;要绝对保守,最坏情况(鲁棒)更彻底。但 CVaR 在**所有**这些维度上都不差——满足全部一致性公理、\(\alpha\) 直观可解释、有干净的 LP 形式、IQN 能即时实现它。这种"多维度均衡"正是工程上选型的关键:真实项目要的不是某个维度的极致,而是各维度都过关的综合最优。这也解释了为什么本章以 CVaR 为主线、而把谱风险 / 熵风险作为"更一般但各有取舍"的后续——理解这个"均衡而非极致"的选型逻辑,比记住某个度量"最好"更有价值(这个逻辑在 §U5.5 选安全条件、进阶五选安全谱位置时反复出现)。
进阶专题八:为什么估计极端尾部这么难——CVaR 的样本复杂度 ⭐⭐⭐⭐¶
§U5.2 的思维陷阱提到"\(\alpha\) 越高越需要更多样本",这里讲清背后的统计学,这对实际用 CVaR 至关重要。
根本困难:CVaR\(_\alpha\) 依赖最坏 \((1-\alpha)\) 尾部。\(N\) 个样本里,落在这个尾部的期望只有 \((1-\alpha)N\) 个。\(\alpha=0.99\)、\(N=1000\) 时,尾部只有约 10 个样本——用 10 个样本估"最坏 1% 的平均",方差极大。\(\alpha=0.999\) 时更是只有约 1 个。所以 CVaR 估计的方差随 \(\alpha\to1\) 急剧上升,这不是算法问题,是"极端事件本就罕见、罕见就难估"的统计本质。
定量一点:CVaR 经验估计的标准误大致随 \(\frac{1}{\sqrt{(1-\alpha)N}}\) 缩小(有效样本是尾部的 \((1-\alpha)N\) 个,而非全部 \(N\) 个)。要把 \(\alpha=0.99\) 的 CVaR 估到和 \(\alpha=0.9\) 同样的相对精度,需要约 10 倍的样本。这就是为什么实际中 \(\alpha\) 不能盲目调高——估计不准的 CVaR 约束还不如不要。用数字看这个标准误(标准正态,重复 50 次估计的标准差,已实跑核对):
| \(\alpha\) | \(N\) | 尾部有效样本 \((1-\alpha)N\) | CVaR 估计标准差 |
|---|---|---|---|
| 0.90 | 200 | 19 | 0.125 |
| 0.90 | 2000 | 199 | 0.041 |
| 0.95 | 200 | 10 | 0.155 |
| 0.95 | 2000 | 100 | 0.060 |
| 0.99 | 200 | 2 | 0.337 |
| 0.99 | 2000 | 20 | 0.086 |
看两个趋势:(1) 固定 \(\alpha\)、\(N\) 增大 10 倍,标准差约降到 \(1/\sqrt{10}\approx0.32\) 倍(0.125→0.041、0.155→0.060),印证 \(\frac{1}{\sqrt{(1-\alpha)N}}\) 的规律;(2) 固定 \(N\)、\(\alpha\) 越高、标准差越大(\(N=200\) 时 0.90→0.95→0.99 是 0.125→0.155→0.337),因为尾部有效样本从 19 掉到 2。最刺眼的是 \(\alpha=0.99,N=200\) 那行——尾部只有约 2 个样本,标准差 0.337 大到估计基本不可信。这张表给一个实用标尺:想用高 \(\alpha\),先看 \((1-\alpha)N\) 够不够(至少几十),不够就加 \(N\) 或降 \(\alpha\)。
应对手段:(1) 重要性采样——人为多采尾部样本、再加权校正,让有效尾部样本增多;(2) 参数化尾部——用极值理论(EVT)拟合尾部分布,外推到样本稀疏的极端区;(3) 降低 \(\alpha\)——若任务允许,看没那么极端的尾部;(4) 分布式 RL 的间接帮助——IQN 学的是整个分位函数(用全部数据拟合),比直接对尾部样本平均更稳(尾部分位由整条函数的结构约束,不只靠那几个尾部样本)。
对比性思维:CVaR 的"尾部越极端越难估"和它的"对尾部越敏感"是同一枚硬币的两面。CVaR 相对 VaR / 期望的优势是它看尾部的严重程度(§U5.1)——但正因为它依赖尾部,而尾部样本天然稀少,它也比期望更难估准(期望用全部 \(N\) 个样本,CVaR\(_\alpha\) 有效只用 \((1-\alpha)N\) 个)。像 / 不像:期望和 CVaR 都是对分布的泛函、都能从样本估,但期望的有效样本是全部、估计稳,CVaR 的有效样本是尾部、\(\alpha\) 越高越少越不稳。这给一个清醒的工程认识:CVaR 的威力(看尾部)和它的代价(难估尾部)是绑定的——你想看越极端的尾部(越高 \(\alpha\)),就越需要付出样本 / 计算的代价去估准它。这不是 CVaR 的缺陷,是"想了解罕见事件就得见过足够多罕见事件"的统计铁律。选 \(\alpha\) 时把这条铁律和任务需求一起权衡(综合练习第 5 题),是用好 CVaR 的关键。
进阶专题九:CVaR 与鲁棒 MDP 的等价——对偶视角的回报 ⭐⭐⭐⭐¶
§U5.2 的对偶视角(CVaR = 在一族测度上取最坏期望)有一个漂亮的推论:CVaR 优化等价于一类鲁棒 MDP。这把本章的风险敏感和 U2 的鲁棒在数学上连了起来。
回顾对偶形式 \(\mathrm{CVaR}_\alpha(X)=\max_{Q\in\mathcal{Q}}\mathbb{E}_Q[X]\),其中 \(\mathcal{Q}\) 是密度受限的测度族。把它用到序贯决策:嵌套 CVaR 的 risk-averse Bellman(§U5.3)\(V(s)=\min_a\{c+\gamma\,\mathrm{CVaR}_\alpha[V(s')]\}\),用对偶展开内层 CVaR,就变成
这正是一个**鲁棒 MDP(robust MDP)的 Bellman 方程——智能体 min(选动作),一个对抗性的"自然"max(在转移概率的不确定集 \(\mathcal{Q}(s,a)\) 里选最坏的转移)。换句话说:**对回报施加 CVaR 风险厌恶,等价于假设转移概率被一个对抗者在某个不确定集里往最坏方向扰动。Chow–Tamar–Mannor–Pavone(NeurIPS 2015)等正是用这个等价把 CVaR、机会约束、鲁棒统一在一个框架里。
这个等价的实践含义:(1) 解释力——风险厌恶不是凭空的偏好,它精确对应"对模型(转移)不确定的鲁棒",这给 CVaR 一个频率派的、可辩护的解释(你担忧尾部 ⟺ 你不完全信任你的转移模型);(2) 算法迁移——鲁棒 MDP 的求解技术可以搬来解 CVaR-MDP,反之亦然;(3) 设计指导——\(\alpha\) 越大、CVaR 越保守,对应的转移不确定集越大、越鲁棒——\(\alpha\) 同时是"尾部深度"和"对模型不信任程度"的旋钮。
本质洞察:风险敏感和鲁棒是同一件事的两种语言——"担忧坏结果"等价于"不信任模型"。一个初学者会把"风险敏感"(关心回报分布的尾部)和"鲁棒"(关心模型不确定的最坏情况)当成两个独立的话题——U5 讲前者、U2 讲后者。但对偶表示揭示它们在数学上等价:对结果施加 CVaR 风险厌恶 ⟺ 假设模型(转移)被对抗性地往最坏扰动。这不是巧合,是凸对偶的必然——"对结果的次可线性风险泛函"和"对模型的最坏情况"是同一个凸优化的原始与对偶面孔。理解这一点,你就明白为什么本章 §U5.5 的 CVaR-MPC 能和 U2 的鲁棒 MPC 在"换安全条件写法"的框架里统一(进阶五、§U5.5)——它们底层是同一个 min-max 结构,只是一个从"结果尾部"切入、一个从"模型最坏"切入。这也是 Part-U 五安全谱能统一成一张表的深层原因:鲁棒、机会约束、CVaR 在对偶视角下都是"在某个不确定集上取最坏",集越大越保守。
进阶专题十:风险敏感逆强化学习——从演示中学风险态度 ⭐⭐⭐⭐¶
前面都假设风险态度(\(\alpha\)、畸变函数)是工程师**指定**的。但有时我们想从专家演示里**学出**风险态度——比如观察一个老练的越野司机,推断他对"翻车"这类尾部事件有多厌恶。这就是**风险敏感逆强化学习(risk-sensitive IRL)**。
标准 IRL 假设专家最大化期望回报,从演示反推奖励函数。风险敏感 IRL(如 Majumdar–Singh–Mandlekar–Pavone, RSS 2017 的 coherent-risk IRL)放松这个假设:专家最大化的是某个**风险敏感**目标(一致性风险测度下的回报),IRL 要同时反推奖励**和**风险态度(畸变函数)。直觉:一个总是绕开悬崖边缘、宁可多走路的司机,他的演示不能用"最大化期望"解释(期望会让他抄近路),但能用"对坠崖的尾部极度厌恶"解释——风险敏感 IRL 就是要从轨迹里把这个隐含的风险态度量化出来。
技术上,因为一致性风险测度有对偶表示(进阶九),风险敏感 IRL 可以借用鲁棒 / 对抗的机器:把"专家是风险厌恶的"建模成"专家是对某个模型不确定鲁棒的",从演示反推那个不确定集(= 风险态度)。这是个相对前沿、未完全解决的方向。
对比性思维:标准 IRL 学"专家想要什么",风险敏感 IRL 还学"专家有多怕出事"。标准 IRL 从演示反推奖励(目标),隐含假设专家风险中性(最大化期望)。风险敏感 IRL 多反推一个维度——风险态度(畸变函数)。像 / 不像:都从演示反推内在偏好、都用 RL/优化的对偶机器;区别是风险敏感 IRL 承认"专家的谨慎行为可能不是因为他想要别的目标,而是因为他对同一目标的尾部更厌恶"。这在机器人模仿学习里有实际意义:要复现一个老练操作员的安全行为,光学他的目标不够,还得学他的风险态度——否则学出来的策略会在他谨慎的地方变得鲁莽(因为你用风险中性解释了他的谨慎,得到了错的奖励)。这也呼应全章主线:风险态度是决策的一个独立、可量化的维度,不该被默认为"中性"——无论是正向规划(前面各节)还是逆向学习(本专题)。
进阶专题十一:CMDP vs CVaR-CMDP——Safe RL 里的"期望约束 vs 尾部约束" ⭐⭐⭐¶
Safe RL 的主流框架是**约束 MDP(CMDP):最大化期望回报,同时约束**期望代价 \(\mathbb{E}[\sum\gamma^t c_t]\le d\)。OmniSafe(进阶三)里的 CPO、PPO-Lagrangian 都是解 CMDP。但 CMDP 的安全约束是"期望代价"——这又掉进了 §U5.1 的期望盲区:期望代价达标,不代表没有罕见的灾难性代价尾部。
CVaR-CMDP 把约束从期望代价换成代价的 CVaR:\(\mathrm{CVaR}_\alpha(\sum\gamma^t c_t)\le d\)。区别正是本章主线在 Safe RL 里的体现——CMDP 约束"平均有多不安全",CVaR-CMDP 约束"最坏 \(1-\alpha\) 尾部平均有多不安全"。对"偶发严重违规"敏感的任务(如偶尔的剧烈碰撞),CVaR-CMDP 比 CMDP 安全得多。
算法上,CMDP 常用拉格朗日法(把约束松弛进目标,学一个对偶变量 / 拉格朗日乘子)。CVaR-CMDP 类似,但因为 CVaR 是尾部泛函,需要配合分布式 critic(学代价分布、算其 CVaR)或 Rockafellar–Uryasev 的辅助变量(把 CVaR 约束变成期望约束 + 辅助变量,再用 CMDP 的拉格朗日机器)。后者很优雅——RU 公式 \(\mathrm{CVaR}_\alpha(C)=\min_z\{z+\frac{1}{1-\alpha}\mathbb{E}[(C-z)_+]\}\) 把"CVaR 约束"变成了"一个带辅助变量 \(z\) 的期望约束",于是 CVaR-CMDP 可以复用 CMDP 的全部求解技术(只是多一个变量 \(z\) 一起优化)。这是 §U5.2 的 RU 公式在 Safe RL 里的又一次兑现。
对比性思维:CMDP 约束"平均不安全度"、CVaR-CMDP 约束"尾部不安全度"——同一个 Safe RL 框架,换约束的风险态度。CMDP 和 CVaR-CMDP 共享"最大化回报 + 满足代价约束"的框架、共享拉格朗日求解机器;区别只在约束里的代价是取期望还是取 CVaR。像 / 不像:都是约束优化、都学对偶变量;CMDP 对"偶发严重违规"失明(期望把它平均掉),CVaR-CMDP 盯住尾部。而 RU 公式让这个升级几乎免费——把 CVaR 约束变成期望约束 + 一个辅助变量,CMDP 的求解器原样可用。这再次印证全章主线:风险敏感不是另起炉灶,而是"把期望换成 CVaR",且 RU 公式保证这个替换在优化上是廉价的(加一个辅助变量而已)。
进阶专题十二:CVaR-CBF 与随机 CBF 文献的关系 ⭐⭐⭐⭐¶
§U5.5 的 CVaR-CBF 属于一个更大的研究脉络——随机控制障碍函数(stochastic CBF),即在随机扰动下保证安全的 CBF 变体。理清这个脉络能帮你定位 CVaR-CBF 的位置。
随机 CBF 大致有几条路线,对应"在随机下要求什么安全": - 期望 CBF:要求 \(\mathbb{E}[\dot h + \alpha h]\ge0\)(裕量条件在期望意义下成立)——最弱,对尾部失明。 - 概率 / 鞅 CBF:用随机过程的鞅性质 / 上鞅条件,保证"以高概率"安全或"安全集是几乎必然不变的"(如基于 Itô 公式的随机 CBF)——关心概率,但同样不直接看违反的严重程度。 - CVaR-CBF(Ahmadi–Ames,§U5.5):要求裕量损失的 CVaR 受控——关心尾部的平均严重程度,是上述里对尾部最敏感、又比"最坏情况"可行的一档。 - 最坏情况 / 鲁棒 CBF:要求对所有扰动 \(\dot h+\alpha h\ge0\)——最强、最保守,无界扰动下可能不可行。
这条谱和本章 §U5.5 开头列的"鲁棒 / 机会约束 / CVaR"三层次完全对应,只是具体到了 CBF 的安全条件上。CVaR-CBF 的贡献是把 CVaR 这一档引入 CBF 框架,用 Rockafellar–Uryasev 把它写成可嵌进安全滤波 QP 的凸约束,并在 Cassie 双足上验证。
本质洞察:随机 CBF 的各种变体,是"安全条件该在什么意义下成立"这一问题的不同答案,CVaR-CBF 是其中对尾部敏感且可行的一档。确定性 CBF 在随机世界里失效后,研究者们沿"安全条件该要求什么"分化出多条路线——期望意义、概率 / 鞅意义、CVaR 意义、最坏情况意义。它们不是互相替代,而是覆盖了从最弱(期望)到最强(最坏情况)的一条谱,对应对尾部担忧的不同程度。CVaR-CBF 占据"看尾部平均"这一档——比期望 / 概率 CBF 多看了严重程度,比最坏情况 CBF 可行(不要求对无界扰动绝对安全)。这和进阶五"CVaR 在安全谱上卡在鲁棒和机会约束之间"是同一个图景在 CBF 上的投影。理解这点,你遇到任何"随机系统下的安全保证"工作,都能问:它要求安全条件在什么意义下成立(期望 / 概率 / CVaR / 最坏)?这个意义决定了它的保守程度、可行性、和对尾部的敏感度——而这正是本章教你的核心判断维度。
进阶专题十三:Risk-Conditioned 策略——把 α 做成可在线调的输入 ⭐⭐⭐⭐¶
§U5.4 的 IQN 已经能"事后调 \(\tau\) 采样区间"切换风险态度,但每次切换要重新跑贪心。更进一步的前沿是 Risk-Conditioned 策略(如 Risk-Conditioned DSAC, Choi 等 2021–2024):把风险水平 \(\alpha\)(或畸变参数)直接作为**策略网络的输入**,训练一个策略 \(\pi(a\mid s,\alpha)\),它见过各种 \(\alpha\)、能在运行时按指定 \(\alpha\) 即时给出对应风险态度的动作。
直觉对比:IQN 是"学一个分位函数、部署时用不同 \(\tau\) 采样导出不同风险态度的贪心"——风险态度在**决策时**通过采样实现;Risk-Conditioned 策略是"训练时就把 \(\alpha\) 喂进策略、让策略学会'给定 \(\alpha\) 该怎么动'"——风险态度被**编译进策略权重**。后者的好处:(1) 运行时切换 \(\alpha\) 是一次前向(不用重跑贪心 / 重采样);(2) 对连续控制(无 \(\arg\max\))更自然;(3) 一个网络覆盖整个风险态度谱(从激进到保守),可按场景实时调(如平地激进、碎石地保守)。这在需要"运行时动态调风险偏好"的机器人上很有用——同一个策略,过开阔地用低 \(\alpha\)(快),进危险区调高 \(\alpha\)(稳),无需切换模型。
对比性思维:IQN 把风险态度后置到"采样"、Risk-Conditioned 策略把它前置进"训练"——都在让风险态度可调,位置不同。IQN 训练时不管风险态度(学完整分位函数),决策时用 \(\tau\) 采样区间调;Risk-Conditioned 策略训练时就把 \(\alpha\) 作为输入、让策略学会条件于 \(\alpha\) 的行为。像 / 不像:都实现"一个模型、多种风险态度、可调",避免为每个 \(\alpha\) 重训;区别是可调性实现在哪一层——IQN 在决策层(采样),Risk-Conditioned 在策略层(网络输入)。前者更灵活(任意畸变都能采)、后者运行时更快(一次前向)且对连续控制更顺。这又是一次"风险态度是可调旋钮"主线的体现——只是把旋钮装在了不同位置。
进阶专题十四:CVaR-RL 的样本复杂度与谱风险前沿 ⭐⭐⭐⭐¶
风险敏感 RL 的理论基础正在补齐,两个值得关注的前沿方向:
样本复杂度(OCE reductions 等,Wang 等 arXiv 2024):标准 RL 的样本复杂度(学到 \(\epsilon\)-最优需多少数据)有成熟理论,但**风险敏感 RL 的样本复杂度**长期是空白——CVaR 依赖尾部、尾部样本稀少(进阶八),直觉上它该比风险中性 RL 需要更多数据,但缺乏严格的界。近年的工作(如基于 OCE, Optimized Certainty Equivalent 的归约)给出了某些设定(如 exogenous block MDP)下 CVaR RL 的首个样本复杂度保证——把"学风险敏感策略要多少数据"从经验观察变成有理论支撑的结论。这对实际部署很重要:它告诉你"要把 CVaR\(_\alpha\) 学到某精度,大概需要多少交互",而不是盲目试。
谱风险测度的分布式 RL(Static Spectral Risk for DRL, 2025 前后):把分布式 RL 从 CVaR 推广到更一般的**谱风险测度**(进阶七),并仔细处理"静态 vs 动态"一致性(§U5.3/§U5.4 的核心警告)。谱风险比 CVaR 更灵活(尾部内也能按坏的程度递增加权),但把它和分布式 RL 结合、且保证学到的是"静态谱风险最优"而非"动态/迭代"版本,是有挑战的——这正是这条前沿在攻的问题。
本质洞察:风险敏感 RL 的前沿,是把"理论保证"和"更一般的风险测度"两条线同时推进。早期风险敏感 RL(Chow 等)主要给算法(CVaR-PG/actor-critic),理论保证(收敛、样本复杂度)和测度的一般性(超越 CVaR)相对滞后。当前前沿在补这两块:一条线补**理论**(CVaR-RL 的样本复杂度、收敛性,让"学风险敏感策略要多少数据/能不能学到"有据可依),一条线补**一般性**(从 CVaR 到谱风险/任意畸变,且厘清静态 vs 动态一致性)。这两条线呼应了本章 §U5.1 的主线——风险敏感的发展史就是"不断变得更可辩护(理论)、更一般(测度类)"。对想做研究的读者,这两块都是有明确问题、有进展但远未解决的切入点(进阶四的开放问题清单与此呼应)。
进阶专题十五:OmniSafe 里 CVaR-CMDP 与 CPO/PPO-Lagrangian 的算法差异 ⭐⭐⭐¶
进阶三提到 OmniSafe 集成了多种 Safe RL 算法,进阶十一讲了 CMDP vs CVaR-CMDP 的约束差异。这里再具体到算法层面,帮你读懂 OmniSafe 的代码。
主流 Safe RL 算法处理约束的方式分两派: - 拉格朗日派(PPO-Lagrangian、CVaR-CMDP 等):把约束松弛进目标,引入拉格朗日乘子 \(\lambda\),交替优化策略(给定 \(\lambda\) 最大化"回报 \(-\lambda\cdot\) 约束违反")和 \(\lambda\)(约束违反越多、\(\lambda\) 涨得越快)。简单、通用,但 \(\lambda\) 的学习可能不稳、约束只在收敛时近似满足。 - 信赖域派(CPO, Constrained Policy Optimization):每步在一个信赖域内解一个带约束的优化,保证每次更新都(近似)满足约束。理论上更强(单调改进 + 约束满足),但每步要解约束优化、实现复杂。
CVaR-CMDP 通常走拉格朗日派 + Rockafellar–Uryasev:用 RU 公式把 CVaR 约束变成"期望约束 + 辅助变量 \(z\)"(进阶十一),然后套拉格朗日机器——多一个 \(z\) 一起优化、多一个 \(\lambda\) 管 CVaR 约束。读 OmniSafe 的 CVaR-CMDP 实现时,重点看它怎么估代价分布(分布式 critic 还是采样)、怎么用 RU 辅助变量、\(z\) 和 \(\lambda\) 怎么更新——这三点是 CVaR-CMDP 区别于普通 CMDP 的全部。
进阶专题十六:为什么 CVaR 在仿真到现实(sim-to-real)里特别有用 ⭐⭐⭐¶
一个本章没明说但很实际的应用动机:sim-to-real 的差距本质是一种分布偏移,而 CVaR / 分布鲁棒 CVaR 正好对付它。机器人在仿真里训练、到现实部署,现实的动力学 / 扰动分布和仿真不完全一样(摩擦、延迟、传感噪声都有差)。风险中性策略(最大化仿真里的期望回报)可能过拟合仿真的"平均情况",到现实的尾部(仿真没充分覆盖的极端情况)就崩。
CVaR 的两个性质正好帮上忙:(1) 关注尾部——CVaR 策略对"仿真里罕见但现实可能更常见"的尾部情况更鲁棒,不会只优化平均;(2) 对偶 = 鲁棒(进阶九)——对回报施加 CVaR 等价于假设转移被对抗性扰动,这天然提供了对"现实和仿真有差"的一层防护。分布鲁棒 CVaR(进阶 §U5.5 的 DR-CVaR)更进一步,显式地对"分布估计误差"(= sim-to-real 差距)鲁棒。所以风险敏感 / 分布鲁棒方法在 sim-to-real 文献里越来越常见——它们把"现实会偏离仿真"这件事,转化成了"对尾部 / 对分布不确定鲁棒"的可优化目标。
本质洞察:CVaR 对 sim-to-real 的帮助,根源在"尾部敏感"和"对偶即鲁棒"恰好对上了 sim-to-real 的痛点。Sim-to-real 失败的典型模式是:策略在仿真的平均情况上表现好,但现实的某些情况(仿真覆盖不足的尾部、或分布偏移带来的新情况)让它崩。这恰好是风险中性(只优化期望)的盲区、也恰好是 CVaR 的强项——CVaR 盯尾部(对仿真罕见但现实可能出现的极端情况设防),其对偶形式又等价于对转移不确定鲁棒(对"现实≠仿真"设防,进阶九)。所以 CVaR 不是"恰好也能用于 sim-to-real",而是它的两个核心性质(尾部敏感、对偶即鲁棒)精准命中了 sim-to-real 的两个痛点(尾部覆盖不足、分布偏移)。这给了一个选型启示:当你的不确定性来自"训练分布和部署分布不一致"时,风险敏感 / 分布鲁棒方法往往比纯期望方法更值得一试——这也是 Part-U 整条安全谱(尤其 CVaR 和鲁棒)在现代机器人学习里越来越重要的深层原因。
进阶专题十七:实践中到底用静态还是嵌套 CVaR——一个决策清单 ⭐⭐⭐⭐¶
§U5.3 讲清了静态 vs 嵌套的理论区别,这里给一个工程上的决策清单,因为这是文献和实现里最大的混淆源、也是最容易选错的地方。
默认用嵌套 CVaR,除非有明确理由用静态。原因:嵌套和动态规划 / RL 的递推机器兼容(Bellman 成立、VI/PI 收敛、可放心每步重规划),而绝大多数机器人控制是序贯闭环、要用递推求解。具体判断:
- 要用 DP / 值迭代 / RL 求解 → 嵌套(静态根本写不出 Bellman,无法递推)。
- MPC 滚动重规划、每步重解 → 嵌套(静态 + 每步重优化会抖动,§U5.3 思维陷阱)。
- 分布式 RL(IQN 等)逐步 CVaR 贪心 → 你得到的本就是动态 / 迭代 CVaR(≈嵌套),别声称是静态(§U5.4)。
- 一次性规划一整条轨迹、然后承诺执行不中途变 → 可以用静态(精确控制全程总代价的尾部),但要接受不可递推、要用增广状态(把 VaR 阈值 \(z\) 并入状态)或在轨迹空间直接优化。
- 安全认证 / 合规要求"全程总代价 CVaR ≤ 某值"的精确语义 → 必须静态(嵌套给不了这个干净的全程解释),接受其求解代价。
一个实用折中:纯嵌套(每步都施加 CVaR)可能过度保守(进阶专题里讲的复合效应)。实践中可以"每隔几步施加一次 CVaR"或"只在关键决策点施加",在时间一致性(要尽量嵌套)和不过度保守(别每步都施加)之间取平衡。这不是理论上的纯嵌套,但工程上往往更好用。
对比性思维:静态 vs 嵌套的选择,本质是"要精确的全程尾部语义"还是"要可递推的求解"——几乎总是后者赢。静态 CVaR 的唯一优势是语义精确("全程总代价的最坏 \(1-\alpha\) 平均",可解释、可认证),代价是不可递推(DP/RL 用不了)、闭环会抖动。嵌套 CVaR 的优势是可递推(Bellman、VI/PI、稳定闭环),代价是语义没那么干净(逐步复合、通常更保守)、且和静态不是一回事。像 / 不像:都用 CVaR 度量尾部、都让策略风险厌恶;区别在"风险施加的方式"决定了"能不能用递推求解"。工程现实是:机器人控制绝大多数是序贯闭环、必须用递推机器,所以嵌套几乎总是默认选择——静态只在"一次性规划 + 承诺执行"或"硬性的全程语义要求"这两种少数场景才值得用。记住这个清单,你就不会在多步 CVaR 上选错、也不会犯"静态目标 + 每步重优化"的自相矛盾。
进阶专题十八:OCE——一致性风险测度的统一优化框架 ⭐⭐⭐⭐¶
CVaR 的 Rockafellar–Uryasev 变分公式(§U5.2)其实是一个更一般框架的特例:优化确定性等价(Optimized Certainty Equivalent, OCE)。OCE 由 Ben-Tal 和 Teboulle 提出,形式是
其中 \(\phi\) 是一个凸的"惩罚函数"。换不同的 \(\phi\) 就得到不同的风险度量:取 \(\phi(t)=\frac{1}{1-\alpha}\max(t,0)\) 就**正好回到 CVaR 的 RU 公式**;取 \(\phi(t)=\frac{1}{\gamma}(e^{\gamma t}-1)\) 得到熵风险(进阶七、进阶一);取别的 \(\phi\) 得到其他一致性 / 凸风险测度。
OCE 的价值在于**统一**:它把"一大类风险度量"都写成"对辅助变量 \(z\) 取最小"的同一形式——于是 §U5.2 那套"辅助变量 + 凸优化"的可算化技术,不只适用于 CVaR,而是适用于整个 OCE 类。这也是为什么近年的风险敏感 RL 理论(进阶十四的 OCE reductions)用 OCE 作为统一分析框架——证一个 OCE 的结论,就覆盖了 CVaR、熵风险等一大批度量。对实现者,这意味着你为 CVaR 写的"辅助变量 + 凸优化"代码,换个 \(\phi\) 就能算别的 OCE 风险度量,框架不用重写。
本质洞察:CVaR 的可算化不是孤立的技巧,而是 OCE 统一框架的一个实例——"风险度量 = 对辅助变量取最小"是一大类度量的共同结构。§U5.2 教 CVaR 的 RU 公式时,可能觉得"\(\min_z\{z+\ldots\}\)"是 CVaR 特有的巧妙构造。OCE 揭示这是一个普遍模式:一大类一致性 / 凸风险度量都能写成"\(\min_z\{z+\mathbb{E}[\phi(X-z)]\}\)",CVaR 只是 \(\phi\) 取"截断线性"的特例、熵风险是 \(\phi\) 取"指数"的特例。这个统一有两个回报:(1) 可算化通用——为 CVaR 写的辅助变量 + 凸优化框架,换 \(\phi\) 即可算整个 OCE 类;(2) 理论通用——风险敏感 RL 的样本复杂度等结论可以在 OCE 层面一次证明、覆盖一批度量。这呼应了 §U5.1 的表示定理(畸变风险度量的统一)——风险敏感领域反复出现"先找统一的数学结构、再让具体度量当特例"的模式,理解结构比记住单个度量更有力量。
进阶专题十九:CVaR 与 tube-MPC 的关系——确定性收缩 vs 概率收缩 ⭐⭐⭐¶
U2 的鲁棒 MPC 常用 tube(管道) 思想:名义轨迹 + 一个包住所有扰动的误差管道,保证真实轨迹在管道内、管道避开障碍。CVaR-MPC 和 tube-MPC 是处理 MPC 下扰动的两条不同路线,对照能加深对两者的理解。
- tube-MPC(鲁棒):管道大小由"扰动的最坏情况界"决定——管道要包住**所有**扰动(或一个有界扰动集)。扰动无界(高斯)时,要么管道无穷大(不可行),要么人为截断扰动集(牺牲严格保证)。给的是确定性保证(真实轨迹一定在管道内)。
- CVaR-MPC(风险敏感):不要求包住所有扰动,而要求"碰撞代价的尾部平均"受控(§U5.5)。扰动无界也可行(只看尾部 \(\alpha\) 的平均,不看无穷远的尾巴)。给的是风险保证(尾部平均安全,非绝对)。
两者也可结合:用"概率管道"——管道大小由扰动的某个分位数(或 CVaR)决定,而非最坏情况。这就是随机 tube-MPC,它和 CVaR-MPC 在精神上一致(都用概率 / 尾部而非最坏情况定收缩量),是 U2 鲁棒 tube 和 U5 CVaR 之间的桥。
对比性思维:tube-MPC 用"最坏情况管道"、CVaR-MPC 用"尾部平均约束",差在收缩量由什么决定。两者都在 MPC 框架里处理扰动;tube 用一个确定性管道包住扰动(管道大小 = 最坏情况界),CVaR 用尾部平均约束(不画管道、直接约束代价的 CVaR)。像 / 不像:都让 MPC 在扰动下更安全;但 tube 给确定性保证(轨迹一定在管道内)却在无界扰动下不可行,CVaR 给风险保证(尾部平均安全)且无界扰动下可行。这又是 §U5.5"安全谱上选位置"的体现——tube(最坏情况)在谱的保守端、CVaR 在中间、随机 tube 是两者的桥。选哪个看扰动有没有界、要确定性还是风险保证。
进阶专题二十:熵风险 vs CVaR——用数字看两种"风险厌恶"的差异 ⭐⭐⭐¶
进阶一和进阶七提到熵风险(基于指数效用,\(\frac{1}{\gamma}\log\mathbb{E}[e^{\gamma Z}]\))。这里用数字把它和 CVaR 摆在一起,看两种风险厌恶的实际差异(标准正态损失,已实跑核对):
| 度量 | 值(标准正态损失) | 解读 |
|---|---|---|
| 期望 | 0.00 | 风险中性基线 |
| CVaR\(_{0.95}\) | 2.07 | 最坏 5% 尾部的平均 |
| CVaR\(_{0.99}\) | 2.67 | 最坏 1% 尾部的平均 |
| 熵风险 \(\gamma=0.5\) | 0.25 | \(=\gamma/2\)(正态闭式) |
| 熵风险 \(\gamma=1.0\) | 0.50 | |
| 熵风险 \(\gamma=2.0\) | 1.00 |
对正态分布,熵风险有闭式 \(\mu+\frac{\gamma}{2}\sigma^2\)(这里 \(=\gamma/2\)),验证吻合。两者的根本差异:CVaR 的 \(\alpha\) 有"尾部分位"的直接含义(\(\alpha=0.95\) 就是最坏 5%),值也直接是"尾部平均损失"(2.07 个单位);熵风险的 \(\gamma\) 没有这种直观含义(\(\gamma=1\) 对应什么风险态度?说不清),值(0.50)也不对应任何可解释的损失量。这正是进阶一说的"指数效用 \(\gamma\) 不直观、CVaR 的 \(\alpha\) 可解释"——这张表把它量化了。熵风险的好处是有闭式、可微(优化方便),但代价是失去可解释性、且不满足正齐次(非严格一致)。这也是为什么机器人安全场景偏爱 CVaR(可解释、可向审查者辩护)而非熵风险。
进阶专题二十一:分布式 Actor-Critic(DSAC)——把风险敏感带进连续控制 ⭐⭐⭐⭐¶
§U5.4 主要讲值方法(DQN 系)的风险敏感(在贪心步注入)。但机器人更常用**连续控制**(SAC、PPO),它们没有 \(\arg\max\)。风险敏感怎么进连续控制?答案是**分布式 actor-critic**,代表是 DSAC(Distributional Soft Actor-Critic)。
标准 SAC 有一个 critic 学 \(Q(s,a)=\mathbb{E}[Z]\)、一个 actor 据此改进。DSAC 把 critic 升级成**分布式 critic**——学整个回报分布 \(Z(s,a)\)(用分位数回归或 IQN 式的分位函数,§U5.4 的表示)。然后 actor 的改进信号从"提高期望 \(\mathbb{E}[Z]\)"换成"提高畸变期望(如 CVaR)"——actor 朝"让 CVaR 更好"的方向更新。这样风险敏感就进了连续控制:
- 风险中性 DSAC:actor 用 \(\mathbb{E}[Z]\)(= 标准 SAC,分布式 critic 只是更稳的价值估计);
- 风险敏感 DSAC:actor 用 \(\mathrm{CVaR}_\alpha[Z]\),得到风险厌恶的连续控制策略。
DSAC 在机器人连续控制(如四足、机械臂)上让"风险敏感"落地——双足/四足的力矩控制是连续的,没法用 DQN 的离散贪心,DSAC 这类分布式 actor-critic 是把 CVaR 带进这些系统的主要途径。它也呼应进阶十三的 Risk-Conditioned 策略(把 \(\alpha\) 做成 actor 输入,运行时调)。
本质洞察:分布式 actor-critic 把"学全分布、风险态度后置"从离散动作推广到了连续控制——同一个范式,换个载体。§U5.4 的 IQN 在离散动作上通过 \(\arg\max_a\mathrm{CVaR}[Z(s,a)]\) 实现风险敏感;连续控制没有 \(\arg\max\),但 DSAC 把同样的思想搬到 actor-critic 里——critic 学分布、actor 朝畸变期望(CVaR)改进。像 / 不像:都是"分布式 critic 提供完整分布 + 风险态度作为对分布的后处理",只是决策机制从"离散贪心"换成"连续策略梯度"。这再次印证全章主线——风险态度是可后置、可调的旋钮,且这个旋钮能装在任何"用期望做决策"的算法上(值方法的贪心、actor-critic 的策略改进)。对做连续控制机器人的读者,DSAC 是把本章 CVaR 落到你的力矩控制器上的最直接途径。
进阶专题二十二:风险敏感规划的全景地图——五节如何拼成一张网 ⭐⭐⭐¶
学完五节和二十多个专题,容易"见树不见林"。这里给一张全景地图,把本章所有内容织成一张网,帮你建立结构化记忆。
整个风险敏感规划可以沿三个问题组织:
问题一:度量什么?(§U5.1 + 进阶一/二/七) - 候选:期望(盲于尾部)、VaR(盲于尾部内部 + 非凸 + 不一致)、CVaR(尾部平均 + 凸 + 一致)、熵风险(指数效用、非一致)、谱风险(更一般的畸变)。 - 选择依据:Artzner 四公理 + Majumdar–Pavone 六公理 → 满足者是畸变风险度量,CVaR 是甜点(一致 + 可解释 + 可算 + 与 RL 兼容)。 - 历史脉络:指数效用(1972,γ 不直观)→ 四公理(1999)→ CVaR(2000,α 可解释)。
问题二:怎么算 / 怎么递推?(§U5.2 + §U5.3 + 进阶十七/十八) - 单步算:Rockafellar–Uryasev 变分公式 → 辅助变量 → LP/QP(保凸,OCE 是更一般框架)。 - 多步递推:静态 CVaR 时间不一致(不可递推)→ 嵌套 CVaR(逐步施加、时间一致、risk-averse Bellman、VI/PI 收敛)。 - 关键区分:静态 vs 嵌套/动态,几乎总用嵌套。
问题三:怎么学 / 怎么用?(§U5.4 + §U5.5 + 进阶九/十二/十三/十六/十九/二十一) - 数据驱动学:分布式 RL(C51/QR-DQN/IQN)学全分布、风险态度后置;连续控制用 DSAC;运行时调用 Risk-Conditioned 策略。 - 工程落地:CVaR-CBF(安全滤波)、CVaR-MPC(滚动优化)、分布鲁棒 CVaR(应对分布不确定 / sim-to-real);C++ 实时部署是开源空白。 - 统一视角:CVaR 对偶 = 鲁棒 MDP;安全条件可替换(确定性/CC/CVaR/鲁棒在同一 QP 框架)。
这三个问题串起来就是本章的全部:"用什么度量尾部(问题一)→ 怎么算和递推(问题二)→ 怎么学和用到机器人上(问题三)"。二十多个进阶专题都挂在这张网的某个节点上——遇到任何风险敏感的新工作,先问它在回答这三个问题中的哪一个,你就能把它定位到这张网里。
本质洞察:风险敏感规划的所有内容,本质是回答"度量什么、怎么算、怎么用"三个问题。初学时容易把 CVaR、嵌套、分布式 RL、CVaR-CBF 当成一堆零散的技术。这张全景地图揭示它们其实是同一条逻辑链的不同环节:你得先决定用什么度量尾部(CVaR,问题一),然后才能算它(RU 公式,问题二上半)、在多步里递推它(嵌套,问题二下半)、数据驱动地学它(分布式 RL,问题三上半)、落到机器人安全工具上(CVaR-CBF/MPC,问题三下半)。每个技术都是为了回答其中一个问题、并为下一个问题铺路。理解这条"度量→算→递推→学→用"的主链,比记住任何单个技术都重要——它让你在面对新问题、新论文时有一个稳定的定位框架,也是本章反复强调"主线"的原因。
进阶专题二十三:一个完整的选 α 决策案例——四足巡检机器人 ⭐⭐⭐¶
把"怎么选 \(\alpha\)"(综合练习第 5 题、调参诊断)落到一个完整的工程案例上,演示真实的权衡过程。
场景:一个四足机器人在工厂做自主巡检,要在不同地形上规避障碍(碰撞代价 = 撞坏设备的损失)。你决定用 CVaR-MPC 做风险敏感避障,现在要为不同任务阶段选 \(\alpha\)。
分阶段决策: - 开阔平地快速通行:地形可预测、扰动小(打滑概率低)、撞击后果轻(周围空旷)。→ 选**低 \(\alpha\)(如 0.9)甚至接近风险中性**——过度保守会拖慢巡检效率,而这里尾部本就不严重。 - 靠近精密设备的窄道:撞击后果严重(设备昂贵)、空间小容错低。→ 选**高 \(\alpha\)(如 0.99)——这里必须盯住最坏情况的尾部,宁可慢也不能撞。 - **碎石 / 湿滑地形:扰动大且重尾(突然打滑可能很严重)。→ 选**中高 \(\alpha\)(0.95–0.99),但要确保**样本量够——重尾 + 高 \(\alpha\) 意味着尾部样本稀少,按进阶八的表,\(\alpha=0.99\) 要 \((1-\alpha)N\ge\) 几十,即 \(N\ge\) 几千条扰动场景,否则 CVaR 估计不稳、约束失真。
权衡的三个维度(呼应调参诊断):(1) 撞击后果严重程度(越严重 \(\alpha\) 越高);(2) 可获得的扰动样本量(样本少则 \(\alpha\) 不能太高,否则估不准);(3) 对巡检效率的要求(\(\alpha\) 越高越保守越慢)。这个案例里,理想方案是**按地形动态调 \(\alpha\)**——这正是进阶十三 Risk-Conditioned 策略的用武之地:训练一个能按指定 \(\alpha\) 行动的策略,巡检时根据地形实时调 \(\alpha\)(平地低、窄道高、碎石中高),一个策略覆盖全程,无需切换模型。
对比性思维:选 α 不是选一个固定值,而是按"后果严重度 × 样本量 × 效率要求"在不同场景动态权衡。新手容易问"\(\alpha\) 到底该设多少",期待一个标准答案。这个案例说明没有标准答案——同一个机器人在平地、窄道、碎石上该用不同的 \(\alpha\),因为三个权衡维度(后果严重度、样本量、效率)在不同场景下不同。固定 \(\alpha\) 要么在平地过度保守(拖慢)、要么在窄道不够保守(撞设备)。所以"选 \(\alpha\)"的正确姿势是建立一个**按场景调 \(\alpha\) 的策略**(手工规则或 Risk-Conditioned 策略),而非纠结单一数值。这也呼应 §U5.1 的"满足公理 ≠ 适合任务"——CVaR 是好工具,但 \(\alpha\) 怎么用仍需结合任务的工程判断,且这个判断往往是动态的。
本章常见误解汇总¶
把全章最易踩的误解集中列出,供快速自查。
| 误解 | 正确理解 | 出处 |
|---|---|---|
| VaR 只是没 CVaR 好,调高 \(\alpha\) 能补救 | VaR 缺陷是结构性的(违反次可加、对尾部严重程度失明),调 \(\alpha\) 救不了 | §U5.1 |
| 满足公理就等于适合我的任务 | 公理保证度量"讲道理",但不保证风险态度适合任务;探索型任务可能不该风险厌恶 | §U5.1 |
| 辅助变量 \(z\) 是需要手动调的超参数 | \(z\) 是被优化掉的内部变量,优化器自动解到 VaR;固定它会算出上界而非 CVaR | §U5.2 |
对原子分布用 mean(x[x>=VaR]) 估 CVaR |
原子处会算错(且误判次可加);必须用 Rockafellar–Uryasev 公式或 LP | §U5.2 |
| 少量样本也能可靠估极端尾部 | \(\alpha\) 越高、尾部样本越少(\((1-\alpha)N\));估极端尾部需大样本 | §U5.2 |
| 静态 CVaR 和嵌套 CVaR 在多步里一样 | 两者不同目标:静态时间不一致、不可递推;嵌套时间一致、Bellman 成立 | §U5.3 |
| 时间不一致只是理论洁癖 | 有真实闭环后果:每步重优化给出矛盾计划,导致行为抖动 / 振荡 | §U5.3 |
| 一步 CVaR 算子不是压缩、VI 不收敛 | CVaR 的单调性 + 平移不变保证 Bellman 算子是 \(\gamma\)-压缩,VI/PI 收敛 | §U5.3 |
| 分布式 RL 的 CVaR 贪心 = 静态 CVaR 最优 | 那是动态 / 迭代 CVaR(近嵌套),与静态 CVaR 理论上不一致 | §U5.4 |
| C51 回报范围随便设 | 固定支撑,范围设窄会截断尾部、CVaR 失真;尾部敏感时用 QR-DQN/IQN | §U5.4 |
| 学方差就能代替学整个分布做风险敏感 | 方差对称(同等惩罚好坏尾),且非正态下给不出正确 CVaR | §U5.4 |
| CVaR-CBF 里两个 \(\alpha\) 是一回事 | CBF 系数 \(\alpha_{\text{cbf}}\)(裕量恢复速率)和 CVaR 水平 \(\alpha\)(尾部深度)独立可调 | §U5.5 |
| CVaR 安全条件能提供鲁棒那样的硬保证 | CVaR 控尾部平均,非最坏情况绝对界;尾部内仍可能有更极端违反 | §U5.5 |
本章小结¶
本章沿一条主线走完:在"期望最优"和"最坏情况"之间,用一个公理化、可调(\(\alpha\))、可微的中间地带,度量并优化尾部风险。 这条主线背后是一个更朴素的洞察——机器人安全攸关时,"平均表现好"远远不够,你必须管住"最坏情况有多糟",但又不能保守到"为应对几乎不可能的极端而寸步难行"。CVaR 恰好提供了这个"既管尾部、又可行、还可调"的中间地带。 起点是期望的盲区(把罕见大灾难平均掉)和 VaR 的结构缺陷(违反次可加、对尾部严重程度失明)。Artzner 四公理(§U5.1)立下"什么样的风险度量讲道理"的标准,把选择从主观偏好变成数学必然——满足公理的恰是畸变风险度量,CVaR 是其最常用特例。Rockafellar–Uryasev(§U5.2)用辅助变量把 CVaR 写成凸的、可样本化为 LP 的形式,让它能嵌进优化而不破坏凸性。多步设定下(§U5.3),静态 CVaR 时间不一致、塞不进 DP,Ruszczyński 嵌套 CVaR 用"逐步施加一步条件 CVaR"恢复时间一致性和 Bellman 方程。分布式 RL(§U5.4)学整个回报分布、把风险态度解耦成事后的一次重加权,IQN 的 \(\tau\) 重采样能即时实现 CVaR 及任意畸变测度(但务必区分动态 vs 静态 CVaR)。最后落地(§U5.5):把 CVaR 嵌进 CBF 安全滤波和 MPC,在 Part-U 安全谱上滑到"看尾部平均"这一档——而 C++ 实时实现这块生态空白,正是真实的原创机会。
术语速查表¶
| 术语(中 / 英) | 一句话定义 |
|---|---|
| 风险度量(risk measure) | 把随机代价映射到一个实数的函数 \(\rho\),用于排序 / 优化 |
| VaR(风险价值,Value-at-Risk) | 代价分布的 \(\alpha\) 分位数——"有 \(\alpha\) 把握代价不超过它";只看分位点 |
| CVaR(条件风险价值,Conditional Value-at-Risk) | 分位点以上整个尾部的平均——"最坏 \(1-\alpha\) 情况的平均代价";也叫 Expected Shortfall / Tail VaR |
| 一致性风险测度(coherent risk measure) | 满足单调 / 平移不变 / 正齐次 / 次可加四公理的风险度量 |
| 单调性(monotonicity) | 逐样本更坏 ⇒ 风险不更低 |
| 平移不变性(translation / cash invariance) | 加确定代价 \(c\),风险正好加 \(c\) |
| 正齐次性(positive homogeneity) | \(\rho(\beta Z)=\beta\rho(Z)\),风险随规模等比缩放 |
| 次可加性(subadditivity) | \(\rho(Z+Z')\le\rho(Z)+\rho(Z')\),合并不制造风险("a merger does not create extra risk") |
| 共单调可加性(comonotone additivity) | 完全正相关的代价不获分散化折扣(Majumdar–Pavone A5) |
| 律不变性(law invariance) | 同分布的代价同风险(A6) |
| 畸变风险度量(distortion risk metric) | \(\rho_g(Z)=\int_0^1 F_Z^{-1}(\tau)\mathrm{d}g(\tau)\),满足六公理者的一般形式;CVaR 是 \(g\) 取特定形状的特例 |
| 畸变函数(distortion function) | 重新分配各分位数权重的单调函数 \(g\) |
| Rockafellar–Uryasev 公式 | \(\mathrm{CVaR}_\alpha(X)=\min_z\{z+\frac{1}{1-\alpha}\mathbb{E}[(X-z)_+]\}\),把 CVaR 写成凸最小化 |
| SAA(样本平均近似,Sample Average Approximation) | 用样本均值代替期望,把 CVaR 变成有限维 LP |
| 静态 CVaR(static CVaR) | 对全程总代价施加一次 CVaR;时间不一致、不可递推 |
| 嵌套 CVaR(nested / Markov 风险测度) | 每步施加一步条件 CVaR、层层复合;时间一致、Bellman 成立 |
| 时间一致性(time consistency) | \(t=0\) 的最优计划在 \(t=1\) 重优化仍被认同 |
| risk-averse Bellman 方程 | \(V(s)=\min_a\{c+\gamma\,\mathrm{CVaR}_\alpha[V(s')]\}\),把期望换成一步 CVaR |
| 分布式 RL(distributional RL) | 学整个回报分布 \(Z(s,a)\) 而非只学期望 \(Q=\mathbb{E}[Z]\) |
| C51 | 固定 51 个价值原子、学其概率的分布式 RL(支撑固定) |
| QR-DQN | 学 \(N\) 个分位数的分布式 RL(支撑自适应) |
| IQN(隐式分位网络) | 学整个分位函数 \(\psi(s,a,\tau)\);改 \(\tau\) 采样 = 切换风险态度 |
| 动态 / 迭代 CVaR(dynamic / iterated CVaR) | 分布式 RL 逐步 CVaR 贪心得到的目标;近嵌套,与静态 CVaR 不一致 |
| CVaR-CBF | 把 CBF 安全条件从 \(h\ge0\) 升级为 \(\mathrm{CVaR}_\alpha[\cdot]\) 形式 |
| CVaR-MPC | 把 CVaR 约束(RU 辅助变量形式)嵌进 MPC 的 QP |
| 指数效用 / LEQG | 用 \(e^{\gamma Y}\) 效用的风险敏感准则;LQG 的风险敏感推广(Howard–Matheson 1972) |
符号速查表¶
本章用到的核心数学符号(按出现顺序):
| 符号 | 含义 | 出处 |
|---|---|---|
| \(Z, X, L\) | 代价 / 损失随机变量(越大越坏) | §U5.1 |
| \(\rho(\cdot)\) | 风险度量(随机代价 → 实数) | §U5.1 |
| \(\mathrm{VaR}_\alpha\) | 风险价值,\(\alpha\) 分位数 | §U5.1 |
| \(\mathrm{CVaR}_\alpha\) | 条件风险价值,最坏 \(1-\alpha\) 尾部平均 | §U5.1 |
| \(\alpha\) | CVaR 的尾部水平(越接近 1 越保守) | §U5.1 |
| \((\cdot)_+\) | \(\max(0,\cdot)\),取正部 | §U5.2 |
| \(z\) | Rockafellar–Uryasev 辅助变量(最优 = VaR) | §U5.2 |
| \(u_i, v_j\) | SAA-LP 的样本辅助变量 | §U5.2 |
| \(F_Z^{-1}(\tau)\) | \(Z\) 的分位函数(逆 CDF) | §U5.1 |
| \(g(\tau)\) | 畸变函数(重新分配分位权重) | §U5.1 |
| \(\rho_g\) | 畸变风险度量 \(\int_0^1 F_Z^{-1}\mathrm{d}g\) | §U5.1 |
| \(\gamma\) | 折扣因子(§U5.3)/ 指数效用风险系数(进阶一) | §U5.3 |
| \(V(s)\) | risk-averse 值函数 | §U5.3 |
| \(\mathrm{CVaR}_\alpha^s\) | 在状态 \(s\) 的一步条件 CVaR | §U5.3 |
| \(Z(s,a)\) | 回报分布(分布式 RL 学的对象) | §U5.4 |
| \(\psi(s,a,\tau)\) | IQN 的分位函数网络 | §U5.4 |
| \(\tau\) | 分位水平 \(\in[0,1]\)(IQN 采样) | §U5.4 |
| \(\beta(\tau)\) | 畸变函数(IQN 实现风险态度) | §U5.4 |
| \(h(x)\) | CBF 的安全裕量函数(\(h\ge0\) 安全) | §U5.5 |
| \(\alpha_{\text{cbf}}\) | CBF 类 K 函数系数(≠ CVaR 的 \(\alpha\)) | §U5.5 |
| \(\mathcal{Q}\) | CVaR 对偶里的备选测度族 | 进阶九 |
| \(\kappa\) | CVaR 约束的阈值 | §U5.5 |
| \(\lambda\) | 均值–CVaR 权衡权重 | 进阶六 |
知识点总表¶
| 编号 | 知识点 | 核心要点 | 对应节 | 难度 |
|---|---|---|---|---|
| K1 | 期望的尾部盲区 | 期望把罕见大灾难平均掉,对尾部不敏感 | §U5.1 | ⭐⭐ |
| K2 | Artzner 四公理 | 单调 / 平移不变 / 正齐次 / 次可加 = 一致性 | §U5.1 | ⭐⭐⭐ |
| K3 | VaR 违反次可加 | 只看分位点,合并风险可暴涨(反例) | §U5.1 | ⭐⭐⭐ |
| K4 | CVaR 满足全部公理 | 尾部平均,积分光滑 ⇒ 次可加 | §U5.1 | ⭐⭐⭐ |
| K5 | Majumdar–Pavone 六公理 | 加共单调可加 + 律不变;机器人语境 | §U5.1 | ⭐⭐⭐ |
| K6 | 畸变风险度量表示定理 | 满足六公理者 = 对分位函数加权积分;CVaR 是特例 | §U5.1 | ⭐⭐⭐⭐ |
| K7 | Rockafellar–Uryasev 公式 | \(\min_z\{z+\frac{1}{1-\alpha}\mathbb{E}[(X-z)_+]\}\),\(z^*=\)VaR | §U5.2 | ⭐⭐⭐ |
| K8 | CVaR 的 SAA-LP | 辅助变量 \(u_i\ge x_i-z,u_i\ge0\) → 线性规划 | §U5.2 | ⭐⭐⭐ |
| K9 | CVaR 保凸红利 | \(L\) 对 \(\theta\) 凸 ⇒ CVaR 约束凸 ⇒ 可嵌 MPC | §U5.2 | ⭐⭐⭐ |
| K10 | 原子分布的 CVaR 估计 | 朴素平均会错,须用 RU / LP | §U5.2 | ⭐⭐⭐ |
| K11 | CVaR 看穿重尾 | 重尾下 VaR 可能更小但 CVaR 明显更大 | §U5.2 | ⭐⭐⭐ |
| K12 | 静态 CVaR 时间不一致 | 尾部定义随信息漂移 ⇒ DP 不递推 | §U5.3 | ⭐⭐⭐⭐ |
| K13 | 嵌套 CVaR 修复 | 逐步施加一步条件 CVaR ⇒ 时间一致 | §U5.3 | ⭐⭐⭐⭐ |
| K14 | risk-averse Bellman | 期望换一步 CVaR;CVaR 单调 + 平移不变 ⇒ 压缩 ⇒ VI/PI 收敛 | §U5.3 | ⭐⭐⭐⭐ |
| K15 | 分布式 RL 学全分布 | 学 \(Z(s,a)\) 而非 \(\mathbb{E}[Z]\),保留尾部信息 | §U5.4 | ⭐⭐⭐ |
| K16 | C51/QR-DQN/IQN 三表示 | 固定原子 / 固定概率学分位 / 学整个分位函数 | §U5.4 | ⭐⭐⭐⭐ |
| K17 | IQN 的 \(\tau\) 重采样 | \(\tau\sim U(0,\alpha)\) = 下尾 CVaR;任意畸变 = 任意风险测度 | §U5.4 | ⭐⭐⭐⭐ |
| K18 | 动态 CVaR ≠ 静态 CVaR | 逐步 CVaR 贪心是动态 / 迭代,与静态不一致 | §U5.4 | ⭐⭐⭐⭐ |
| K19 | CVaR-CBF | 安全条件 \(h\ge0\) 升级为 CVaR 形式;Cassie 验证 | §U5.5 | ⭐⭐⭐ |
| K20 | CVaR-MPC | RU 辅助变量嵌 MPC 的 QP,保凸可实时 | §U5.5 | ⭐⭐⭐ |
| K21 | 安全条件可替换 | 确定性 / CC / CVaR / 鲁棒在同一 QP 框架互换 | §U5.5 | ⭐⭐⭐ |
| K22 | CVaR 是 CC 的公理化升级 | CVaR 约束更强(≥VaR)、凸、一致、看严重程度 | 进阶二 | ⭐⭐⭐ |
| K23 | 指数效用 / LEQG | 风险敏感史前史;\(\gamma\) 不直观 → CVaR 的 \(\alpha\) 可解释 | 进阶一 | ⭐⭐⭐ |
| K24 | CVaR = 鲁棒 MDP(对偶) | 对结果施加 CVaR ⟺ 假设转移被对抗扰动;风险敏感与鲁棒等价 | 进阶九 | ⭐⭐⭐⭐ |
| K25 | OCE 统一框架 | CVaR 的 RU 公式是 OCE 的特例;一类风险度量共享"对辅助变量取最小" | 进阶十八 | ⭐⭐⭐⭐ |
| K26 | CVaR 对 sim-to-real | 尾部敏感 + 对偶即鲁棒,命中分布偏移痛点 | 进阶十六 | ⭐⭐⭐ |
| K27 | 静态 vs 嵌套求解 | 嵌套有递推结构(每步小 LP、可并行);静态须轨迹空间 / 增广状态 | §U5.3 | ⭐⭐⭐⭐ |
| --- |
综合练习¶
跨节 / 跨章的综合题,检验是否把风险敏感规划织进了整张知识网。
-
[跨节·端到端 CVaR 流水线] 把本章实现一、实现五、实现九拼成一个完整的风险敏感决策流水线:用实现一的 CVaR-LP 算约束、用实现九的方式把 CVaR 作为约束嵌进一个 2D 点机器人的 MPC(§U5.5 的 QP 结构)、用实现五的方式在重尾扰动下对比 CVaR-MPC 与机会约束 MPC。在重尾混合高斯扰动下跑闭环,对比 CVaR-MPC 与机会约束 MPC 的尾部碰撞代价(累积项目的核心实验)。串起 §U5.1(为什么重尾要 CVaR)/§U5.2(CVaR-LP)/§U5.5(嵌 MPC)。
-
[跨章·U5 × U3] U3 的机会约束把安全写成 \(\Pr(\text{碰撞})\le\delta\),本章 §U5.1/进阶二指出这等价于 VaR 约束、是 CVaR 约束的特例。请:(a) 写出同一个避障问题的机会约束形式和 CVaR 约束形式;(b) 论证"满足 CVaR\(_{1-\delta}\le0\) ⟹ 满足 \(\Pr(\text{碰撞})\le\delta\)"(即 CVaR 约束更强);(c) 构造一个具体场景,两个方案有相同的碰撞概率(机会约束认为一样好)但碰撞严重程度不同(CVaR 能区分),用数字说明 CVaR 约束如何选出更安全的那个。
-
[跨章·U5 × U4] U4 处理感知端不确定(belief),本章处理尾部风险。设计一个"风险敏感的信念空间规划":在 belief 的每个粒子上评估回报分布,对"belief + 未来随机性"联合施加 CVaR。请写出这个联合问题的形式(提示:把 §U5.3 的 risk-averse Bellman 里的状态换成 belief,期望换成"对 belief 不确定性 + 转移随机性的一步 CVaR"),并讨论它如何同时处理"状态看不清"和"尾部风险"两个正交维度。
-
[跨章·五安全谱] 回顾 U0 五安全谱:U2 鲁棒、U3 机会约束、U5 CVaR、U4 POMDP、U1 分支。请画一张表,对每条谱列出:它处理哪类不确定性(动力学 / 交互 / 感知 / 尾部)、用什么数学对象(tube / \(\delta\) / CVaR / belief / 分支树)、在"对尾部担忧程度"的连续谱上处于什么位置(进阶五)。然后论证:为什么 CVaR 正好卡在鲁棒和机会约束之间、由 \(\alpha\) 连续调节。
-
[思考题·α 的工程权衡] CVaR\(_{0.95}\) 的直觉是"最坏 5% 情况的平均损失"。如果你是一个四足机器人的安全工程师,你会选 \(\alpha=0.95\)(关注最坏 5%)还是 \(\alpha=0.99\)(关注最坏 1%)?请综合考虑三个因素给出判断并说明理由:(a) 任务的安全攸关程度;(b) 你能采到的扰动样本量(\(\alpha\) 越高、尾部样本越少、估计越不稳,§U5.2);(c) 对性能的牺牲(\(\alpha\) 越高越保守)。
-
[思考题·超越 CVaR] IQN 可通过对 \(\tau\) 施加任意畸变函数 \(\beta(\tau)\) 实现任意畸变风险度量(§U5.4)。请设计一个具体机器人导航场景,其中单纯 CVaR("均匀平均最坏 \(\alpha\) 尾部"的阶跃畸变)不够用——你需要对"中等坏"和"极端坏"赋予不同的、非阶跃的权重。说明你会选什么形状的 \(\beta(\tau)\)、为什么,以及它相比 CVaR 多表达了什么风险态度。
累积项目:统一不确定性导航测试台 + 风险敏感模块¶
延续 Part-U 的累积项目——一个 2D 双积分器机器人在带不确定性的环境里导航的统一测试台。前几章给它装了鲁棒(U2)、机会约束(U3)、分支(U1)、POMDP 信念(U4)四个范式。本章给它加装**第五个、也是收官的范式:风险敏感(CVaR)尾部约束**,主干测试台不动,只新增一个安全约束模块。
本章新增模块:给测试台的扰动模型换成**混合高斯**(大部分时候是小扰动,偶发一个大扰动——模拟"罕见但严重"的重尾,这正是 CVaR 大显身手、机会约束失明的场景)。然后在规划器里加两个可切换的安全约束写法:
- 机会约束版(复用 U3):\(\Pr(\text{碰撞代价} > 0)\le\delta\)。
- CVaR 版(本章):\(\mathrm{CVaR}_{1-\delta}(\text{碰撞代价})\le\) 阈值,用 Rockafellar–Uryasev 辅助变量嵌进 MPC 的 QP(§U5.2 + §U5.5)。
实验设计与该测什么(评估指标):用蒙特卡洛跑两种约束下的闭环,对比——(1)碰撞频率(两者都应达标 \(\le\delta\),验证 CVaR 至少不比 CC 差,因为 CVaR 约束更强);(2)碰撞代价的尾部均值(CVaR\(_{0.95}\) of 碰撞代价,CVaR 约束应明显更低——这是核心,证明 CVaR 控住了"一旦碰撞有多严重"而 CC 对此失明,§U5.1 场景二的活例);(3)任务完成时间 / 路径长度(CVaR 更保守,可能略慢——量化"为控尾部付出的性能代价");(4)\(\alpha\) 扫描:把 CVaR 的 \(\alpha\) 从 0.9 扫到 0.99,看尾部代价随 \(\alpha\) 升高如何下降、性能如何随之牺牲、以及高 \(\alpha\) 下估计稳定性如何变差(呼应 §U5.2 的"\(\alpha\) 越高越需要更多样本")。这组指标把 §U5.1(CVaR vs VaR/期望)、§U5.2(RU 嵌 QP)、§U5.5(CVaR-MPC vs CC-MPC)全变成可观测的数字。
预期实验结果(基于实现五的真实数字组织):跑完上述蒙特卡洛,你应当看到类似下表的对照(具体数值随实现细节变,但定性结论稳健):
| 指标 | 机会约束 MPC | CVaR-MPC | 解读 |
|---|---|---|---|
| 碰撞频率 | ~3.2%(达标 ≤10%) | ~2.2%(达标) | 两者都达标,CVaR 略低——CVaR 约束更强 |
| 碰撞代价的 CVaR\(_{0.9}\) | ~0.87(高) | ~0.48(低) | 核心差异:CVaR 把尾部严重程度压低近一半 |
| 平均绕路 | ~0(不绕) | ~0.11(略绕) | CVaR 更保守,为压尾部付出的性能代价 |
这张表把本章主线变成可观测的数字:机会约束和 CVaR 在"碰撞频率"上几乎打平(都达标),却在"碰撞代价的尾部均值"上拉开近一倍——机会约束选择不绕路(碰撞概率已达标就停),CVaR 选择略微绕路把尾部严重程度压下来。这正是 §U5.1 场景二、§U5.5 主线的实证:机会约束对"碰撞有多重"失明,CVaR 看得见并控制它。把 \(\alpha\) 从 0.9 扫到 0.99,还会看到 CVaR-MPC 进一步压低尾部代价、绕路相应增加、且高 \(\alpha\) 下估计方差变大(呼应进阶八的样本量表)——这把全章的 \(\alpha\) 权衡也变成了可观测的曲线。
本质洞察:这个模块让测试台的不确定性处理从"管概率"升级到"管尾部严重程度",补齐 Part-U 安全谱的最后一块。前四章的模块处理的是"哪种不确定性"(动力学鲁棒 / 概率 / 交互 / 感知),本章模块处理的是一个正交的问题——给定不确定性,你对它的尾部担忧到什么程度。把扰动换成重尾混合高斯,正是为了暴露"期望 / 机会约束看不见、CVaR 看得见"的尾部——跑完这个实验,你会亲眼看到机会约束和 CVaR 在碰撞频率上打平、却在碰撞严重程度上拉开差距。这就是本章相对前几章的独特价值:它不是又一种"处理不确定性"的方法,而是给所有方法加上了一个"对尾部担忧程度"的旋钮。
方法选型决策指南¶
把本章的选择浓缩成可操作的决策。面对一个风险敏感规划问题,依次问:
第一层:我到底要不要风险敏感? - 任务可重试、单次失败代价小、纯探索 → 可能**不需要**风险厌恶(期望就够,过度保守反而一事无成)。 - 安全攸关、失败代价大且不可逆、罕见灾难致命 → **需要**风险敏感,往下走。
第二层:用机会约束还是 CVaR?(核心选择,见进阶二) - 只关心"达标率"、违反的后果都差不多严重 → 机会约束(U3)够用,约束更松、性能更好。 - 违反的后果**严重程度差异大**(轻碰 vs 撞毁)、要兼顾"概率 + 严重程度" → CVaR(更强、凸、一致、看尾部均值)。 - 扰动**有界**且要绝对硬安全 → 退到**鲁棒**(U2,CVaR \(\alpha\to1\) 的极限)。
第三层:单步还是多步?(见 §U5.3) - 单步 / 一次性决策 → 直接 §U5.2 的 CVaR-LP / QP。 - 多步序贯、要用 DP/RL 递推 → 嵌套 CVaR(时间一致、Bellman 成立);别用静态 CVaR 配每步重优化(行为抖动)。 - 坚持要"全程总代价 CVaR"的精确语义 → 静态 CVaR + 承诺执行 / 增广状态,接受不可递推。
第四层:怎么选 \(\alpha\)?(见 §U5.2、§U5.5 思考题) - \(\alpha\) 越接近 1 → 越保守(看越极端的尾部),但**估计越不稳定**(尾部样本越少)、性能牺牲越大。 - 经验起点:安全攸关取 \(\alpha=0.95\sim0.99\),并确保样本量让 \((1-\alpha)N\) 至少几十到上百。 - 拿不准 → 做 \(\alpha\) 扫描(如累积项目),看尾部代价 vs 性能 vs 估计稳定性的权衡曲线,按任务容忍度定。
第五层:CVaR 够不够,要不要更一般的畸变测度?(见 §U5.4 思考题) - CVaR 是"阶跃畸变"(只均匀平均最坏 \(\alpha\) 尾部)→ 多数情况够用。 - 需要对"中等坏"和"极端坏"赋予不同的、非阶跃权重 → 用更一般的**畸变 / 谱风险测度**,IQN 的 \(\tau\) 重采样可实现任意畸变 \(\beta(\tau)\)。
实现路径: - 算 / 约束 CVaR → Rockafellar–Uryasev LP / QP(§U5.2 实现一),Python 用 CVXPY 原型。 - 风险敏感 RL → 分布式 RL(IQN,§U5.4 实现三),风险态度后置成 \(\tau\) 采样旋钮。 - 上实时机器人 → CVaR-MPC(acados + RU 辅助变量)/ IQN 分位函数 ONNX 导出到 C++(§U5.5,生态空白、原创机会)。
任务特征 → 推荐范式速查表:
| 任务特征 | 推荐 | 理由 |
|---|---|---|
| 可重试、单次失败代价小、纯探索 | 期望(风险中性) | 不需要风险厌恶,过度保守反而低效 |
| 只关心达标率、违反后果都差不多 | 机会约束(U3) | 约束松、性能好,无需分布信息 |
| 违反后果严重程度差异大、安全攸关 | CVaR(本章) | 看尾部严重程度、凸、一致 |
| 扰动有界、要绝对硬安全 | 鲁棒(U2) | CVaR \(\alpha\to1\) 的极限,硬保证 |
| 分布本身估不准(sim-to-real) | 分布鲁棒 CVaR | 对分布估计误差也鲁棒(进阶十六、十九) |
| 多步序贯、要用 DP/RL | 嵌套 CVaR | 时间一致、Bellman 成立(§U5.3、进阶十七) |
| 高维图像观测、要端到端学 | 分布式 RL(IQN) | 学全分布、风险态度后置(§U5.4) |
| 要运行时动态调风险偏好 | Risk-Conditioned 策略 | \(\alpha\) 作为输入、一次前向切换(进阶十三) |
> 一句话决策:先判断要不要风险敏感(不是所有任务都要),再在"机会约束 ↔ CVaR ↔ 鲁棒"的谱上按"违反严重程度 + 可行性要求"选点,多步务必用嵌套 CVaR,\(\alpha\) 按"尾部容忍度 vs 样本量 vs 性能"权衡。¶
延伸阅读¶
按主题与难度分类,均已核实。先用一张时间线把这些工作的发展脉络串起来:
| 年份 | 工作 | 里程碑意义 |
|---|---|---|
| 1972 | Howard–Matheson | 风险敏感 MDP 开山,指数效用 / LEQG(γ 不直观) |
| 1999 | Artzner 等 | 一致性风险测度四公理(公理化革命) |
| 2000 | Rockafellar–Uryasev | CVaR 的 LP 可算化(α 可解释) |
| 2010 | Ruszczyński | 嵌套 CVaR / risk-averse Bellman(时间一致) |
| 2014–18 | Chow 等 | CVaR-MDP 的策略梯度 / actor-critic(数据驱动) |
| 2017 | Bellemare 等 (C51) | 分布式 RL 开端(学整个回报分布) |
| 2017 | Majumdar–Pavone | 机器人风险六公理(畸变风险度量) |
| 2018 | Dabney 等 (QR-DQN, IQN) | 分位表示 → IQN 的 τ 重采样暴露任意风险测度 |
| 2021 | Ahmadi–Ames | CVaR-CBF(嵌进安全滤波,Cassie 验证) |
| 2022–25 | DR-MPC / DSAC / Risk-Conditioned / 谱风险 DRL | 分布鲁棒、连续控制、运行时调 α、更一般测度 |
这条时间线就是本章的主线在文献上的投影——从"不直观的指数效用"(1972)到"公理化的 CVaR"(1999–2000)到"与 DP/RL 兼容"(2010–2018)到"落地机器人"(2021+)。下面按主题展开。
奠基论文(核心) - Artzner, Delbaen, Eber, Heath, "Coherent Measures of Risk", Mathematical Finance 9(3):203–228, 1999(DOI 10.1111/1467-9965.00068)——四公理的源头,§U5.1 的根基。⭐⭐⭐ - Rockafellar, Uryasev, "Optimization of Conditional Value-at-Risk", Journal of Risk 2(3):21–42, 2000——CVaR 的 LP 可算化,§U5.2 的核心。⭐⭐⭐ - Howard, Matheson, "Risk-Sensitive Markov Decision Processes", Management Science 18(7):356–369, 1972——风险敏感 MDP 开山,指数效用 / LEQG(进阶一)。⭐⭐⭐
动态风险与时间一致性(进阶) - Ruszczyński, "Risk-averse dynamic programming for Markov decision processes", Mathematical Programming 125:235–261, 2010——嵌套 CVaR / Markov 风险测度 / risk-averse Bellman,§U5.3 的核心。⭐⭐⭐⭐ - Shapiro, Dentcheva, Ruszczyński, Lectures on Stochastic Programming: Modeling and Theory, SIAM (2nd ed., 2014)——随机规划与动态风险测度的权威教材。⭐⭐⭐⭐
机器人风险(核心 → 进阶) - Majumdar, Pavone, "How Should a Robot Assess Risk? Towards an Axiomatic Theory of Risk in Robotics", ISRR 2017(Puerto Varas, Chile;arXiv:1710.11040)——机器人六公理 + 畸变风险度量,§U5.1 的机器人扩展。⭐⭐⭐ - Ahmadi, Xiong, Ames, "Risk-averse control via CVaR barrier functions: application to bipedal robot locomotion", IEEE Control Systems Letters (L-CSS) 6:878–883, 2021——CVaR-CBF,Cassie 验证,§U5.5 的核心。⭐⭐⭐ - Akella, Dixit, Ahmadi, Lindemann, Chapman, Pappas, Ames, Burdick, "Risk-aware robotics: tail risk measures in planning, control, and verification", IEEE Control Systems 45(4):46–78, 2025——风险感知机器人的最新综述,全景入口。⭐⭐⭐
分布式 RL(核心 → 进阶) - Bellemare, Dabney, Munos, "A Distributional Perspective on Reinforcement Learning", ICML 2017(arXiv:1707.06887)——C51,分布式 RL 开端,§U5.4。⭐⭐⭐ - Dabney, Rowland, Bellemare, Munos, "Distributional Reinforcement Learning with Quantile Regression", AAAI 2018(arXiv:1710.10044)——QR-DQN,§U5.4。⭐⭐⭐ - Dabney, Ostrovski, Silver, Munos, "Implicit Quantile Networks for Distributional Reinforcement Learning", ICML 2018(arXiv:1806.06923, PMLR 80:1096–1105)——IQN,\(\tau\) 重采样 = 任意畸变风险度量,§U5.4 的核心。⭐⭐⭐⭐ - Bellemare, Dabney, Rowland, Distributional Reinforcement Learning, MIT Press, 2023(免费在线)——分布式 RL 权威教材,第 5 章(QR)、第 8 章(风险敏感)。⭐⭐⭐⭐
CVaR RL 理论(进阶 → 研究级) - Chow, Ghavamzadeh, "Algorithms for CVaR Optimization in MDPs", NeurIPS 2014——CVaR-MDP 的策略梯度。⭐⭐⭐⭐ - Chow, Tamar, Mannor, Pavone, "Risk-Sensitive and Robust Decision-Making: a CVaR Optimization Approach", NeurIPS 2015 / 相关 JMLR 工作——CVaR 与机会约束 / 鲁棒的统一。⭐⭐⭐⭐
开源代码:PKU-Alignment/omnisafe(Safe RL 框架,CVaR-CMDP)、PKU-Alignment/safety-gymnasium(CMDP 环境)、CVXPY(凸优化建模)、acados + CasADi(实时 MPC)。详见进阶专题三。
本章与后续章节的关系¶
| 后续 | 关系 | 本章铺垫的知识点 |
|---|---|---|
| Part-U 附录 | 附录汇总 Part-U 的统一测试台、五安全谱对照、跨章选型总表。本章是五安全谱的收官(尾部风险维),附录会把 U1–U5 五个范式在一张表里对齐 | 五安全谱中 CVaR 的定位(进阶五)、累积项目 CVaR 模块、方法选型决策指南 |
| U4 POMDP(回指) | U4 处理感知端不确定(belief),本章处理尾部风险——两者正交可叠加。"风险敏感的信念空间规划"(在 belief 上用 CVaR 目标)是两维结合,也是 U4 进阶专题八(风险敏感 POMDP)的展开 | belief 与尾部风险的正交性、risk-averse Bellman(§U5.3)与 belief-MDP 的结合 |
| U2/U3(回指) | 本章 §U5.5 的 CVaR-CBF/MPC 把 U2 的 CBF、U3 的机会约束统一进"安全条件可替换"的框架——同一 QP 骨架换不同安全条件写法 | 安全条件可替换(K21)、CVaR 是 CC 的公理化升级(进阶二) |
| RL / 世界模型方向 | 分布式 RL(§U5.4)是"学整个回报分布"的范式,为风险敏感 RL、分布式 actor-critic(如 DSAC)打底;与 U4 的 RSSM(摊销 belief)同属"超越点估计"的潮流 | C51/QR-DQN/IQN 三表示、IQN 的风险态度后置 |
把本章放回 Part-U 五安全谱,一张表看清它和其他章节的关系与分工:
| 章 | 处理的不确定性 | 核心数学对象 | 对尾部的态度 | 与本章(U5)的关系 |
|---|---|---|---|---|
| U2 鲁棒 | 动力学端(有界扰动) | tube / 最坏情况界 | 对最坏情况(最保守) | CVaR \(\alpha\to1\) 的极限;§U5.5 CVaR-CBF 是其软化 |
| U3 机会约束 | 动力学端(概率) | VaR / 违反概率 | 只看分位点(盲于严重程度) | CVaR 是其公理化升级(进阶二) |
| U5 CVaR | 动力学端(尾部) | CVaR(尾部均值) | 看尾部平均(中间地带) | 本章 |
| U4 POMDP | 感知端(状态看不清) | belief(分布) | 正交维度 | 可组合成"风险敏感信念空间规划" |
| U1 分支 | 交互端(他者意图) | 加权分支树 | 正交维度 | 正交可叠加 |
这张表把本章在 Part-U 的位置钉死:U2/U3/U5 处理**同一个**动力学端不确定性,按"对尾部担忧程度"排成连续谱(鲁棒最保守 → CVaR 中间 → 机会约束最松),由 \(\alpha\) 连续调节;U4/U1 处理**正交**的感知端 / 交互端维度,可与 U5 叠加。这正是 U0 五安全谱的核心图景,本章补上了"尾部风险"这块。
衔接 Part-U 附录与收官:本章把"对尾部担忧到什么程度"这一维补齐后,Part-U 的五安全谱就完整了——U2 鲁棒(对所有扰动)、U3 机会约束(高概率)、U5 CVaR(尾部平均)覆盖动力学端从最保守到中间的连续谱,U4 POMDP(感知端)、U1 分支(交互端)覆盖正交的不确定性维度。附录会把这五个范式在统一测试台上对齐、给出完整的跨范式选型总表,作为整个 Part-U 的收束。本章的方法选型决策指南是那张总表的"风险敏感"分支。
一个值得展开的组合——"风险敏感的信念空间规划"(U4 × U5):U4 处理"状态看不清"(belief),U5 处理"尾部风险",两者正交、可叠加。把它们结合:在 belief 上做规划时,不最大化期望回报,而对"belief 的不确定性 + 未来转移的随机性"联合施加 CVaR——即把 §U5.3 的 risk-averse Bellman 里的状态换成 belief、把一步期望换成"对 belief 和转移的一步 CVaR"。这样的机器人既"知道自己看不清"(belief),又"对看不清导致的尾部后果厌恶"(CVaR)——比如一个在烟雾中导航的机器人,既维护对障碍位置的 belief,又对"belief 错误导致碰撞"的尾部风险设防。这是 U4 进阶专题(风险敏感 POMDP)和本章的交汇点,也是综合练习第 3 题让你推导的方向。它说明 Part-U 的五个范式不是互斥的菜单,而是可以正交组合的维度——真实复杂任务往往要同时处理多个不确定性维度。¶
调参诊断:α、λ、N 怎么调¶
风险敏感规划有三个核心旋钮——\(\alpha\)(CVaR 尾部水平)、\(\lambda\)(均值–CVaR 权衡权重,进阶六)、\(N\)(场景 / 样本数)。它们怎么调、调坏了什么症状,集中在这里。
| 旋钮 | 调大的效果 | 调小的效果 | 常见调坏的症状 | 建议 |
|---|---|---|---|---|
| \(\alpha\)(尾部水平) | 看更极端的尾部、更保守 | 看较浅的尾部、更进取 | \(\alpha\) 太高:估计方差爆、约束不稳、可能不可行(§U5.2、进阶八) | 安全攸关 \(0.9\sim0.99\);确保 \((1-\alpha)N\) 至少几十 |
| \(\lambda\)(均值–CVaR 权重) | 更重视尾部、牺牲平均表现 | 更重视平均、接近风险中性 | \(\lambda\) 太大:策略过度保守、平均表现差到没用(进阶六) | 扫 \(\lambda\) 画有效前沿、按任务在前沿上选点 |
| \(N\)(场景 / 样本数) | CVaR 估计更准更稳 | 更快但估计方差大 | \(N\) 太小:CVaR 每次跑都跳、约束失真(§U5.2);\(N\) 太大:QP 变量 / 约束随 \(N\) 线性增长、求解慢(§U5.5) | 实时场景几十到一两百;权衡精度与速度 |
联动关系:\(\alpha\) 和 \(N\) 不独立——\(\alpha\) 越高,要保持同样的估计精度,\(N\) 要越大(有效尾部样本 \((1-\alpha)N\) 要够,进阶八)。所以"调高 \(\alpha\)"几乎总要伴随"调大 \(N\)",否则尾部估计不准、高 \(\alpha\) 形同虚设。
诊断流程:CVaR 行为异常时,先分清是"估计问题"还是"优化问题"——(1) 固定一个已知分布,单独测 CVaR 估计器(对不对、稳不稳,§U5.2 实现一),排除估计 bug;(2) 估计没问题再看优化——QP 是否可行(\(\alpha\) 太高 / 阈值太严会不可行,§U5.5)、是否凸(辅助变量是否正确,§U5.2);(3) 多步问题还要查静态 vs 嵌套是否用对(行为抖动多半是静态 + 每步重优化,§U5.3)。这个"先估计、后优化、再递推"的三步诊断顺序不是随意的——它和门禁 G2(知识/数值)→ G1(结构/约束)→ G4(多步逻辑)的层次对应:先确认数值算对(估计器),再确认优化结构对(凸性 / 可行性),最后确认多步语义对(静态 vs 嵌套)。按这个顺序排查,能快速定位 CVaR 实现里绝大多数问题。
本章各节关系¶
各节如何环环相扣:
| 节 | 解决什么 | 依赖 | 为后文铺垫 |
|---|---|---|---|
| §U5.1 四公理 | 什么样的风险度量讲道理;为什么 VaR 出局、CVaR 入选 | U3 机会约束、概率统计 | 全章地基(CVaR 的合法性) |
| §U5.2 CVaR-LP | CVaR 怎么算、怎么变成可嵌优化的凸形式 | §U5.1 CVaR 定义、凸优化 | §U5.5 嵌 MPC 的基础;实现一 |
| §U5.3 嵌套 CVaR | 多步怎么办;静态 CVaR 为何不可递推、嵌套如何修复 | §U5.2 一步 CVaR、DP/Bellman | §U5.4 动态 vs 静态的辨析;实现四 |
| §U5.4 分布式 RL | 数据驱动地学全分布、把风险态度后置 | §U5.1 畸变测度、§U5.3 动态 CVaR、RL | 实现三;C++ 部署的 IQN 导出 |
| §U5.5 CVaR-CBF/MPC | 怎么把 CVaR 落到真实安全工具 | §U5.2 CVaR-LP、U2 CBF、U3 机会约束 | C++ 部署;累积项目 |
主线串联:§U5.1 立地基(公理 → CVaR 合法)→ §U5.2 可算化(变分 → LP)→ §U5.3 序贯化(嵌套 → Bellman)→ §U5.4 数据化(分布式 RL → 风险态度后置)→ §U5.5 工程化(嵌 CBF/MPC)。五节是"度量 → 算 → 递推 → 学 → 用"的完整链条。
FAQ¶
Q1:CVaR 和期望、VaR 到底差在哪,一句话说清? 期望看平均(罕见灾难被平均掉);VaR 看尾部从哪开始(不管尾部里多惨);CVaR 看尾部的平均严重程度(既知道尾部位置、又知道有多惨)。安全攸关、灾难严重程度差异大时用 CVaR(§U5.1)。
Q2:CVaR 是机会约束的"升级",那我以后都用 CVaR 不用机会约束? 不一定。CVaR 约束更强(更保守)、需要分布信息、计算稍重。如果你只关心"达标率"、违反后果都差不多严重,机会约束更简单、约束更松、性能更好。违反后果差异大才值得上 CVaR(进阶二、选型指南)。
Q3:为什么我多步 CVaR 规划的机器人行为一直抖动? 多半是用了静态 CVaR 目标 + 每步重优化——静态 CVaR 时间不一致,每步重优化给出互相矛盾的计划(§U5.3)。改用嵌套 CVaR(时间一致、可放心每步重规划),或静态 CVaR + 承诺执行整条计划。
Q4:分布式 RL 的 CVaR 贪心,是不是就最小化了整条轨迹的 CVaR? 不是。那是动态 / 迭代 CVaR(每步对未来分布施加),与静态 CVaR(对全程总量施加一次)理论上不一致(§U5.4、Lim–Malik 2022)。多数实时控制场景动态 CVaR 够用,但别声称它是静态 CVaR 最优。
Q5:我该选多大的 \(\alpha\)? 综合三点:安全攸关程度(越攸关越高)、样本量(\(\alpha\) 越高需越多样本,\((1-\alpha)N\) 要够)、性能容忍度(越高越保守)。安全攸关常 \(0.9\sim0.99\),拿不准就扫 \(\alpha\) 看权衡曲线(综合练习第 5 题、调参诊断)。
Q6:CVaR-MPC 上不了实时怎么办? Python + 通用求解器确实赶不上 kHz。把 RU 辅助变量嵌进 acados 生成 C 代码(SQP_RTI 实时迭代)、减小场景数 \(N\)、用 OSQP 这类实时 QP 求解器(从 Python 到 C++ 部署那节)。这块 C++ 生态空白,也是原创机会。
Q7:CVaR 给的是"绝对安全保证"吗? 不是。CVaR 控的是尾部的**平均**,不是最坏情况的绝对界——尾部内仍可能有更极端的个别违反(§U5.5)。要绝对硬安全(且扰动有界)用鲁棒(U2)。CVaR 是"鲁棒太保守 / 不可行"时的可行折中。
Q8:我的扰动是重尾的,用 CVaR\(_{0.9}\) 够吗? 要小心。重尾分布的危险只在高 \(\alpha\) 才暴露(实现八)——\(\alpha=0.9\) 可能还没探到那条肥尾巴,会低估危险。重尾场景建议用更高的 \(\alpha\)(如 0.95–0.99),并确保样本量够(\((1-\alpha)N\) 至少几十,进阶八)。先画 \(\alpha\) 扫描曲线看尾部代价何时开始陡增,据此定 \(\alpha\)。
Q9:分布式 RL 训练慢,我能不能只用 CVaR-LP / CVaR-MPC? 能,取决于你的问题。如果你有显式的扰动模型(能采样场景)、问题是优化 / 控制(不是从零学策略),那么 CVaR-MPC(§U5.5,用 RU 辅助变量 + 优化器)通常更直接、更快、更可解释,不需要训练。分布式 RL(§U5.4)适合"没有显式模型、要从交互中学"的场景(高维图像观测、复杂未知动力学)。两者不是二选一——很多系统用 CVaR-MPC 做底层安全控制、用分布式 RL 做高层决策。先看你有没有模型:有模型优先 CVaR-MPC,没模型 / 高维感知才上分布式 RL。
🔧 故障排查手册¶
风险敏感规划实现中最常见的故障,按"症状→可能原因→排查步骤→相关节"组织。
| 症状 | 可能原因 | 排查步骤 | 相关节 |
|---|---|---|---|
| CVaR 估计值明显偏小、且次可加性"被违反" | 对有原子(离散值)的损失用了朴素估计 mean(x[x>=VaR]) |
1. 检查损失分布是否有原子(大量样本取同一值)2. 换用 Rockafellar–Uryasev 公式或 LP 重算 3. 对已知解析 CVaR 的离散分布(如 4%→100,理论 80)测试估计器 | §U5.2 |
| CVaR-MPC 的 QP 不可行 / 无解 | \(\alpha\) 太接近 1(趋近鲁棒,对无界扰动无解)或约束阈值太严 | 1. 降低 \(\alpha\)(看没那么极端的尾部)2. 放松 CVaR 约束阈值 3. 检查扰动是否无界(无界 + \(\alpha\to1\) 必无解)4. 确认用的是 CVaR 约束而非最坏情况约束 | §U5.2、§U5.5 |
| CVaR 估计每次跑都大幅跳动 | 尾部样本太少(\(\alpha\) 高但 \(N\) 小,\((1-\alpha)N\) 不足) | 1. 算 \((1-\alpha)N\),若 < 几十则样本不足 2. 增大 \(N\) 3. 或降低 \(\alpha\) 4. 考虑重要性采样补尾部 | §U5.2 |
| 多步 CVaR 规划行为抖动 / 振荡 | 用静态 CVaR 目标 + 每步重优化(时间不一致的恶果) | 1. 确认用的是静态还是嵌套 CVaR 2. 改用嵌套 CVaR(时间一致、可放心每步重规划)3. 或静态 CVaR + 承诺执行整条计划 | §U5.3 |
| risk-averse 值迭代不收敛 / 发散 | 一步 CVaR 算子实现有误(如归一化错、\(\alpha\) 方向反) | 1. 单独测试一步 CVaR 算子(对已知分布核对)2. 确认 \(\gamma<1\)(折扣保证压缩)3. 检查 CVaR 的代价 / 回报方向是否一致 | §U5.3 |
| 分布式 RL 的 CVaR 贪心策略不如预期保守 | 把动态 CVaR 误当静态 CVaR,或 \(\tau\) 采样方向 / 区间错 | 1. 确认 \(\tau\) 采样区间(下尾风险厌恶应是 \(U(0,\alpha)\),注意回报 vs 代价方向)2. 明确你要动态还是静态语义 3. 检查 IQN 分位函数训练是否收敛 | §U5.4 |
| C51 算出的 CVaR 在极端尾部失真 | 回报范围 \([V_{\min},V_{\max}]\) 设太窄,尾部被截断 | 1. 检查实际回报是否触及范围边界 2. 放宽回报范围 3. 或换支撑自适应的 QR-DQN/IQN | §U5.4 |
| CVaR-CBF 调参后行为莫名其妙 | 两个 \(\alpha\)(CBF 系数 vs CVaR 水平)搞混了 | 1. 确认代码里区分了 \(\alpha_{\text{cbf}}\) 和 CVaR 的 \(\alpha\) 2. 分别单独调(\(\alpha_{\text{cbf}}\) 调裕量恢复、CVaR \(\alpha\) 调尾部深度) | §U5.5 |
API 速查表¶
本章实现涉及的核心 API 与函数签名速查(Python 生态;CVaR-MPC 实时部分见下一节的 C++ 路径)。
NumPy / SciPy(CVaR 计算与 LP)
| API | 签名 / 用法 | 说明 |
|---|---|---|
np.quantile |
np.quantile(x, alpha) |
经验 \(\alpha\) 分位数 = VaR\(_\alpha\)。注意:百万样本上反复调用会慢,批量用 np.sort 一次后索引 |
np.maximum |
np.maximum(x - z, 0.0) |
逐元素 \((x-z)_+\),Rockafellar–Uryasev 公式的核心项 |
scipy.optimize.linprog |
linprog(c, A_ub, b_ub, bounds, method='highs') |
解 CVaR 的 SAA-LP;method='highs' 是当前推荐求解器 |
np.sort |
np.sort(x) |
排序一次得经验分位函数,避免反复 np.quantile(IQN 演示用) |
CVXPY(凸优化建模,推荐用于 CVaR-LP/SOCP 原型)
| API | 用法 | 说明 |
|---|---|---|
cp.Variable |
z = cp.Variable(); u = cp.Variable(N, nonneg=True) |
声明决策变量;nonneg=True 直接施加 \(u_i\ge0\) |
cp.Minimize |
cp.Minimize(z + cp.sum(u)/((1-alpha)*N)) |
CVaR 的 RU 目标 |
cp.Problem |
cp.Problem(obj, constraints).solve() |
构建并求解;约束里写 u >= x - z |
cp.pos |
cp.pos(x - z) |
\((x-z)_+\) 的直接建模(CVXPY 自动转辅助变量) |
PyTorch(IQN / 分布式 RL)
| API | 用法 | 说明 |
|---|---|---|
torch.rand |
tau = torch.rand(batch, N_tau) |
采样 \(\tau\sim U(0,1)\);风险敏感改成 tau = alpha * torch.rand(...) 即 \(U(0,\alpha)\) |
| 分位数 Huber 损失 | 自定义 pinball / quantile Huber loss | IQN/QR-DQN 的训练损失;对分位残差非对称加权 |
torch.onnx.export |
torch.onnx.export(model, args, "iqn.onnx") |
把训练好的分位函数网络导出,供 C++ 在线 CVaR 贪心(下一节) |
acados + CasADi(实时 CVaR-MPC,见下一节)
| 组件 | 用途 | 说明 |
|---|---|---|
casadi.SX / casadi.MX |
符号化构建 OCP 的代价 / 约束 | 把 RU 辅助变量 \(z,v_j\) 作为额外决策变量加入 |
acados_template.AcadosOcp |
定义最优控制问题 | 在 constraints 里加 CVaR 的线性约束行 |
AcadosOcpSolver |
实时求解 OCP | 生成 C 代码,毫秒级求解嵌 CVaR 的 QP |
说明:CVaR 的算法本身只用到
maximum/quantile/linprog这几个基础 API——它的"可算化"恰恰体现在不需要任何特殊库,标准 LP/QP 工具即可。复杂性在工程集成(嵌进 MPC、导出到 C++),而非算法本身。
从 Python 到 C++ 部署:填补 CVaR 实时落地的空白¶
本章反复提到 CVaR-MPC 的 C++ 生态几乎空白——这一节给出具体的部署路径,把教学用的 Python 原型推向 kHz 控制回路。这既是工程指南,也是 §U5.5 强调的原创贡献方向的落地清单。
为什么需要 C++:Python 原型与实时控制的鸿沟¶
§U5.2 的 CVaR-LP、§U5.5 的 CVaR-MPC 在 Python(CVXPY、scipy)里写起来很自然,适合验证算法、调通逻辑。但真实机器人的控制回路常跑在 kHz(足式机器人的 WBC、无人机的姿态环),每个周期只有几百微秒到几毫秒的预算——Python 的解释开销 + 通用求解器的非实时性,根本赶不上。要上车,CVaR 约束必须嵌进一个**为实时优化生成 C 代码**的求解器(acados、OSQP),且任何神经网络部分(IQN)要导出成 C++ 可加载的格式。这正是当前缺少成熟开源工具的环节。
路径一:CVaR-MPC 嵌进 acados(辅助变量法)¶
acados 把最优控制问题(OCP)编译成高效 C 代码。关键是把 §U5.5 那个 QP 里的 Rockafellar–Uryasev 辅助变量 \(z\)、\(\{v_j\}\) 作为**额外的决策变量**加进 OCP,把 CVaR 约束作为额外的线性约束行。用 CasADi 符号化构建:
# CVaR-MPC 嵌进 acados 的骨架(伪代码级, 展示如何加辅助变量与约束)
import casadi as ca
from acados_template import AcadosOcp, AcadosOcpSolver
# 1) 状态/控制 + CVaR 辅助变量(作为额外"控制"或参数化变量加入)
x = ca.SX.sym('x', nx) # 机器人状态
u = ca.SX.sym('u', nu) # 控制
z = ca.SX.sym('z', 1) # RU 辅助标量(会自动解到 VaR)
v = ca.SX.sym('v', N_scenario) # 每条扰动场景的辅助变量
# 2) CVaR 约束: z + 1/((1-alpha)*N) * sum(v_j) <= kappa
# 以及 v_j >= c_collision_j - z, v_j >= 0
alpha, kappa = 0.95, threshold
cvar_expr = z + ca.sum1(v) / ((1 - alpha) * N_scenario)
g_cvar = cvar_expr - kappa # <= 0
g_vj = [c_collision[j] - z - v[j] for j in range(N_scenario)] # <= 0 (v_j >= c_j - z)
# v_j >= 0 通过 acados 的变量下界 lbx/lbu 施加
# 3) 把 g_cvar, g_vj 作为 OCP 的非线性约束 (con_h), 标称代价/动力学照常
ocp = AcadosOcp()
ocp.model.con_h_expr = ca.vertcat(g_cvar, *g_vj) # 全部 <= 0 的约束
ocp.constraints.lh = -1e9 * np.ones(...) # 下界(松)
ocp.constraints.uh = np.zeros(...) # 上界 0 (<= 0)
# ... 设置标称二次代价 W、动力学 f、求解器选项(SQP_RTI 实时迭代) ...
solver = AcadosOcpSolver(ocp) # 生成 C 代码, 毫秒级求解
要点:(1) 辅助变量 \(z,v_j\) 维度随场景数 \(N\) 线性增长,\(N\) 太大 QP 会变慢——实时场景下 \(N\) 通常取几十到一两百,权衡尾部估计精度与求解速度;(2) 用 acados 的 SQP_RTI(实时迭代)模式,每周期只做一次 SQP 迭代,保证实时;(3) 扰动场景 \(\{c_{\text{collision}}^{(j)}\}\) 要预先采好(整条轨迹场景,§U5.5 编程陷阱)传进求解器作参数。这条路把 §U5.5 的 QP 从 Python 原型变成可上车的 C 代码。
路径二:IQN 分位函数导出到 C++(ONNX / TorchScript)¶
§U5.4 的 IQN 在 PyTorch 里训练,但在线 CVaR 贪心要在 C++ 控制器里跑。两条导出路径:
# 路径 2a: 导出为 ONNX, C++ 端用 ONNX Runtime 加载
import torch
iqn_model.eval()
# 输入: 状态 s 与分位水平 tau; 输出: 分位值 psi(s,a,tau)
dummy_s = torch.randn(1, state_dim)
dummy_tau = torch.rand(1, n_tau) # 在线时改成 alpha*rand 即 CVaR 采样
torch.onnx.export(
iqn_model, (dummy_s, dummy_tau), "iqn_quantile.onnx",
input_names=["state", "tau"], output_names=["quantile_values"],
dynamic_axes={"tau": {1: "n_tau"}}, # 允许在线改采样数
)
# 路径 2b: 或导出 TorchScript, C++ 端用 libtorch 加载
scripted = torch.jit.script(iqn_model)
scripted.save("iqn_quantile.pt")
C++ 端(ONNX Runtime 或 libtorch)加载后,在线做 CVaR 贪心的逻辑极简:对每个候选动作 \(a\),采 \(\tau\sim U(0,\alpha)\)(下尾、风险厌恶),前向得分位值 \(\psi(s,a,\tau)\),取均值作为该动作的 CVaR 值,选 CVaR 最优的动作。风险态度的旋钮(\(\tau\) 采样区间)完全在 C++ 端控制,无需重新训练或重新导出——这正是 §U5.4 "风险态度后置"在部署层面的兑现。
这块为什么是真实的原创机会¶
把上面两条路径做成一个**干净、可复用的开源库**(CVaR-MPC 的 acados 封装 + IQN 分位函数的 C++ 推理 + CVaR 贪心),目前在开源生态里是缺失的。CVaR 的理论(§U5.1–§U5.2)和 Python 原型(实现一至三)都成熟,分布式 RL 的训练框架(OmniSafe 等)也有,唯独"训练好之后高效部署到实时 C++ 控制器"这一环没有成熟工具。对想做开源贡献的学习者,这不是造重复的轮子,而是填一块真实的、有明确用户(做实时风险敏感控制的机器人团队)的空白——本章给的两条路径就是起点。
本质洞察:CVaR 落地的瓶颈不在算法、不在训练,而在"实时 C++ 部署"这最后一公里。回顾全章:度量(§U5.1 公理)、可算化(§U5.2 LP)、多步(§U5.3 嵌套)、学习(§U5.4 分布式 RL)、嵌入(§U5.5 CVaR-MPC/CBF)——理论链条完整且成熟。Python 生态(CVXPY、scipy、PyTorch、OmniSafe)也齐备。但这些都停在"能验证、能训练",没跨到"能在 kHz 控制回路里实时跑"。这最后一公里——把 RU 辅助变量塞进 acados 生成 C 代码、把 IQN 分位函数导出到 C++ 做在线贪心——恰恰是开源空白。这给学习者一个清晰的定位:风险敏感规划的"科学"已基本就绪,缺的是"工程落地"的临门一脚,而这一脚的价值(让真实机器人用上风险敏感安全)和难度(实时优化 + 神经网络部署)都足够撑起一个有影响力的开源项目或研究方向。
结语¶
风险敏感规划给不确定性规划补上了一块被"期望最优"长期忽视的拼图:当罕见但严重的尾部事件足以致命时,如何理性地度量并优化它,而不被平均值掩盖、也不被"达标概率"的视角蒙蔽。本章的主线清晰而统一——从期望的尾部盲区和 VaR 的结构缺陷出发,用 Artzner 的一致性公理立下"什么样的风险度量讲道理"的标准(把选择从主观偏好变成数学必然),用 Rockafellar–Uryasev 的辅助变量把 CVaR 变成可嵌进优化的凸形式,用 Ruszczyński 的嵌套构造让风险与动态规划兼容,用分布式 RL 把风险态度解耦成对回报分布的一次重加权,最后用 CVaR-CBF/MPC 让这一切落到真实的安全滤波与模型预测控制上。
对机器人安全工程师,本章最该带走的是:风险态度不是拍脑袋的工程口味,而是有公理依据、有可算形式、有连续旋钮(\(\alpha\))的可辩护选择——当你向同事或审查者解释"为什么用 CVaR 不用碰撞概率"时,次可加性和"看尾部严重程度"就是你的论据。对做 RL / 世界模型的读者,最该带走的是:分布式 RL 不是又一个刷分技巧,而是"学整个分布、风险态度后置"的范式转变——它在不牺牲 Bellman 收敛性的前提下,把算任意风险测度所需的信息一路保留到决策阶段,IQN 的 \(\tau\) 旋钮把这一点做到了极致。
回到 U0 的五安全谱:U5 占据"尾部风险"这一维——它在动力学端的安全谱上正好卡在鲁棒(对所有扰动)和机会约束(看分位点)之间,由 \(\alpha\) 连续调节"对尾部担忧到什么程度";它与 U4(感知端 belief)、U1(交互端意图)处理的是正交的不确定性维度,可层层叠加成"风险敏感的信念空间规划"这样的组合。至此,Part-U 的五安全谱——U2 鲁棒、U3 机会约束、U5 CVaR、U4 POMDP、U1 分支——五块拼图集齐。接下来的 **Part-U 附录**会把这五个范式在统一测试台上对齐、给出完整的跨范式选型总表,作为整个不确定性规划方向的收束。而本章指出的那块 C++ 实时部署空白,则留给你去填——风险敏感规划的科学已经就绪,等的正是把它送上真实机器人的那临门一脚。
最后给三句叮嘱,是本章最容易被忽略、却最影响实战的点。其一,风险态度是一个需要主动选择的维度,不是默认的"风险中性"——动手任何机器人决策前,先问"这个任务在乎尾部吗",别不假思索地用期望。其二,多步问题务必分清静态与嵌套 CVaR——这是文献和实现里最大的混淆源,用错(静态目标 + 每步重优化)会让机器人朝令夕改。其三,\(\alpha\) 不是越高越好——它越高越保守、但估计越不稳、性能越牺牲,要按任务的"后果严重度 × 样本量 × 效率要求"权衡,甚至按场景动态调。把这三点刻进肌肉记忆,你就能避开风险敏感规划最常见的坑,真正用好这把"度量并优化尾部"的利器。Part-U 的旅程到此告一段落——从 U2 的鲁棒到 U5 的尾部风险,你已经有了一整套在不确定性下做安全决策的工具;接下来的附录会把它们汇成一张可随时查阅的总图。¶
研究实践建议¶
分层次的上手 / 深入建议:
- 入门(建立直觉 + 跑通):读 §U5.1–§U5.2 + 跑本章实现一、二(CVaR 三算法、尾部敏感性);亲手验证朴素估计的原子坑、CVaR 看穿重尾。理解"期望盲区 → 公理 → CVaR → RU 可算化"这条主线。
- 理论(补齐基础):读 Artzner 1999 + Rockafellar–Uryasev 2000 原文;读 Ruszczyński 2010 理解时间一致性(§U5.3 最易踩坑);读《Distributional RL》第 5、8 章。重点搞清"静态 vs 嵌套 / 动态 CVaR"的区分——这是文献里最大的混淆源。
- 动手 Safe RL:跑 OmniSafe 的 CVaR-CMDP + Safety-Gymnasium 环境;实现本章实现三(IQN 风险态度切换),亲手感受"同一分位函数、改 \(\tau\) 采样 = 切风险态度"。
- 动手 CVaR-MPC:用 CVXPY 把 §U5.2 的 CVaR-LP 嵌进一个小 MPC(§U5.5 练习一),蒙特卡洛对比 CVaR-MPC vs 机会约束 MPC 的尾部控制(累积项目)。
- 研究切入(填空白):从进阶四的开放问题挑——C++ 高效 CVaR-MPC(acados + RU 辅助变量)、IQN 分位函数 ONNX 导出到 C++、嵌套 CVaR Bellman 的高效求解。这些是真实的 C++ 生态空白,有显著教育和开源价值。
- 避坑:分清静态 vs 嵌套 CVaR(§U5.3/§U5.4);原子分布用 RU 不用朴素平均(§U5.2);高 \(\alpha\) 要大样本(§U5.2);两个 \(\alpha\) 别搞混(§U5.5);CVaR 不是硬保证(§U5.5)。
版本信息速查¶
本章引用的关键工作与版本(便于查证):
| 对象 | 版本 / 年份 / 出处 |
|---|---|
| 一致性风险测度四公理 | Artzner-Delbaen-Eber-Heath, Mathematical Finance 9(3):203–228, 1999, DOI 10.1111/1467-9965.00068 |
| CVaR 的 LP 优化 | Rockafellar-Uryasev, Journal of Risk 2(3):21–42, 2000 |
| 风险敏感 MDP(指数效用) | Howard-Matheson, Management Science 18(7):356–369, 1972 |
| 嵌套 CVaR / Markov 风险测度 | Ruszczyński, Mathematical Programming 125:235–261, 2010 |
| 机器人风险六公理 | Majumdar-Pavone, ISRR 2017(Puerto Varas, Chile), arXiv:1710.11040 |
| C51(分布式 RL) | Bellemare-Dabney-Munos, ICML 2017, arXiv:1707.06887 |
| QR-DQN | Dabney-Rowland-Bellemare-Munos, AAAI 2018, arXiv:1710.10044 |
| IQN | Dabney-Ostrovski-Silver-Munos, ICML 2018, arXiv:1806.06923, PMLR 80:1096–1105 |
| CVaR-CBF | Ahmadi-Xiong-Ames, IEEE L-CSS 6:878–883, 2021 |
| 分布式 RL 教材 | Bellemare-Dabney-Rowland, MIT Press, 2023 |
| 风险感知机器人综述 | Akella et al., IEEE Control Systems 45(4):46–78, 2025 |
| OmniSafe | PKU-Alignment/omnisafe, Apache-2.0, Python |
| Safety-Gymnasium | PKU-Alignment/safety-gymnasium, MIT, Python |