ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

端到端自动驾驶训练深水区:数据、算法与平台如何协同破局

端到端自动驾驶训练深水区:数据、算法与平台如何协同破局

1. 端到端自动驾驶为什么突然被推到"训练深水区"

过去两年,只要聊到自动驾驶,话题几乎绕不开"端到端"这三个字。从模块化堆叠到一体化网络,从规则驱动到数据驱动,整个行业像是集体换了一条赛道。但真正在一线做训练的人心里都清楚,端到端不是把感知、预测、规划简单拼成一个网络就完事了,它带来的最大变化,是训练这件事本身变得前所未有的复杂。

我最早接触端到端方案时,第一反应是"这不就是把中间模块的接口去掉,让梯度自己流动吗"。实际跑起来才发现,问题根本不在网络结构,而在训练过程。模块化时代,每个子任务都有相对清晰的评价指标,感知看mAP,预测看minADE,规划看碰撞率和舒适度。到了端到端,输出直接是控制信号或者轨迹,中间过程变成了黑盒,你很难说清楚到底是哪一层出了问题。这就逼着团队把大量精力从"设计模块"转向"设计训练"。

所谓"训练深水区",我理解有三层含义。第一层是数据层面,端到端模型对数据规模、数据质量、数据分布的要求远超以往,以前一个感知模型几百万帧就能收敛,现在动辄需要千万级甚至亿级片段,而且这些片段还得覆盖足够多的长尾场景。第二层是算法层面,端到端模型的损失函数设计、时序建模、多任务平衡,都是没有标准答案的开放问题。第三层是平台层面,训练这样一个模型,对算力调度、数据流水线、实验管理的要求,已经接近甚至超过很多大模型训练任务。

这三层里,数据、算法、平台到底谁才是"上帝之手",其实没有唯一答案。但有一点是确定的:任何一层拖后腿,整个项目就会卡在某个瓶颈上动弹不得。我见过太多团队,算法想法很好,数据也攒了不少,最后死在训练平台不稳定、实验无法复现上。也见过平台很强、数据很多,但算法设计不合理,训出来的模型只会"抄近道",遇到稍微复杂一点的场景就崩。

这篇文章我想做的,不是给端到端自动驾驶下一个定义,而是把训练深水区里那些真正让人头疼的问题拆开来讲。数据怎么组织、算法怎么设计、平台怎么搭,每一块我都会结合常见的工程实践,给出可参考的思路和踩坑经验。如果你正在做端到端相关的训练,或者准备进入这个方向,希望这些内容能帮你少走一些弯路。

2. 数据闭环:端到端训练真正的"燃料"到底长什么样

2.1 为什么端到端对数据的胃口这么大

模块化架构下,每个子任务可以单独采数据、单独标注、单独训练。感知模型需要的是标注好的图像和点云,预测模型需要的是带轨迹标注的场景片段,规划模型甚至可以用仿真数据来补。数据需求是分层的,也是可拆解的。

端到端模型不一样,它吃进去的是原始传感器输入,吐出来的是驾驶决策,中间没有人工设计的接口。这意味着模型必须自己学会从像素到动作的映射,而这个映射的复杂度极高。举个简单的例子,人类司机看到前方车辆刹车灯亮起,会下意识松油门,这个"下意识"背后是多年的驾驶经验积累。端到端模型要学会这个映射,需要看到足够多"刹车灯亮起"和"随后减速"的配对样本。

更麻烦的是,端到端模型很容易学到虚假关联。比如训练数据里大部分左转场景都出现在某个特定路口,模型可能会把路口特征和左转动作绑定,而不是真正理解左转的语义。要打破这种虚假关联,就需要数据在分布上足够多样,让模型无法依赖某个单一特征来做决策。

