☰
控制即推断:从概率图模型到最大熵强化学习的统一框架
2026/10/15 13:43:31 网站建设 项目流程

1. 从“控制”到“推断”:一个视角的转换

第一次接触Control as Inference这个概念,是在啃一本强化学习的专著时。当时我正在做一个机械臂轨迹优化的项目,用传统的MPC(模型预测控制)框架调参调得头大——约束稍微紧一点,求解器就报无解;噪声大一点,控制量就抖得厉害。后来有人建议我看看“把控制问题当成推断问题”的思路,说实话,刚听到这个说法的时候我是懵的。控制和推断,一个是让系统按照我的意愿动,一个是从数据里猜真相,这俩怎么能是一回事?

但深入研究之后,我发现这个视角的转换不仅优雅,而且实用。它把随机最优控制问题重新解释为概率图模型中的后验推断问题,用变分推断、KL散度这些工具来求解。好处是什么呢?原本硬邦邦的优化问题,变成了一个可以处理不确定性、天然支持概率建模的框架。你不再需要显式地写一个代价函数然后求最小值,而是定义一个“最优性变量”,让推断算法自己去找到那条最可能产生最优行为的轨迹。

这篇文章主要面向有一定强化学习或最优控制基础的读者,比如做机器人控制、自动驾驶决策、或者序列决策相关工作的工程师和研究生。如果你正在用MPC做控制但被约束处理和噪声问题困扰,或者你想理解为什么变分推断会出现在控制文献里,那这篇内容应该能帮你把这条线索理清楚。我会从基本理论讲起,把概率图模型的构建、变分推断的推导、以及它和传统MPC的关系都拆开来讲,尽量让每一步的“为什么”都落到实处。

2. 为什么要把控制问题当成推断问题

2.1 传统最优控制的痛点在哪里

在经典的最优控制框架里,我们通常这样定义问题:给定一个动态系统 (x_{t+1} = f(x_t, u_t)),找一个控制序列 (u_{0:T-1}) 使得代价函数 (J = \sum_t c(x_t, u_t)) 最小。如果是随机系统,那就写成期望代价最小。这个框架很直观,数学上也成熟,MPC就是在这个基础上做滚动时域优化。

但实际用起来,有几个地方特别别扭。第一,约束处理很麻烦。硬约束容易导致不可行,软约束的权重又很难调。第二,不确定性传播困难。当系统噪声比较大的时候,你只能通过鲁棒MPC或者场景法来近似,计算量爆炸。第三,探索和利用的平衡在最优控制框架里没有自然的表达。你只能人为地加噪声或者设计探索策略,缺乏一个统一的概率框架。

我印象很深的一次经历是调一个无人车的横向控制器。路面附着系数变化导致模型不确定,用鲁棒MPC保守得不行,过弯速度慢得像蜗牛。后来换成基于采样的随机MPC,计算量又上去了。当时就想,有没有一种方法能把不确定性和控制目标统一在一个概率框架里?

2.2 概率图模型带来的新视角

Control as Inference的核心洞察是:我们可以把“最优控制”这件事,看成是在一个概率图模型里做后验推断。具体来说,引入一个二值的“最优性变量” (O_t),它表示在时刻 (t) 是否达到了最优。我们假设 (O_t = 1) 的概率与代价的负指数成正比,也就是 (p(O_t=1|x_t, u_t) \propto \exp(-c(x_t, u_t)))。代价越小,最优性变量为1的概率越大。

这样一来,整个系统的联合分布就可以写成:

[ p(\tau, O_{0:T}) = p(x_0) \prod_{t=0}^{T-1} p(x_{t+1}|x_t, u_t) p(O_t|x_t, u_t) ]

其中 (\tau = (x_{0:T}, u_{0:T-1})) 是轨迹。控制的目标就变成了:在给定 (O_{0:T}=1) 的条件下,求轨迹的后验分布 (p(\tau | O_{0:T}=1))。这个后验分布的均值或者众数,就是我们要找的最优控制序列。

这个转换的美妙之处在于,它把“优化”变成了“推断”。优化问题里的代价函数,变成了概率模型里的似然;约束变成了先验或者条件概率;不确定性自然地通过概率分布来表达。而且,一旦写成推断问题,我们就可以用变分推断、消息传递、蒙特卡洛这些成熟的工具来求解。

