做自动驾驶预测模型的同学,大概率都经历过这个尴尬时刻:模型在公开数据集上刷新了 ADE/FDE 纪录,上车路测却被安全员频繁接管。指标漂亮,实际表现拉胯,问题往往出在“平均指标”掩盖了场景差异。我这两年一直在折腾轨迹预测模型的评估体系,最后发现真正管用的做法就是标题里那句话——场景驱动评估(Scenario-Driven Evaluation),只测“重要的东西”,按场景切分、按难度分层、按危险度加权。这篇文章不讲花哨理论,直接给一套可以落地的评估框架,包括场景分类方案、分层指标计算方法、自动化场景挖掘工具选型,以及我踩过的几个坑。适合做预测算法、模型迭代、仿真评测的团队参考。
1. 先聊聊为什么平均指标会骗人
1.1 ADE/FDE 只告诉你“平均误差”,不告诉你“哪里危险”
业界评估轨迹预测模型,最常用的两个指标就是 ADE(Average Displacement Error,平均位移误差)和 FDE(Final Displacement Error,最终位移误差)。ADE 算的是整条预测轨迹和真值轨迹逐点误差的平均,FDE 看的是预测终点和真实终点的距离。这两个指标好处是简单、可复现、论文里能直接横向对比,坏处也恰恰在这里:它们把所有场景的误差揉在一起取平均,一旦场景分布不均匀,平均值就会把危险场景的“大误差”稀释掉。
我举个例子你就明白了。假设测试集里有 90% 的高速直线巡航场景,模型预测这类场景几乎零误差,ADE 只有 0.1 米;剩下 10% 是城市路口左转、旁边有电瓶车抢行的常见场景,模型在这里经常预测偏 2 到 3 米。表面上看整体 ADE 只有 0.29 米,数字很好看,但真正决定系统能不能安全通过路口的,恰恰是那 10% 的场景。如果你只盯着平均指标迭代模型,优化算法会自动“抄近路”:把所有精力花在把已经很好的高速场景打磨得更好,因为这样做对平均分的贡献最大,而路口场景几乎不参与评分。最后模型自然就变成了“高速王者、路口哑巴”。
更麻烦的是,平均指标还会掩盖预测方差的问题。同一个场景下,模型可能这次预测得很好,下次预测得离谱,但平均下来误差好像不大。真实自动驾驶系统对预测的要求是“持续稳定”,不是“偶尔精准”。一次失误的预测如果撞上决策规划模块恰好没兜住,就是一次安全事故。所以你会发现,业界真正敢上路的预测团队,早就不把公开榜的平均指标当唯一准绳了,大家更愿意看的是“在危险场景下你的模型表现到底如何”。
1.2 场景分布不均让评估结果失真
如果你做过一段时间的预测模型训练,应该能感受到一个明显现象:公开数据集的场景分布和真实道路场景分布存在巨大差异。公开数据集为了覆盖多样性,会刻意采集很多类型的数据,但受限于采集成本和标注成本,高频场景仍然占大头。比如城市道路的直行、低速跟车这类简单场景可能占了 60% 以上,而高交互、高风险场景在所有数据里可能连 10% 都不到。
这种分布不均会带来一个连锁反应:模型在训练时大量见简单场景,少量见复杂场景。评估时如果沿用相同的分布,模型打出来的分数自然很好看,但这只是“同分布测试”的成绩单,代表它学会了训练集的统计学规律,不代表它真正掌握了复杂场景下的推理能力。这就像学生考试,如果每次都考当天讲过的例题,成绩肯定漂亮;可一旦题目换个场景,把知识点放到复杂应用题里,真实水平立刻见分晓。
所以,光换测试集还不够,关键是换“评估视角”。场景驱动评估的核心思想,就是强行把分布掰开:把直行、转弯、变道、汇入、路口博弈、避让行人这些场景拆开来看,分别测每个场景下的表现。这样一来,简单场景的分数不再给复杂场景“填坑”,模型在哪个场景弱,一目了然。也正因为评估视角变了,优化方向才会跟着变——团队才会去重视那个 10% 的危险场景,而不是把资源全砸在 90% 的简单场景上。
1.3 回归均值的陷阱与“分数通胀”
还有一个做评估的人要特别警惕的现象,我管它叫“分数通胀”。意思是,模型在训练集上的表现越来越好,在测试集上的平均指标也越来越好,但实际驾驶表现却几乎没提升,甚至某些场景还在倒退。原因是模型的容量是有限的,当它专注于拟合那些在训练集里高频出现的模式时,就会牺牲掉低频场景的泛化能力。因为评估时低频场景对平均分影响小,这种牺牲在指标上看不出来。
我之前接手过一个项目,基线模型的 ADE 从 0.8 米降到了 0.5 米,看起来进步巨大。但当我们把某个交叉路口的突发横穿行人场景单独拎出来测试时,发现碰撞率反而从 2% 涨到了 5%。团队都很震惊,后来检查才发现,模型为了把整体误差压下来,学会了把预测轨迹往“中间的、保守的方向”偏,这在多数场景下误差更小,但遇到需要精准判断行人意图的场景时,这种保守反而导致反应过度或者反应不及时。可以说,如果没有场景维度的评估指标,我们根本发现不了这种“进步下的退步”。
这也是为什么我会坚定地用场景驱动评估去替代纯平均指标。评估的本质是反馈,反馈的信息必须是可操作的。平均指标给不了操作方向,场景化指标才能告诉你是该优化感知融合、增加交互建模还是调整预测时域。
2. 场景驱动评估到底在测什么
2.1 首先定义“什么值得测”
做场景驱动评估的第一步,不是马上写代码算指标,而是和团队把“场景”的定义统一起来。什么叫一个场景?一辆自车遇到一个行人横穿马路,这是一个场景;两辆车在十字路口同时到达,存在路权争议,这也是一个场景。场景的切分粒度会直接影响后续标签设计、数据统计和指标计算。
我建议从四个维度来定义场景标签。第一是静态道路结构,比如直行、弯道、十字路口、环岛、匝道、收费站等。第二是动态交通参与者状态,比如前方车辆减速、侧方车辆变道、行人横穿、非机动车侵入等。第三是环境状态,比如白天、夜晚、雨雪天、光照不足等。第四是自车意图,比如跟车、巡航、自动变道、绕障、靠边停车等。
这四个维度组合起来,就形成了一个多层级的场景标签体系。举个例子,同样是“十字路口左转”,可以细分为“十字路口左转+对向直行车流”“十字路口左转+同向非机动车”“十字路口左转+视野遮挡”等多个更细的场景。粒度太粗会导致评估结果没有区分度,粒度太细又会导致每个子场景样本量不足、指标波动大。我自己的实践经验是,先按“道路结构+主要交互对象+关键事件”三个关键维度去组合,把粒度控制在每个子场景至少有三五百个样本,然后再根据实际数据进行迭代细化。
2.2 难度分层与关键事件识别
有了场景标签之后,还需要给每个场景打一个“难度分”。很多团队对难度分没有明确定义,靠工程师拍脑袋,结果不同人拍出来的标准差距很大。我建议用可量化的指标来做难度分层,至少包含四个因素:交互复杂度、预测时域、威胁等级、信息完整度。
交互复杂度指自车周围有多少个需要同时建模的交通参与者,以及这些参与者的运动模式是否多变。一般情况下,参与者在 3 个以内属于低交互,3 到 6 个属于中交互,6 个以上属于高交互。预测时域是指本车需要预测未来多长的轨迹,时域越长,不确定性越大,难度越高。这里可以按 2 秒内、2 到 4 秒、4 到 6 秒分成三档。威胁等级和碰撞时间(TTC)直接相关,如果预测目标与自车的预计碰撞时间小于 3 秒,就属于高风险场景。信息完整度主要看传感器的遮没情况、目标遮挡比例、历史轨迹长度,信息越缺失难度越高。
把这些因素量化之后,可以给每个场景算一个综合难度评分,从 0 到 1 归一化。难度分的作用有两个:一是评估时做分组对比,看模型在低、中、高三档难度下的表现曲线;二是做风险加权,难度越高的场景,出现误判时权重越大。很多团队评估时只分组不权重,这其实不够,因为我们真正希望的是模型把能力集中在高风险场景上,而不是均匀地把能力分散在所有场景里。这也是“Measuring What Matters”里“What Matters”的另一个隐含含义——重要的不是所有场景的平均表现,而是关键风险场景的兜底能力。
2.3 指标体系:不只 ADE/FDE
场景驱动评估的落地,还需要一套比 ADE/FDE 更全面的指标体系。坐标误差类指标一定要保留,但必须按场景分组计算;在此基础上,我建议增加三类指标。
第一类是安全类指标,包括预测碰撞率(Prediction Collision Rate)、最小安全距离余量(Safety Margin)、违反交通规则率(如压实线预测、闯红灯预测)。这些指标直接反映模型输出的轨迹是否可被下游规划安全执行。第二类是行为合理性指标,包括加速度冲击率、横向摆动频率、与意图分布的一致性。如果模型预测出来的轨迹在物理上不可行,哪怕与真值误差很小,也不是好预测。第三类是决策支持类指标,包括预测置信度校准误差(Calibration Error)、多模态覆盖度(Coverage Rate)。覆盖度是计算模型给出的 TopK 轨迹是否包含真实未来轨迹的比例,这直接关系到下游规划器是否有“正确答案”可选。
我只补充一点:安全指标的阈值一定要慎重设定。碰撞率并不是越低越好,如果模型为了规避碰撞把预测轨迹全部偏离真值,甚至把横向误差拉到离谱的水平,那碰撞率降低了但整体可用性也丧失了。所以实践中我建议把安全指标和精度指标配对观察,比如同时看“高风险场景碰撞率”和“高风险场景 ADE”,两者一起改善才算真正提升。
3. 实操:如何搭一套场景驱动评估框架
3.1 给测试数据打场景标签
我见过不少团队想直接拿公开数据集跑场景评估,但发现公开数据集往往没有细粒度的场景标签,只有粗分类,比如“路口”“直行”这种。这种情况下,就需要自己搭一套标签工具。标签来源建议分三条路并行。
第一条路是规则打标。基于高精地图和自车历史轨迹,可以用几何关系自动判断道路结构类型和自车意图。比如通过自车航向角变化判断转弯,通过车道中心线距离判断变道,通过前方车辆相对距离变化判断跟车还是接近。第二条路是交互识别。通过计算周围目标的运动状态、与自车的相对速度和位置关系,判断是否存在换道切入、行人横穿等关键交互事件。第三条路是数据挖掘。先用一个基础模型跑全量数据集,统计预测误差大的样本,再用无监督聚类把它们归成几类,人工审核后形成新的场景标签。这条路往往是发现真实道路长尾场景最有效的方法。
打标完成之后,还要做一致性校验。不同标注员对“危险”“交互”的定义容易不一样,建议提前准备一份标注规范文档,明确每个标签的判定边界,然后至少随机抽 10% 的样本做双人交叉标注,用 Cohen's Kappa 观察一致性,阈值低于 0.7 就要回头修订规范。这一步看起来费功夫,但它决定了后面所有场景统计结论的可靠性。标签都不一致,指标再漂亮都是白算。
3.2 按场景分组计算核心指标
标签体系建立之后,接下来就是把评估指标按场景分组计算。我先给一个最小可用的 Python 实现逻辑,你可以直接套进自己的评估流程。
import numpy as np import pandas as pd def compute_grouped_metrics(df, scene_col='scene_label', pred_cols=['ade','fde','collision_rate']): results = [] for scene, group in df.groupby(scene_col): # 样本量不足时标记为 nan,不参与最终汇总 if len(group) < 50: continue scene_result = {'scene': scene, 'sample_count': len(group)} for col in pred_cols: if col in group.columns: scene_result[f'mean_{col}'] = group[col].mean() scene_result[f'p95_{col}'] = group[col].quantile(0.95) results.append(scene_result) return pd.DataFrame(results)这段代码的核心逻辑很简单:先按场景标签分组,再分别计算每个场景里各项指标的均值和 95 分位值。为什么要有 p95?因为评估不能只看平均,高风险的尾部表现往往比平均更值得关注。一个场景的 ADE 均值很低但 p95 很高,说明这个模型大多数时候表现好,但偶尔会出现离群预测,这种“偶发失误”恰恰是安全上最难防范的。把 p95 指标纳入评估,本质上就是在约束预测分布的尾部。
分组计算之后,可以把结果输出为一张二维表:行是场景标签,列是各项指标。我习惯先用热力图快速浏览,看看哪个场景在哪个指标上偏红,再针对性地深入分析。这里还想强调一下样本量的问题。有些长尾场景,比如“夜间高速匝道汇入”可能只有二三十个样本,算出来的均值几乎不可信。我的建议是这类场景不进综合分,但单独走案例回顾流程,一条一条人工看,分析模型的具体失败模式。
3.3 加权综合分数与通过阈值
分组指标是“体检报告”,但团队开会时还是需要一个能快速拍板的综合分数。我常用的方案是分层加权和。先把场景按风险等级分成三档:低风险、中风险、高风险。低风险场景权重设为 1,中风险设为 2,高风险设为 4。如果某个场景发生过安全事故或者被安全员接管过,权重再额外乘 1.5。然后对每个场景内部的指标做归一化,再加权求和。
下面是一个场景综合分计算例子,假设只考虑 ADE、FDE 和碰撞率:
| 场景 | 样本数 | ADE(m) | FDE(m) | 碰撞率(%) | 风险权重 | 加权归一化得分 |
|---|---|---|---|---|---|---|
| 高速直行 | 500 | 0.15 | 0.30 | 0.0 | 1.0 | 8.2 |
| 城市跟随 | 400 | 0.30 | 0.62 | 0.1 | 1.5 | 7.5 |
| 路口左转 | 300 | 1.20 | 2.10 | 1.8 | 4.0 | 3.6 |
| 汇入博弈 | 180 | 0.90 | 1.80 | 2.5 | 4.0 | 3.2 |
从表里能直接看出,高速直行和路口左转的绝对 ADE 差着数量级,但单纯平均的话,路口问题会被高速场景掩盖掉。加权之后,路口的低评分对你整个预测模型的“可上路性”影响会非常明显。
加权分算出之后,还要定一个“通过阈值”。这个阈值不能凭空拍,最好参考两个数据来源:一是安全测试场地里人工驾驶数据的预测误差分布,二是过去几代被测系统在路测中被接管时对应的离线指标值。把这些历史数据拉出来画个散点图,找到分界点,作为初步阈值。后续每迭代一版模型,都拿同一套评估集跑分,只有新模型的综合加权分超过旧模型,且高风险场景的碰撞率没有恶化,才算真正有效提升。
4. 常见问题与排查技巧实录
4.1 场景挖掘不充分导致评估盲区
做场景驱动评估最忌讳的就是场景集合自己“定死”。我最早做第一版的时候,只凭工程师经验列了二十几个场景,结果评估效果不错,但模型上路依然有大问题。后来分析才发现,我们漏了一个非常典型的场景:左转时侧后方来车快速接近。这个场景在数据集里数量不多,但它恰恰是很多路测接管事件的诱因。
后来我养成了一个习惯:每次模型迭代完成后,用残差分析去挖掘“预测误差特别大、但场景标签里没有覆盖”的样本。具体做法是,将模型在验证集上的预测误差按 99 分位切出来,然后对这些高误差样本做特征统计,看它们是不是聚集在某个空间或者某个时序模式里。如果聚出来一个可描述的新场景,就把它补充进场景标签体系。这样评估体系就能随着数据积累不断自我扩展,而不是停留在最初的专家知识里。评估集本身是活的,这一点非常重要。
4.2 标签不一致导致跨场景对比失效
刚开始用场景标签时,最容易翻车的地方是标签不一致。比如 A 标注师认为“跟车变道”和“前车插入”是相同场景,B 标注师觉得必须分开;再比如不同标注师对“是否有行人干预”判定标准不同,导致同一个样本被打在不同场景里。一旦标签错了,分组统计的结果自然全乱了,模型明明没有变化,指标却忽高忽低,整个团队都会被误导。
我的解决办法有三条。一是制定详细的标签判定规则:能用量化阈值判断的就不用文字描述,比如相对距离小于多少米且横向速度超过多少算“切入”,必须有明确数字。二是定期做交叉标注一致性检查,每次新增数据或修订规范后,都抽一批样本让两位标注师独立打标,算 Kappa 值,低于 0.8 就要重看规范。三是所有场景标签都保留原始特征快照,方便回溯,一旦后续发现某个场景的判定边界有歧义,可以快速找到历史样本来重新评估影响范围。
4.3 长尾场景量化难,容易过拟合到场景标签
另一个常见问题是模型对评估标签产生间接过拟合。我们做评估是希望发现问题,但如果团队日夜盯着“路口左转”这个标签优化,模型慢慢会被“驯化”成只在有标签数据上表现好,到了真实的、没有经过标注的任意路口反而变差。尤其是当你把标注信息直接暴露给训练流程时,这个问题会更严重。
因此我的建议是训练流程和评估流程彻底分离。场景标签只用于评估环节,训练时模型不要接触这些标签信息,用来训练的原始数据也不需要打标,让模型纯粹从轨迹、地图和感知结果中自学习。评估标签只在最后测试时按需标注。这样能最大程度避免模型把场景标签当作“作弊信息”。另外,评估集中的场景要定期轮换,至少每次发布新版本模型时换掉其中 20% 的场景样本,防止评估集本身被模型记住。
4.4 离线评估与在线路测的 gap 怎么缩小
离线评估做得再细,也免不了被人问一句“路测表现如何”。我踩过很多次坑之后总结出:离线场景评估解决的是“模型能力上限”的问题,在线路测解决的是“系统整体配合”的问题,两者之间有天然 gap。预测误差不一定等于行车风险,因为后面还有规划和控制模块可能在兜底。反过来也一样,一个预测很准但置信度给错的模型,也可能让规划器做出激进决策。
要缩小这个 gap,最好的办法是把场景驱动评估接入闭环仿真。也就是用真实采集到的场景片段,在仿真环境里把新模型和旧模型分别跑一遍模拟自动驾驶系统,对比最终的接管率、碰撞率、通行效率。离线评估负责在算法层面筛选候选模型,闭环仿真负责在系统层面验证最终表现。两套结果结合起来,就能比较全面地反映模型的真实价值。不要只看离线指标就急着上车,也不要把路测问题全归因给预测模块,先把离线评估和闭环仿真的数据摆在一张表上分析。
5. 写在最后的一些体会
聊到最后,说点务虚的。这套场景驱动评估框架,本质上是在帮团队回答一个问题:哪些场景的错误会被下游放大,哪些场景的错误可以被兜住。平均指标做不到这一点,只有把场景拆开、把风险权重加进去,才能让评估结果和驾驶安全真真正正地挂上钩。从我的经验看,引入场景驱动评估之后,团队的开发习惯会发生明显变化:大家开始主动讨论“哪个场景是薄弱点”,而不是只说“这次指标涨了 0.05”,这种从“刷分思维”到“找茬思维”的转变,比任何一个具体指标都更有价值。
另外还有个小建议:评估框架不要一开始就追求完美。先用规则完成粗粒度分场景,再把高频危险场景逐步细化,把长尾场景靠数据挖掘慢慢补充,你的评估体系就会像模型一样,在迭代中变得越来越好用。最后再分享一个小技巧:评估结果出来以后,一定要把“最差场景的典型失败案例”做成一个视频集,每次评审都放给团队看。真实影像比任何曲线和表格都更能让人做出正确的判断,这比增加一个评估指标有用得多。