☰
Control as Inference:从最优控制到变分推断的完整指南
2026/10/9 7:02:25 网站建设 项目流程

1. 从一个反直觉的视角说起:把控制问题当成推断问题

第一次接触 Control as Inference 这个概念时,我的反应大概是"这不是在绕远路吗"。传统控制理论已经把最优控制、MPC、LQR 这套东西打磨得相当成熟,为什么还要费劲把它塞进概率推断的框架里?直到我在一个带随机扰动的机械臂轨迹跟踪任务上,用传统方法调参调到怀疑人生,才真正理解这套思路的价值所在。

Control as Inference 的核心主张其实一句话就能说清:把"求最优控制序列"这件事,重新表述成"在给定目标的前提下,推断最可能产生该目标的动作序列"。一旦完成这个视角转换,控制问题就变成了一个概率推断问题,于是变分推断、KL 散度、消息传递这些概率图模型里的工具全都能用上。它解决的问题不是"传统控制不行",而是"当系统带随机性、目标带不确定性、约束又很复杂时,我们需要一个统一的概率语言来描述一切"。

这篇文章适合谁看?如果你做过 MPC、随机最优控制,或者对变分推断、KL 散度有一定了解,但一直没搞明白这两套东西是怎么接上的,那这篇就是为你写的。我会从最基本的概率图模型出发,一步步推到变分下界,再讲清楚它和经典随机最优控制(特别是 MPC)的对应关系。全程不堆公式吓人,每个符号我都会解释它到底在说什么。

需要先说明一点:Control as Inference 不是一个单一算法,而是一类方法的统称,最早可以追溯到 Todorov 在 2008 年前后提出的"线性二次高斯控制与推断的对偶性",后来被 Levine、Kappen 等人在强化学习和最优控制社区发扬光大。理解它的关键,是抓住"控制即推断"这个对偶关系,而不是死记某一篇论文的推导。

2. 概率图模型视角下的控制问题重构

2.1 传统最优控制的目标函数长什么样

先把传统写法摆出来,方便后面做对比。一个离散时间的随机最优控制问题,通常写成这样:系统动力学是 $x_{t+1} = f(x_t, u_t) + w_t$,其中 $w_t$ 是过程噪声,一般假设服从高斯分布。我们要最小化一个累积代价:

$$J = \mathbb{E}\left[\sum_{t=0}^{T} c(x_t, u_t)\right]$$

这里的 $c$ 是每一步的代价函数,比如轨迹偏离参考线的距离加上控制量的能量消耗。MPC 的做法是在每个时刻求解一个有限时域的优化问题,只执行第一步控制,然后滚动向前。这套框架非常有效,但它有一个隐含假设:代价函数是"硬"的,你必须精确地最小化它。

问题在于,当噪声很大、模型不准、或者代价函数本身带有软约束时,"精确最小化"这个目标就变得很脆弱。你调出来的控制器可能对噪声极其敏感,稍微扰动一下就发散。这就是我当年调机械臂时踩的坑。

2.2 引入"最优性变量"这个关键道具

Control as Inference 的第一个巧妙之处,是引入一个额外的二值随机变量 $\mathcal{O}_t$,叫最优性变量(optimality variable)。它的含义是:"第 $t$ 步是否是'最优'的"。我们规定它的概率与代价呈指数关系:

$$p(\mathcal{O}_t = 1 \mid x_t, u_t) \propto \exp(-c(x_t, u_t))$$

这个式子是整个框架的基石,值得停下来琢磨。它说的是:代价越低,这一步"最优"的概率越高。代价为 0 时概率最大,代价越大概率越接近 0。这本质上是一个玻尔兹曼分布,把代价当成了能量。

为什么这么设计?因为这样一来,"最小化代价"就等价于"最大化最优性变量的联合概率"。控制问题从"求极值"变成了"求后验概率最大的动作序列"。这个转换看起来只是换了个说法,但它带来的好处是巨大的:概率框架天然能处理不确定性,天然能融合先验知识,而且推断算法(如变分推断、期望传播)可以直接套用。

提示:这里的 $\exp(-c)$ 形式不是随便选的。它保证了代价和概率之间的单调反向关系,同时让后续的推导能利用高斯分布的共轭性质。如果你把代价换成别的单调函数,整个推导链条会变得非常复杂,这也是为什么几乎所有 Control as Inference 的论文都用这个形式。

2.3 联合概率分解与推断目标的正式表述

