ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

扩散模型如何赋能端到端自动驾驶轨迹规划:干净轨迹与L2损失机制解析

扩散模型如何赋能端到端自动驾驶轨迹规划:干净轨迹与L2损失机制解析 说实话第一次在端到端自动驾驶的框架里看到扩散模型diffusion model规划器时我最大的疑惑不是它效果好不好而是两个看起来非常基础的问题为什么它输出的轨迹那么“干净”以及为什么训练损失要选L2而不是 L1、不是正则化、不是别的度量这两个问题问的人很多但我发现能把来龙去脉讲清楚的人很少。这篇文章就把我自己的理解、跑实验的一些经验以及复现这类模型时踩过的坑一起梳理出来。先说清楚这篇在聊什么围绕 diffusion model 做自动驾驶 End-to-End 轨迹规划的核心机制回答“为什么能输出干净轨迹”和“为什么用L2”这两个灵魂拷问顺带讲清楚扩散模型训练目标、采样策略、损失函数之间的关系。适合正在复现 diffusion planner、或者想搞清楚生成模型在规划里到底怎么起作用的人看能帮你少走不少弯路。1. 端到端规划为什么要请出扩散模型1.1 传统回归头的两个致命痛点在端到端自动驾驶里规划模块的常规做法是把感知到的障碍物、地图信息、自车状态、导航意图全部编码成特征然后送进一个回归头直接输出未来几秒的轨迹点。这个思路本身没什么毛病真正的问题出在回归头的表达力上。第一个痛点是单模态平均。前方有一辆车挡路左边可以绕、右边也可以绕合理的轨迹至少有两条。但回归头最终只能输出一条轨迹。如果你拿两条都合理的轨迹去算 L2 平均结果大概率是直直地撞向那辆车。这就是经典的“多模态求平均”问题。你可以用多个分支、多个 anchor 来缓解但分支之间怎么协调、anchor 怎么设全是额外的工程复杂度而且覆盖面始终有限。第二个痛点是概率表达不足。就算你把回归头升级成输出一个高斯分布的均值和协方差它本质上仍然只能表达“单峰”。真实驾驶场景中右转和直行是两个完全不同的决策这种概率分布明显是多峰的单峰高斯描述不了。于是就有了一个自然的想法能不能不要强行预测一条轨迹而是从一个分布里“采样”出一条轨迹这个想法正好是生成模型的强项。1.2 扩散模型把“预测轨迹”变成“生成轨迹”扩散模型做的事从直觉上理解就是从一个充满随机噪声的样本出发一步步去噪直到得到一个符合训练数据分布的结果。把这条路用在自动驾驶规划里它的角色就从“预测轨迹”变成了“生成轨迹”。用大白话对比一下回归头的思路输入信息输出唯一一条轨迹相当于在问“最可能的轨迹是什么”。扩散模型的思路输入信息定义一个轨迹分布每次从中采样一条轨迹相当于在问“有哪些轨迹是合理且可能的”。这个转变很关键因为多模态不再需要人为指定模态数了。你采样几条就出来几条采样十次可能得到十个合理轨迹的近似其中包含了左绕和右绕。前面说的“平均撞车”问题在生成框架下天然消失。不过这里有个新的疑问冒出来了既然扩散模型是从噪声开始、一路带着随机性生成的那最后采出来的轨迹会不会噪声残留、乱抖动为什么实际看到的效果反而是干净的这是很多人卡住的地方我把它单独拿出来讲。2. 为什么扩散模型能输出“干净”的轨迹2.1 先定义“干净”平滑、可行、符合专家分布在很多讨论里“干净”这个词被用得很随意导致问题说不清楚。我觉得要回答这个问题必须先明确“干净”在这里指什么。在自动驾驶轨迹这个语境下干净主要指这几件事时间维度上平滑轨迹点之间没有突然的跳变曲率连续加速度不会异常突变。空间维度上合理不穿越障碍物不压路沿和道路走向一致。行为维度上像人符合人类专家驾驶的统计特征比如变道前有转向灯提醒时段的轻微偏移、跟车时有合理的速度调整。换句话说“干净”并不是指信号处理意义上的“无噪声”而是指“落在专家轨迹分布的高概率区域里”。一辆真车留下的轨迹天然带有微小传感器噪声但扩散模型生成的是“专家意图层面的轨迹”它学到的分布已经把那些不重要的高频抖动过滤掉了。所以理解干净轨迹的关键不是模型有什么神奇的“过滤器”而是它学到的数据分布本身是干净轨迹的分布。2.2 去噪过程本身就是迭代精炼那扩散模型是怎么保证“落点”落在高概率区域的呢这要从它的采样过程说起。扩散模型的逆向采样过程可以看成一个不断向高概率区域移动的迭代过程。我们经常用分数函数score function来解释模型学到的其实是数据分布的梯度方向即 \( \nabla_x \log p(x) \)它告诉采样过程“往哪个方向调整能让轨迹更像训练数据”。每一步去噪都是在把带噪轨迹向这个方向推一点点。数学上DDPM 的采样更新可以写成\[ x_{t-1} \frac{1}{\sqrt{\alpha_t}} \left( x_t - \frac{\beta_t}{\sqrt{1 - \bar{\alpha}t}} \epsilon\theta(x_t, t, c) \right) \sigma_t z \]这个式子看着复杂但直觉很简单预测出当前轨迹里混入的噪声把它减掉再补一点随机扰动得到更干净的一步。这个过程重复 T 次每一步都在修正上一步留下的瑕疵。只要 T 足够大、网络训得足够好最终结果就会非常接近真实数据分布里的样本。打个比方给你一团泥巴让你捏一个头像。如果让你一次成型难度极高但如果允许你上千次微调每次只削掉一点点多余的部分最终成品就会相当精细。扩散模型的迭代去噪就是这种“逐步雕刻”的过程。干净不是某一步的功劳而是整个链条共同作用的结果。2.3 条件生成把轨迹绑在专家的“支撑集”上如果只是无条件的生成模型当然不知道该怎么生成“自动驾驶轨迹”。所以实际的 diffusion planner 全是条件扩散模型conditional diffusion model条件信息一般包括自车历史状态位置、朝向、速度、加速度高精地图信息车道线、路沿、中心线障碍物信息其他车、行人、静态障碍的包围框或占据网格导航意图下一目标点、意图类型有了这些条件模型学到的就不是一个笼统的“所有轨迹分布”而是“在当前场景条件 c 下的轨迹分布 p(x | c)”。这个条件分布的高概率区域集中在“当前场景下专家会怎么开”的流形上。因此采样过程即便从随机噪声出发也会被条件一步步拉回到合法轨迹附近。这也能解释为什么实际推理时即使两次采样用了不同的随机种子生成结果在宏观走向上往往是稳定一致的——条件信息把分布约束得很紧模型在高概率区域内做小幅波动而不是在全部空间里乱逛。当然如果你把引导强度调得过高可能又会走向另一个极端——轨迹过于保守多样性下降这个后面会提到。2.4 工程上的“清洗”策略候选采样与最后一步直出理论上讲扩散模型只要训练好、采样步数够输出就会干净。但工程落地时大家通常还会叠几个“保险”手段这些手段进一步强化了“干净”的观感。第一个策略是并行采样多个候选轨迹再用成本函数筛选。比如一次采样 8 条轨迹然后用碰撞成本、舒适性成本、偏移中心线成本去打分选一条最优的。相当于在“模型觉得不错”的轨迹里再套一层“物理校验”多模态候选和安全性都兼顾了这是 diffusion planner 比单支回归头更容易做好的地方。第二个策略是最后一个去噪步直接返回模型预测的 x0。在一些实现里推理时最后一步并不执行完整采样而是直接用网络输出的干净轨迹预测值作为最终结果。因为最后一步的网络头已经在预测去噪后的 x0把它取出来自然就是一条干净轨迹完全省掉了最后一步的随机噪声注入。这种做法非常实用也是“为什么输出很干净”的重要工程原因之一。还有一个容易被忽视的点如果模型在推理时用 DDIM 之类的加速采样器并且步数太少反而会产生明显的残噪或锯齿。很多“扩散模型输出不干净”的报告最后排查下来都是采样步数不足、或者跳过最后一步 x0 预测导致的。所以严格说“输出干净轨迹”是“训练目标正确 采样策略合理”共同作用的结果不是模型单方面自带的神奇属性。2.5 一个小弯路干净不等于越干净越好这里我想插一句个人经验在尝试调高条件引导强度来让轨迹更“干净”时我踩过坑。Classifier-free guidance 的引导权重调高以后轨迹确实更贴近车道中心、更平滑了代价是变道行为变得极其保守有点“死板”。因为引导越强模型就越倾向生成训练数据里出现频率最高的那类轨迹而真实驾驶中合理且多样的行为会被牺牲掉。所以扩散模型的输出具有一种“可调性”你可以在干净保守和多样激进之间做取舍。在端到端系统里这个取舍通常不是由模型结构决定的而是由采样策略和引导强度决定的。这是生成式规划器非常独特的一个优点。3. 为什么扩散模型训练一定要用L2损失3.1 从高斯加噪到L2数学上的必然很多人误以为 L2 损失只是工程上随便选的默认项其实错了。在扩散模型的训练目标里L2 几乎是推导出来的必然结论。扩散模型的前向过程是逐步加高斯噪声\[ q(x_t | x_0) \mathcal{N}(x_t; \sqrt{\bar{\alpha}_t} x_0, (1 - \bar{\alpha}_t) I) \]逆向过程也被建模成高斯分布。训练时优化的目标是最小化变分下界ELBO而 ELBO 展开后包含多个 KL 散度项每一项都是在比较两个高斯分布。高斯分布之间的 KL 散度化简到最后是一个期望形式的 L2 范数。经典的 DDPM 推导把逆向过程的均值参数化之后训练目标最终写成\[ L \mathbb{E}{t, x_0, \epsilon} \left[ \| \epsilon\theta(x_t, t, c) - \epsilon \|^2 \right] \]也就是说训练目标就是让模型预测出的噪声与真实注入的噪声尽量一致误差用 L2 范数衡量。如果换成 x0-prediction 的形式目标变为\[ L \mathbb{E} \left[ \| x_0^\theta(x_t, t, c) - x_0 \|^2 \right] \]归根结底还是 L2。为什么高斯噪声假设下 L2 这么自然因为高斯分布的负对数似然里指数部分本身就是二次型。你没法在不改变概率假设的前提下随便把 L2 换成 L1否则你实际上是在假设“噪声服从拉普拉斯分布”那个模型就不是标准扩散模型了。3.2 L1 vs L2谁的轨迹更“干净”既然训练目标出自高斯假设那是不是意味着 L1 完全不能用也不是但换 L1 会有代价尤其在轨迹生成这个具体任务里。L1 损失对离群点更鲁棒因为它的梯度幅度恒定不会因为某个点误差特别大而疯狂放大梯度。这在一些回归任务里是优点。但在扩散模型的去噪训练里你会遇到一个更实际的问题L1 在误差接近零时梯度仍然是常数模型在收敛后期容易在一个小范围内来回震荡导致最终生成的轨迹出现高频抖动。而 L2 的梯度幅度是随误差减小而减小的训练后期梯度越来越小优化过程更平滑生成的轨迹在时间序列上更稳定。另外自动驾驶轨迹评估的常用指标 ADEAverage Displacement Error和 FDEFinal Displacement Error本质上都是 L2 距离。你用 L2 做训练目标和评估指标天然同源训练时优化的方向直接对齐了最终线上评测的指标。用 L1 训练可能在鲁棒性上有好处但评估分数上往往不如 L2 好看。3.3 别搞混L2损失、L2正则化、轨迹回归L2热搜词里同时出现了“L1正则化和L2正则化”“l2范数”这些词这提醒我很多人会把几类 L2 概念混在一起谈。这里我做一个清晰的对表。概念作用对象形式作用L2 损失MSE模型预测值与真值\(|pred - true|^2\)训练目标让预测逼近真值L2 正则化Weight Decay模型权重\(\lambda |W|^2\)约束权重不要过大抑制过拟合轨迹回归 L2轨迹点集合对轨迹点逐点算欧氏距离平方再平均直接回归轨迹时的目标函数扩散模型 L2 去噪损失噪声残差或 x0 残差\(|\epsilon_\theta - \epsilon|^2\)让模型学会还原干净样本在扩散模型里论文里提到的“L2 loss”指的是最后一行即去噪目标函数的 L2 范数形式。它不是正则项不参与约束网络复杂度它是主损失函数。这个区分非常重要因为如果你把它当成正则化去理解整个训练目标就会理解错。3.4 直接用L2路径回归的问题在扩散模型里为什么不存在现在到了最容易绕晕的地方。既然轨迹可以用 L2 直接回归扩散模型的去噪损失也是 L2那扩散模型凭什么比直接回归好这不矛盾吗关键在于同样是 L2作用的位置完全不同。直接回归轨迹时模型是一步到位输出轨迹的它把多模态场景下所有可能轨迹的“期望”都算成一个点。在 L2 的均值回归作用下两条合理路径会被平均成一条不合理的中间路径。这是本质缺陷L2 作为“点到点”的损失天生鼓励求均值。扩散模型里的 L2 作用在噪声残差上目标是“把当前带噪轨迹的噪声分量估出来”它不做端到端的均值回归。生成轨迹是通过采样完成的每次采样都会在数据分布里重新选一个点。多模态信息是在采样过程中被保持住的而不是在 L2 求均值时被磨平的。用一句大白话总结回归 L2 是在逼模型输出“平均答案”扩散 L2 是在教模型识别“什么是脏的”然后靠自己一步步把脏的去掉。所以扩散模型没有继承回归 L2 的“平均病”这是它能在多模态轨迹预测上胜出的核心原因之一。4. 复现过程中的实操细节与常见问题排查4.1 训练与推理的步数该怎么选标准 DDPM 训练一般会用到 T1000 步加噪训练数据里每个样本都会随机抽一个时间步 t 来做去噪学习。推理时如果也按 1000 步反向采样速度太慢端到端系统基本扛不住。实际部署会把反向采样缩短到 2050 步常用的是 DDIM 或者 DPM-Solver 这类加速采样器。跑实验时我习惯先按 100 步采样验证模型是否正常确认训练没问题后再缩到 20 步左右测实时性。有一个规律是采样步数越少对条件信息的依赖越强条件引导的作用就越明显。如果步数太少轨迹细碎的噪声会变明显此时可以尝试最后一步直接输出模型预测的 x0而不是继续采样通常能压掉大部分残噪。4.2 训练时预测ε还是预测x0这是另一个影响 L2 损失具体形式的选择。ε-prediction网络预测噪声损失为 \(\|\epsilon_\theta - \epsilon\|^2\)这是最经典的做法训练稳定不用额外处理。x0-prediction网络直接预测干净轨迹损失为 \(\|x_0^\theta - x_0\|^2\)更直观方便推理时直接取最后一步结果但在训练后期容易出现预测均值偏移的问题。我之前复现时优先用 ε-prediction稳定之后如果推理速度不够再考虑在最后一步切换成预测 x0。注意训练目标和推理方式最好保持一致别训练用 ε-prediction推理却硬要从轨迹输出里抠 x0那样会引入不必要的误差。4.3 我踩过的坑轨迹太保守、抖动、发散这里列几个我实际遇到的问题和解法应该能帮到正在复现的人。问题一轨迹太保守全程贴着车道中心不敢变道。排查后发现是条件信息里导航意图表达得太弱模型感知到前方有障碍但不知道导航希望它变道。解决方法是把导航意图做成显式的 token 或向量拼接到条件里并加大它在训练时被随机 mask 的概率让模型学会更积极地利用意图信息。问题二静态障碍物旁边轨迹抖动。采样后轨迹本身没有碰撞但在障碍物附近出现反复的微幅摆动像在犹豫。原因是我纯靠训练时的碰撞损失来让模型避障推理时没有把碰撞成本显式加到采样指导里。后来改成在推理时对候选轨迹做碰撞校验并对过近轨迹惩罚抖动明显消失。问题三训练发散。扩散模型对学习率比普通回归头敏感得多。我一开始用标准规划模型惯用的 3e-4 学习率结果损失曲线前期下降正常中途突然跳变。降到 1e-4 并加上线性 warmup 之后训练就稳定了。扩散模型的去噪任务是逐时刻学习的不同 t 的难度差异很大学习率太高会破坏已经学好的低噪声步。问题四训练正常但测试输出脏噪声。基本是采样器步数不足或者没有对数噪声尺度做校正。优先检查是否用对了噪声调度器对应的采样器以及有没有在最后一步跳过随机噪声注入。4.4 评测指标怎么选扩散模型规划器的评测我习惯看这几项ADE/FDE 用来衡量轨迹精确度碰撞率用来衡量安全性加速度/曲率变化用来衡量舒适性多次采样的轨迹方差用来衡量多样性。需要提醒一点ADE/FDE 都是 L2 类的指标扩散模型整体性能通常是通过“采样一批轨迹然后选最优”的方式评测的这时它更容易拿到好的 FDE因为候选多最终点的命中概率更高。但如果只看单次采样扩散模型不一定比精细调优过的回归头强。实际部署时要根据你的场景决定用哪种评测口径别被指标刷得过于乐观。5. 一些更进一步的思考5.1 从“生成轨迹”到“生成策略”扩散模型在自动驾驶里的潜力不止于输出一条轨迹。现在很多工作在试图把扩散模型用到更底层的控制策略上比如 Diffusion Policy 这类思路在机器人操作里已经验证了效果。它的核心优势是一致的能表达多模态行为而且训练目标统一。往这个方向延伸未来端到端模型完全可能把决策、规划、控制放在一个生成式框架里统一建模中间层的很多手工设计就有机会被取代。5.2 与端到端感知-规划大框架的配合在实际的端到端框架中扩散规划器并不是孤立的模块。它需要感知模块提供障碍物和地图的向量化表达也需要有机制把多帧历史信息和导航意图编码成条件向量。我在实验里的体会是感知特征的质量直接决定扩散模型条件分布的质量。如果感知输出的框抖动很大再好的生成式规划器也只能在“脏条件”上生成“看似平滑但语义不一致”的轨迹。所以做 diffusion planner 之前先保证你的感知特征是可用的别一上来就调采样参数。比较值得留意的方向是把地图、障碍物、历史轨迹、导航意图如何做成一个统一的条件编码器这个编码器的信息泄露会直接反映在轨迹多样性上。我们团队在实验中发现把导航意图做得越清楚模型输出的轨迹就越“有主见”而不是在多个合理行为之间犹豫。5.3 一个很有用的工程小技巧最后分享一个对我帮助很大的操作在训练条件扩散模型时对条件信息做随机的“信息丢弃”也就是类似 classifier-free guidance 的做法。以一定概率把导航意图丢成空或者把历史轨迹对齐失败的数据随机混入。一开始我以为这会损害精度结果反而提升了鲁棒性模型在条件信息不完整时也不会崩坏生成轨迹的干净程度和稳定性都有提升。如果遇到推理时感知结果偶发抖动的情况这个技巧值得一试。这是我复现扩散模型规划器以来收获最大的一个经验。生成式规划器不是简单地把回归头换成 UNet 就完事了它的训练、采样、条件设计、评测方式是一个整体系统。把每个环节的关系理清楚“为什么输出干净”和“为什么用L2”这类问题自然就有了答案。
返回列表