资讯动态

自动驾驶:扩散模型作为规划器

发布时间:2026/10/23 6:38:18 来源:尧图企业网站定制
端到端范式下,自动驾驶规划器几乎无一例外地被训练为回归:输入场景特征,输出一条轨迹,损失函数是均方误差(MSE)。本文论证这一范式的结构性缺陷——在多模态驾驶场景中,MSE 的最优解是各模态的条件期望,而条件期望往往不在任何一条合理轨迹上。同一场景既可绕左也可绕右时,回归输出的均值轨迹恰好穿过正中间的障碍物。本文的演示复现了这一失败:回归规划器的最小间距为 0.00 m(碰撞),而一个仅 2.6 万参数、训练约 40 秒的扩散模型,通过分布采样 代价打分,最小间距 2.58 m 且覆盖两个模态。本文的核心论点有三:其一,规划的多模态性不是边缘情况,而是驾驶决策的常态;其二,扩散模型的价值不在于生成得逼真,而在于把输出一条轨迹改为从轨迹分布中采样,从而把模式覆盖与模式选择解耦为两个各自可控的阶段;其三,场景条件有三种注入方式(训练条件化、采样时引导、采样后重排),小模型场景下第三种最稳健。扩散规划器是规划问题表述方式的更换;它的真实代价是多步去噪的算力,而蒸馏与截断式架构正在快速摊薄这一代价。1.规划不是回归过去数年,规划模块的神经网络化沿一条清晰的路线推进:从模仿学习直接回归轨迹,到端到端架构中规划头输出轨迹序列。形式上,它们共享同一个表述——给定场景,预测轨迹,训练目标为最小化。这个表述隐含了一个假设:给定场景,存在唯一正确的轨迹,数据中的其他轨迹只是围绕它的噪声。驾驶场景不满足这个假设。前方慢车,绕左与绕右同样合理;四路口相遇,让与抢各有其理;同一条走廊,不同司机会开出不同的走法。专家数据天然是多模态分布——而多模态分布恰恰是回归的难题。这一困境并非新发现。2019 年 Waymo 的 MultiPath 就放弃了直接回归,改用锚轨迹分类 残差回归来保留多模态[5];此后多假设、多头预测等工程变体层出不穷。但这些都是修补:模型的输出形式仍是若干条固定候选,模态数量与位置由人工先验决定。扩散模型提供的是另一条路:不预设模态,直接建模轨迹的完整分布,从中采样。2.均值坍缩MSE 损失下,最优预测器是条件期望:(对关于求导即得。)若是双峰分布——例如 50% 的专家绕左(m)、50% 绕右(m)——则条件期望为:。两条合理轨迹的均值,是一条谁都不会走、且正好撞上障碍物的轨迹。这与分类任务不用 MSE 回归类别标签是同一个道理,只是在轨迹空间中,均值坍缩的后果不是分类错误,而是物理碰撞。3.扩散模型把规划改成采样扩散模型分两个过程[1]:前向加噪(固定,不学习):对真实轨迹逐步添加高斯噪声,,经步后近似纯高斯。记,可一步采样:。反向去噪(学习):训练网络预测加入的噪声,损失为采样时从出发,按 ancestral 公式迭代:去噪采样的模式选择由采样路径中的随机项决定:不同的初始噪声把轨迹拉向不同的模态盆地,去噪过程只是把样本搬回数据流形。因此次采样天然得到条分属不同模态的轨迹——多模态覆盖不需要任何专门设计,它是迭代去噪的固有性质。相比之下,回归网络的前向是确定性的,一次前向只能得到一个点;要多个候选,只能靠人工多假设机制。对规划而言,这个性质改变的不是输出质量,而是问题结构:生成(覆盖所有合理走法)与决策(选定一种走法)被拆成两个独立阶段,各自可用最合适的工具——前者用生成模型,后者用代价函数。4.条件注入的三种方法扩散规划器绕不开的问题:场景条件(障碍在哪、导航去哪)如何进入采样?文献中形成三条路线:路线一:训练条件化。条件与噪声轨迹一并输入去噪网络[2][3],配合 classifier-free guidance 放大条件影响。表达能力强,但对模型容量与训练量有实质要求。路线二:采样时引导。训练无条件模型,采样过程中沿代价函数的负梯度修正去噪方向[2][8](CTG 用此机制实现可控交通流生成)。灵活:换一个代价函数即换一种条件,无需重训;但每步去噪需额外一次梯度反传。路线三:采样后重排(best-of-N)。采样 $N$ 条候选,用代价函数(碰撞、间距、平顺、进度)打分取最优。最简单、最稳健,也是量产管线中最常见的形态——扩散头负责给出多样的合理候选,安全与偏好判断交给显式打分器。三条路线不是互斥的,量产系统中常见组合:粗粒度条件走训练,细粒度偏好走引导或重排。5.代码演示5.1场景与设置自车沿轴以 10 m/s 行驶,前方 25 m 同车道有一辆慢车,左右相邻车道(车道宽 3.6 m)均可绕行。轨迹为 20 个路点(步长 0.2 s,时域约 4 s),用横向序列表示(纵向步长固定为 2 m)。专家数据 4096 条:50% 绕左、50% 绕右的 S 形变道,叠加 0.12 m 噪声——对称双模态,回归的最坏情况。两个被试模型均为三层 MLP、规模相当(参数量约 1.9 万与 2.6 万):回归规划器以障碍状态为条件直接输出序列;扩散规划器为无条件 DDPM($T200$ 步,线性噪声表)——场景条件不进入网络,而经代价打分注入,训练 8000 步、采样 200 步。5.2结果指标回归规划器扩散规划器障碍居中:输出形态单条轨迹(条件期望)16 条采样,左 11 / 右 5障碍居中:最小间距0.00 m(碰撞)选定轨迹 2.58 m障碍左偏 1.2 m:Top-3 模态—(未评测)右 / 左 / 右(打分改选宽侧)障碍左偏 1.2 m:选定间距—3.58 m单次推理耗时1 ms(一次前向)120 ms(200 步去噪)(a) 专家数据的双模态分布;(b) 回归输出平直穿过障碍,红色标记处最小间距 0.00 m——注意其训练是成功的;(c) 扩散 16 次采样覆盖两个模态,绿色为打分选定;(d) 障碍左偏 1.2 m 后,同一个模型、重新采样的 16 条候选(左 13 / 右 3),代价打分把选择翻转到间距更宽的绕右侧。64 条轨迹从纯高斯噪声逐步组织成双模态云,直观展示模式在去噪中分化。本文在实现过程中对训练条件化路线做了完整尝试,其失败模式有普遍参考价值:1. 首先验证核心机制:无条件 DDPM 在标量双模态分布上左占比 0.52、在 20 维轨迹分布上 0.55(64 采样直方图双峰清晰)2. 加入条件后,2.6 万参数的去噪网络始终欠拟合条件分布:以障碍横偏为自变量对采样做五点扫描,专家规则下左占比应从 0.9(障碍偏右,绕左让行)单调过渡到 0.1(障碍偏左)。四种条件化变体(加宽条件特征、FiLM 调制、余弦噪声表 classifier-free guidance、线性噪声表 classifier-free guidance)逐一尝试:加宽特征版完全平坦(左占比恒 0.22),FiLM 无改善,余弦表 guidance 版倒向单侧(左占比全为 0),最好的线性表 guidance 版方向单调正确、幅度严重不足——障碍居中(专家左右各半)时左占比仅 0.12,障碍偏右(应 0.9)时仅 0.36。小网络的容量被均匀时间步下的高噪声步主导,条件信号(集中在中等噪声区间)学不动;3. classifier-free guidance 在条件欠拟合时放大的是残余偏差而非条件差,余弦噪声表则在序列末端引入数值放大步,二者叠加反而更差。均告失败。这组阴性结果指向:条件扩散的表达能力红利,要大到一定模型规模才能兑现;小模型 小数据场景下,无条件生成 采样后重排是更稳定的起点。5.3代码# -*- coding: utf-8 -*- 扩散模型当规划器 | 演示:回归规划的均值坍缩 vs 扩散采样的模式覆盖 场景:自车沿 x 行驶,前方同车道有慢车(障碍),左右相邻车道均可绕行。 专家数据为对称双模态分布(50% 绕左 / 50% 绕右)——这正是回归规划器的 最坏情况:多模态分布的条件期望不在数据流形上。 对照: 1) 回归规划器:MLP 直接回归 y 序列,MSE 最优解 条件期望 → 穿过障碍; 2) 扩散规划器:DDPM 学习轨迹分布 → 采样覆盖两个模态 → 代价打分选优。 场景条件(障碍位置)不经训练注入,而是通过代价函数在采样端生效 import os import time import numpy as np import torch import torch.nn as nn import matplotlib.pyplot as plt import matplotlib.font_manager as fm from matplotlib import animation from matplotlib.patches import Rectangle # ---------- 中文字体 ---------- for _f in (Microsoft YaHei, SimHei): if any(_f f.name for f in fm.fontManager.ttflist): plt.rcParams[font.sans-serif] [_f] break plt.rcParams[axes.unicode_minus] False # ---------- 配色 ---------- C_A #2a78d6 # 蓝:绕左模态 C_B #eb6834 # 橙:绕右模态 C_DIST #1baf7a # 绿:选定轨迹 C_LIMIT #d03b3b # 红:回归失败/碰撞 C_GRID #e1e0d9; C_AXIS #c3c2b7; C_INK #0b0b0b; C_INK2 #52514e C_MUTED #898781; C_ROAD #f0efec; C_EDGE #c3c2b7; C_SURF #fcfcfb # ---------- 场景参数 ---------- LANE_W 3.6 # 车道宽 [m] Y_L, Y_R LANE_W, -LANE_W # 相邻车道中心(左 / 右) N_WP 20 # 轨迹点数 DX_STEP 2.0 # 每点纵向步长 v·DT 10×0.2 [m] X_GRID np.arange(N_WP) * DX_STEP # 0,2,...,38 m X_SHIFT0, X_SHIFT1 6.0, 18.0 # 横向变道起止 [m] OBS_HALF_L, OBS_HALF_W 2.4, 0.95 # 障碍包围盒半长/半宽 [m](含自车余量) SEED 42 torch.manual_seed(SEED) rng np.random.default_rng(SEED) OUT_DIR os.path.dirname(os.path.abspath(__file__)) # # 1. 专家数据:对称双模态分布 # def smoothstep(x): u np.clip((x - X_SHIFT0) / (X_SHIFT1 - X_SHIFT0), 0.0, 1.0) return 3 * u ** 2 - 2 * u ** 3 def make_expert(n, rng): 双模态专家轨迹:y ±3.6 · S 形变道 噪声 shape smoothstep(X_GRID)[None, :] mode (rng.uniform(0, 1, n) 0.5).astype(np.float64) * 2 - 1 # 1 左 / -1 右 traj mode[:, None] * Y_L * shape rng.normal(0, 0.12, (n, N_WP)) return traj.astype(np.float32), mode def dmin_to_box(traj, x_obs, y_obs): 轨迹点到障碍 AABB 的最小距离(自车按中心线,余量并入盒宽) dx np.maximum(np.abs(X_GRID[None, :] - x_obs) - OBS_HALF_L, 0.0) dy np.maximum(np.abs(traj - y_obs) - OBS_HALF_W, 0.0) return np.hypot(dx, dy).min(axis1) # # 2. 网络 # def time_embed(t, dim32): half dim // 2 freqs torch.exp(torch.linspace(np.log(1e-3), np.log(1e3), half)) ang t.float()[:, None] * freqs[None, :] return torch.cat([torch.sin(ang), torch.cos(ang)], dim1) class Regressor(nn.Module): 回归基线:障碍状态 → y 序列(一次前向) def __init__(self, cond_dim2, n_wpN_WP, hid128): super().__init__() self.net nn.Sequential( nn.Linear(cond_dim, hid), nn.SiLU(), nn.Linear(hid, hid), nn.SiLU(), nn.Linear(hid, n_wp)) def forward(self, c): return self.net(c) class Denoiser(nn.Module): ε 预测网络:输入 [y_t, 时间嵌入] → 噪声 ε def __init__(self, n_wpN_WP, hid128, tdim32): super().__init__() self.tdim tdim self.net nn.Sequential( nn.Linear(n_wp tdim, hid), nn.SiLU(), nn.Linear(hid, hid), nn.SiLU(), nn.Linear(hid, n_wp)) def forward(self, y_t, t): return self.net(torch.cat([y_t, time_embed(t, self.tdim)], dim1)) # # 3. DDPM(前向加噪 / 反向去噪) # class DDPM: def __init__(self, T200, beta01e-4, beta10.02): self.T T beta torch.linspace(beta0, beta1, T) alpha 1.0 - beta abar torch.cumprod(alpha, dim0) self.beta, self.alpha, self.abar beta, alpha, abar def add_noise(self, y0, t, eps): a self.abar[t][:, None] return a.sqrt() * y0 (1 - a).sqrt() * eps def sample(self, model, K): ancestral 采样:纯高斯 → 轨迹;返回 [K,N_WP] 与各步快照 y torch.randn(K, N_WP) snaps {} for t in range(self.T - 1, -1, -1): tt torch.full((K,), t, dtypetorch.long) with torch.no_grad(): eps model(y, tt) coef self.beta[t] / (1 - self.abar[t]).sqrt() y (y - coef * eps) / self.alpha[t].sqrt() if t 0: y y self.beta[t].sqrt() * torch.randn_like(y) snaps[t] y.clone() return y, snaps def train(model, steps, batch, lr, loss_fn): opt torch.optim.AdamW(model.parameters(), lrlr) for _ in range(steps): idx torch.randint(0, N_DATA, (batch,)) opt.zero_grad() loss loss_fn(idx) loss.backward() opt.step() return loss.item() # # 4. 代价打分与选定 # def score(traj, dmin_arr): 轨迹代价:硬安全 间距偏好 平顺性 终点回正 c_clear 10.0 * np.maximum(1.2 - dmin_arr, 0.0).max() # 硬安全 c_clear 0.3 * max(0.0, 3.0 - dmin_arr.min()) # 软偏好:间距越宽越好 c_smooth 0.5 * ((np.diff(traj, 2)) ** 2).sum() c_end 0.1 * traj[-1] ** 2 return c_clear c_smooth c_end def pick_best(samples, x_obs, y_obs): dmins dmin_to_box(samples, x_obs, y_obs) costs np.array([score(s, d) for s, d in zip(samples, dmins)]) order np.argsort(costs) return order, costs, dmins # # 5. 绘图 # def draw_car(ax, x, y, colorC_MUTED, labelNone): ax.add_patch(Rectangle((x - OBS_HALF_L, y - OBS_HALF_W), 2 * OBS_HALF_L, 2 * OBS_HALF_W, fccolor, ecC_EDGE, lw1.0, zorder4, labellabel)) def style_ax(ax, title, ylabFalse): ax.set_facecolor(C_ROAD) ax.axhline(0, colorC_EDGE, lw1.4, zorder1) # 本车道中心 for yl in (Y_L, Y_R): ax.axhline(yl, colorC_EDGE, lw1.0, ls--, zorder1) ax.set_xlim(-2, 40) ax.set_ylim(-6.2, 6.2) ax.grid(True, colorC_GRID, lw0.7) for s in ax.spines.values(): s.set_color(C_AXIS) ax.set_title(title, fontsize11, colorC_INK2) if ylab: ax.set_ylabel(横向 y [m], fontsize10, colorC_INK2) ax.set_xlabel(纵向 x [m], fontsize10, colorC_INK2) def plot_traj(ax, traj, color, lw1.6, alpha0.9, zorder3, labelNone): ax.plot(X_GRID, traj, colorcolor, lwlw, alphaalpha, zorderzorder, labellabel) def make_figure(traj, mode, reg, ddpm, model_d, x1, y1, y2): fig, axes plt.subplots(2, 2, figsize(12.5, 9.0), dpi180) fig.patch.set_facecolor(C_SURF) fig.suptitle(扩散模型当规划器 | 回归的均值坍缩 vs 扩散的模式覆盖, fontsize14.5, fontweightbold, colorC_INK) # (a) 专家数据:双模态 ax axes[0, 0] style_ax(ax, (a) 专家数据:同一场景、两种走法(对称双模态分布), ylabTrue) draw_car(ax, x1, y1) ax.text(x1, y1 - 2.1, 慢车, fontsize9, colorC_INK2, hacenter, zorder4) sel rng.choice(len(traj), 60, replaceFalse) for i in sel: plot_traj(ax, traj[i], C_A if mode[i] 0 else C_B, lw1.1, alpha0.55) plot_traj(ax, traj[sel[0]], C_A, lw2.2, alpha1.0, label绕左模态) plot_traj(ax, traj[sel[1]], C_B, lw2.2, alpha1.0, label绕右模态) ax.legend(loclower right, fontsize8.5, framealpha0.92) # (b) 回归规划器:均值坍缩 ax axes[0, 1] style_ax(ax, (b) 回归规划器:MSE 最优解 条件期望 → 穿过障碍, ylabTrue) for i in rng.choice(len(traj), 40, replaceFalse): plot_traj(ax, traj[i], #c9c8c0, lw0.8, alpha0.5) pred reg(torch.tensor([[x1 / 30.0, y1 / 1.5]], dtypetorch.float32))[0].detach().numpy() plot_traj(ax, pred, C_LIMIT, lw2.6, label回归输出(条件期望)) dmin_reg dmin_to_box(pred[None, :], x1, y1)[0] gaps np.hypot(np.maximum(np.abs(X_GRID - x1) - OBS_HALF_L, 0), np.maximum(np.abs(pred - y1) - OBS_HALF_W, 0)) k_bad int(np.argmin(gaps)) ax.plot(X_GRID[k_bad], pred[k_bad], X, ms13, colorC_LIMIT, zorder6) ax.annotate(f最小间距 {dmin_reg:.2f} m → 碰撞, xy(X_GRID[k_bad], pred[k_bad]), xytext(X_GRID[k_bad] - 16, pred[k_bad] 2.6), fontsize9.5, colorC_LIMIT, arrowpropsdict(arrowstyle-, colorC_LIMIT, lw1.2)) draw_car(ax, x1, y1) ax.legend(loclower right, fontsize8.5, framealpha0.92) # (c) 扩散采样:模式覆盖 打分选优(查询 1:障碍居中) ax axes[1, 0] style_ax(ax, (c) 扩散规划器:16 次采样覆盖两个模态 → 代价打分选优, ylabTrue) s1, _ ddpm.sample(model_d, 16) s1 s1.numpy() is_left1 s1.mean(axis1) 0 for i in range(16): plot_traj(ax, s1[i], C_A if is_left1[i] else C_B, lw1.1, alpha0.55) order1, costs1, dmins1 pick_best(s1, x1, y1) k1 int(order1[0]) plot_traj(ax, s1[k1], C_DIST, lw2.8, labelf打分选定(间距 {dmins1[k1]:.1f} m)) draw_car(ax, x1, y1) ax.text(0.5, Y_L 1.6, f左 {int(is_left1.sum())} / 右 {int((~is_left1).sum())}, fontsize9.5, colorC_INK2) ax.legend(loclower right, fontsize8.5, framealpha0.92) # (d) 条件注入(代价打分):障碍左偏 → 同一模型,选优变为绕右 ax axes[1, 1] style_ax(ax, (d) 场景变化:障碍左偏 1.2 m → 打分改选更宽的一侧, ylabTrue) s2, _ ddpm.sample(model_d, 16) s2 s2.numpy() is_left2 s2.mean(axis1) 0 for i in range(16): plot_traj(ax, s2[i], C_A if is_left2[i] else C_B, lw1.1, alpha0.55) order2, costs2, dmins2 pick_best(s2, x1, y2) k2 int(order2[0]) plot_traj(ax, s2[k2], C_DIST, lw2.8, labelf打分选定(间距 {dmins2[k2]:.1f} m)) draw_car(ax, x1, y2) ax.text(x1, y2 - 2.2, 障碍左偏, fontsize9, colorC_INK2, hacenter, zorder4) ax.text(0.5, Y_L 1.6, f左 {int(is_left2.sum())} / 右 {int((~is_left2).sum())}, fontsize9.5, colorC_INK2) ax.legend(loclower right, fontsize8.5, framealpha0.92) fig.tight_layout(rect(0, 0, 1, 0.955)) out os.path.join(OUT_DIR, diffusion_planner.png) fig.savefig(out, facecolorC_SURF) plt.close(fig) print(f已保存: {out}) return pred, dmin_reg, (s1, is_left1, order1, costs1, dmins1), \ (s2, is_left2, order2, costs2, dmins2) def make_gif(ddpm, model_d, x1, y1): 去噪过程动画:64 条轨迹从纯高斯逐步组织成双模态云 s_all, snaps ddpm.sample(model_d, 64) s_all s_all.numpy() order, costs, dmins pick_best(s_all, x1, y1) k_best int(order[0]) frames list(np.unique(np.linspace(ddpm.T - 1, 0, 36).astype(int))) fig, ax plt.subplots(figsize(8.6, 4.4), dpi110) fig.patch.set_facecolor(C_SURF) def update(i): ax.clear() t frames[min(i, len(frames) - 1)] style_ax(ax, fDDPM 反向去噪 | 步 t {t}(共 {ddpm.T} 步), ylabTrue) yt snaps[t].numpy() if t 0 else s_all for j in range(len(yt)): plot_traj(ax, yt[j], #b9b8b0, lw0.8, alpha0.6) if t 0: for j in range(len(s_all)): col C_A if s_all[j].mean() 0 else C_B plot_traj(ax, s_all[j], col, lw1.0, alpha0.6) plot_traj(ax, s_all[k_best], C_DIST, lw2.8, labelf打分选定(间距 {dmins[k_best]:.1f} m)) ax.legend(loclower right, fontsize9, framealpha0.92) draw_car(ax, x1, y1) ani animation.FuncAnimation(fig, update, frameslen(frames) 4, interval110) out os.path.join(OUT_DIR, diffusion_planner.gif) ani.save(out, writeranimation.PillowWriter(fps9), savefig_kwargs{ facecolor: C_SURF}) plt.close(fig) print(f已保存: {out}) return k_best, dmins[k_best], is_left_frac(s_all) def is_left_frac(samples): return float((samples.mean(axis1) 0).mean()) # # 6. 主流程 # def main(): global N_DATA print( * 64) print(扩散模型当规划器 | DDPM(T200)vs 回归基线 | PyTorch CPU) print( * 64) # ---- 数据 ---- N_DATA 4096 traj, mode make_expert(N_DATA, rng) x1, y1, y2 25.0, 0.0, 1.2 # 查询 1:障碍居中;查询 2:障碍左偏 1.2 m print(f数据:{N_DATA} 条专家轨迹(对称双模态 ±{Y_L:.1f} m)) # ---- 回归基线(条件:障碍位置) ---- t0 time.time() reg Regressor() Y_t torch.tensor(traj) C_t torch.tensor(np.stack([np.full(N_DATA, x1 / 30.0), rng.uniform(-0.4, 0.4, N_DATA) / 1.5], axis1).astype(np.float32)) def loss_reg(idx): return ((reg(C_t[idx]) - Y_t[idx]) ** 2).mean() train(reg, steps3000, batch256, lr1e-3, loss_fnloss_reg) t_reg time.time() - t0 # ---- 扩散规划器(无条件学习轨迹分布) ---- t0 time.time() ddpm DDPM(T200) model_d Denoiser() def loss_diff(idx): y0 Y_t[idx] t torch.randint(0, ddpm.T, (len(idx),)) eps torch.randn_like(y0) y_t ddpm.add_noise(y0, t, eps) return ((model_d(y_t, t) - eps) ** 2).mean() train(model_d, steps8000, batch256, lr1e-3, loss_fnloss_diff) t_diff time.time() - t0 print(f训练:回归 3000 步({t_reg:.1f} s)| 扩散 8000 步({t_diff:.1f} s)) # ---- 采样耗时 ---- t0 time.time() ddpm.sample(model_d, 16) t_sample time.time() - t0 print(f采样:16 条轨迹 × 200 步去噪 {t_sample * 1000:.0f} ms f(回归一次前向 1 ms)) # ---- 图 ---- (pred, dmin_reg, q1, q2) make_figure(traj, mode, reg, ddpm, model_d, x1, y1, y2) s1, is_left1, order1, costs1, dmins1 q1 s2, is_left2, order2, costs2, dmins2 q2 # ---- 打分排序(查询 2:条件经代价函数注入) ---- sides1 [左 if is_left1[k] else 右 for k in order1[:3]] sides2 [左 if is_left2[k] else 右 for k in order2[:3]] # ---- GIF ---- k_gif, dmin_gif, frac_gif make_gif(ddpm, model_d, x1, y1) # ---- 指标 ---- print() print( 查询 1:障碍居中 (x25 m, y0)) print(f 回归:最小间距 {dmin_reg:.2f} m → f{碰撞(均值坍缩) if dmin_reg 1.0 else 安全}) print(f 扩散:左 {int(is_left1.sum())} / 右 {int((~is_left1).sum())} f | 代价 Top-3 模态:{/.join(sides1)} f | 选定间距 {dmins1[order1[0]]:.2f} m) print(f 查询 2:障碍左偏 (y{y2} m)——同一模型,条件经代价注入) print(f 扩散:左 {int(is_left2.sum())} / 右 {int((~is_left2).sum())} f | 代价 Top-3 模态:{/.join(sides2)} f | 选定间距 {dmins2[order2[0]]:.2f} m) print(f(GIF 64 采样左占比 {frac_gif:.2f} | 选定间距 {dmin_gif:.2f} m)) if __name__ __main__: main()6.产业现状与实时性从 2022 年至今,扩散规划器完成了从论文到量产管线的跨越:奠基(2022):Diffuser 首次把轨迹作为生成对象、规划作为引导采样表述为通用框架[2];Decision Diffuser 证明约束与奖励都能以条件生成的方式进入决策[3];Diffusion Policy 在机器人操作上以多模态专家数据为核心论据确立了生成式策略的优势[4]。交通仿真:CTG 用引导扩散生成可控的交互交通流,为闭环评测提供场景供给[8]——与世界模型在评测端的角色互补。端到端上车(2024–2025):DiffusionDrive 提出截断式扩散,把端到端规划的去噪步数压到 1–2 步[6];Diffusion Planner(2025)以灵活引导为卖点,支持多类约束即插即用[7]。实时性是这一路线的真实代价:本文演示中 200 步去噪需 120 ms(CPU、16 条采样),而回归一次前向不足 1 ms。当前的工程答案是蒸馏——渐进蒸馏[9]与一致性模型[10]可以把数十步去噪压缩到 1–4 步,DiffusionDrive 即以此把扩散头做到端到端管线可接受的开销[6]。方向上,算力曲线站在扩散这一边:采样步数每降一档,相对回归的开销就小一个量级,而模式覆盖能力不随蒸馏消失。7.局限与讨论模式覆盖不等于模式正确。扩散模型学到的是专家数据的分布,包括专家的坏习惯;采出的轨迹也不保证运动学可行。可行性与安全性仍需显式层(打分、约束投影或安全滤波)兜底——生成式架构没有取消安全工程,只是移动了它的位置。打分器成为新的规则之墙。路线三中,代价函数决定最终输出,这意味着规则与偏好从网络内部移到了网络外部。好处是透明可审计;代价是打分函数的设计质量重新成为系统上限——这与世界模型篇讨论的评测循环性同构:把智能移出黑盒的每一部分,都会在白盒里留下一个同样难写的新组件。8.参考文献[1] Ho J., Jain A., Abbeel P. Denoising Diffusion Probabilistic Models. arXiv:2006.11239, 2020.[2] Janner M., Du Y., Tenenbaum J., Levine S. Planning with Diffusion for Flexible Behavior Synthesis (Diffuser). ICML, 2022. arXiv:2205.09991.[3] Ajay A., Du Y., Gupta A., Tenenbaum J., Jaakkola T., Agrawal P. Is Conditional Generative Modeling all you need for Decision-Making? (Decision Diffuser). ICLR, 2023. arXiv:2211.15657.[4] Chi C., Xu Z., Feng S., Cousineau E., Du Y., Burchfiel B., Russell S., Song S. Diffusion Policy: Visuomotor Policy Learning via Action Diffusion. RSS, 2023. arXiv:2303.04137.[5] Chai Y., Sapp B., Bansal M., Anguelov D. MultiPath: Multiple Probabilistic Anchor Trajectory Hypotheses for Behavior Prediction. arXiv:1910.05449, 2019.[6] Liao B., Chen S., Yin H. et al. DiffusionDrive: Truncated Diffusion Model for End-to-End Autonomous Driving. arXiv:2411.15139, 2024.[7] Zheng Y., Liang R., Zheng K. et al. Diffusion-Based Planning for Autonomous Driving with Flexible Guidance. arXiv:2501.15564, 2025.[8] Zhong Z., Rempe D., Xu D. et al. Guided Conditional Diffusion for Controllable Traffic Simulation (CTG). arXiv:2210.17366, 2022.[9] Salimans T., Ho J. Progressive Distillation for Fast Sampling of Diffusion Models. ICLR, 2022. arXiv:2202.00512.[10] Song Y., Dhariwal P., Chen M., Sutskever I. Consistency Models. ICML, 2023. arXiv:2303.01469.

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