2.3 变分推断为什么适合这个框架

直接计算后验 (p(\tau | O_{0:T}=1)) 通常不可行,因为归一化常数涉及对所有可能轨迹的积分。变分推断的思路是:找一个简单的分布 (q(\tau)),让它尽可能接近真实后验。接近程度用KL散度来衡量:

[ \text{KL}(q(\tau) | p(\tau | O_{0:T}=1)) = \int q(\tau) \log \frac{q(\tau)}{p(\tau | O_{0:T}=1)} d\tau ]

最小化这个KL散度,等价于最大化证据下界(ELBO)。而ELBO可以写成:

[ \mathcal{L}(q) = \mathbb{E}{q(\tau)}[\log p(\tau, O{0:T}=1)] + \mathcal{H}(q) ]

其中 (\mathcal{H}(q)) 是熵。这个形式很有意思:第一项鼓励 (q) 把概率质量放在联合概率高的轨迹上,也就是代价低、动态可行的轨迹;第二项鼓励 (q) 保持一定的熵,也就是不要过早坍缩到单条轨迹,保持探索性。

我个人的理解是,这个熵项就是Control as Inference框架里“探索”的来源。在传统最优控制里,你要么手动加噪声,要么设计复杂的探索策略。而在这里,探索是变分推断的自然产物——因为你要最小化KL散度,就不能让 (q) 变成一个点质量,否则熵项会惩罚你。

3. 核心推导:从KL散度到可执行的控制算法

3.1 轨迹分布的因子分解

为了推导可执行的算法,我们需要对 (q(\tau)) 做因子分解。最常用的分解方式是:

[ q(\tau) = q(x_0) \prod_{t=0}^{T-1} q(x_{t+1}|x_t, u_t) q(u_t) ]

这里 (q(u_t)) 是控制量的变分分布,(q(x_{t+1}|x_t, u_t)) 通常假设等于系统的真实动态 (p(x_{t+1}|x_t, u_t)),因为动态模型是已知的。这个分解对应的是“控制作为推断”里的一个关键假设:我们只对控制序列做变分近似,状态轨迹由动态模型决定。

把联合分布和变分分布代入ELBO,经过一番推导(具体步骤可以参考Levine的教程),可以得到一个很直观的结果:最大化ELBO等价于最小化以下目标:

[ \mathcal{J}(q) = \mathbb{E}{q(\tau)} \left[ \sum{t=0}^{T-1} c(x_t, u_t) \right] - \sum_{t=0}^{T-1} \mathcal{H}(q(u_t)) ]

第一项是期望代价,第二项是控制分布的熵。所以,Control as Inference给出的控制律,是在最小化期望代价的同时,最大化控制熵。这其实就是“最大熵强化学习”的目标函数。如果你之前接触过Soft Actor-Critic或者最大熵逆强化学习,会发现这里的推导给出了它们的最优控制解释。

3.2 后向消息传递与前向采样

有了目标函数,下一步是怎么求解。由于动态模型已知,我们可以用动态规划的思想来做推断。具体来说,定义后向消息 (\beta_t(x_t)),它表示从时刻 (t) 到终端的最优性似然的期望。后向递归是:

[ \beta_t(x_t) = \mathbb{E}{q(u_t)} \left[ \exp(-c(x_t, u_t)) \mathbb{E}{p(x_{t+1}|x_t, u_t)} [\beta_{t+1}(x_{t+1})] \right] ]

终端条件 (\beta_T(x_T) = 1)。这个后向递归看起来像什么?如果你把 (\exp(-c)) 看成是“软”的即时奖励,把 (\beta) 看成是值函数,那这个递归就是软贝尔曼方程的变体。实际上,(\log \beta_t(x_t)) 就是软值函数。

有了后向消息,前向采样就简单了。在时刻 (t),给定状态 (x_t),最优控制分布是:

[ q(u_t) \propto \exp \left( -c(x_t, u_t) + \mathbb{E}{p(x{t+1}|x_t, u_t)} [\log \beta_{t+1}(x_{t+1})] \right) ]

这个分布就是“软最优”控制律。你可以从里面采样,也可以取众数作为确定性控制。如果取众数,就退化成传统的最优控制;如果采样,就保留了探索性。

