Files
2026-05-18 19:02:23 +08:00

376 lines
17 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>同伦策略迭代 (Homotopic PI) — Deep NN 实现</title>
<script>
window.MathJax = {
tex: {
inlineMath: [['$', '$'], ['\\(', '\\)']],
displayMath: [['$$', '$$'], ['\\[', '\\]']],
tags: 'ams'
}
};
</script>
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
<style>
:root {
--bg: #fdfdfc;
--card-bg: #ffffff;
--text: #2c2c2c;
--text-secondary: #5a5a5a;
--accent: #2563eb;
--accent-light: #eff6ff;
--border: #e5e7eb;
--radius: 10px;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
background: var(--bg);
color: var(--text);
font-family: 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', 'Noto Sans SC', system-ui, -apple-system, sans-serif;
line-height: 1.78;
font-size: 16px;
-webkit-font-smoothing: antialiased;
}
.container { max-width: 820px; margin: 0 auto; padding: 48px 24px 80px; }
.paper-meta {
background: var(--card-bg);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 28px 32px;
margin-bottom: 40px;
}
.paper-meta h1 { font-size: 1.5rem; font-weight: 700; line-height: 1.4; margin-bottom: 6px; color: #111; }
.paper-meta .sub { font-size: 0.9rem; color: var(--text-secondary); }
h2 { font-size: 1.22rem; font-weight: 700; margin: 48px 0 16px; padding-bottom: 8px; border-bottom: 2px solid var(--border); color: #111; }
h3 { font-size: 1.05rem; font-weight: 700; margin: 34px 0 12px; color: #222; }
p { margin-bottom: 14px; }
.math-block { overflow-x: auto; padding: 4px 0; }
code {
font-family: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace;
font-size: 0.9em;
background: #f3f4f6;
padding: 1px 6px;
border-radius: 4px;
color: #1e40af;
}
pre {
background: #1e1e2e; color: #cdd6f4;
padding: 16px 20px; border-radius: var(--radius);
overflow-x: auto; font-size: 0.85rem; line-height: 1.6;
margin: 16px 0;
}
blockquote {
margin: 20px 0;
padding: 16px 22px;
border-radius: var(--radius);
border-left: 4px solid var(--accent);
background: var(--accent-light);
font-size: 0.94rem;
}
blockquote p { margin-bottom: 8px; }
blockquote p:last-child { margin-bottom: 0; }
blockquote strong { color: var(--accent); }
blockquote.danger { border-left-color: #dc2626; background: #fef2f2; }
blockquote.danger strong { color: #dc2626; }
blockquote.definition { border-left-color: #7c3aed; background: #faf5ff; }
blockquote.definition strong { color: #7c3aed; }
blockquote.algorithm { border-left-color: #059669; background: #ecfdf5; }
blockquote.algorithm strong { color: #059669; }
blockquote.proof { border-left-color: #d97706; background: #fffbeb; }
blockquote.proof strong { color: #d97706; }
blockquote.key { border-left-color: #db2777; background: #fdf2f8; }
blockquote.key strong { color: #db2777; }
blockquote.impl { border-left-color: #0891b2; background: #ecfeff; }
blockquote.impl strong { color: #0891b2; }
.danger-box {
margin: 18px 0;
padding: 16px 22px;
border-radius: var(--radius);
border: 1px solid #fecaca;
background: #fef2f2;
font-size: 0.94rem;
}
.danger-box .label { font-weight: 700; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.04em; color: #dc2626; margin-bottom: 6px; }
ol.alg { counter-reset: step; list-style: none; padding-left: 0; margin: 12px 0; }
ol.alg > li { counter-increment: step; position: relative; padding-left: 42px; margin-bottom: 14px; }
ol.alg > li::before {
content: counter(step);
position: absolute; left: 0; top: -1px;
width: 28px; height: 28px;
background: var(--accent); color: #fff;
font-size: 0.82rem; font-weight: 700;
border-radius: 50%;
display: flex; align-items: center; justify-content: center;
}
ol.alg ul { margin: 6px 0 0 0; padding-left: 20px; list-style: disc; color: var(--text-secondary); font-size: 0.93rem; }
ol.alg ul li { margin-bottom: 4px; }
hr { border: none; border-top: 1px solid var(--border); margin: 40px 0; }
.footer { margin-top: 56px; padding-top: 20px; border-top: 1px solid var(--border); font-size: 0.82rem; color: #b0b0b0; }
@media (max-width: 640px) {
.container { padding: 24px 16px 48px; }
.paper-meta { padding: 20px; }
h2 { font-size: 1.12rem; }
}
</style>
</head>
<body>
<div class="container">
<div class="paper-meta">
<h1>Adaptive Optimal Control of Unknown Nonlinear Systems via Homotopy-Based Policy Iteration</h1>
<div class="sub">Chen et al., IEEE Trans. Autom. Control, Vol. 69, No. 5, pp. 33963403, May 2024</div>
<div class="sub" style="margin-top:8px;"><strong>本实现:</strong>Deep NN 函数逼近器 (CriticNN + ActorNN),梯度下降训练 (Adam)</div>
</div>
<!-- ═══ 一 ═══ -->
<h2>一、这篇文章解决了什么问题?</h2>
<p>用强化学习做最优控制,本质上是在<strong>模型信息不完全</strong>的情况下,通过数据学习一个最优策略。Policy Iteration (PI) 的前提是必须先有一个 <strong>admissible policy</strong> 来启动迭代。但求解 admissible policy 本身需要模型信息——形成循环依赖。</p>
<div class="danger-box">
<div class="label">PI 的初始化困境</div>
PI 要求初始策略是 admissible 的 → 没有模型就算不出 admissible 策略 → 没有 admissible 策略就无法启动 PI → 无法启动 PI 就学不出最优策略。
</div>
<blockquote class="definition">
<strong>什么是 Admissible Policy</strong><br><br>
给定广义代价函数 $$ J(x_0) = \int_0^\infty \left[ Q(x) + u^T R(x) u \right] dt $$
称 $u(x)$ 是 <strong>admissible</strong> 的,当且仅当:对任意初始状态 $x_0$,$J(x_0)$ 有限,且系统状态被驱动到原点。
</blockquote>
<hr>
<!-- ═══ 二 ═══ -->
<h2>二、核心思想:同伦 (Homotopy)</h2>
<p>对原始系统动态方程做<strong>同伦变换</strong>,人为引入阻尼项:</p>
$$ \underbrace{\dot{x} = f(x) + g(x)u}_{\text{原始系统}} \quad\longrightarrow\quad \underbrace{\dot{x} = f(x) - L_i x + g(x)u_i(x)}_{\text{同伦系统}} $$
<p>加上 $-L_i x$ 之后,即使 <strong>$u = 0$</strong>(零控制),系统也是稳定的。$u=0$ 天然就是 admissible 的,PI 可以直接启动。然后逐步减小 $L_i$,让同伦系统逼近原始系统。当 $L_i$ 归零时,得到原系统下的 admissible 策略。</p>
<blockquote class="key">
<strong>关键点</strong><br>
同伦项 $-L_i x$ 是<strong>人工阻尼</strong>让系统自治稳定,不是去「抵消」未知动态 $f,g$。$f,g$ 的未知性通过 off-policy 积分消除 + 深度神经网络逼近来绕过。
</blockquote>
<hr>
<!-- ═══ 三 ═══ -->
<h2>三、数学原理</h2>
<h3>3.1 问题设定</h3>
$$ \dot{x} = f(x) + g(x)u $$
$$ \|f(z)-f(y)\| \le L_f\|z-y\|, \qquad \|g(z)-g(y)\| \le L_g\|z-y\| $$
控制目标:极小化 $ J(x_0) = \int_0^\infty \left[ Q(x) + u^T R(x) u \right] dt $
<strong>Hamiltonian 方程</strong>
$$ 0 = \left( \frac{\partial V}{\partial x} \right)^T \bigl( f(x) + g(x)u \bigr) + Q(x) + u^T R(x) u \tag{5} $$
<strong>最优策略解析形式</strong>
$$ u^*(x) = -\frac{1}{2} R^{-1}(x) g^T(x) \frac{\partial V(x)}{\partial x} \tag{6} $$
<strong>HJB 方程</strong>$V(0)=0$):
$$ 0 = \left( \frac{\partial V}{\partial x} \right)^T f(x) + Q(x) - \frac{1}{4} \left( \frac{\partial V}{\partial x} \right)^T g R^{-1} g^T \frac{\partial V}{\partial x} \tag{7} $$
<h3>3.2 传统 PI 方法</h3>
<blockquote class="algorithm">
<strong>Policy Iteration</strong>
<ol class="alg">
<li><strong>策略评估</strong><br>给定 $u_i^0$,求解 $V_i^0$$V_i^0(0)=0$):
$$ 0 = \left( \frac{\partial V_i^0}{\partial x} \right)^T \bigl( f + g u_i^0 \bigr) + Q + (u_i^0)^T R u_i^0 \tag{8} $$
</li>
<li><strong>策略改进</strong><br>
$$ u_{i+1}^0(x) = -\frac{1}{2} R^{-1} g^T \frac{\partial V_i^0}{\partial x} \tag{9} $$
</li>
</ol>
</blockquote>
<p>PI 保证 $V_{i+1}^0(x) \le V_i^0(x)$,收敛到最优解。前提:<strong>$u_0^0$ 必须是 admissible 的</strong></p>
<h3>3.3 同伦 PI 方法</h3>
<blockquote class="definition">
<strong>Definition 2 (Lipschitz Admissibility)</strong><br>
零控制 $u=0$ 是 <strong>Lipschitz admissible</strong> 的,如果存在 $L$ 使得 $\dot{x} = f(x) - Lx + g(x)u$ 渐近稳定。充分条件:$L > L_f$。
</blockquote>
<ul style="margin-bottom:14px; padding-left:22px;">
<li><strong>策略评估</strong>(同伦 Bellman 方程):
$$ 0 = \left( \frac{\partial V_i}{\partial x} \right)^T \bigl[ f - L_i x + g u_i \bigr] + Q + u_i^T R u_i \tag{12} $$
</li>
<li><strong>策略改进</strong>
$$ u_{i+1}(x) = -\frac{1}{2} R^{-1} g^T \frac{\partial V_i}{\partial x} \tag{13} $$
</li>
<li><strong>步长选取</strong>(保证收敛):
$$ (1-\gamma)Q\gamma_{i+1} \;\le\; \left( \frac{\partial V_i}{\partial x} \right)^T x \;\le\; (1-\gamma)(Q + u_{i+1}^T R u_{i+1}) + (u_i - u_{i+1})^T R (u_i - u_{i+1}) \tag{14} $$
</li>
</ul>
<blockquote class="proof">
<strong>收敛性保证</strong>
<ol style="margin:0;padding-left:20px;">
<li>$u_{i+1}$ 在同伦系统下是 admissible 的。</li>
<li>若 $(\frac{\partial V_i}{\partial x})^T x \ge \beta V_i(x)$,有限步内 $L_i = 0$。</li>
</ol>
</blockquote>
<hr>
<!-- ═══ 四 ═══ -->
<h2>四、数据驱动的同伦 PI — Deep NN 实现</h2>
<h3>4.1 Off-Policy 积分消除</h3>
<p>将系统重写为:$\dot{x} = \underbrace{f - L_i x + g u_i}_{\text{同伦系统}} \;+\; L_i x + g v_i \tag{18}$,其中 $v_i = u - u_i$ 是实际执行的 control(PE + 旧策略)与目标策略的偏差。</p>
<p>沿轨迹积分消去 $f,g$</p>
$$ V_i(x(t_{k+1})) - V_i(x(t_k)) - \int_{t_k}^{t_{k+1}} \left(\frac{\partial V_i}{\partial x}\right)^T L_i x\,dt
= -\int_{t_k}^{t_{k+1}} \Bigl[ Q + u_i^T R u_i + 2u_{i+1}^T R v_i \Bigr] dt \tag{20} $$
<blockquote class="key">
<strong>为什么能绕过 $f$ 和 $g$</strong><br>
$f,g$ 被 $V_i(x(t_{k+1})) - V_i(x(t_k))$ 隐式替代,等式仅含状态采样和待求函数。
</blockquote>
<h3>4.2 Deep NN 函数逼近</h3>
<p><strong>本实现用深度神经网络替代多项式基函数</strong>,彻底规避多项式带来的多重共线性问题(原多项式 cond(A) ~ 1e9,矩阵奇异)。</p>
<blockquote class="impl">
<strong>CriticNN — 值函数 $V(x) \ge 0$</strong><br><br>
<pre>Linear(2, 32, bias=False) → Tanh
Linear(32, 32, bias=False) → Tanh
Linear(32, 2, bias=False) # 原始输出 z₁, z₂
V(x) = z₁(x)² + z₂(x)² # 结构保证 V≥0, V(0)=0</pre>
<code>bias=False</code> 全程保证 $V(0)=0$(结构保证)。两个输出头使原点 Hessian 可达 rank-2。
</blockquote>
<blockquote class="impl">
<strong>ActorNN — 策略 $u(x): \mathbb{R}^2 \to \mathbb{R}$</strong><br><br>
<pre>Linear(2, 32, bias=True) → Tanh
Linear(32, 32, bias=True) → Tanh
Linear(32, 1, bias=True) # 有符号控制输出</pre>
</blockquote>
<h3>4.3 解耦损失函数(梯度下降替代矩阵求逆)</h3>
<blockquote class="impl">
<strong>Critic Loss — Bellman 残差</strong><br>
$$ \text{Loss}_C = \mathbb{E}\left[ \left( \Delta V_k - \textstyle\int \nabla V \cdot (Lx)dt + \textstyle\int (Q + R\hat{u}^2)dt + \textstyle\int 2R\hat{u}_{\text{new}} v\,dt \right)^2 \right] $$
Actor 输出被 <code>.detach()</code>,梯度仅流向 Critic。
</blockquote>
<blockquote class="impl">
<strong>Actor Loss — 最优策略回归</strong><br>
$$ \text{Loss}_A = \mathbb{E}\left[ \left( u_{\text{NN}}(x) - \left(-\frac{1}{2}R^{-1}g^T(x)\nabla V(x)\right) \right)^2 \right] $$
对倒立摆 ($J=1, R=1$)$u^* = -0.5 \cdot \partial V / \partial x_2$<br>
Critic 梯度被 <code>.detach()</code>,梯度仅流向 Actor。两个网络各有独立 Adam 优化器。
</blockquote>
<blockquote class="key">
<strong>为什么解耦?</strong><br>
原论文用线性系统 $A\theta = b$ 联合求解 Critic 和 Actor 权重。对于 NN,联合训练 Bellman 残差会导致 Actor 梯度通过积分项传播,噪声大且不稳定。解耦后 Actor 直接学习最优控制律 $u^* = -(1/2)R^{-1}g^T\nabla V$(策略改进公式 13),训练稳定且收敛快。
</blockquote>
<h3>4.4 算法三阶段</h3>
<blockquote class="algorithm">
<strong>Algorithm 1:完整执行流程</strong>
<ol class="alg">
<li>
<strong>Phase One — 寻找 L₀</strong>
<ul>
<li>用 $u =$ PE 信号(零策略)采集一条轨迹</li>
<li>扫描所有 $L \in [L_{\text{start}}, L_{\text{max}}]$,每个 L 训练独立 trainer</li>
<li>选取 <strong>Bellman 残差最低</strong> 的 L(而非第一个正定的 L</li>
<li>Critic 必须通过正定性检验:Hessian at origin PD + $V(x) \ge 0$ on trajectory</li>
</ul>
</li>
<li>
<strong>Phase Two — 同伦收缩至 $L=0$</strong>
<ul>
<li>用当前策略 + PE 采集新轨迹</li>
<li>解耦训练:Critic 极小化 Bellman 残差,Actor 回归最优控制律</li>
<li>用 safety constraint (14) 计算步长 $\alpha$$L \leftarrow \max(0, L - \alpha)$</li>
<li>PD 不通过 → 回退到 best weights;连续拒绝 > 15 次 → 提前终止</li>
</ul>
</li>
<li>
<strong>Phase Three — 标准 PI$L=0$</strong>
<ul>
<li>设 $L = 0$,用 Phase Two 策略作初始</li>
<li>交替 Critic 评估 + Actor 改进,直到 loss 收敛</li>
<li>输出 $u^*(x)$ 和 $V^*(x)$</li>
</ul>
</li>
</ol>
</blockquote>
<hr>
<!-- ═══ 五 ═══ -->
<h2>五、实现架构</h2>
<table style="width:100%; border-collapse:collapse; margin:16px 0; font-size:0.93rem;">
<tr style="background:#f3f4f6;">
<th style="padding:8px 12px; text-align:left; border:1px solid var(--border);">模块</th>
<th style="padding:8px 12px; text-align:left; border:1px solid var(--border);">文件</th>
<th style="padding:8px 12px; text-align:left; border:1px solid var(--border);">职责</th>
</tr>
<tr>
<td style="padding:8px 12px; border:1px solid var(--border);"><strong>NN 模型</strong></td>
<td style="padding:8px 12px; border:1px solid var(--border);"><code>hpi/nn_models.py</code></td>
<td style="padding:8px 12px; border:1px solid var(--border);">CriticNN, ActorNN, compute_q, check_positive_definite, check_lyapunov_decrease</td>
</tr>
<tr>
<td style="padding:8px 12px; border:1px solid var(--border);"><strong>训练器</strong></td>
<td style="padding:8px 12px; border:1px solid var(--border);"><code>hpi/nn_trainer.py</code></td>
<td style="padding:8px 12px; border:1px solid var(--border);">NNTrainer: 解耦 Critic/Actor 损失 + Adam 优化</td>
</tr>
<tr>
<td style="padding:8px 12px; border:1px solid var(--border);"><strong>控制器</strong></td>
<td style="padding:8px 12px; border:1px solid var(--border);"><code>hpi/hpi_controller.py</code></td>
<td style="padding:8px 12px; border:1px solid var(--border);">三阶段 HPI 主循环 + safety constraint</td>
</tr>
<tr>
<td style="padding:8px 12px; border:1px solid var(--border);"><strong>数据采集</strong></td>
<td style="padding:8px 12px; border:1px solid var(--border);"><code>hpi/data_collector.py</code></td>
<td style="padding:8px 12px; border:1px solid var(--border);">倒立摆仿真 + PE 信号生成</td>
</tr>
</table>
<hr>
<!-- ═══ 六 ═══ -->
<h2>六、总结</h2>
<h3>本文贡献</h3>
$$ \text{同伦阻尼 } L_i x \;\xrightarrow{\text{使 }u=0\text{ 稳定}}\; \text{Lipschitz admissible} \;\xrightarrow{\text{逐步归零 }L_i}\; \text{admissible} \;\xrightarrow{\text{传统 PI}}\; \text{最优策略} $$
<h3>本实现的改进</h3>
<ol style="padding-left:22px; margin-bottom:14px;">
<li><strong>Deep NN 替代多项式基函数</strong>:消除多重共线性 (cond(A) ~ 1e9),系统矩阵不再奇异</li>
<li><strong>梯度下降替代矩阵求逆</strong>Adam 优化 Bellman 残差 + 策略回归,规避病态线性系统</li>
<li><strong>解耦 Actor-Critic 训练</strong>Actor 直接回归 $u^* = -1/(2R)g^T\nabla V$,比联合求解更稳定</li>
<li><strong>Phase One 全扫描</strong>:扫描所有 L 取最低 loss,而非第一个正定的 L</li>
</ol>
<div class="footer">
笔记整理自 Chen et al., "Adaptive Optimal Control of Unknown Nonlinear Systems via Homotopy-Based Policy Iteration," IEEE TAC, 2024.<br>
本实现使用 Deep NN (PyTorch) 替代多项式基函数,梯度下降替代矩阵求逆。<br>
HPI 在所有测试初始状态下均稳定倒立摆,性能优于 LQR 基线。
</div>
</div>
</body>
</html>