我自己的经验是,端到端模型的数据需求大致可以用一个公式来估算:基础数据量乘以场景复杂度系数再乘以安全冗余系数。基础数据量取决于模型参数量和任务难度,场景复杂度系数取决于你希望覆盖的ODD范围,安全冗余系数则是为了应对长尾场景。这三个乘数任何一个变大,数据需求都会指数级上升。

2.2 数据采集:从"多采"到"采对"

早期做自动驾驶数据采集,思路很简单:车多跑、多录、多存。但到了端到端阶段,这种粗放式采集的弊端就暴露出来了。你可能会发现,采集了几百万帧数据,其中百分之八十都是直行跟车,真正有价值的切入、避让、施工区通行等场景少得可怜。

我在实际项目里总结了一套"场景配额"的采集策略。具体做法是,先根据ODD定义列出所有需要覆盖的场景类型,然后给每类场景设定一个最低采集配额。采集车在运行过程中,系统会实时识别当前场景类型,如果某类场景的采集量已经达标,就降低该类数据的存储优先级,把存储空间留给稀缺场景。

这套策略的关键在于场景识别模块的准确性。我们当时用了一个轻量级的分类网络,在车端实时判断当前场景属于哪一类。这个分类网络不需要特别高的精度,但召回率一定要高,宁可多存一些,也不能漏掉稀缺场景。实测下来,同样的采集里程,采用配额策略后,长尾场景的数据量提升了三到五倍。

还有一个容易被忽略的点是数据的时间连续性。端到端模型需要理解时序关系,所以采集时不能只存单帧,而要存连续片段。片段长度一般建议在十到三十秒之间,太短了模型学不到完整的驾驶行为,太长了存储和训练成本都会飙升。我们当时试过五秒片段,发现模型对变道这种需要几秒完成的行为学得很差,后来调整到十五秒,效果明显改善。

2.3 数据标注:端到端需要什么样的"老师"

端到端模型的标注方式和传统模块化有很大不同。模块化时代,标注是分任务的:感知标框、预测标轨迹、规划标动作。端到端模型需要的是一个统一的"驾驶指令"或者"目标轨迹",这个标注既要反映当前应该怎么做,也要隐含未来一段时间的行为意图。

常见的标注方案有三种。第一种是直接标注控制信号,比如方向盘转角、油门刹车开度。这种标注最接近模型输出,但问题在于不同司机的驾驶风格差异很大,同样的场景,有人喜欢急加速,有人喜欢缓加速,模型学出来会精神分裂。第二种是标注目标轨迹,让模型预测未来几秒的行驶路径。这种标注相对客观,但轨迹的平滑性和合理性需要额外处理。第三种是标注驾驶意图,比如"保持车道""准备左转""避让前方障碍",然后让模型自己学习从意图到控制的映射。

我比较推荐的是第二种和第三种结合的方式。先用轨迹标注让模型学会基本的行驶能力,再用意图标注来约束模型的行为风格。具体操作上,可以设计一个多任务损失函数,轨迹预测损失占主导,意图分类损失作为辅助正则项。这样训出来的模型,既不会太激进,也不会太保守。

标注质量的控制也是个大问题。端到端模型的标注一致性要求很高,同一个场景,不同标注员给出的轨迹如果差异太大,模型就会困惑。我们的做法是,先让标注员在仿真环境里跑一遍,把他们的驾驶轨迹录下来作为参考,然后再让他们标注真实数据。这样标注出来的轨迹更接近真实驾驶行为,一致性也更好。

2.4 数据闭环:从"一次性采集"到"持续迭代"

端到端模型不是训一次就完事的,它需要持续迭代。数据闭环的核心逻辑是:模型在真实或仿真环境中运行,发现bad case,把这些bad case回流到训练集,重新训练模型,再部署验证。这个循环转得越快,模型进步就越快。