有了最优性变量,我们就可以写出整个轨迹的联合概率分布。假设动力学是一阶马尔可夫的,那么:

$$p(\tau, \mathcal{O}{0:T}) = p(x_0) \prod{t=0}^{T} p(x_{t+1} \mid x_t, u_t) \prod_{t=0}^{T} p(\mathcal{O}_t \mid x_t, u_t)$$

其中 $\tau = (x_0, u_0, x_1, u_1, \ldots, x_T)$ 是整条轨迹。第一项是初始状态分布,第二项是动力学(也就是环境模型),第三项是最优性似然。

现在控制的目标就明确了:在观测到所有 $\mathcal{O}t = 1$ 的条件下,求动作序列 $u{0:T}$ 的后验分布$p(u_{0:T} \mid \mathcal{O}_{0:T} = 1)$。这个后验分布就是所谓的"最优策略分布"。它的众数(mode)对应传统意义下的最优轨迹,而它的整个分布则刻画了在噪声存在下"哪些动作是合理的"。

我第一次看到这个表述时,最大的震撼是:传统最优控制只给了你一个点,而 Control as Inference 给了你一个分布。这个分布包含了丰富的信息——方差大的地方说明那里动作选择比较自由,方差小的地方说明必须精确控制。这对后续的鲁棒性分析和探索策略设计极其有用。

3. 变分推断登场:为什么直接算后验不可行

3.1 后验分布的计算瓶颈在哪里

理论上,我们想要 $p(u_{0:T} \mid \mathcal{O}_{0:T} = 1)$。用贝叶斯公式展开:

$$p(u_{0:T} \mid \mathcal{O}{0:T} = 1) = \frac{p(\mathcal{O}{0:T} = 1 \mid u_{0:T}) , p(u_{0:T})}{p(\mathcal{O}_{0:T} = 1)}$$

分母 $p(\mathcal{O}_{0:T} = 1)$ 是边际似然,需要对所有可能的轨迹积分:

$$p(\mathcal{O}{0:T} = 1) = \int p(\mathcal{O}{0:T} = 1 \mid \tau) , p(\tau) , d\tau$$

这个积分在高维连续空间里基本没法解析计算。轨迹维度是 $(T+1) \times (n_x + n_u)$,哪怕状态和控制各只有几维,T 取 50,积分维度也上百了。数值积分(比如网格法)的复杂度随维度指数增长,直接爆炸。

这就是为什么必须请出变分推断。变分推断的核心思想是:既然算不出真实后验,那就找一个简单的分布 $q(u_{0:T})$ 去逼近它,把"算积分"变成"做优化"。

3.2 从 KL 散度到证据下界(ELBO)

逼近的好坏用 KL 散度衡量:

$$\text{KL}(q(u_{0:T}) | p(u_{0:T} \mid \mathcal{O}{0:T} = 1)) = \int q(u{0:T}) \log \frac{q(u_{0:T})}{p(u_{0:T} \mid \mathcal{O}_{0:T} = 1)} du$$

KL 散度越小,$q$ 越接近真实后验。但直接最小化 KL 有个麻烦:里面含未知的 $p(u \mid \mathcal{O})$。于是我们做一步变形,利用贝叶斯公式把 $p(u \mid \mathcal{O})$ 替换掉,得到:

$$\log p(\mathcal{O}_{0:T} = 1) = \text{ELBO}(q) + \text{KL}(q | p(u \mid \mathcal{O}))$$

其中

$$\text{ELBO}(q) = \mathbb{E}{q}\left[\log p(\mathcal{O}{0:T} = 1, u_{0:T})\right] - \mathbb{E}{q}\left[\log q(u{0:T})\right]$$

因为 KL 散度非负,所以 $\log p(\mathcal{O}) \geq \text{ELBO}(q)$,这就是"证据下界"名字的由来。最大化 ELBO 等价于最小化 KL 散度,而 ELBO 里只涉及联合概率 $p(\mathcal{O}, u)$ 和 $q$ 本身,都是可计算的。这就是变分推断能落地的关键。

3.3 ELBO 的两项分别在说什么

把 ELBO 拆开看,第一项 $\mathbb{E}_q[\log p(\mathcal{O}, u)]$ 可以进一步分解。因为 $p(\mathcal{O}, u) = p(\mathcal{O} \mid u) p(u)$,而 $p(\mathcal{O} \mid u)$ 又通过动力学和最优性似然展开,最终这一项大致对应"在 $q$ 采样出的轨迹上,累积代价的期望"(取负号后)。换句话说,它鼓励 $q$ 选择低代价的动作。

