研究强化学习的人,迟早会遇到一句话:控制问题可以被改写成概率推断问题。这句话在学术界已经流行了很多年,但真正把它讲清楚、并能从推导一路走到深度学习算法实现的课程内容,其实并不多。伯克利 2026 春季深度强化学习课程的第 13 讲,主题就是“控制作为变分推断(Control as Variational Inference)”。这一讲不教你调 PID,也不直接给某个网络的代码,而是从贝叶斯推理的视角,把最优控制、随机控制和现代强化学习算法重新组织到同一个数学框架下。
这一讲的定位非常硬核,但收益也很大。如果你已经学过策略梯度、Q 学习这类基础 RL 方法,再看这一讲,会发现很多算法背后的损失函数不是随便拍脑袋拍出来的,而是从“最小化轨迹分布与期望分布之间的 KL 散度”一步步推出来的。整个讲座的核心卖点可以归纳为三点:第一,用概率图模型统一“预测、推断、控制”三个概念;第二,给出从最优控制到 KL 控制再到策略优化的一条完整推导链;第三,能解释 SAC、MPO 这类熵正则化或最大后验策略优化算法为什么要那样设计。
本文会围绕四个问题展开:控制为什么可以被看成变分推断?“变分”到底变分在哪里?KL 散度在这个框架里承担什么角色?以及这套理论和我们熟悉的工程控制热词,比如 PID 控制、FOC 控制、电机控制,是什么关系。文章最后会给出一个最小化的 Python 教学示例,方便你跑通一次基于变分推断的策略分布更新。如果你正在学习深度强化学习,或者写论文时需要理解 SAC、MPO 这些算法的理论动机,这一篇文章可以收藏备用。
1. 讲座内容速览
| 属性 | 说明 |
|---|---|
| 课程来源 | 伯克利 2026 春季深度强化学习课程,第 13 讲 |
| 核心主题 | 将控制问题转化为概率推断问题,用变分推断统一最优控制与强化学习 |
| 前置知识 | 概率论、KL 散度、贝叶斯推断、最优控制基础、深度强化学习基础 |
| 使用工具 | 理论推导为主,可配合 Python、PyTorch、NumPy 做最小复现 |
| 主要难点 | 变分下界推导、KL 方向选择、分布建模、与经典控制概念映射 |
| 适合人群 | RL 研究者、控制理论入门者、研究生、算法工程师 |
| 不涉及内容 | 本讲不重点讲 PID 参数整定、FOC 磁场定向控制、PLC 梯形图等传统工程控制实现 |
这里先给你一个判断标准:如果你只是要做 STM32 直流电机调速、FPGA 相控阵相位控制、或者调试一套 PLC 系统,那这一讲的实用性不强,古典控制方法论已经足够好;但如果你关心机械臂、四旋翼仿真、自动驾驶这类“状态多、约束强、策略需要自适应”的控制问题,变分推断视角就是一套非常值得掌握的建模武器。
2. 为什么“控制”可以看成“变分推断”
要理解这一讲,首先要接受一个思维模式的转换:经典控制是在“找一个动作序列”,变分推断下的控制是在“拟合一个轨迹分布”。
经典最优控制的起点是状态方程和代价函数,目标是最小化累积代价值。而概率推断的起点是一个关于轨迹的概率模型。我们可以把一条从初始状态到目标状态的轨迹看成随机变量,它服从某个分布。贝尔曼最优性告诉我们,最优策略应该让轨迹尽可能进入低代价区域;变分推断则告诉我们,最优策略应该让策略诱导出的轨迹分布尽可能接近某个“期望轨迹分布”。
这时候,控制问题就变成了一个分布逼近问题。假设我们有一个理想的轨迹分布 (p(\tau)),它表示“好的、值得发生的轨迹”。我们当前策略 (\pi_\theta) 会诱导出一个实际的轨迹分布 (q(\tau))。我们希望调整 (\theta),让 (q(\tau)) 尽量接近 (p(\tau))。两个分布之间的距离,最常用的度量就是 KL 散度:
[ \min_{\theta} \mathrm{KL}\left(q_\theta(\tau) | p(\tau)\right) ]
展开写就是:
[ \mathrm{KL}\left(q_\theta(\tau) | p(\tau)\right) = \mathbb{E}{q\theta}\left[\log q_\theta(\tau) - \log p(\tau)\right] ]
看到这个式子,你应该已经能感觉到,它和策略梯度里常见的“最大化期望回报”其实是同一件事的不同表达。回报高的轨迹在 (p(\tau)) 里的概率大,最小化 KL 散度就会让策略更倾向于产生高回报轨迹。
这一讲之所以强调“变分推断”,是因为直接计算后验轨迹分布通常是不可行的。状态空间一高,轨迹组合数就是指数级的,根本没法精确求和或积分。变分推断的思路是:我们不去求精确后验,而是从一族简单的分布里找一个最接近的。这个“找一个最接近的分布”的过程,就是变分优化。放在控制里,就是我们不去穷举所有可能的控制序列,而是在参数化策略族中搜索最优策略。
所以,标题“控制作为变分推断”可以拆成两个层面:控制的目标是推理出最理想的轨迹分布;控制的计算过程是变分近似。这就是这一讲的骨架。
3. 学习这一讲需要准备什么
这一讲不是纯工程操作,但要有足够的知识储备才能跟上推导。我建议你在进入第 13 讲之前,先确认下面五块基础已经到位。
3.1 数学基础
最基础的是概率论里的条件概率、边缘化、贝叶斯公式。其次需要理解 KL 散度、交叉熵和期望。变分推断里常用到 Jensen 不等式推导证据下界(ELBO),但“控制作为变分推断”通常不会只讲静态概率模型,它会把 KL 散度放进轨迹空间里,因此你最好能习惯“轨迹上的积分”这种写法,而不是仅仅会算一维分布。
3.2 强化学习基础
至少要知道马尔可夫决策过程(MDP)、策略、价值函数、Bellman 方程。因为第 13 讲一定会把变分推断和这些概念做映射。许多人在这里卡住,是因为还没搞清楚“策略”和“轨迹分布”之间的区别。策略是条件概率 (\pi(a|s)),轨迹分布是由动力学 (p(s'|s,a)) 和策略共同诱导出来的联合分布。
3.3 最优控制基础
如果了解一点线性二次调节器(LQR)、模型预测控制(MPC),会很有帮助。变分推断视角可以看作对非线性、高维控制问题的另一种建模方式。你不一定需要会手推 LQR,但要知道“最优控制的核心是找一组控制信号让代价函数最小”这个经典目标。
3.4 编程环境
虽然这一讲主要做理论,但动手写代码能把抽象公式具象化。你只需要一个普通的 Python 环境,装上 NumPy、PyTorch 和 matplotlib 就够做最小实验。
# 安装最小依赖,Python 3.9+ 环境即可 pip install numpy torch matplotlib3.5 资料获取方式
伯克利这类公开课通常会在课程主页放出课件、视频和作业。你可以在搜索引擎里搜“Berkeley deep RL course spring 2026”或直接进入课程官网,找到 Lecture 13 对应的 slides。这里不对 URL 做硬编码,因为你可能找到镜像或者课程仓库,以实际页面为准。
4. 核心方法:从最优控制到 KL 控制
这一讲最重要的理论成果,是把最优控制问题重写成一个 KL 最小化问题。整个过程可以分成三步:随机化控制、定义目标分布、迭代更新策略分布。
4.1 把确定性控制随机化
经典控制里的控制信号通常是一个确定性函数 (u_t = K(x_t))。但在变分推断框架下,我们更希望把控制信号看作从一个条件概率分布 (u_t \sim \pi_\theta(\cdot|x_t)) 中采样。这样做有两个好处:一是提供了探索机制,二是让“策略分布”和“轨迹分布”之间有了明确的概率关系。
随机化并不是丢掉确定性。当策略分布的方差趋于零时,它就退化为确定性控制。所以 KL 控制框架实际上是经典确定性最优控制的一种推广,它把“最优解”从一条轨迹变成一个分布族。
4.2 定义目标轨迹分布
变分推断需要一个目标。在概率图模型里,轨迹上的概率可以写成:
[ p(\tau) \propto p(s_0) \prod_{t=0}^{T-1} p(s_{t+1}|s_t,a_t) \exp(-c(s_t,a_t)) ]
这里 (p(s_{t+1}|s_t,a_t)) 是环境动力学,(\exp(-c(s_t,a_t))) 是代价项。代价越小,轨迹概率越大。整个 (p(\tau)) 可以理解为“既符合物理规律,又代价足够低”的轨迹分布。这就是目标分布。
需要注意的是,这个分布通常不是归一化的。变分推断处理未归一化分布时,会引入一个配分函数,这个配分函数在实际计算中往往可以忽略,因为我们要最小化的是带归一化常数的 KL 散度,优化过程对常数不敏感。
4.3 KL 控制迭代公式
假设我们当前策略诱导的轨迹分布为 (q_\theta(\tau)),目标轨迹分布为 (p(\tau)),KL 控制的目标是:
[ \min_\theta \mathrm{KL}(q_\theta | p) ]
把 KL 散度展开后,去掉与 (\theta) 无关的项,等价于最小化:
[ \mathcal{L}(\theta)
\mathbb{E}{q\theta}\left[ \log q_\theta(\tau) - \log p(\tau) \right] ]
再进一步,用代价函数替换 (\log p(\tau)):
[ \mathcal{L}(\theta)
\mathbb{E}{q\theta}\left[ \log q_\theta(\tau) + \sum_t c(s_t,a_t) \right] + \text{const} ]
这个形式已经非常接近强化学习里的损失函数了。第一项鼓励策略分布尽量大(熵大),第二项鼓励轨迹代价尽量低。所以 KL 控制本质上是“熵正则化最优控制”。你后面看到 SAC 里加上熵项,就不会觉得奇怪了,因为它在数学上和变分推断控制是相通的。
一个典型的 KL 控制迭代流程可以写成这样:
# 伪代码:KL 控制迭代更新 for iteration in range(max_iter): # 1. 从当前策略采样一批轨迹 trajectories = policy.sample_trajectories(model, horizon=H, num_samples=N) # 2. 估计每条轨迹的代价 costs = [sum_cost(traj) for traj in trajectories] # 3. 计算每个轨迹的“重要性权重”,近似目标分布 weights = softmax(-costs) # 4. 用加权最大似然更新策略分布 policy.update(weighted_surrogate(trajectories, weights))这个流程非常像加权模仿学习,只是“模仿”的目标不是专家的轨迹,而是低代价轨迹的加权集合。它和 CEM(交叉熵方法)、MPPI(模型预测路径积分)也有很强的联系,因为这些方法同样在反复采样、加权、更新分布。
5. 从变分推断视角看现代强化学习算法
第 13 讲不会只停留在 KL 控制理论,它一定会把结论推广到现代深度强化学习算法。这里选三个典型例子。
5.1 SAC:最大熵策略与变分推断
SAC(Soft Actor-Critic)的损失函数里有一个显式的熵正则项。它的目标函数可以写成:
[ J(\pi)
\mathbb{E}{(s,a) \sim \pi}\left[ r(s,a) \right] + \alpha \mathbb{E}{s \sim \rho_\pi}\left[ \mathcal{H}(\pi(\cdot|s)) \right] ]
从变分推断视角看,这个熵正则项就是在控制“策略分布不要过早坍缩到某一条确定性轨迹”。它让策略在实现高回报的同时保持一定随机性。这和在 KL 控制里最小化 (\mathrm{KL}(q_\theta | p)) 的项是完全对应的。你可以把 SAC 理解成在有限模型表达力下,用变分方式逼近目标轨迹分布的一种实现。
5.2 MPO:最大后验策略优化
MPO 是 DeepMind 提出的离线强化学习算法,它的名字“最大后验策略优化”本身就带有贝叶斯色彩。MPO 把策略优化拆成 E 步和 M 步:E 步用变分推断估计动作的后验分布,M 步让当前策略去拟合这个后验分布。这种写法直接继承了控制作为变分推断的思想。MPO 在处理离线数据时更稳定,就是因为它考虑到了动作分布的不确定性,而不仅是点估计。
5.3 SVG:可计算图上的变分策略优化
如果你读论文读到 Stein Variational Policy Gradient(SVPG),会发现它把策略参数本身当作随机变量,用 Stein 变分梯度下降来更新参数分布。这也是变分推断在控制中的另一种应用:不直接优化一个固定的策略参数,而是维护参数的分布。这个方向更数学化,但它的初衷仍然是“在不精确可解的情况下,寻找一个近似的后验策略分布”。
6. 最小可运行示例:用变分推断更新高斯策略
理论讲多了,还是要动手。这里给一个教学级最小示例,目的是让你直观感受“控制作为变分推断”的更新过程。我们假设一个一维状态的控制问题,策略用一个高斯分布表示,目标是通过 KL 最小化让策略收敛到某个理想的动作分布。
6.1 定义一个高斯策略网络
import torch import torch.nn as nn import torch.distributions as dist class GaussianPolicy(nn.Module): def __init__(self, dim=1, hidden=32): super().__init__() self.net = nn.Sequential( nn.Linear(1, hidden), nn.ReLU(), nn.Linear(hidden, dim * 2) ) def forward(self, t): # t 是时间步,离散控制问题中通常用不到,但保留接口便于扩展 features = torch.tensor([t], dtype=torch.float32) out = self.net(features) mean = out[:1] log_std = torch.clamp(out[1:], min=-5, max=1) std = log_std.exp() return dist.Normal(mean, std)这个网络输入时间步 (t),输出动作分布的均值和标准差。为了教学,状态被简化成时间索引,实际工程里应把状态向量喂进来。
6.2 定义目标分布并最小化 KL
我们假设某一步的“期望动作分布”是均值 2.0、标准差 0.5 的高斯分布。用 KL 散度作为损失函数更新策略。
def train_kl_control(): policy = GaussianPolicy() optimizer = torch.optim.Adam(policy.parameters(), lr=0.01) target = dist.Normal(torch.tensor([2.0]), torch.tensor([0.5])) for step in range(500): current = policy(t=1) # 只更新一步的控制分布,简化的教学场景 loss = dist.kl_divergence(current, target).mean() optimizer.zero_grad() loss.backward() optimizer.step() if step % 100 == 0: print(f"step {step}, loss={loss.item():.4f}, " f"mean={current.mean.item():.4f}, std={current.std.item():.4f}") train_kl_control()这个示例非常简化,但它说明了变分推断控制的核心:通过最小化策略诱导分布与目标分布之间的 KL 散度,策略会逐渐把分布移动到目标区域。你运行后会看到 loss 下降,均值接近 2.0,标准差接近 0.5。
6.3 实验配置模板
真实项目里,你会希望把超参数和路径放在配置文件中。
{ "horizon": 10, "dt": 0.05, "state_dim": 1, "action_dim": 1, "target_trajectory_file": "./targets/demo.npy", "policy": { "type": "gaussian", "hidden_size": 32, "log_std_clip": [-5, 1] }, "train": { "epochs": 500, "lr": 0.01, "kl_weight": 1.0, "seed": 42 } }如果你要做批量实验,可以写一个循环读取多个 JSON 配置,自动跑不同 seed 或不同目标分布。但要注意,这只是教学模板,接入真实控制环境时,目标分布不可能是一个固定高斯,它应该来自环境动力学和代价函数的组合。
7. 变分推断控制与经典控制热词的对照
搜索热词里高频出现的“PID 控制”“FOC 控制”“电机控制”“PLC 控制系统设计”,代表的是工业界最常用的确定性控制方法。很多人会问:学了变分推断控制,是不是以后可以用它替代 PID?答案很明确:不是替代,而是互补。
PID 控制适合模型不确定但有明确误差信号的系统,它的优势是简单、可解释、计算开销几乎为零。FOC 控制需要把三相电流变换到旋转坐标系,再对 id/iq 电流做 PI 调节,它的成功依赖电机的物理模型。PLC 设计梯形图则完全属于逻辑控制和顺序控制,和概率推断几乎没有交集。
变分推断控制的目标并不是这些细分场景,而是高维、非线性、强耦合的决策问题。比如机械臂避障、四旋翼滑模控制、麦克纳姆轮运动学控制、交通信号灯强化学习控制,这些场景的状态量多、约束复杂,很难手工设计出一套 PID 参数。这时,把控制看成变分推断,就能借用深度学习工具在轨迹分布空间里搜索策略。
可以把两者的适用边界列一个表:
| 维度 | 经典控制(PID、FOC 等) | 变分推断控制 |
|---|---|---|
| 模型需求 | 低维线性或局部线性,可离线整定 | 可处理非线性、高维模型 |
| 实时性 | 微秒到毫秒级,计算极轻 | 通常需要 GPU 加速或离线训练 |
| 可解释性 | 每个参数物理意义明确 | 策略分布和代价函数结构可解释,但网络参数难解释 |
| 数据需求 | 不依赖大数据,靠反馈闭环 | 依赖环境交互或离线数据 |
| 适用场景 | 伺服电机、电源模块、机器人底层驱动 | 自动驾驶决策、机械臂规划、多智能体协同 |
如果你在做底层电机控制,继续用 FOC 和级联 PID 就好。如果你在写“基于强化学习和图注意力网络的交通信号灯控制方法”,或者做“ai 控制机械臂”这类研究,变分推断视角会给你提供理论支撑。
8. 常见理解误区和排查方法
这里列几个初学者最容易踩的坑,以及对应的排查思路。
| 误区 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 把“变分推断”当成“预测” | 混淆后验估计和轨迹生成 | 重读贝叶斯推断定义 | 明确“推断”是求后验分布,不是仿真轨迹 |
| KL 散度方向写反 | 不理解 forward KL 和 reverse KL 的区别 | 检查损失函数是 (KL(q|p)) 还是 (KL(p|q)) | 控制问题通常用 (KL(q|p)) 让策略集中在低代价区域 |
| 策略分布过于简单 | 高斯分布无法表达多模态轨迹分布 | 检查采样的轨迹是否覆盖多个模式 | 改用混合高斯或标准化流 |
| 显存不足 | 批量采样轨迹过多 | 降低 num_samples 或 horizon | 用重要性采样和重复使用样本 |
| 训练不收敛 | KL 权重过大或学习率过高 | 检查 loss 曲线,看是否震荡 | 降低学习率,先固定 KL 权重再训练 |
| 代码示例无法复现 | 只抄了示例但没有适配环境动力学 | 对比目标分布是否来自真实代价 | 根据实际模型重新定义 p(tau) |
特别提醒一点:实现时一定要先确认 KL 方向。在变分推断控制里,使用 (\mathrm{KL}(q_\theta | p)) 还是 (\mathrm{KL}(p | q_\theta)) 会导致完全不同的策略行为。前者会促使策略概率密度尽量落在代价低的区域,后者会要求策略覆盖所有高概率轨迹,哪怕那条轨迹代价不高。SAC 等算法本质上在近似前者的优化路径。
9. 工程实践与学习路径建议
把这讲内容真正消化,不能只靠看视频,需要配合推导和实验。
第一,建议先手推一遍 KL 控制的最简形式。从一维状态、单步控制开始,写出概率模型,代入高斯分布,推导 KL 散度关于策略参数的梯度。这个过程能让你彻底明白“变分”是在变什么。
第二,去复现一个已知算法。最简单的是 SAC 或类似带熵正则的策略优化算法。你不需要从头实现整个环境,可以用 OpenAI Gym 的 Pendulum-v1 做测试。复现完再回到这一讲的理论,你会看到每个损失项都有概率解释。
第三,学完理论后做一个扩展实验。把第 6 节的示例从固定目标分布替换成“环境动力学 + 代价函数”诱导的目标分布。你可以给轨迹循环加上代价项,比如越靠近目标点的轨迹,权重越高,然后观察策略分布是否逐渐向目标区域移动。
第四,建立术语映射表。把“最优控制”“回报最大化”“对数后验”“KL 散度”“熵正则化”这些概念放在一起对比,你会更容易在不同课程和论文之间迁移。
如果你是工程向的读者,建议不要直接把这套方法搬到实时控制器上。变分推断控制目前更适合离线训练、仿真验证、以及样本效率敏感的研究场景。工业落地时,可以先在仿真环境里训练,再结合 MPC 作为安全兜底。
10. 总结与下一步
这一讲最值得花时间的点,是它给你提供了一套统一语言:控制不是找一条轨迹,而是拟合一个分布;强化学习不是单纯最大化回报,而是逼近理想轨迹分布。这个视角能解释很多现有算法设计,也能帮你设计新算法。第 13 讲之后,建议你先用第 6 节的最小示例跑通一次高斯策略的 KL 更新,再回到公式推导,把 (KL(q_\theta|p)) 展开到最后,感受一下“策略分布 - 目标分布 - 代价函数”三者之间的循环关系。
最容易踩的坑就是不要急着跳过数学直接调库。变分推断控制的推导链比较长,任何一个符号理解错了,代码里的 loss 曲线都会变得不可解释。下一步你可以重点关注两个方向:一是把这套思想用在 MPC 里,把轨迹优化问题改成交替采样和加权更新;二是研究离线强化学习里的 MPO 类算法,它们会把“控制作为变分推断”变成更工程化的实现。连续体控制、多主体控制、机械臂自适应控制这类复杂问题,也会是这套理论未来的主要应用场景。