搭建数据闭环有几个关键点。第一是bad case的自动挖掘。靠人工看视频找问题效率太低,必须有一套自动化的指标来筛选。常用的指标包括:模型输出与人类驾驶的偏差、模型输出的不确定性、场景的稀有度等。第二是数据回流的高效处理。挖出来的bad case需要快速标注、快速入库、快速参与训练,任何一个环节慢了,闭环就转不起来。第三是版本管理。每次迭代都会产生新的模型版本和数据集版本,必须有一套清晰的版本管理机制,否则很快就会乱成一锅粥。

我们当时搭闭环时踩过一个坑:bad case挖出来之后,直接混进训练集重新训练,结果模型在新数据上过拟合了,旧数据上的性能反而下降。后来改成按比例混合,新数据占比控制在百分之二十到三十之间,并且用课程学习的方式,先训旧数据再训新数据,才解决了这个问题。

3. 算法设计:端到端网络里那些"说不清道不明"的取舍

3.1 输入输出设计:到底该喂什么、吐什么

端到端网络的输入输出设计,是整个算法架构的起点,也是最容易产生分歧的地方。输入侧,常见的选择有纯视觉、视觉加雷达、视觉加激光雷达等。纯视觉方案成本低、数据易获取,但对光照和天气的鲁棒性差。多传感器融合方案鲁棒性好,但数据同步和标定是个大麻烦。

我个人的经验是,如果目标是量产乘用车,纯视觉或者视觉加低成本雷达是比较务实的选择。原因很简单,激光雷达的成本和寿命问题在量产车上很难解决。但如果是做Robotaxi或者限定区域的低速车,激光雷达带来的精度提升是值得的。

输出侧的选择更关键。直接输出控制信号是最简单的,但控制信号是高频的,模型需要输出很平滑的序列,否则车会抖。输出轨迹再通过控制器跟踪,是更常见的做法,轨迹的频率可以低一些,对模型的时序建模能力要求也低一些。还有一种做法是输出未来一段时间的行为概率分布,让规划器去选,这种方案更灵活,但训练难度也更大。

我们当时试过直接输出控制信号,发现模型在低速时还行,高速时方向盘抖动很厉害。后来改成输出轨迹,再用模型预测控制去跟踪,抖动问题就解决了。这个经验说明,端到端不一定要端到端到控制层,中间留一个轻量级的控制器,反而能让系统更稳定。

3.2 时序建模:端到端模型怎么"记住"过去

驾驶是一个强时序任务,当前决策很大程度上依赖于过去几秒的观察。端到端模型如果只处理单帧,就会像失忆一样,无法理解动态场景。所以时序建模是端到端算法的核心组件之一。

常见的时序建模方案有几种。第一种是帧堆叠,把过去几帧的图像在通道维度拼起来,简单粗暴,但计算量随帧数线性增长。第二种是循环神经网络,用LSTM或者GRU来维护隐状态,计算效率高,但长距离依赖建模能力有限。第三种是Transformer,用自注意力机制来建模时序关系,效果好,但计算复杂度是平方级的。

实际项目中,我比较推荐的是混合方案:用轻量级的循环网络做短时序建模,再用注意力机制做关键帧的选择。具体来说,先用一个CNN提取每帧特征,然后用GRU维护一个隐状态,同时用注意力机制从历史帧中挑选出与当前决策最相关的几帧,把这些帧的特征和GRU隐状态拼接起来,送入后续网络。这样既保证了计算效率,又提升了长距离依赖的建模能力。

时序建模还有一个容易被忽略的问题是时间对齐。多传感器数据的时间戳必须严格对齐,否则模型学到的时序关系就是错的。我们当时因为相机和雷达的时间戳差了十几毫秒,导致模型在高速场景下表现很差,排查了很久才发现是时间同步的问题。后来加了一个硬件触发同步模块,才彻底解决。

3.3 损失函数:怎么让模型"听话"又不"死板"

端到端模型的损失函数设计,直接决定了模型的行为风格。损失函数太简单,模型学不到复杂的驾驶策略;损失函数太复杂,模型又容易陷入局部最优。