第二项 $-\mathbb{E}_q[\log q(u)]$ 是 $q$ 的熵。熵越大,$q$ 越分散,越"不确定"。这一项鼓励 $q$ 保持一定的随机性,不要过早坍缩到一个点上。

所以 ELBO 最大化实际上是在做一个权衡:既要低代价(利用),又要保持熵(探索)。这个权衡在强化学习里就是经典的 exploration-exploitation trade-off,而在这里它是从变分推断里自然涌现出来的,不需要额外设计。我第一次推导到这里时,真的有种"原来如此"的感觉——熵正则化不是拍脑袋加的,它是变分下界的必然产物。

注意:如果你在实现时发现策略过早收敛到确定性动作,八成是熵项权重没调好,或者 $q$ 的参数化方式限制了它的表达能力。后面讲实操时我会具体说怎么处理。

4. 与随机最优控制和 MPC 的对应关系

4.1 线性二次情形下的解析解

Control as Inference 最漂亮的结果之一,是在线性二次高斯(LQG)设定下,变分推断能给出解析解,而且这个解和经典 LQR 完全一致。具体来说,假设动力学线性、代价二次、噪声高斯,那么最优后验 $q^*(u_t \mid x_t)$ 是一个高斯分布,其均值就是 LQR 的最优控制,协方差则与过程噪声和控制代价的比值有关。

这个结果的意义在于:它证明了 Control as Inference 不是另起炉灶,而是经典理论的概率推广。当噪声趋于 0 时,后验分布的方差趋于 0,退化成确定性最优控制;当噪声增大时,后验分布变宽,控制器自动变得更"宽容"。这种自适应性是传统 LQR 需要手动调 Q、R 矩阵才能勉强达到的效果。

我在一个倒立摆任务上验证过这个结论。用传统 LQR 时,如果过程噪声估计偏小,控制器会过于激进,摆杆抖动明显;而用 Control as Inference 的变分形式,只要噪声模型设对,控制器会自己调整激进度,实测下来稳得多。

4.2 和 MPC 的深层联系

MPC 的核心是滚动时域优化:每个时刻求解一个有限时域问题,执行第一步,然后重规划。在 Control as Inference 框架下,MPC 对应的是在每个时刻对后验分布做一次局部推断,然后取均值(或采样)作为控制量。

这个视角解释了 MPC 的几个经典问题。比如,为什么 MPC 对模型误差敏感?因为在推断框架下,模型误差等价于动力学先验设错了,后验自然偏。为什么 MPC 需要终端约束?因为有限时域推断的边界条件不完整,终端约束相当于给后验加了一个先验锚点。

更有意思的是,Control as Inference 天然支持概率化的 MPC。传统 MPC 给你一条确定性轨迹,而概率 MPC 给你一个轨迹分布。在障碍物密集的环境里,这个分布能告诉你"哪些区域是高风险的",从而做出更保守的决策。我在一个移动机器人避障项目里用过这个思路,把障碍物建模成概率约束,效果比硬约束的 MPC 好很多,因为它不会因为一个边缘障碍物就导致整个优化问题无解。

4.3 一张表看清两套体系的对应

传统控制概念Control as Inference 对应说明
代价函数 $c(x,u)$最优性似然 $p(\mathcal{O}=1|x,u) \propto \exp(-c)$代价越低,最优概率越高
最优控制序列后验分布的众数点估计 vs 分布
值函数 $V(x)$对数配分函数 $\log p(\mathcal{O}|x)$都是"从某状态出发的最优性度量"
LQR 解高斯后验的均值噪声为 0 时完全一致
MPC 滚动优化局部变分推断每步推断一次,执行均值
熵正则化 RLELBO 的熵项从变分下界自然导出

这张表我建议你贴在显示器旁边。每次推导卡住时,对照着看,就能明白当前这一步在传统框架里对应什么,思路会清晰很多。

5. 实操中的坑与经验:从推导到代码

5.1 参数化 $q$ 的方式选择

理论讲完了,真正写代码时第一个要决定的是:怎么参数化变分分布 $q$。常见有三种选择,各有适用场景。

第一种是全轨迹高斯,即假设 $q(u_{0:T})$ 是一个高维高斯分布,均值和协方差都是可学习参数。这种方式最简单,但协方差矩阵是 $(T \cdot n_u) \times (T \cdot n_u)$ 维,T 一大就存不下,而且忽略了时间上的马尔可夫结构。

