一句话理解Failure Analysis

Failure Analysis不是找bug——而是通过系统化方法确定"模型在当前场景下为什么不行",并据此判断这究竟是数据问题、模型能力边界、还是系统设计缺陷,最终决定要不要、以及如何投入修改资源。

训练一个自动驾驶模型也许需要3个月,但让它在长尾场景中可靠运行可能需要3年。在工业级自动驾驶研发中,Failure Analysis(故障分析)相关的工作量通常占总研发资源的40–60%。这不仅是"修bug"的问题,而是一套从数据收集到根因定位再到回归防御的完整工程体系。本文不讨论具体算法如何改进,而是聚焦于Failure Analysis的方法论框架和工程落地经验。


1. Failure Analysis的方法论框架

1.1 基本分析流程

Failure Analysis的标准工作流包含六个阶段:

  1. Bad Case收集(24小时内):从路测数据或仿真日志中标记异常行为(碰撞、接管、违规)
  2. 现象描述(2小时):用结构化模板记录故障表现的上下文信息
  3. 假设生成(1天):基于领域经验提出3–5个可能的根因假设
  4. 假设验证(2–5天):通过消融实验、仿真复现、数据回放验证每个假设
  5. 根因确认(0.5天):确定主要根因和次要根因
  6. 修复计划(0.5天):确定修复方案优先级和预计工时
class FailureCase:
    def __init__(self, case_id, timestamp):
        self.case_id = case_id
        self.severity = None  # critical / major / minor
        self.module = None    # perception / prediction / planning / control
        self.scenario_type = None
        self.phenomenon = ""
        self.hypotheses = []
        self.root_cause = None
        self.fix_plan = ""
        self.fix_verified = False

一个case从进入到根因确定需3–10天。在资源紧张时,最有效的做法是按照严重程度和复现率排序,优先处理"影响大"且"复现率高"的case——修复一个高频bad case对系统整体表现的提升远大于修复十个偶发case。

1.2 故障分类Taxonomy

采用"四层分类"体系:失效模块×场景语义×触发条件×严重程度。

第一层:失效模块(占比来自某L4级城区公司1000个bad case统计)

-----------------((((~FF~~~3aa2315llM5退00>%ssi%%%1ees>>)))>0oc53>00fNPlm0>v5.meoa/%ss3sfgsssamaaisgittieliifnuvvitreeceast)ion

纯视觉系统感知层故障可占50%以上,多模态融合(LiDAR+相机+Radar)系统可降至25%左右。

严重程度分级

级别定义示例处理优先级
CRITICAL必然导致碰撞对向车道车辆完全漏检48h内修复
MAJOR高概率碰撞未避让横穿行人1周内修复
MINOR影响舒适性不必要的急刹或频繁变道1月内修复
INFO可改进轨迹不够平滑可选修复

2. 故障归因的消融策略

2.1 消融实验设计

模块化消融(Modular Ablation)逐层替换或抠除可疑模块来隔离故障源头。对于端到端系统:

SSSStttteee-eppppb+++123a4:::sGGG:eTTTline"(((812652%"0%%):k))m/h,(<0.-9565mm%/)5s0²0,ms25m
class AblationExperiment:
    def __init__(self, model, scenario_loader):
        self.model = model
        self.scenarios = scenario_loader
    
    def evaluate(self, debug_mode):
        modes = ["gt_perception", "gt_prediction", "gt_planning", "gt_all", "full"]
        results = {}
        for mode in modes:
            collisions = 0
            for scenario in self.scenarios:
                if mode == "gt_perception":
                    detections = load_gt(scenario)
                    predictions = model.predict(detections)
                    trajectory = model.plan(predictions)
                # ...其他模式
                if check_collision(trajectory, scenario): collisions += 1
            results[mode] = collisions / len(self.scenarios)
        return results

2.2 因果链追踪的5个问题

Q1: 是否感知到了?——检查检测结果中是否包含目标。如果没有,说明是感知漏检;如果有,检查检测框精度和速度估计是否准确。

Q2: 是否预测对了?——对比预测轨迹与后验数据,计算ADE(平均位移误差)和FDE(最终位移误差)。

Q3: 是否规划出了安全轨迹?——区分优化失败(无可行解)vs 决策错误(选了不安全轨迹)。

Q4: 是否控制到位?——检查跟踪误差和执行器是否饱和。

Q5: 是否存在系统级失效?——通信延迟、计算资源竞争、时间戳未同步等不归因于单模块的系统性问题。

2.3 传感器故障模式

  • LiDAR遮挡:前车尾气/大雨/泥污使有效距离从100m降至40m
  • 相机过曝/欠曝:隧道出口10lux→100,000lux,需HDR或自动曝光调节,过渡需3–5帧
  • IMU漂移:消费级IMU零偏约5°/h,无GPS隧道中60秒位置漂移10–30m
  • Radar干扰:多车近距离互扰,点迹密度增加5–10倍

传感器故障呈"间歇性"——同一场景复现率低,但同类故障在不同场景反复出现。应提取模式进行批量修复。


3. 场景还原与仿真复现

3.1 从路测到仿真场景

技术流程:离线时间戳对齐(使用PTP时间戳)→自车位姿重建(若定位已发散则需后验batch优化+loop closure)→交通参与者轨迹提取(使用离线LiDAR追踪避免感知模块污染)→静态环境重建(从HD Map或SLAM地图提取路网)→场景格式转换(OpenSCENARIO 2.0)。

难点在于交互还原——仿真回放中预录轨迹固定,参与者不会对自车变化做出反应。常用折衷方案是"混合回放":自车由被测算法控制,其他参与者按预录轨迹刚性执行。

3.2 可复现率与置信度