常见的损失函数包括:轨迹回归损失,比如L1或者L2距离;行为分类损失,比如交叉熵;舒适度损失,比如加速度和 jerk 的惩罚项;安全损失,比如碰撞惩罚。这些损失怎么加权,是个经验活。

我的做法是分阶段调整权重。训练初期,轨迹回归损失占主导,让模型先学会基本的行驶能力。训练中期,逐渐增加行为分类损失的权重,让模型学会区分不同场景。训练后期,加入舒适度和安全损失,对模型行为进行微调。这种课程学习的方式,比一开始就把所有损失加在一起效果要好得多。

还有一个技巧是使用不确定性加权。每个损失项都预测一个不确定性参数,最终的损失是各项损失除以各自的不确定性再求和。这样模型会自动学习各项损失的相对重要性,减少人工调参的工作量。我们在实际项目里用了这个方法,发现模型收敛更快,最终性能也更稳定。

3.4 多任务平衡:端到端不是"一个任务"

虽然叫端到端,但端到端模型内部往往同时在做多个任务:感知、预测、规划、控制。这些任务之间会相互竞争,如果处理不好,就会出现"跷跷板"现象,一个任务性能提升,另一个任务性能下降。

解决多任务平衡,常见的方法有几种。第一种是梯度归一化,让不同任务的梯度在反向传播时保持相近的尺度。第二种是动态权重调整,根据每个任务的训练进度来调整损失权重。第三种是任务分组,把相关性强的任务放在一起训练,减少冲突。

我们当时采用的是动态权重调整加任务分组的方案。具体来说,把感知相关的任务分为一组,预测和规划相关的任务分为一组,两组之间用共享的主干网络连接,但各自有独立的头部。训练时,根据每个任务的验证集性能来动态调整损失权重,性能好的任务降低权重,性能差的任务提高权重。这样训出来的模型,各个任务的性能都比较均衡。

4. 训练平台:端到端模型背后的"隐形战场"

4.1 算力调度:不是有卡就能训

端到端模型的训练对算力的需求非常大。一个中等规模的端到端模型,参数量可能在几亿到几十亿之间,训练数据量在千万级片段以上,单次完整训练可能需要几百甚至上千张GPU卡跑好几天。这种规模的训练,算力调度就成了一个核心问题。

算力调度要解决的核心矛盾是:如何让有限的算力资源,高效地服务于多个训练任务。常见的调度策略有几种。第一种是静态分配,每个任务固定分配一定数量的卡,简单但利用率低。第二种是动态分配,根据任务的优先级和资源需求实时调整,利用率高但实现复杂。第三种是抢占式调度,高优先级任务可以抢占低优先级任务的资源,适合有紧急训练需求的场景。

我们当时用的是动态分配加抢占式调度的混合方案。具体来说,每个训练任务提交时会声明自己的资源需求和优先级,调度器根据当前集群的负载情况,动态分配资源。如果高优先级任务提交时资源不足,调度器会暂停一些低优先级任务,把资源让出来。被暂停的任务会保存检查点,等资源空闲时再恢复。

这套方案的关键在于检查点保存和恢复的效率。如果保存一个检查点要几分钟,那抢占的代价就太大了。我们后来优化了检查点的存储格式,只保存模型参数和优化器状态,不保存中间激活值,把保存时间压缩到了几十秒以内。

4.2 数据流水线:别让GPU等数据

训练端到端模型时,数据流水线往往是第一个瓶颈。GPU的计算速度很快,但如果数据供给跟不上,GPU就会大量时间处于空闲状态。我见过不少团队,买了很贵的卡,结果利用率只有百分之三四十,大部分时间都在等数据。

数据流水线的优化,核心是做好预取和缓存。预取是指,在GPU计算当前批次的同时,CPU提前把下一批次的数据准备好。缓存是指,把常用的数据缓存在高速存储上,减少从慢速存储读取的次数。

