想象你走进一家米其林后厨,老师傅正在教新来的帮厨做一道“创意牛排”。同一块牛肉,不同客人给出了完全不同的诉求:有人要七分熟、有人要酥皮、有人要带焦边。帮厨如果只记住一个“平均做法”——把每种要求都折中成不冷不热的五分熟,结果没有一个客人满意。机器人学里也有类似困境:同一个视觉场景下,好的动作其实不止一种;传统模仿学习却常常把这些“多种正确答案”揉成一个平庸的平均值。Diffusion Policy 的做法则像是请来了一位耐心雕塑家:它不追求一步到位,而是从一块满是噪声的“石头毛坯”开始,每一次只削掉一点点多余的瑕疵,反复几十步后,才雕刻出一条平滑、自然且符合当前场景的动作轨迹。本文会用这条“后厨 + 雕塑”的故事线,带你看懂 Diffusion Policy 是如何训练、如何注入条件、如何处理多模态动作,并最终让机械臂在真实世界端出“一桌好菜”。
掌握 Diffusion Policy,是进入具身智能、机器人操作与生成式控制交叉领域的关键一跃;它让你既能理解大模型时代“生成动作”的底层逻辑,又能在真实机器人项目中落地可用的闭环策略。
目录
可视化演示
交互展示Diffusion Policy前向加噪、逆向去噪生成多模态动作轨迹、条件注入生成机器人动作的完整扩散流程。
本节配有交互动效(进入视口后自动加载,约 3KB)。
前向扩散:动作轨迹加噪 逐步向干净轨迹添加高斯噪声 噪声强度σ从0增至1破坏轨迹结构 q(x_t|x_0) = N(√ᾱ_t·x_0, (1-ᾱ_t)·I) 前向扩散定义马尔可夫链为训练提供噪声样本
问题与动机:为什么“平均答案”会砸了招牌
后厨里的新帮厨发现,老师傅教“糖醋排骨”时,有时放三勺糖,有时放两勺糖,客人还分南甜北咸。帮厨心想:那就取个平均,放二点五勺吧。结果南方客人觉得不够甜,北方客人又觉得太腻。机器人模仿学习也面临同样的“帮厨困境”:当专家演示中包含多种合理动作时,常用的均方差回归会把它们平均成一条“四不像”轨迹。比如从侧面抓杯子和从上方抓杯子都对,平均出来的抓手位置却悬在杯沿外,根本抓不住。
这正是 Diffusion Policy 要解决的问题。它不再强迫策略输出一个确定动作,而是让策略学习“动作的条件分布”。在复杂操作任务中,视觉特征、物体位姿、接触状态都可能对应多种成功动作;一个足够有表达力的策略,必须能够保留这种多模态性。
从数学上看,传统行为克隆常用的均方误差目标,最终会把策略逼向条件均值:
- 最优策略符号 \(\pi^*_{\text{MSE}}\)表示在均方误差目标下求出的“最优”策略;它不是真正的优秀策略,而是被平均陷阱扭曲后的策略。
- 条件期望 \(\mathbb{E}_{\mathbf{a} \sim p(\mathbf{a} \mid \mathbf{o})}\)意思是“在观测到 o 的所有演示动作中取平均”。就像把南甜北咸的配方混在一起,得到谁都不满意的中庸配方。
- 动作向量 \(\mathbf{a}\)机器人的关节角度、末端速度或夹爪开合等控制指令;它是策略需要输出的“菜谱步骤”。
- 结论这个公式说明,传统回归学到的是条件均值,而非完整的动作分布;Diffusion Policy 正是为了打破这种“帮厨式平均”而出现。
扩散模型原理:从噪声毛坯中雕出动作
续用雕塑家的比喻:如果老师傅先把一块大理石“反向凿碎”成一堆碎石渣,然后再教徒弟一点一点把碎石渣拼回完整雕像,这个过程看起来绕路,却意外地有效。扩散模型正是这样“先毁掉、再修复”的生成范式。
前向过程是故意“毁掉”动作:从干净动作 \(\mathbf{a}_0\) 出发,逐步加入高斯噪声,直到它完全变成随机噪声。反向过程则是训练一个神经网络,学习“如何把噪声移除”。Diffusion Policy 把机器人的动作序列看作这张待修复的“雕像”,用同样的去噪过程生成动作。
前向加噪公式如下:
- 干净动作 \(\mathbf{a}_0\)专家演示中的真实动作,也就是雕像尚未被打碎前的原貌。
- 加噪后的动作 \(\mathbf{a}_t\)经过 t 步加噪后的中间状态;t 越大,噪声越明显,雕像越模糊。
- 噪声调度 \(\sqrt{\bar{\alpha}_t}\)控制每一步保留多少原始信号;它像雕刻师手里的“保留力度”,一步步退让给噪声。
- 高斯噪声 \(\epsilon\)从标准正态分布中采样的随机扰动,代表完全无意义的“碎石渣”。
策略网络结构:一套分工明确的厨房流水线
Diffusion Policy 并不是一个散装模块,而是一条完整的“后厨流水线”:视觉编码器像后厨门口的摄像头,负责看清客人、餐桌和当前菜品状态;扩散骨干网络像负责反复试菜的主厨,从噪声中逐步修正动作;动作解码器则像是最后装盘的人,把修正结果还原成可执行的机器人指令。
与传统只输出单步动作的策略不同,Diffusion Policy 经常一次输出一整段“动作块”。它把未来 H 步动作打包成一条序列,再交给去噪网络整体优化。这样做的好处是:动作之间彼此连贯,不会出现“一步一顿”的割裂感。
动作块的定义可以写成:
- 动作块 \(\mathbf{A}_t\)从当前时刻 t 开始的一段连续动作序列;就像主厨一次写下未来十秒的完整烹饪动作。
- 未来动作 \(\mathbf{a}_{t+k}\)第 k 步之后要执行的动作,表示机器人对未来规划的“腹稿”。
- 预测长度 H动作块的窗口长度;H 越大,动作越有前瞻性,但难度也越高。
- 整体含义把所有未来动作看成一个整体去生成,避免“走一步看一步”造成的抖动。
条件信息注入:订单、监控画面与手感缺一不可
如果雕塑家闭着眼睛雕刻,作品必然离谱。Diffusion Policy 必须把当前环境信息注入去噪过程,告诉网络“现在该往哪个方向修”。这就像后厨里的主厨需要同时看订单、看监控画面、感受手下的面团湿度,才能决定下一步动作。
常见的条件信息包括:当前相机图像、机械臂关节角度、夹爪开合状态、历史动作序列,以及去噪步数 t。设计上,网络可以在输入端拼接这些特征,也可以通过 FiLM 调制、交叉注意力等方式把条件融入扩散骨干网络。
条件化去噪网络的输入可以抽象为:
- 噪声预测网络 \(\epsilon_\theta\)训练出来的“修瑕疵”模型,它根据当前状态预测该移除多少噪声。
- 视觉观测 \(\mathbf{o}^{\text{vis}}\)摄像头捕捉到的场景信息,相当于后厨监控画面。
- 历史动作 \(\mathbf{A}^{\text{hist}}\)过去的动作序列,让机器人知道自己的“手”刚才在做什么。
- 去噪步数 t告诉网络现在处于雕刻早期还是后期,从而调整每次削切的力度。
多模态动作输出:一份菜谱的多种合理做法
回到开篇的“创意牛排”:七分熟和脆皮焦边都是正确答案,但它们不是同一个答案。Diffusion Policy 之所以能处理这种多模态动作,是因为它本质上是在学习一个条件概率分布,而不是一个唯一的映射函数。每次推理时,它从随机噪声出发,经过多步去噪,自然落向某一个合理动作模式。
这种生成方式让机器人具备“多种合理做法”的表达能力:同一个杯子,既可以从左侧绕过障碍抓取,也可以从上方直接抓取;同一个人形机器人,既可以选择左腿迈步,也可以选择右腿迈步。只要演示数据中存在这些模式,扩散模型就能把它们保留下来。
从概率视角看,整条去噪链定义了一个策略分布:
- 策略分布 \(p_\theta(\mathbf{A}_0 \mid \mathbf{o})\)给定观测时,机器人生成最终动作块的概率分布;它可以有多个峰。
- 初始噪声分布 \(p_\theta(\mathbf{A}_T \mid \mathbf{o})\)一般就是标准正态噪声,相当于雕刻开始时那块随机的毛坯。
- 去噪转移 \(p_\theta(\mathbf{A}_{t-1} \mid \mathbf{A}_t, \mathbf{o})\)每一步从稍微干净的版本推出更干净的版本;每一步只修掉一点多余部分。
- 积分 \(\int \cdots d\mathbf{A}_{1T}\):把所有中间路径都考虑进来,最终形成完整的“多峰菜谱”。
训练与推理流程:试菜、调方子、出餐
训练 Diffusion Policy 的过程,很像让帮厨反复试菜:先看老师傅做好的完整动作(演示数据),然后把成品“打碎”成不同程度噪声,再让网络学习“刚才打碎了哪部分”。网络不直接预测最终动作,而是预测被加入的噪声;这好比帮厨学会的不是“整道菜怎么做”,而是“这步削多了还是少了”。
在实际部署中,Diffusion Policy 还常采用类似模型预测控制的做法:每执行一小段动作块后,就重新获取最新传感器图像,再次采样去噪,生成新的动作块。这样即使机器人被碰偏了,也能立刻调整回来。
训练损失函数如下:
- 训练损失 \(\mathcal{L}_{\text{DP}}\)衡量“真实噪声”和“预测噪声”之间的差距;差得越少,说明修雕技能越熟练。
- 随机采样 \(t, \epsilon, \mathbf{o}\)每一步随机选一个加噪程度、一个随机噪声和一条真实观测样本。
- 加噪动作 \(\sqrt{\bar{\alpha}_t} \mathbf{A}_0 + \sqrt{1 - \bar{\alpha}_t} \epsilon\)将干净动作块人为打碎后的结果。
- 误差平方 \(\|\cdot\|^2\)用均方误差惩罚预测偏差;网络因此学会“反推刚才加了多少噪声”。
应用与部署优势:真正端上一桌好菜
学会了去噪,机器人就能在复杂任务中“端出好菜”:机械臂可以完成柔性插装配、线束连接、食品分拣等精细操作。相比传统行为克隆,Diffusion Policy 的优势既来自“多模态”,也来自“闭环重规划”。即使环境被扰动,机器人也能在新一轮去噪中快速生成修正动作,而不是硬着头皮执行旧轨迹。
它的部署效率也得益于“动作分块 + 滚动预测”:机器人不以每个控制周期为代价反复推理整条很长轨迹,而是按需生成未来 H 步动作块、执行其中前若干步、再重新规划。这就像主厨不会一口气做好一整桌菜再上桌,而是边做边看客人反应,随时调整火候。
推理阶段的执行动作可以概括为:
- 实际执行动作 \(\mathbf{a}_t^{\text{exec}}\)机器人真正下发的当前步指令;它只是动作块中的第一刀。
- 随机初始噪声 \(\mathbf{A}_T \sim \mathcal{N}(0, \mathbf{I})\)每次采样生成都可能走向不同的合理动作模式。
- 去噪生成 \(\text{Denoise}_\theta\)在条件 o 下逐步修出完整动作块;相当于整套“反打碎”过程。
- 取出首步 \(\text{FirstAction}\)只执行动作块中的第一个动作,随后继续观测、继续重规划。
AI 应用场景
机械臂精密装配
阶段:策略训练与闭环部署
解决的问题:传统视觉伺服需要手工设计特征和位姿估计,遇到公差小、反光强的插拔任务容易失败。Diffusion Policy 直接从图像与力觉历史中生成连续动作序列,自动适应装配时的微小偏差。
具体案例:手机装配线上,机器人需要在 0.1 毫米公差内把排线端子插入连接器。工程师采集几十次人工演示数据,训练 Diffusion Policy 后,机械臂能对不同摆放角度的端子生成多种“绕行 + 插入”动作,并在插歪时通过重规划及时修正。
柔性物体操控
阶段:多模态策略学习
解决的问题:叠衣物、铺床单、抓取软体食材等任务中,物体的状态变化复杂,正确动作高度多模态。Diffusion Policy 能把“这次从左角开始折”和“这次从右角开始折”同时学到手。
具体案例:厨房机器人面对一整盘不同形状的鸡块,需要将鸡块夹到对应盒子中。扩散策略会根据当前食材姿态和托盘布局,采样出多条可行夹取轨迹,再由执行器安全选择其中一条。
人形机器人扰动恢复
阶段:实时推理与重规划
解决的问题:真实世界中,机器人常被意外碰撞或地面摩擦改变状态。Diffusion Policy 的“动作块预测 + 重新采样”机制,能像主厨边做边尝一样,每看到新状态就重新生成未来动作。
具体案例:人形机器人在搬运箱子时被旁边的线缆绊了一下,髋关节角度偏移。策略系统基于最新关节编码器与相机图像,在几十毫秒内重新采样一条稳定的重心调整轨迹,避免摔倒。
Python 演示
import numpy as np def make_demo_data(n_per=40): labels = [] actions = [] angles = [0.0, np.pi / 2, np.pi, 3 * np.pi / 2] for label, angle in enumerate(angles): for _ in range(n_per): labels.append(label) actions.append([ np.cos(angle) + np.random.normal(0, 0.05), np.sin(angle) + np.random.normal(0, 0.05) ]) obs = np.eye(4, dtype=float)[labels] return obs, np.asarray(actions, dtype=float) class LinearNoiseModel: def __init__(self, input_dim, output_dim, lr=0.05): self.W = np.random.randn(input_dim, output_dim) * 0.01 self.lr = lr def predict(self, obs_onehot, x_t): feat = np.concatenate([obs_onehot, x_t]) return feat.dot(self.W) def train_step(self, obs_onehot, x_t, eps_target): feat = np.concatenate([obs_onehot, x_t]) pred = feat.dot(self.W) grad = 2 * np.outer(feat, pred - eps_target) self.W -= self.lr * grad class SimpleDiffusionPolicy: def __init__(self, T=20): self.T = T self.model = LinearNoiseModel(input_dim=6, output_dim=2, lr=0.05) self.beta = np.linspace(0.02, 0.2, T) self.alpha = 1.0 - self.beta self.alpha_bar = np.cumprod(self.alpha) def train(self, obs, actions, epochs=200): rng = np.random.default_rng(0) for _ in range(epochs): i = int(rng.integers(0, len(obs))) t = int(rng.integers(0, self.T)) a0 = actions[i] eps = rng.standard_normal(2) x_t = np.sqrt(self.alpha_bar[t]) * a0 + np.sqrt(1 - self.alpha_bar[t]) * eps self.model.train_step(obs[i], x_t, eps) def sample(self, obs_onehot): x = np.random.randn(2) for t in range(self.T - 1, -1, -1): eps_hat = self.model.predict(obs_onehot, x) x = (x - self.beta[t] / np.sqrt(1 - self.alpha_bar[t]) * eps_hat) / np.sqrt(self.alpha[t]) if t > 0: x += np.sqrt(self.beta[t]) * np.random.randn(2) return x if __name__ == "__main__": obs, actions = make_demo_data() policy = SimpleDiffusionPolicy(T=20) policy.train(obs, actions, epochs=200) test_obs = np.eye(4, dtype=float)[3] print("sampled action for label 3:", policy.sample(test_obs))
obs = np.eye(4, dtype=float)[labels]把类别标签变成 one-hot 向量,模拟“当前观测条件”。self.alpha_bar = np.cumprod(self.alpha)计算累积噪声保留系数,控制前向加噪强度。x_t = np.sqrt(self.alpha_bar[t]) * a0 + np.sqrt(1 - self.alpha_bar[t]) * eps完成一步前向加噪,生成带噪声动作。grad = 2 * np.outer(feat, pred - eps_target)计算线性噪声预测模型的梯度,相当于后厨“尝一口找偏差”。self.W -= self.lr * grad用梯度下降更新模型参数,让网络逐渐学会“预测刚才加了多少噪声”。x = (x - self.beta[t] / np.sqrt(1 - self.alpha_bar[t]) * eps_hat) / np.sqrt(self.alpha[t])根据预测噪声完成一步反向去噪。if t > 0: x += np.sqrt(self.beta[t]) * np.random.randn(2)在反向过程保留随机扰动,让多模态多样性得以延续。
常见误区
误区Diffusion Policy 就是把普通神经网络输出的动作再接一个扩散模型,让动作更平滑。
正解实际上,整个策略本身就是一个条件扩散模型:输入是观测,输出是一整段动作块;网络的训练目标不是“预测动作”,而是“预测噪声”。它更像一整套“雕刻流程”,而不是最后撒一层胡椒粉。
为何常见:很多同学先接触过扩散模型生成图片,容易把去噪网络看作一个可选的图像后处理模块,忽略了它就是策略主体。
误区要处理多种正确动作,必须先把演示数据聚类成几类,再训练多个策略。
正解Diffusion Policy 不需要显式聚类。它通过连续加噪和去噪过程,天然能表达多峰分布;不同的初始随机噪声会走向不同合理动作模式。就像同一个菜谱可以通过“随机起点”变化出多种合格成品。
为何常见:因为传统分类任务常用标签来区分模式,大家容易把“多模态”等同于“多标签”。
误区机器人要稳定,就必须完全去掉随机噪声,保证给定同样观测时输出完全相同动作。
正解扩散模型的随机采样正是多样性的来源。部署时真正需要保证的是“每次采出的动作都成功”,而不是“每次完全一样”。动作分块与重规划已经提供了闭环稳定性,不需要把生成过程退化成确定性映射。
为何常见:强化学习与控制论强调“确定性策略”的稳定性,因此大家容易把随机性与不可靠画等号。
误区Diffusion Policy 既然看图像,那条件就只有摄像头画面。
正解实际系统通常同时注入视觉特征、机械臂关节角度、夹爪状态、历史动作序列和去噪步数 t。条件越丰富,策略越能感知“自己现在在哪里、手刚才做了什么”;只看图像等于让主厨只看菜谱却不看锅。
为何常见:视觉模仿学习给初学者留下的印象太深,容易忽略机器人本体状态的重要性。
面试题
Q1. Diffusion Policy 最核心的创新是什么?
- A.用扩散模型生成机器人动作序列← 正确答案
- B.用强化学习优化机械臂关节转矩
- C.用决策树规划全局路径
- D.用卡尔曼滤波估计物体位姿
答案:A。Diffusion Policy 的核心是“用扩散模型生成动作”,而不是强化学习、决策树或传统状态估计。它把动作生成看作逐步去噪过程,让多模态动作分布得以保留。
Q2. 反向去噪过程中,扩散模型主要预测什么?
- A.真实动作轨迹
- B.当前观测误差
- C.被加入的高斯噪声← 正确答案
- D.环境奖励大小
答案:C。训练时模型拟合的目标是“人为加入的高斯噪声”。只要预测出这一步加入的噪声,就能通过反向公式反推出更干净的动作,而不是直接输出最终轨迹。
Q3. 下列哪些可以作为 Diffusion Policy 的条件信息?
- A.当前视觉观测← 正确答案
- B.机械臂关节状态← 正确答案
- C.历史动作序列← 正确答案
- D.商品市场价格表
答案:ABC。视觉、关节状态、历史动作都是机器人决策所需的环境信息;商品价格与操作任务无关,不能作为动作生成条件。
Q4. 动作分块(action chunk)的含义是什么?
- A.一次只预测一个动作点
- B.一次预测未来多步动作并打包执行← 正确答案
- C.将图像切成多块输入
- D.把动作空间离散成网格
答案:B。动作分块指一次输出未来 H 步动作序列,整体去噪生成。它提升了动作连贯性,也为模型预测式重规划提供基础。
Q5. 为什么均方差模仿学习不适合多模态动作?
- A.损失函数会变成常数无法优化
- B.条件均值会模糊多个正确模式← 正确答案
- C.梯度消失导致网络不收敛
- D.动作空间通常不是向量空间
答案:B。均方差损失的最优解是条件均值。当多个正确动作差异很大时,均值落在两个模式之间,既不属于任何模式,也不可执行。这是“平均值陷阱”。
Q6. 训练 Diffusion Policy 时,损失函数主要在比较什么?
- A.输入图像与输出图像的像素差
- B.预测噪声与真实噪声的误差← 正确答案
- C.预测动作与最优动作的欧氏距离
- D.当前位姿与目标位姿的距离
答案:B。Diffusion Policy 的训练本质是噪声预测。网络输入“加噪后的动作块 + 观测条件”,输出“预测噪声”,并与真实噪声计算均方误差。
Q7. 为提升闭环性能,Diffusion Policy 部署时通常采用哪些策略?
- A.一次推理后不再更新
- B.定期做模型预测重规划← 正确答案
- C.只执行预测序列首个分块← 正确答案
- D.等待整条序列执行完毕
答案:BC。Diffusion Policy 常采用类似模型预测控制的做法:预测一段动作块后只执行其中一部分,再根据最新观测重新生成;这样即使被扰动也能快速修正。
Q8. 以下哪个是 Diffusion Policy 的典型应用场景?
- A.语音情感识别
- B.社交网络推荐
- C.机械臂柔性插装配← 正确答案
- D.数据库索引优化
答案:C。Diffusion Policy 面向机器人动作生成,典型应用是机械臂插装配、分拣、柔性物体操控等;语音、推荐和数据库不是它的主场。
Q9. 关于推理时初始随机噪声,下列说法正确的是?
- A.初始噪声应固定为零以保证稳定
- B.初始噪声决定去噪起点并影响采样多样性← 正确答案
- C.初始噪声只影响训练不影响推理
- D.初始噪声必须用预训练图像生成
答案:B。推理时从随机噪声出发,不同起点会走向不同合理动作模式;固定为零会破坏扩散模型的生成机制,也不必要地丢失多样性。
Q10. Diffusion Policy 中常用的条件注入方式包括哪些?
- A.将观测特征拼接到噪声向量← 正确答案
- B.在骨干网络中使用 FiLM 调制← 正确答案
- C.通过交叉注意力注入视觉特征← 正确答案
- D.用蚁群算法搜索全局路径
答案:ABC。条件信息可以通过拼接、FiLM 调制、交叉注意力等方式注入扩散网络;蚁群搜索属于传统路径规划,不是扩散策略的条件注入方法。