影响复现率的三因素:

  1. 传感器差异:仿真与真实传感器特性不完全一致,复现率80–85%
  2. 车辆动力学误差:极限工况下Bicycle Model偏差大,复现率50–60%
  3. 环境交互差:路面起伏/风阻/轮胎温度等被简化

综合复现率65–75%,25–35%的故障无法在仿真中复现,需依赖其他方法分析。

3.3 场景裁剪与最小复现条件

逐项移除场景元素,每次检查故障是否仍然发生:

----60km==/036h00,km/h5,0km/h,,3300mm,,,,

最小条件直接指示根因——系统在前车静止且高速接近时存在感知或预测问题。


4. 长尾场景的系统性发现

4.1 基于聚类的场景发现

从大量路测数据中挖掘相似场景:

(1000(hU,MA~P3)6TB)(HDBSC(AN)/////)

HDBSCAN无需预设聚类数。500小时城区路测通常产出80–120个场景簇,其中15–20个是系统从未见过的"新场景"。聚类质量取决于特征设计——既要判别性又要可解释性,避免>100维导致结果难以解读。

4.2 基于异常检测的场景发现

三种信号:

  1. 预测不确定性:MC Dropout/Deep Ensemble的方差在OOD场景中是正常值的3–10倍
  2. 特征空间距离:中间层embedding距训练集距离超阈值时为分布外样本
  3. 动作差异:模型输出与历史外推趋势的显著偏差(如直道上突然大转向)
class ActionAnomalyDetector:
    def __init__(self, window_size=10, z_threshold=3.0):
        self.history = deque(maxlen=window_size)
    
    def detect(self, current_action):
        if len(self.history) < 5:
            self.history.append(current_action); return False
        predicted = np.mean(np.array(self.history)[-3:], axis=0)
        residuals = np.abs(np.array(current_action) - predicted)
        std = np.std(np.array(self.history)[-5:], axis=0) + 1e-6
        z_scores = residuals / std
        is_anomaly = np.any(z_scores > self.z_threshold)
        self.history.append(current_action)
        return {"is_anomaly": is_anomaly, "z_scores": z_scores}

4.3 基于对抗搜索的场景发现

基于RL的场景生成器:训练RL agent配置场景参数使被测系统失效。场景生成器学会的"攻击策略"本身有分析价值——揭示系统在哪种场景中最脆弱。

基于BEV-Grid的对抗搜索:将场景表示为BEV网格上的离散变量,用遗传算法搜索使规划损失最大的配置。发现的场景往往"反直觉"——看起来不危险但正好落在模型薄弱环节(如小角度切入在BEV离散化中边缘模糊)。


5. Bad Case追踪与回归防御体系

5.1 Bad Case追踪系统

持久化数据库记录每个case的完整生命周期:

CREATE TABLE failure_cases (
    case_id SERIAL PRIMARY KEY,
    severity VARCHAR(10),
    module VARCHAR(20),
    scenario_type VARCHAR(50),
    description TEXT NOT NULL,
    root_cause VARCHAR(50),
    fix_status VARCHAR(20) DEFAULT 'pending',
    fix_commit_hash VARCHAR(40),
    parent_case_id INTEGER,
    regression_ids INTEGER[]
);
CREATE INDEX idx_severity ON failure_cases(severity);
CREATE INDEX idx_module ON failure_cases(module);
CREATE INDEX idx_status ON failure_cases(fix_status);

关键能力:同类聚合(同一根因的几十个case自动归并,修复后统一验证)、回归溯源(git blame关联到提交记录)、趋势分析(按月统计新增/关闭/backlog数量)。

5.2 回归测试场景库管理

规模控制:Core Suite 500个(每commit),Extended Suite 5000个(每日),Full Suite 50000个(每周)。

清理策略:修复后连续3个月无报警,core→extended→archive逐级降级。约60%不复发,但约30%会因其他模块变更重新出现。

5.3 CI中的Failure Analysis集成

自动标注:路测数据上传后自动检查碰撞/接管/违规,召回率>95%。

自动建议:faiss向量检索匹配历史case推荐根因:

class RootCauseRecommender:
    def __init__(self, historical_cases):
        self.index = faiss.IndexFlatL2(feature_dim)
        self.labels = []
        for case in historical_cases:
            vec = self.extract_features(case)
            self.index.add(np.array([vec]))
            self.labels.append(case.root_cause)
    
    def recommend(self, new_case, top_k=3):
        vec = self.extract_features(new_case)
        distances, indices = self.index.search(np.array([vec]), top_k)
        return [{"root_cause": self.labels[i], "similarity": 1.0/(1.0+d)}
                for i, d in zip(indices[0], distances[0])]

自动回归防御:每commit运行core suite,失败时定位最近变更并通知开发者。


6. Failure Analysis成熟度模型

等级名称特征平均修复时间
L1被动响应bug来了才修,凭个人经验2–4周
L2系统化追踪有追踪系统和标准分析流程5–10天
L3主动发现聚类/异常检测主动探索边界2–5天
L4自动化防御全自动标注/建议/回归防御1–2天

很多团队卡在L2→L3跃迁上,因为主动发现需要场景挖掘系统和仿真闭环(3–6个月建设投入)。但从长期看,主动发现决定了系统能否从"demo级"走向"产品级"——被动响应的速度永远追不上长尾场景的涌现速度。


7. 总结

Failure Analysis的核心问题不是"这个bug怎么修",而是"如何在数万小时驾驶数据中找到系统真正的薄弱环节,并判断哪些值得投入资源"。从故障分类到消融归因、从场景复现到长尾搜索、从bad case追踪到回归防御,这是一条从被动救火到主动防御的演进路线。成熟的FA体系可将长尾故障率降低1–2个数量级,其投入产出比在自动驾驶工程化中是最高的——远高于刷一个新的SOTA评测指标。