具体实现上,可以用多进程的方式来做数据加载。每个进程负责一部分数据的读取和预处理,然后把处理好的数据放入一个共享队列,GPU从队列里取数据。队列的长度要设置合理,太短了起不到缓冲作用,太长了会占用过多内存。我们的经验是,队列长度设置为GPU数量的两到三倍比较合适。

还有一个容易被忽略的点是数据格式。端到端模型的输入往往是图像序列,如果存储的是压缩格式,每次读取都要解压,会消耗大量CPU。我们后来把训练数据转成了一种未压缩的二进制格式,虽然存储空间大了,但读取速度快了很多,整体训练效率反而提升了。

4.3 实验管理:别让实验变成"玄学"

端到端模型的训练实验非常多,因为超参数空间很大,学习率、批大小、损失权重、数据配比,每一个都可能影响最终效果。如果没有一套好的实验管理工具,很快就会陷入"这个实验好像有效,但我不确定是不是随机波动"的困境。

实验管理要解决几个问题。第一是实验记录,每次实验的超参数、代码版本、数据版本、训练日志、评估结果,都要完整记录下来。第二是实验对比,能够方便地对比不同实验的指标曲线。第三是实验复现,给定一个实验记录,能够一键复现出相同的结果。

我们当时用了一套开源的实验管理工具,配合自己写的脚本,实现了实验的自动记录和对比。每次提交训练任务时,脚本会自动把当前代码的commit hash、数据集的版本号、超参数配置保存下来。训练过程中,指标会实时上报到数据库。训练结束后,可以生成对比报告,直观地看到哪个超参数组合效果最好。

这里有个经验:实验管理工具一定要在项目早期就搭好,不要等到实验多了再补。我们一开始觉得实验不多,手动记录就行,结果后来实验数量爆炸,很多早期实验的记录都不完整,想复现都复现不了,白白浪费了很多算力。

4.4 训练稳定性:端到端模型为什么这么"难伺候"

端到端模型的训练稳定性是个大问题。模块化时代,每个子任务单独训练,出了问题容易定位。端到端模型是一个大网络,梯度在深层网络中传播,很容易出现梯度消失、梯度爆炸、损失震荡等问题。

提升训练稳定性,有几个常用的手段。第一是梯度裁剪,把梯度的范数限制在一个合理范围内,防止梯度爆炸。第二是学习率预热,训练初期用很小的学习率,逐渐增加到设定值,防止初期梯度太大导致模型发散。第三是批归一化或者层归一化,让每一层的输入分布保持稳定。

我们当时还用了一个技巧:在训练初期,先用一个较小的模型或者较少的数据进行预训练,等模型稳定后再扩展到完整模型和完整数据。这种渐进式训练的方式,比直接训大模型要稳定得多。

还有一个坑是混合精度训练。混合精度可以大幅提升训练速度,减少显存占用,但如果不小心,很容易出现数值溢出。我们的做法是,在混合精度训练时,对损失函数做缩放,把损失值放大一定倍数,反向传播后再缩回来。这样既享受了混合精度的好处,又避免了数值问题。

5. 数据、算法、平台:到底谁才是"上帝之手"

5.1 三个要素的相互制约关系

回到标题里的问题:数据、算法、平台,谁才是上帝之手?我的答案是,这个问题本身可能就问错了。在端到端自动驾驶的训练深水区,这三个要素不是独立的,而是相互制约、相互成就的。

数据决定了模型性能的上限。无论算法多精妙,平台多强大,如果数据不够好、不够多、不够多样,模型就不可能学到真正的驾驶能力。但数据的作用又依赖于算法,好的算法能够从同样的数据里挖掘出更多信息,差的算法即使喂再多数据也学不出名堂。平台则是数据和算法的支撑,没有强大的平台,数据处理和模型训练的效率都会大打折扣。

