轨迹预测评估的"分数陷阱":自动驾驶场景驱动评测到底该怎么落地
做自动驾驶规划预测的同学,大概率都有过这样的体验:模型在公开榜单上的 ADE(平均位移误差)很好看,排行榜名次靠前,但是一上车路测,碰到环岛、连续变道加塞、或者行人横穿被前车遮挡的场景,预测轨迹明显发飘,甚至导出危险决策。问题出在哪?不是模型不努力,而是我们一直在用一个"总分思维"在评估它——把所有场景的误差拉平取平均,少数派但致命的场景被 99% 的常规场景淹没了。这也是轨迹预测评估领域这两年越来越强调场景驱动(Scenario-Driven Evaluation)的根本原因:只造一个总冠军没有意义,我们要知道模型在哪些考场上会不及格。
这篇文章不讲论文复现,也不做纯理论推演,我以实际在自动驾驶预测团队做评估体系的经验,把"如何构造一套场景驱动的轨迹预测评估框架"这件事从头到尾拆开讲:为什么聚合指标不靠谱、场景标签怎么打、分场景指标怎么计算、以及我踩过的各种坑。适合正在做预测模型选型、评测集构建、或者想给团队搭一套靠谱评估看板的算法工程师和研究人员参考。
1. 为什么"平均指标"会骗人:先看看我们一直在用的分数有什么盲区
1.1 ADE、FDE 这些主流指标到底在测什么
先快速对齐一下基础。轨迹预测的评估指标,主流就是几个:ADE 是全部预测时刻预测点与真实轨迹点的平均欧氏距离,FDE 是最终时刻预测终点与真实终点的距离。多模态预测里通常还会报 minADE / minFDE,意思是取模型输出 K 条候选轨迹里误差最小的一条来计算,反应的是"模型有没有能力猜到正确轨迹",而不是"模型有多大把握猜中正确轨迹"。另外常用的还有 Miss Rate(漏检率),一般定义是预测终点距离真实终点超过某个阈值(比如 2 米)就算 miss。
这些指标本身没问题,它们是几十毫秒到几秒的几何误差度量,直观、可复现、便于横向对比。但问题也恰好出在"可复现"和"便于横向对比"上——为了跨模型、跨实验室比较,我们必须把分母归一化,于是一切都被压缩成一个标量:所有样本所有时刻误差的均值。这个均值一旦被当作核心 KPI,就自然会产生一种现象:模型在好开的场景上继续抠那几厘米的精度提升,在难开的场景上却可以一直摆烂,因为难场景在总量里占比小,对均值的贡献有限。
1.2 一个数学上必然出现的现象:长尾场景被平均稀释
举一个我实际遇到过的例子。评估集里包含约 85% 的城市主干道直行跟车场景、10% 的路口转弯场景、5% 的复杂交互场景(无保护左转、加塞、行人与非机动车混行)。某次迭代的模型 A 在直行场景上 ADE 比旧版下降了 6cm,但复杂交互场景的 ADE 恶化了 40cm。由于交互场景只占 5%,整体 ADE 仍然显示下降了大约 2cm——从聚合分数看这是一次"成功优化",实际上模型在最需要安全冗余的场景里退化得相当明显。
这不是个例,是聚合指标的结构性缺陷。你可以把它理解成一张班级成绩单:全班平均分 90,看起来很好,但里面有人数学满分、物理不及格。自动驾驶的安全评估恰好不应该用"平均分"来拍板,因为极端交互场景的预测误差可能直接关联到刹车时机、变道决策、甚至事故规避能力。
那是不是把安全场景的比例人为提高就行了?数据重采样确实能缓解,但会引入新的问题——你改变了评估集相对于真实道路频率的分布,导致分数不能反映实际路上的平均表现,榜单横向比较又不公平了。真正解决问题的思路是:分数不合并,分开算,分开报,场景驱动评估的核心思想就是这么一句话。
2. 场景驱动评估的总体设计:从"总分制"改成"分科会考"
2.1 核心思路:每个场景都是一场独立的考试
场景驱动评估说起来不复杂,就是把评测样本按照某种语义标准分类,在每一类上独立计算指标并独立报告。关键动作是两步:第一步是建立一个"场景分类体系",第二步是给每一个预测样本打上场景标签。
这两步做得好不好,直接决定评估结论的质量。分类体系太粗,比如只分"路口/直行",交互密度差异巨大的无保护左转和右转会被混在一起,等于没分;分类体系太细,每种场景样本量太少,指标置信度不够,跑一次评测算出的分数波动比模型真实差异还大,参考价值就没了。所以场景分类体量的把握是设计阶段最重要的权衡。
从团队实际落地经验看,一套比较稳妥的场景分类体系通常沿着三个维度展开:道路拓扑(直行、路口、环岛、匝道汇入汇出)、交互关系(无交互、跟车、被加塞、主动变道、行人横穿)、环境条件(光照、天气、遮挡)。三个维度可以做笛卡尔积,但实践中不需要全组合,通常做法是选一个主维度做报告粒度,其他维度作为筛选条件。
2.2 场景分类体系到底怎么建:拓扑、交互与环境三维度
先说道路拓扑。这个维度主要描述"地图给模型出了什么题"。直行场景考察的是速度保持和微调能力;路口场景考察的是转向曲率和过弯意图识别;环岛场景考察的是进出环岛的轨迹弧线以及让行关系的理解;匝道场景考察的是汇入汇出时对目标车道车流的预测。
再说交互关系。这个维度描述的是"周围交通参与者给模型施加了什么压力"。这里我要特别强调一个容易踩的误区:很多人把交互简单等价于"周围车多",这其实不准确。对预测模型来说,真正有意义的是这些车的行为是否显著影响了主车/目标车的决策自由度。高速高密度交通流里大家都在车道内匀速行驶,虽然车辆多但几乎没有交互压力;反而是空旷道路上有一辆车打了转向灯斜插过来,这一个交互就足够让预测难度陡增。
所以交互场景的标签我建议基于行为事件而不是密度统计。具体来说就是检测目标车轨迹是否有变速意图、他车是否有切入本车道、双方是否有明显的空间竞争关系。这部分后面在标签实现环节再细说。
环境条件维度则相对简单,主要是通过传感器数据或数据源标注来区分晴雨、昼夜、遮挡程度。对轨迹预测而言,环境的影响更多是间接的——它影响感知结果的质量,进而影响预测输入。如果团队的数据管线里暂时没有环境标注,这个维度可以留空,不阻塞评估框架上线。
2.3 场景评估与通用评估的关系:不是替代,而是补充
需要澄清一个容易误解的点:场景驱动评估并不是要推翻 ADE/FDE 体系,也不该替代通用的聚合评估。聚合指标的价值在于它给了你一个"总分"来做快速横向对比和筛选;场景指标的价值在于它告诉你"总分背后有什么隐患"。
团队内部的做法是两层并行:第一层是全量样本的聚合指标报告,用于模型迭代过程中的快速回归测试;第二层是场景维度的分科报告,用于候选模型 POC 评审、安全评估里程碑、以及针对性困难场景的专项优化。如果模型在总分上合格,但在"无保护左转"这个场景上 Miss Rate 超过 30%,那么即使总分再好看,这个模型也过不了评审。
这个双向约束的关系,我拿一句话总结就是:聚合指标决定能不能进候选池,场景指标决定能不能上车。两者一起用,既保留了效率,又堵住了安全漏洞。
3. 场景标签与场景化指标:实操层面的关键实现
3.1 样本级场景标签怎么打:规则驱动先跑通,再考虑模型驱动
场景标签落在"样本"维度,也就是每一个待预测的目标(agent)在每一个预测时刻的数据样本,都需要对应一组场景标签。打标签的工程实现路径基本分为三种:规则驱动、模型驱动、人工标注。
团队刚起步时最务实的方案是规则驱动。因为轨迹预测数据天然自带地图信息(车道中心线、道路边界、信号灯位置等)和目标历史轨迹,我们不需要额外标注就能算出一大批规则特征。以拓扑分类为例,可以这样落地:
def label_topology(agent, map_info): lane = map_info.get_current_lane(agent.position) if lane.is_intersection: turn_type = classify_turn_angle(agent.vx, agent.vy, lane) return f"intersection_{turn_type}" # left / right / straight if lane.is_roundabout: return "roundabout" if lane.is_ramp: return "ramp" return "straight"这个示例里最关键的是classify_turn_angle的实现,不要只看当前时刻的车辆朝向,要综合车辆在过去几帧的航向变化率和地图车道的连接关系来判定转弯方向。常见的错误是转向前 0.5 秒车还没明显转向,系统就已经把它标成"直行",等到转弯完成再标就产生大量标签错误。
交互维度用规则驱动也完全可以实现。判断"他车切入"这类事件,可以检测邻车道车辆在未来 3 秒内是否跨越车道边界线,并同时测量它与目标车的纵向间距以及相对速度:
def label_interaction(target_track, neighbor_tracks): for nt in neighbor_tracks: lateral_change = abs(nt.lateral_displacement(3s) - nt.lateral_displacement(0s)) if lateral_change > LANE_WIDTH * 0.5: time_to_lane_cross = compute_tlc(nt) if target_track.is_ahead(nt) and time_to_lane_cross < 2.0: return "cut_in" return "no_interaction"这套方案的优点是完全可复现、无标注成本、逻辑透明;缺点是规则的覆盖范围有限,复杂交互(比如多车协同博弈)很难用几条规则描述干净。所以规则驱动的定位是:第一版快速跑通,建立评估框架的骨架,等样本积累和经验到位了再考虑上模型驱动的标签。
模型驱动打标签,本质上是训练一个场景分类器或使用大语言模型对场景进行理解分类,好处是能覆盖更多长尾情况,坏处是分类器本身有误差,而且引入了一层"你在评估预测模型的同时也受制于分类模型的性能"的耦合。团队如果追求标签的绝对稳定性(评估基准需要版本可对比),我建议标签体系里主维度永远用规则驱动,模型驱动只作为辅助维度。
3.2 场景化指标计算:聚合方式与报告口径
标签打完之后,指标计算本身不复杂,就是分组加聚合。但是"分组加聚合"这几步里有几个口径问题必须提前定清楚,不然不同的人算出来的同一场景指标数值不一致,评审时对不上就尴尬了。
第一个口径问题是平均的粒度。ADe 在场景内聚合时,有两种做法:一是先对每个样本的每个预测时刻求误差,再对场景内所有样本所有时刻求平均,这是最常用的做法;二是先对每个样本求整段轨迹的 ADE,再对场景内样本做平均,两种做法在样本长度不一致时结果会不同。我建议使用第二种,即"先样本后场景",因为这样每个样本的权重是平等的,避免长轨迹样本在总体均值里权重过大。
第二个口径问题是多模态的取法。minADE 的"min"在场景维度下要明确是对每个样本内部取最小,还是把场景内所有样本的所有轨迹放在一起取最小。前者才是正确做法,后者会严重低估误差(相当于给了每个场景一个作弊机会)。这个说起来好像是常识,但我确实见过评估脚本写错的情况。
第三个口径问题是要不要加权。纯场景内平均是等权重的,但场景内部也分难易。比如"路口左转"场景里,有的样本车流稀疏、视野良好,有的样本车流密集、目标车处于队列尾部,两类样本混合在一起,左转场景的指标同样存在内部稀释问题。如果团队还想再细一层,可以对场景内的交互事件标记忙闲,做加权的困难样本统计。不过提醒一句:加权系数一旦引入就很难客观确定,我倾向于在报告中同时给出加权前和加权后的指标,让评审看到两种口径的差异。
3.3 场景级指标看板的呈现方式:用分位数代替纯均值
场景化评估报告如果只是把 ADE/FDE 换成"在 20 个场景里分别报 ADE/FDE",信息量其实还是不够。我建议在分场景指标之外,再加三个维度的统计量:
第一个是百分位数。比如 p50 和 p90 的 ADE。p90 比均值更能反映模型在场景内困难样本上的表现。从控制风险的角度看,p90 其实就是"模型在这个场景里最差的那 10% 时刻的表现",一个预测系统在关键场景的 p90 误差直接关联它的容错能力。
第二个是Miss Rate 的分布。前面提过 Miss Rate 是按阈值判定的,建议把阈值从 1 米到 5 米做多档阈值,画一个累积曲线。只报一个固定阈值 2 米的 Miss Rate 容易遗漏信息——可能模型 A 和 B 在 2 米阈值上表现相同,但 A 的误差分布有厚尾,在 3 米阈值上明显更差。多档阈值才能看出分布形态差异。
第三个是失败样本的具体追溯。指标只能告诉你"哪个场景不行",不能告诉你"为什么不行"。所以在评估流水线里必须保留一个可追溯的通道:当某个场景 p90 指标触发告警阈值时,可以抽取对应的具体数据样本,可视化它的地图、历史轨迹和预测输出,做失败案例分析。
这里是一个实际的场景评估报告片段,展示核心场景维度的指标对比方式:
| 场景类型 | 样本数 | minADE(m) | p90 ADE(m) | Miss Rate@2m(%) |
|---|---|---|---|---|
| 主干道直行 | 12800 | 0.82 | 2.05 | 3.1 |
| 路口左转(无保护) | 860 | 1.67 | 4.52 | 18.6 |
| 路口右转 | 720 | 1.12 | 2.86 | 7.4 |
| 环路匝道汇入 | 410 | 1.38 | 3.64 | 12.9 |
| 被加塞切入 | 530 | 1.74 | 4.10 | 16.2 |
| 行人横穿(可见) | 350 | 0.95 | 2.43 | 8.0 |
注意表格里"行人横穿"场景的 minADE 只有 0.95m,看起来比"被加塞"场景好很多,但它的样本只有 350 个,置信区间很宽。所以在看板里我还会给每个场景标一个置信度指示,样本量小于 500 的场景,指标仅作为参考,不纳入硬性阈值评审。
4. 实操中的常见问题与排坑实录
4.1 场景分布严重不均衡:直行场景几万个样本,加塞场景几百个
这是做场景评估最早遇到的现实问题。公开数据集(比如 nuScenes、Argoverse 2)里的场景本身就存在天然偏斜,直行巡航场景占比极高,真正带强交互的场景占比很低。带来的直接后果是:交互场景的指标方差大,跑一次评测换一个数字,模型对比的置信度不够。
解决办法分两步走。第一步是评估集层面的场景配额,在构建评测集时不做自然分布的随机采样,而是对每个场景类型设一个最低样本配额。试点位操作会牺牲一点"与道路真实频率一致"的特性,换来的是每个场景都有足够的样本支撑稳定指标。这其实也是业界做评测集构建的常见手法——分布偏移可以接受,只要报告里写清楚采样策略就行。
第二步是置信度量化和结果解读。对样本量少的场景,在报告里同时给出置信区间。一个简单的做法是用 bootstrap 重采样计算指标的标准差。我团队里定了一个规矩:当某场景的指标标准差超过均值的一半时,该场景指标只用于内部参考,禁止写入对外评测报告。这个方法虽然朴素,但可以很好防止把噪声当信号。
4.2 场景标签的边界模糊:同一个样本同时符合两种交互标签
规则驱动的标签体系容易出现边界情况。比如目标车正在通过路口,同时旁边有一辆车在并行向右转,这个样本既可以被标记为"路口左转",也可以被标记为"并行交互"。如果标签体系没有处理好这类边界,就会出现同一个样本被重复计入多个场景的指标统计,导致场景间指标不可比。
这里推荐一个原则:场景标签做优先级排序,每个样本只归属一个主场景。比如拓扑维度优先于交互维度,交互维度优先于环境维度。这样每个样本在报告里只占一个格子,总分和分项的对账关系才成立。团队内部的标签优先级排序我建议这样定:先按拓扑(因为地图先验最强),再按交互(因为安全相关性最高),环境维度作为筛选器不参与主分类。
同时在标签验证环节加一道自动校验:抽样检查每个场景里随机 N 个样本的标签与人工判断的一致性。规则驱动虽然逻辑透明,但规则无法覆盖的边界情况依然存在,自动校验配合人工抽检是控制标签质量的兜底手段。具体做法可以每轮评测集更新后抽 100 个样本,由两名标注人员独立打标签,计算与规则标签的 Kappa 系数。Kappa 低于 0.8 就说明咱们的分类体系或者规则实现有问题,需要回头调整,而不是硬着头皮继续用。
4.3 用场景指标反哺模型训练:从"评估工具"变成"优化指南针"
场景评估框架跑通之后,最大的价值其实不在评测本身,在于它可以让模型优化方向变得非常清晰。举个我们团队的真实案例:在一次模型迭代中,聚合 ADE 只提升了 1.5%,看起来是小步优化,但按场景拆开看,发现"被加塞切入"场景的 Miss Rate 从 24% 降到 11%,而"直行巡航"场景的 ADE 几乎没有变化。这时候我们才知道这次迭代的收益集中体现在交互感知上,这个认知反过来指导了下一步训练数据的配比——我们在训练集里增加了加塞场景的重采样权重,针对性地上了更多这类样本的数据增强,形成了一条"场景评估发现短板 → 定向补数据 → 再评估验证"的闭环。
这一点我觉得是场景驱动评估最值得投入的原因:它让你不再盲目地调模型,而是先定位病灶再精准下药。另外提醒一个小技巧,当你要针对某个短板场景做专项优化时,场景评估里最好同时提供一个"困难子集"的筛选接口,比如在路口左转场景内只选择有来车交互的样本,专门跟踪这部分指标。否则你优化了整体左转场景的平均表现,很可能是在"无冲突左转"上努力了,而真正危险的"有冲突左转"反而没被触及。
4.4 版本管理与复现性:评估脚本比模型代码更需要做版本控制
最后一个实操层面的坑是评估脚本的版本管理。轨迹预测模型本身迭代快,但很多人忽略了评估逻辑也需要严格版本化。场景标签规则、聚合口径、置信度统计方法,任何一项变动都会让历史指标失去可比性。团队内部发生过一次事故:因为改了场景分类里"路口"的判定逻辑(从基于车道中心线改为基于信号灯关联),导致新老版本的场景样本划分不一致,结果对比时出现了"模型没变,分数大起大落"的诡异现象,排查了一个星期。
所以评估体系上线那一天起,就要把标签规则、评估脚本、数据集版本三者统一纳入版本管理。每一次评测必须记录用的是什么版本的标签规则和评估代码,而不是只记录模型权重版本。这个习惯养成之后,跨周、跨月的指标对比才具备真正的可比性。
我个人在实际操作中最深的体会是:评估体系的设计实际上是在和"不确定性"博弈。模型误差本身有不确定性,场景标签有边界,指标聚合有口径,任何一个环节的处理方式都会改变你最终看到的"真相"。场景驱动评估并不能让这个真相变得绝对清晰,但它至少能把不确定性的颗粒度从"整条数据集的平均误差"细化到"某一个可解释的语义场景下的误差分布"。这份细化带来的洞察力,是任何聚合指标都给不了的。
最后再分享一个小技巧:如果你现在刚接手的评测流程还在用"一个平均 ADE + 一个 Miss Rate"打天下,不用急着推翻重做,先找 1000 个样本按拓扑维度粗分三类(直行/路口/其他),把三个场景的指标分别打出来看一眼。大概率你会在那个瞬间理解我为什么说平均分数会骗人——因为你会亲眼看到那个"路口"场景的误差比"直行"场景高出一大截。这就是把场景维度加进评估体系的第一步,也是最划算的一步。