一辆智能车在路上跑一天保守估计也会产生几十GB的传感器数据图像、点云、里程、驾驶状态。如果车队有个两三百辆这个数据量足以把存储机房撑得满满当当。但真正让人头疼的不是多而是多而重复——同一个路口反复排队同一条高架桥的同一个弯道同一个晴天下午的匀速巡航这些画面今天录一遍、明天录一遍内容几乎一模一样。真正稀缺的、能让模型能力上限往上抬一截的样本可能只有总数据里的百分之几。基于这个观察我所在的某个智驾项目里逐步尝试了一种做法把是否值得学习这个判断权下放给车端让车自己决定学习哪些数据自动筛选高价值数据再用这些精挑细选的数据去替代传统全量训练最终输出一个更高效的模型。整套思路我做下来之后发现它不是在原有训练流程上加一个过滤器而是从根本上把数据闭环的逻辑颠倒了一遍。这篇文章就把这套方案的来龙去脉、落地细节和坑都写出来给同样被数据量压得喘不过气的人一个参考。1. 全量训练不是不好是账越来越算不过来1.1 数据量在涨算力在涨但有效信息增量没涨很多人谈到训练数据默认的思维是越多越好。这在模型早期确实成立早期模型表达能力有限数据多一点点泛化能力就好一点点。可当模型规模和数据规模都上来之后你会发现一个尴尬的事实边际收益在快速递减。我习惯把训练数据想象成学生刷题。一个学生做第一遍题错误率降得很快做到第五遍同一套题几乎是在浪费时间。全量训练就是让模型一遍遍刷同一套卷子刷一遍要花费大量GPU时间、大量存储带宽最后模型真正学到的新知识却很少。具体到智能驾驶场景全量训练的浪费更直观。车辆每天在城市道路上跑95%以上的时间处于正常行驶状态直行、等红灯、跟车、变道这些场景模型早就见过无数遍。我见过一个车载日志统计一天下来真正包含可学习信息的片段按帧数算经常不到15%。把这15%提取出来训练效果不一定比全量训练差但成本可以低一个数量级以上。1.2 简单样本刷屏让训练过程营养失衡全量训练的第二个问题不只是浪费而是它会产生一种隐性的偏差简单样本过量复杂样本稀缺模型被简单样本喂饱了。在一个未经筛选的数据集里晴天直行、车道线清晰、无车干扰的样本占比极高。这样的样本在损失函数里贡献了大部分梯度模型很容易就把它们学到接近满分。而真正影响自动驾驶安全的长尾场景——夜晚光线突变、施工路段的无序引导、前车突然切入、行人从遮挡物后探出——本来数量就少再被海量简单样本稀释在训练过程中几乎翻不起浪花。你可以去看训练loss曲线通常前几轮降得很快后面就在一个平台期徘徊。这个平台期不是因为模型能力到顶了而是因为数据里已经没有足够多的新东西可学。全量训练相当于把大量预算花在了巩固已学会的知识上。1.3 迭代速度被拖垮出了问题来不及修全量训练另一个容易被低估的代价是迭代周期。一辆车发现了一个新的问题场景——比如某个地库出口的坡度识别错误——对应数据传回云端进入训练集重新训练一个版本。如果训练集是过去一整年的全量数据一次训练可能要在上百张GPU上跑几天等模型发回车上已经过去一两周。智能驾驶的数据问题讲究发现即修复。新问题发生之后最有价值的是问题发生前后几十秒内的上下文。如果让车自己决定学习哪些数据把那些异常时刻自动选出来云端只需要把这个小批量数据接到已有模型上做增量训练或者微调一天之内就能发布新版本。全量训练保证的是覆盖面但跟不上变化速度。2. 把该学什么变成车端能算的分数价值评分的四个信号让车自己决定学习哪些数据听上去像是一种主观意愿落到工程上其实是一个评分问题。我们需要给每一帧或者每一个连续片段算出一个数值这个数值代表它值不值得进入训练集。我在实践中发现单纯靠某一种信号很容易出现偏科最好组合四类信号。2.1 不确定性模型自己知道自己没把握最直觉的信号是模型当前输出有多犹豫。如果一个检测模型对前方障碍物的置信度只有0.6或者分割模型对路肩边界给出了一团模糊的预测这帧数据很可能包含它没见过或没学透的模式。车端在正常行驶时本来就在跑感知模型顺手把每一帧输出的置信度、熵值记录下来几乎不增加额外算力。具体可以看几个指标检测框的类别置信度、多目标之间的混淆程度、车道线回归结果的方差。这些信号总结成一句人话就是如果连模型自己都拿不准这帧数据就该进训练集。2.2 新颖性和已经会的东西越不像越值得学不确定性解决没把握但光看不确定性还不够。有些场景模型输出很自信比如第一次见到一段特殊纹理的隧道内壁模型可能粗暴地把它识别成普通墙面同时置信度还很高。这种自信的错误恰恰最危险光靠不确定性信号抓不到它。所以还要有一个新颖性信号衡量当前帧与已训练数据分布之间的距离。做法是把当前帧经过一个轻量embedding网络变成特征向量和历史训练集里的特征中心算距离。距离越大说明这种数据此前没见过价值越高。这里需要注意embedding网络不要太重不然车端算力吃不消后面会单独说。2.3 风险暴露把场景的危险程度也当成学习信号并不是所有有价值的数据都体现在模型输出上。有些场景即使模型处理得很好也应该被记录下来反复学习因为这些场景一旦出错后果更严重。比如车辆紧贴大货车并行的画面、儿童在路边嬉戏的画面、夜间对向车开远光灯的画面。这一块我是用规则引擎来做打分的把危险场景的关键要素拆成规则比如目标类别、相对距离、相对速度、道路属性、光照条件只要命中高危组合就给这一帧的风险项加分。这部分的实现不依赖模型纯靠工程规则好处是稳定、可解释坏处是规则需要人工维护。2.4 分布漂移当车跑进陌生的世界时第四类信号是分布漂移。智能车经常跑陌生区域或者遇到季节更替、天气剧变整个输入分布会整体偏移。比如一条新开通的城市快速路交通标识牌样式和训练数据里的不一样又比如深秋满地落叶车道线被遮挡。分布漂移信号的做法是车端每隔一段时间计算当前帧特征与基准分布的距离如果连续一段时间偏移都很大就把这段时间的数据整体标记为高价值。这有点像人到了一个陌生城市自然会放慢速度多看路况。分布漂移信号能把一批看起来普通但实际是新世界的数据抓回来。2.5 加权合成比分与一键触发规则这四个信号算出来后我会做一个加权合成value alpha * uncertainty beta * novelty gamma * risk delta * drift权重在项目初期靠经验定后期靠实验对比调整。但我不建议只用一个总分来决策因为总分会把某些极端情况平均掉。更稳的做法是双轨制一轨看总分超过阈值就保留另一轨看单项如果风险项超过单独设定的阈值即使总分不高也必须保留。实际车端部署时不需要每帧都跑完整评分。我的习惯是按事件组织数据先让车端以低帧率持续评估一旦评分超过阈值就把触发前6秒、触发后10秒这一段完整数据打包上传。这样既避免逐帧上传的碎数据问题也保留了事件的上下文给标注和后续训练留出理解空间。3. 车端挑数据、云端重训一个最小的闭环设计3.1 车端滚动缓存、评分、打包上传说完了分数来看整个系统在车端是怎么组织的。很多人以为让车自己决定学习哪些数据就是简单地在车里放一个判断程序觉得重要就传觉得不重要就删。实际上更稳妥的设计是多加一层滚动缓存。车端传感器数据先写进一个循环缓冲区容量大约能覆盖几十秒到几分钟。评分器持续对缓冲区里的新数据打分一旦触发高价值事件就把事件前后的一段数据固化下来而不是只存当前触发帧。为什么这样做因为真正有用的信息经常出现在事件发生之前的几秒——比如前车司机有一个微妙的偏离意图人的预测系统能从车头轻摆中读出来而纯图像模型可能要到前车真正压线时才发现。如果只存触发帧等于把最关键的因果信息丢掉了。上传之前车端还会做一个轻量的后处理剔除完全静止的帧、做基本去重、统一压缩格式。能省一点带宽是一点尤其车队规模大了之后带宽成本不是小数目。3.2 云端二次编排、主动采样兜底、优先级标注云端收到的不是一堆原始数据而是一批带价值分数的数据包。云端数据中心要做的第一件事不是直接丢进训练集而是先做二次编排。二次编排主要包括三件事。一是跨车辆、跨时间的去重同一辆车在同一个路口反复触发的高价值事件价值已经在递减只保留代表性样本即可。二是标注优先级的排序标注员人力有限分数最高的数据包优先安排标注。三是主动采样兜底我强烈建议无论怎么筛选必须保留5%-10%的随机样本进训练集。这个兜底非常关键后面讲坑的时候会展开。云端训练这边通常的做法是在已有模型基础上做增量训练或微调。因为筛选后的数据量远小于全量数据一次训练的时间和资源消耗都大幅下降团队可以用更高频率来发布模型版本形成快节奏的学习闭环。3.3 阈值不是定死的要用模型自信度动态调整价值评分的阈值如果定成固定值会有一个隐患模型在持续变强同样一段数据旧模型看很新奇新模型看已经平淡。不确定性分数会随着模型迭代整体下降如果阈值不变筛选出来的数据会越来越少慢慢退化回只挑危险场景的路线。我比较推荐的做法是每发布一个新模型就在云端用一批固定的历史数据重新计算一遍价值分找到当前分布下的某个分位数作为新阈值。比如把阈值定在分数超过当前分布80%分位数的数据才保留。这样阈值会跟着模型能力自动调整——模型变强了阈值自动变严模型某方面变弱了相关数据的不确定性分数抬升又会自动被筛进来。4. 跑了小半年之后我印象最深的五个坑这套方案听起来逻辑通顺但真正放到车队里跑踩过的坑比我想象的多。我挑几个影响最大的展开。4.1 模型越练越强数据价值会缩水第一个坑就是上面说的阈值漂移。项目初期我们设定了一个固定阈值第一周筛出来的数据量还正常跑了两三个模型版本之后筛出来的数据量肉眼可见地变少。原因不是路上的场景变简单了而是模型对新场景的适应速度变快同一个场景第二次遇到时不确定性分数已经降下来了。这个坑的教训是数据价值不是数据的绝对属性而是数据和当前模型之间的关系。同一个路口的夕阳逆光场景对V1模型是地狱难度对V3模型可能已经是小菜一碟。系统设计一定要围绕当前模型能力来动态调整而不是一次性写死。4.2 筛选偏差只学自己想学的必然出现盲区第二个坑比较隐蔽。如果车端完全靠评分器决定学什么训练集就会慢慢变成评分器认为有价值的数据的集合这个集合不等于所有值得学的数据的集合。评分器本身也有盲区它没见过的东西自然不会给它高分。举个真实的例子某次我们发现模型对一种非常规施工路障的识别能力几乎为零但回查筛选记录这种施工路障的画面从来没被筛进来过因为评分器里没有针对它的规则embedding距离也没有把它判成足够新颖。这是一个鸡生蛋蛋生鸡的问题。解决的办法是给筛选系统打一个补丁在保留高价值事件的同时按固定比例混入随机采样数据。随机采样不一定都能用但它能保证训练集不会完全被筛选器的主观偏好主导总有一部分意外数据能流进来。比例我建议控制在5%-10%太低起不到兜底作用太高又失去了筛选的意义。4.3 冷启动没有历史分布新颖性分数从哪来第一个版本上线时我们根本没有历史训练集特征中心这个东西新颖性信号无从算起。一开始直接用预训练embedding来替代但预训练模型的特征空间和车辆实际场景的分布差得挺远算出来的分数参考意义有限。后来我学乖了冷启动阶段不做精细评分先用规则加不确定性打底同时保证随机采样的比例拉高到20%左右。跑了两周积累了足够的新数据之后再逐渐降低随机比例把新颖性信号接进来。这个过程有点像一个新员工先跟着师傅做熟悉业务之后才让他独立判断。不能上来就全靠评分器。4.4 高价值数据挑出来了但没人标注筛选只是一个环节选出高价值数据之后还得标注标注才是真正的瓶颈。我记得有一次车端筛选器一天传上来大量夜间复杂场景的数据包云端AI平台存了几百GB但标注团队按正常节奏要消化两周。等标注完、训练完这些场景的时效性已经下降了。应对思路有两条。一是给标注队列做严格排序让分数最高的数据包优先被处理不必按到达时间排队。二是引入半监督和自动预标注用已有模型先跑一轮粗标签标注员只负责修正关键目标大幅压缩人工标注时间。对智驾来说要接受一个现实筛选器挑选数据的速度可以远超人类标注的速度所以系统里必须设计好标注预算的分配策略。4.5 触发时机没抓好想要的数据根本不在包里最后一个坑是关于数据包的截取时机。早期我们只在评分超过阈值后触发记录结果发现有些高价值事件的前半段被浪费了。比如一次轻微剐蹭事故真正有用的信息其实在事故发生前10秒——前车异常减速、路面湿滑、驾驶员开始变道。等我们的评分器通过感知结果识别到异常时前几秒的传感器流已经被循环缓冲区覆盖掉了。后来我把方案改成两层触发第一层是低阈值预览只要评分有上升趋势就先冻结缓冲区给后续保留空间第二层是高阈值确认真正打包上传。同时把事件包的截取范围往前扩展了几秒。这样虽然会上传一些误报数据但漏报的概率大幅下降。5. 复刻一条自筛选数据管道的最短路径如果你现在想在自己的项目里试一下这套东西不一定要先搭车队可以先在一个小范围里把它跑通。我给你一条我验证过的最短路径。5.1 先只加一个信号不要一上来就搞四信号加权很多人听到四个信号之后的第一反应是马上把四套算法都实现出来再调一堆权重。我劝你打住。先只做不确定性信号理由很实际它实现成本最低车端本来就在跑模型顺手记录置信度就行。用一段时间之后你会自然发现哪些高价值样本被漏掉了这时再针对性地补第二个信号。比如发现晴天高速巡航的重复数据太多就补一个简单的新颖性信号发现危险场景经常漏就补规则风险信号。增量式迭代比一步到位稳得多。5.2 一个可参考的评分器简化实现这块我贴一个伪代码级别的参考实际工程里需要根据你的模型接口自己做适配。def compute_frame_value(sensor_frame, model, embedder, history_index): # 1. 不确定性取模型关键输出的平均熵 pred model.predict(sensor_frame) uncertainty average_entropy(pred.key_outputs) # 2. 新颖性当前帧与历史特征中心的最短距离 feat embedder.encode(sensor_frame) novelty distance_to_nearest_cluster(feat, history_index) # 3. 风险规则引擎打分命中危险要素直接抬分 risk rule_risk_engine(sensor_frame) # 4. 组合 value ( 0.4 * normalize(uncertainty) 0.2 * normalize(novelty) 0.3 * normalize(risk) 0.1 * normalize(drift_score(sensor_frame, history_index)) ) return value def should_trigger(value, single_alerts): if value config.HIGH_VALUE_THRESHOLD: return True if any(single_alerts[k] config.ALERT_THRESHOLD[k] for k in single_alerts): return True return False这个简版实现有三个关键点所有信号都要先做归一化再加权否则数值范围大的信号会压过其他信号触发逻辑是总分过线和单项过线的或关系drift_score一开始可以直接设成0后面有数据了再接。5.3 用一场仿真实验验证整体收益落地之前强烈建议先在仿真环境里跑一组对照实验。我当初做的方式是同一个场景集一组用全量数据训练一组用跑完评分器之后筛选出的5%-10%数据训练对比两组在保留场景和长尾场景上的表现。第一次做这个实验时我的预期是筛选组和全量组持平但成本降低实际结果比预期好一点筛选组在典型场景上准确率略有波动但在长尾困难场景上往往能超过全量组。原因也容易解释全量训练被大量简单样本稀释而筛选训练把数据量集中在了模型真正欠缺的地方。如果你做出来的结果不是这样大概率是筛选器漏掉了某些重要信号好好检查一下你的评分项。6. 车只是第一个例子自主选数据思路的通用配方最后想多说一点这套让终端自己决定学习哪些数据的思路绝对不只在智能驾驶领域有用。它本质上是一个通用配方终端设备判断自己的数据价值只把高价值数据传回中心中心用精挑细选的数据更新模型再将更聪明的模型下发到终端形成循环。我在工业质检项目里试过类似的做法。产线上的相机如果每张照片都传回服务器网络和存储很快会爆改成在相机端跑一个轻量评分器只把疑似缺陷但模型置信度低的照片传回去服务器的存储压力立刻降了下来模型对新型缺陷的发现速度反而更快。还有语音助手设备、智能安防摄像头、工业机器人场景不同逻辑一模一样。我觉得这套思路最核心的认知转变是终端设备不再是一个被动的数据采集器而是一个有判断能力的参与者。它虽然不能像云端一样做大规模训练但它离数据最近最清楚当前这个时刻遇到的事情是平淡还是异常。把是否值得学习这个判断下放给终端云端就能从海量低价值数据里解放出来把算力花在真正改变模型能力的数据上。如果要从这套方法论里提炼一句最有价值的经验我的体会是不要追求一个完美的评分器而是设计一个能兜底的筛选闭环。评分器一定会犯错但只要你保留了一部分随机采样、让你的筛选器能识别自己的盲区系统的整体安全性就依然可控。筛选器的目标不是帮助你找到所有高价值数据而是帮助你用最低的成本找到绝大部分高价值数据同时不被自己的偏差困住。