我见过一个团队,算法很先进,平台也很强,但数据质量很差,标注错误率很高,结果训出来的模型在实车上表现一塌糊涂。也见过另一个团队,数据质量很好,但算法设计不合理,模型只会模仿人类司机的平均行为,遇到稍微复杂一点的场景就不知所措。还见过平台不稳定的团队,训练经常中断,实验无法复现,大量时间浪费在排查环境问题上。

所以我的观点是,在端到端自动驾驶的训练中,不存在单一的"上帝之手"。数据、算法、平台是一个铁三角,任何一个角缺失或者薄弱,整个系统就会失衡。真正重要的是找到三者之间的平衡点,根据项目的阶段和目标,动态调整投入。

5.2 不同阶段的优先级差异

虽然三者都重要,但在项目的不同阶段,优先级确实有差异。

项目早期,数据是瓶颈。这个阶段模型还没定型,算法和平台可以先用相对成熟的方案,把主要精力放在数据采集和标注上。没有足够的数据,后面的算法迭代和平台优化都是空中楼阁。

项目中期,算法是瓶颈。数据积累到一定规模后,会发现模型性能提升变慢,这时候需要算法上的创新,比如更好的时序建模、更合理的损失函数、更高效的多任务学习方案。

项目后期,平台是瓶颈。当数据和算法都相对成熟后,训练效率就成了关键。如何用更少的算力训出更好的模型,如何加快实验迭代速度,如何保证训练稳定性,这些都需要平台层面的优化。

我们当时的做法是,每个阶段设定一个核心指标。早期看数据覆盖率和标注质量,中期看模型在验证集上的性能提升速度,后期看单位算力下的模型性能。根据核心指标的变化,动态调整资源投入。

5.3 一个常见的误区:过度追求"端到端"

最后想聊一个我观察到的误区。很多团队在做端到端自动驾驶时,会陷入一种"纯粹主义"的执念,觉得端到端就应该从传感器直接到控制,中间不能有任何人工设计的模块。这种想法在理念上很美好,但在工程上往往行不通。

实际项目中,适当的模块化设计反而能提升端到端模型的性能。比如,在端到端网络前面加一个轻量级的图像预处理模块,做去噪和增强,可以让后续网络学得更轻松。在端到端网络后面加一个安全监控模块,对模型输出做合理性检查,可以避免一些低级错误。这些模块不参与端到端训练,但它们的引入并不违背端到端的思想,反而让整个系统更鲁棒。

我自己的经验是,端到端的"端"应该理解为"从原始输入到最终决策的联合优化",而不是"中间不能有任何人工设计的组件"。只要最终目标是联合优化的,中间有一些辅助模块是可以接受的。关键是要保证这些辅助模块不会成为信息瓶颈,不会阻断梯度流动。

6. 从训练深水区游出来的几点体会

做端到端自动驾驶的训练,最深的体会是:这是一个系统工程,不是单点突破。数据、算法、平台,每一块都需要深耕,但更重要的是它们之间的协同。我见过太多团队,在某一个点上做得很好,但因为其他环节的短板,整体效果就是上不去。

另一个体会是,端到端模型的训练非常依赖工程能力。学术界可以只关注算法创新,但工业界必须考虑数据怎么采、平台怎么搭、实验怎么管。这些工程细节,往往决定了算法能不能真正落地。

还有一个经验是,不要迷信"大力出奇迹"。端到端模型确实需要大量数据和算力,但盲目堆资源并不一定能带来性能提升。关键是要找到瓶颈在哪里,然后有针对性地投入。有时候,优化一下数据流水线,比多买一百张卡更有效。

最后,端到端自动驾驶还在快速演进中,今天的最佳实践可能明天就被推翻。保持开放的心态,持续学习,比固守某个方案更重要。我在这个方向上踩过的坑、积累的经验,也只是阶段性的认知,希望能给同行一些参考,也期待看到更多新的思路和方案出现。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进