3.3 与MPC的自然衔接

这个框架和MPC的衔接非常自然。MPC的核心思想是滚动时域:在每个时刻,求解一个有限时域的优化问题,只执行第一步控制,然后重新求解。在Control as Inference框架下,你可以在每个时刻做有限时域的后向消息传递,得到当前时刻的控制分布,采样或取众数后执行,然后移动到下一个时刻。

区别在于,传统MPC求解的是一个确定性优化问题,而这里求解的是一个概率推断问题。好处是,你可以自然地处理不确定性:后向消息传递里的期望操作,就是对不确定性的积分。如果动态模型有噪声,这个期望会自动把噪声考虑进去。另外,由于控制分布是概率的,你可以根据任务需求调整探索程度——比如在安全关键场景下取众数,在探索阶段采样。

我试过在一个简单的倒立摆任务上对比这两种方法。传统MPC在噪声小的时候表现很好,但噪声一大就抖得厉害。Control as Inference的方法在噪声大的时候反而更稳,因为它通过后向消息传递把未来的不确定性也考虑进去了。当然,计算量会大一些,因为要做期望。

4. 实操中的关键细节与避坑指南

4.1 数值稳定性:指数和对数域的切换

后向递归里有一个 (\exp(-c)) 和 (\log \beta) 的交替。代价函数通常是非负的,如果代价很大,(\exp(-c)) 会下溢到零;如果代价很小,(\log \beta) 又可能上溢。这是实际实现时第一个要解决的问题。

我的做法是在对数域做后向传递。定义 (V_t(x_t) = \log \beta_t(x_t)),那么递归变成:

[ V_t(x_t) = \log \mathbb{E}{q(u_t)} \left[ \exp(-c(x_t, u_t) + \mathbb{E}{p(x_{t+1}|x_t, u_t)} [V_{t+1}(x_{t+1})]) \right] ]

这个形式里,指数内部的量是“负代价加未来值”,通常在一个合理的范围内。但外层的 (\log \mathbb{E}[\exp(\cdot)]) 仍然需要小心,如果方差很大,数值上可能不稳定。一个实用的技巧是用log-sum-exp的数值稳定版本,或者用蒙特卡洛采样来近似期望,然后对样本做log-sum-exp。

注意:如果你用高斯分布来近似控制分布,那么 (\log \mathbb{E}[\exp(\cdot)]) 可以解析计算,因为高斯积分有闭式解。这是为什么很多实现选择高斯变分分布的原因之一。

4.2 控制分布的参数化选择

控制分布 (q(u_t)) 的参数化直接影响算法的复杂度和性能。常见的选择有:

  • 高斯分布:(q(u_t) = \mathcal{N}(\mu_t, \Sigma_t))。优点是解析性质好,后向传递可以推导出闭式更新。缺点是只能表示单峰分布,对于多模态的最优控制可能不够。
  • 混合高斯:(q(u_t) = \sum_k \pi_k \mathcal{N}(\mu_k, \Sigma_k))。可以表示多模态,但后向传递会变得复杂,通常需要EM算法或者采样。
  • 隐式分布:不显式参数化,而是通过采样来近似。比如用SVGD或者MCMC。灵活但计算量大。

我个人的经验是,对于大多数连续控制任务,高斯分布已经够用了。如果你的任务确实需要多模态控制(比如避障时左右绕行都可以),那混合高斯或者隐式分布值得考虑。但要注意,混合高斯的后向传递里,(\log \sum_k \pi_k \exp(\cdot)) 需要log-sum-exp,数值上要小心。

4.3 时域长度和计算量的权衡

Control as Inference的后向传递是 (O(T)) 的,但每一步的期望计算可能很贵。如果动态模型是非线性的,期望没有闭式解,需要用sigma点或者蒙特卡洛。这时候时域长度 (T) 就直接影响计算量。

在MPC的滚动时域框架下,你不需要一次算完整个任务时域,只需要算一个有限时域。但有限时域会引入终端效应:时域末端的最优性假设会影响前面的控制。常见的做法是在终端加一个值函数近似,或者用足够长的时域让终端效应衰减。

我试过在倒立摆任务上,时域长度从10增加到50,控制性能提升很明显,但计算时间也线性增长。后来发现,用终端值函数近似可以在时域长度20的情况下达到时域长度50的效果。终端值函数可以用一个简单的二次型近似,或者用神经网络拟合。