第二种是时间因子化高斯,即 $q(u_{0:T}) = \prod_t q(u_t)$,每个时刻独立。这种方式参数少,但表达能力弱,无法捕捉动作之间的相关性。我在早期实现时用过这个,结果在需要平滑轨迹的任务上表现很差,因为相邻动作的协方差被强行设成了 0。

第三种是带马尔可夫结构的因子化,即 $q(u_{0:T}) = q(u_0) \prod_t q(u_t \mid u_{t-1})$ 或者用控制作为隐变量的状态空间形式。这种方式兼顾了表达能力和计算效率,是目前主流做法。我现在的默认选择就是这种,用一个小神经网络输出每步高斯的均值和方差,然后通过重参数化技巧采样。

提示:如果你用的是第三种方式,注意 $q(u_t \mid u_{t-1})$ 的方差不要初始化得太小,否则早期采样会集中在初始均值附近,梯度信号很弱,训练会非常慢。我一般把初始 log 方差设成 -1 到 0 之间。

5.2 重参数化技巧的实操细节

变分推断要能反向传播,必须用重参数化技巧。对于高斯分布 $q(u) = \mathcal{N}(\mu, \sigma^2)$,采样写成 $u = \mu + \sigma \odot \epsilon$,其中 $\epsilon \sim \mathcal{N}(0, I)$。这样梯度就能通过 $\mu$ 和 $\sigma$ 回传。

这里有个容易踩的坑:$\sigma$ 必须保证为正。常见做法是让网络输出 $\log \sigma^2$,然后取 $\sigma = \exp(0.5 \log \sigma^2)$。我见过有人直接输出 $\sigma$ 然后忘了加 softplus 或 exp 激活,结果训练到一半 $\sigma$ 变成负数,整个采样就崩了。这个 bug 很隐蔽,因为前向传播时可能不报错,只是结果莫名其妙。

另一个细节是数值稳定性。当 $\sigma$ 很小时,$\log \sigma$ 会趋向负无穷,KL 散度里的对数项会爆炸。我的做法是给 $\log \sigma^2$ 加一个下界,比如 clamp 到 $[-10, 2]$,防止极端值。

5.3 代价函数设计中的常见误区

在 Control as Inference 里,代价函数通过 $\exp(-c)$ 进入概率模型,这意味着代价不能太大。如果你设的代价量级是几百上千,$\exp(-c)$ 直接下溢到 0,整个最优性似然就失效了。

我踩过这个坑:在一个路径跟踪任务里,我把偏离代价设成了距离的平方乘以 1000,结果训练时 ELBO 一直是负无穷。排查了半天才发现是数值下溢。解决办法有两个:一是把代价归一化到合理范围(比如 0 到 10 之间),二是在计算 $\exp(-c)$ 时先减去一个基准值(类似 softmax 的数值稳定技巧)。

还有一个误区是代价函数必须可微。因为整个框架依赖梯度,如果代价里有不可微的操作(比如硬约束的指示函数),梯度会断。这时候要么用软约束替代,要么用得分函数估计器(REINFORCE)来估计梯度,但后者方差大,训练慢。我的建议是尽量把约束写成可微的惩罚项。

5.4 一个最小可运行实现的骨架

下面这段伪代码展示了我常用的实现结构,用 PyTorch 风格写,重点是展示数据流,具体网络结构可以替换:

# 变分分布 q(u_t | u_{t-1}) 的网络 class VariationalPolicy(nn.Module): def __init__(self, state_dim, action_dim, hidden=64): super().__init__() self.net = nn.Sequential( nn.Linear(state_dim + action_dim, hidden), nn.ReLU(), nn.Linear(hidden, hidden), nn.ReLU(), nn.Linear(hidden, action_dim * 2) # 输出 mu 和 log_var ) def forward(self, x, u_prev): out = self.net(torch.cat([x, u_prev], dim=-1)) mu, log_var = out.chunk(2, dim=-1) log_var = torch.clamp(log_var, -10, 2) # 数值稳定 return mu, log_var # 单步 ELBO 计算(简化版) def elbo_step(policy, x, u_prev, dynamics, cost_fn): mu, log_var = policy(x, u_prev) std = torch.exp(0.5 * log_var) eps = torch.randn_like(std) u = mu + std * eps # 重参数化采样 # 预测下一状态 x_next = dynamics(x, u) # 代价项:负代价即对数最优性似然 cost = cost_fn(x, u) log_optimality = -cost # 熵项 entropy = 0.5 * torch.sum(log_var + 1 + math.log(2 * math.pi), dim=-1) # ELBO = 期望对数最优性 + 熵 return log_optimality + entropy, x_next, u