4.4 与MPC模型预测控制的对比实测

为了更直观地展示差异,我整理了一个对比表格,基于我在倒立摆和无人车横向控制上的实测经验:

维度传统MPCControl as Inference
问题形式确定性优化概率推断
不确定性处理鲁棒优化或场景法自然通过期望积分
探索性需手动加噪声熵项自动提供
约束处理硬约束或软约束通过先验或条件概率
计算量取决于求解器取决于期望近似
数值稳定性较好需注意指数/对数域
多模态控制困难混合分布可表示

实测下来,在噪声小、约束简单的场景下,传统MPC更快更直接。但在噪声大、需要探索、或者多模态最优的场景下,Control as Inference的优势很明显。特别是当你想把学习和控制统一在一个框架里时,这个视角几乎是必经之路。

5. 常见问题与排查技巧实录

5.1 后向消息发散怎么办

后向递归里,如果代价函数是负的(比如奖励为正),(\exp(-c)) 会大于1,后向消息可能指数增长。这是实际实现时最常见的问题。解决方法有两个:一是把代价函数平移,保证非负;二是用归一化的后向消息,每一步除以一个常数。

我个人的习惯是,在定义代价函数的时候,就保证它非负。如果任务本身是奖励最大化的,那就把奖励取负再加一个常数。这样后向消息就不会发散。

5.2 控制分布熵过大导致控制抖动

熵项鼓励探索,但如果熵权重太大,控制分布会变得很宽,采样出来的控制量抖动厉害。这时候需要调整熵权重,或者在执行时取众数而不是采样。

我在无人车横向控制里遇到过这个问题。当时熵权重设得太大,方向盘抖得像在跳舞。后来把熵权重降下来,并且在执行时取控制分布的均值,抖动就消失了。所以,熵权重是一个需要仔细调的参数,它控制探索和利用的平衡。

5.3 动态模型不准确时的表现

Control as Inference假设动态模型已知。如果模型不准确,后向消息传递会基于错误的动态做推断,导致控制性能下降。这时候可以考虑在线学习动态模型,或者用鲁棒变分推断来考虑模型不确定性。

我试过在模型有偏差的情况下,用高斯过程来学习残差动态,然后把学习到的动态代入后向传递。效果比直接用错误模型好很多,但计算量也上去了。如果实时性要求高,可以考虑用神经网络来近似动态,然后做批量后向传递。

5.4 常见问题速查表

问题现象可能原因排查思路解决方法
后向消息发散代价为负或太小检查代价函数范围平移代价保证非负
控制抖动大熵权重过大检查熵权重和采样方式降低熵权重或取众数
控制性能差动态模型不准对比模型预测和实际在线学习或鲁棒推断
计算太慢时域太长或期望太贵分析计算瓶颈缩短时域或用终端值函数
终端效应明显时域太短观察末端控制加终端值函数近似

5.5 一个容易被忽略的细节:初始分布的选择

变分分布 (q(x_0)) 通常假设等于真实初始分布 (p(x_0))。但如果初始状态有不确定性,这个假设可能不成立。我试过在初始状态不确定的情况下,用 (q(x_0)) 来近似后验初始分布,效果比固定初始分布好。这个细节在文献里经常被忽略,但在实际系统里很重要。

6. 从理论到代码:一个最小可复现示例

6.1 问题设定与参数选择

为了让你能直接上手,我用一个一维线性系统来演示。系统动态是 (x_{t+1} = x_t + u_t + \epsilon_t),(\epsilon_t \sim \mathcal{N}(0, \sigma^2))。代价函数是 (c(x, u) = q x^2 + r u^2)。终端代价是 (q_T x_T^2)。这个系统有闭式解,方便验证。

参数选择:(q = 1.0),(r = 0.1),(q_T = 10.0),(\sigma = 0.1),时域 (T = 20)。初始状态 (x_0 = 1.0)。

6.2 后向传递的实现

由于系统是线性的,代价是二次的,后向消息可以假设为高斯形式:(\beta_t(x_t) = \exp(-V_t(x_t))),其中 (V_t(x_t) = \frac{1}{2} P_t x_t^2 + p_t x_t + c_t)。代入后向递归,可以推导出 (P_t, p_t, c_t) 的更新公式。这里不展开推导,直接给代码:

import numpy as np # 参数 q = 1.0 r = 0.1 q_T = 10.0 sigma = 0.1 T = 20 x0 = 1.0 # 初始化后向消息参数 P = np.zeros(T+1) p = np.zeros(T+1) c = np.zeros(T+1) P[T] = q_T # 后向传递 for t in range(T-1, -1, -1): # 动态: x_{t+1} = x_t + u_t + eps # 后向递归的闭式更新 # 这里省略推导,直接给结果 A = 1.0 B = 1.0 # 期望项 E_P = P[t+1] E_p = p[t+1] # 更新 P[t] = q + E_P - (E_P * B)**2 / (r + E_P * B**2) p[t] = E_p * A - (E_P * B * E_p * A) / (r + E_P * B**2) c[t] = c[t+1] + 0.5 * E_P * sigma**2 - 0.5 * (E_p * A)**2 / (r + E_P * B**2) # 前向采样 x = x0 trajectory = [x] controls = [] for t in range(T): # 最优控制分布的均值 u_mean = -(P[t+1] * 1.0 * x + p[t+1] * 1.0) / (r + P[t+1] * 1.0**2) # 采样 u_std = np.sqrt(1.0 / (r + P[t+1] * 1.0**2)) u = np.random.normal(u_mean, u_std) controls.append(u) # 状态转移 x = x + u + np.random.normal(0, sigma) trajectory.append(x) print("控制序列:", controls) print("状态轨迹:", trajectory)

这段代码可以直接运行,你会看到控制量逐渐把状态拉向零。由于有噪声,轨迹不会完美收敛,但整体趋势是对的。

6.3 结果分析与调参心得

运行上面的代码,你会发现几个现象。第一,控制量在初始时刻比较大,因为状态离零远。第二,随着状态接近零,控制量变小。第三,由于噪声的存在,状态会在零附近波动。

调参方面,(r) 控制控制量的惩罚。(r) 越大,控制越保守,收敛越慢。(r) 越小,控制越激进,但可能过冲。(q_T) 控制终端代价,(q_T) 越大,终端状态越接近零。(\sigma) 是噪声,噪声越大,控制分布越宽,采样出来的控制越随机。

我个人的经验是,先把 (r) 和 (q_T) 调到一个合理的范围,然后根据噪声大小调整熵权重。如果噪声大,熵权重可以小一点,因为噪声本身提供了探索。如果噪声小,熵权重可以大一点,保持探索性。

6.4 扩展到非线性系统的思路

对于非线性系统,后向消息没有闭式解,需要用近似方法。常见的做法有:

  • 扩展卡尔曼滤波(EKF):对动态和代价做一阶线性化,然后套用线性二次型的闭式解。
  • 无迹变换(Unscented Transform):用sigma点来近似期望,比EKF精度高。
  • 蒙特卡洛采样:直接从动态和代价里采样,用样本均值近似期望。灵活但计算量大。

我试过在倒立摆上用无迹变换做后向传递,效果比EKF好,计算量也可以接受。如果你要做实时控制,无迹变换是一个不错的折中。

7. 这个框架还能怎么用

Control as Inference的基本理论就讲到这里。但它的应用远不止于此。比如,你可以把它和逆强化学习结合起来:从演示数据里推断代价函数,然后用推断出来的代价做控制。你也可以把它和模型学习结合起来:用变分推断同时学习动态模型和控制分布。甚至,你可以把它和表示学习结合起来:用神经网络来参数化后向消息,然后端到端训练。

我个人在实际操作中的体会是,这个框架最大的价值不是替代传统MPC,而是提供了一个统一的概率视角,让你能把控制、学习、推断放在同一个数学框架里思考。当你遇到传统方法不好处理的问题时,比如不确定性大、需要探索、多模态最优,这个视角往往能给你新的思路。

最后再分享一个小技巧:如果你觉得后向传递的计算量太大,可以试试用神经网络来近似后向消息,然后离线训练,在线只用前向传播。这样可以把在线计算量降下来,同时保留概率框架的好处。我试过在无人车横向控制里用这个方法,在线计算时间从几十毫秒降到了几毫秒,控制性能几乎没有损失。

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

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

立即咨询