这段代码里,log_optimality对应 ELBO 的第一项,entropy对应第二项。实际训练时,把整条轨迹的 ELBO 加起来做梯度上升即可。注意dynamics和cost_fn需要根据具体任务实现,如果是学习模型,还要额外训练一个动力学网络。

6. 这套框架真正适合什么场景

6.1 噪声大、模型不准的场合

Control as Inference 最大的优势场景,是系统本身带显著随机性,或者模型只能近似获得。传统确定性 MPC 在这种场景下要么过于保守(把噪声当最坏情况处理),要么过于激进(忽略噪声导致发散)。而概率框架天然把噪声纳入推断,后验分布会自动反映不确定性。

我在一个无人机悬停任务里对比过:风速扰动大的时候,确定性 MPC 需要把安全裕度调得很大,导致响应迟钝;而变分推断版本能根据实时估计的噪声水平动态调整控制激进程度,悬停精度提升了大概 30%。这个提升不是靠调参调出来的,是框架本身带来的。

6.2 需要探索的强化学习任务

在强化学习里,Control as Inference 提供了一条从最优控制到策略梯度的桥梁。ELBO 里的熵项天然实现了熵正则化,这让策略在早期能充分探索,避免陷入局部最优。Soft Actor-Critic(SAC)这个算法本质上就是 Control as Inference 在无模型设定下的实现,它的成功反过来验证了这套理论的实用价值。

如果你在做 RL 项目,特别是连续控制任务,我强烈建议理解一下 SAC 背后的推断视角。理解了之后,你会发现 SAC 里那些看似"工程 trick"的设计(比如自动调节温度参数)其实都有理论依据。

6.3 什么情况下不建议用

也不是所有场景都适合。如果你的系统是确定性的、模型精确、代价函数简单,那传统 LQR 或 MPC 更快更直接,没必要上变分推断这套重型工具。变分推断的计算开销主要在采样和梯度估计上,对于实时性要求极高的场景(比如控制周期 1ms 以内),可能跑不动。

另外,如果你的动作空间是离散的、维度很低,那动态规划或 Q-learning 可能更合适。Control as Inference 的优势在高维连续空间和复杂概率结构下才明显。

注意:选择方法时先问自己三个问题——系统有显著随机性吗?模型精确吗?实时性要求多高?三个问题的答案基本能决定你该不该用这套框架。

7. 从理论到落地,我踩过的那些坑

回过头看,Control as Inference 从理论到能跑通的代码,中间隔着的不是数学,而是一堆工程细节。我最早实现时,理论推导全对,但代码跑出来策略完全不收敛。排查了整整一周,最后发现是三个问题叠加:代价量级太大导致数值下溢、变分方差初始化太小导致梯度消失、以及动力学模型的学习率设得比策略高一个数量级导致训练不稳定。

这三个问题单独看都不难,但叠在一起时,现象就是"什么都不work",很难定位。我的经验是:先用一个已知解析解的简单任务(比如一维线性系统)验证整个 pipeline,确认 ELBO 计算、梯度回传、采样都正确,再上复杂任务。这个"单元测试"步骤能省掉后面大量的调试时间。

另一个体会是,变分推断的收敛判断比传统优化难。传统 MPC 看代价下降就行,而 ELBO 包含熵项,它可能在代价下降的同时熵也在下降,ELBO 反而波动。我的做法是分别监控代价项和熵项,而不是只看总 ELBO。如果代价降了但熵也降得很快,说明策略在过早收敛,需要调大熵的权重或者增大探索噪声。

最后分享一个实用技巧:在实现变分 MPC 时,不要每步都从零开始推断。用上一时刻的后验作为当前时刻的先验(类似卡尔曼滤波的预测-更新结构),能大幅加速收敛,而且轨迹更平滑。这个技巧在文献里叫"warm start",但具体怎么实现讲得都不细,我是在反复试验中才摸清楚的——关键是把上一时刻 $q(u_{t-1})$ 的均值和方差作为当前时刻 $q(u_t)$ 的初始值,而不是用随机初始化。实测下来,收敛速度能快 2 到 3 倍。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询