The End-to-End Autonomous Driving Paradigm, Part 2
视觉语言模型(Vision-Language Model, VLM)拆开来是三个标准组件,驾驶场景在尾部再加一个驾驶头。
视觉编码器把图像变成一串视觉 token。主流做法是 ViT(Vision Transformer)的切块编码: 的图像被切成 个 的 patch,每个 patch 展平后经线性投影成一个 维向量,加上位置编码后进入 Transformer 编码:
其中 是 token 数, 是 patch 边长(常用 14 或 16)。SimLingo 用 InternViT,AutoMoT 用 Qwen3-VL 自带的视觉塔——两者都是这条路线,差别在规模与训练数据。
视觉 token 与文本 token(指令、问题)混排进同一个序列,交给预训练语言模型统一做自注意力。关键在”预训练”三个字:这个主干读过万亿级 token 的文本,世界常识(校车要礼让、警灯意味着靠边)已经以参数形式预置其中。驾驶模型不需要从零学世界,只需要学”把世界接到动作上”。
语言模型原生输出是文字。要开车,需要在输出端接一个驾驶头(driving head),把”会说”变成”会开”:常见做法是让模型先以思维链(Chain-of-Thought)生成一句决策理由,再由驾驶头把隐藏状态解码成未来轨迹点序列与期望速度。SimLingo 的”语言-动作对齐”就是让这两种输出共享同一套内部表征,互相校准。
语言模型输出文字是自回归(autoregressive)的:每生成一个 token 都要做一次完整的前向传播,第 个 token 依赖前 个的结果,无法并行。KV 缓存(key-value cache)能避免重算历史 token 的注意力键值,把每步前向的计算量从整序列压到单个新 token,但前向次数一次都省不掉——生成 个 token 就要 次前向。
VLM 驾驶每帧要先生成一句决策理由(几十次前向)再解码轨迹,帧耗时就由”语言生成长度 × 单次前向耗时”决定。控制回路期望 10 Hz 以上,矛盾是天然的。
SimLingo 在 RTX 5090 上闭环推理实测 0.04–0.065 倍实时(约 0.7–1 秒/帧)。冒烟评测 3 条路线:仿真内时钟走了 93 秒,墙钟跑了 1758 秒(约 29 分钟),放大 19 倍。按此外推,Bench2Drive 全量 220 条路线的墙钟预算必须按”天”而不是”小时”来排。
两个推论:
调研报告 §10.4 的三模型对比矩阵(分数为 Bench2Drive DS/SR):
| SimLingo(主) | AutoMoT(第二) | MindDrive(备选) | |
|---|---|---|---|
| 骨干 | InternVL2-1B | Qwen3-VL 4B + 1.6B 双专家 | Qwen2.5-3B + EVA02/PETR |
| 传感器 | 单前视相机 | 前视相机 + LiDAR | 6 目环视相机 |
| 动作解码 | 语言-动作对齐 | 异步快慢双专家 | 双 LoRA 专家 |
| DS / SR | 85.9 / 66.8 | 87.3 | 80.6 / 58.3 |
| 5090 微调 | 可(LoRA 2.72%) | 不可(训练需 80GB) | IL 可微调,但需先移植 |
分数都在 80+ 档,差距不到 9 分;真正把三者分开的是传感器组合与开放度,不是分数。
三条交叉后只剩这三个,而三者的架构维度恰好完全错开。
矩阵不是排名榜,是实验设计工具。如果三个模型同构(比如都是单目纯视觉 1B),渲染结论只能推广到这一类模型,审稿人一句话就能质疑外部效度。现在单目、环视、双模态三种”看世界的方式”,规模也从 1B 跨到 5.6B:渲染结论若跨架构一致,可信度大增;若不一致,差异本身就是发现。选型时把差异摆到一张表里,是为了让对照实验的变量结构一目了然。
分数口径说明:AutoMoT 的 87.3 出自官方 README,89.4 出自 HF 模型卡(权重更新后的成绩),引用时须注明来源。
成绩:CVPR’25 Highlight、CARLA Challenge 2024 冠军,Bench2Drive DS 85.9(README 口径;论文 Table 2 为 85.07±0.95,3 种子),发布时为该基准史上最高。
三个条件同时满足的候选只有它:
三档实验设计(UE4 基线 / UE5 zero-shot / UE5 微调)里的微调档,只有它能承担——AutoMoT 训练需 80GB 显存直接出局,MindDrive 要先完成移植。这就是拍板的最后一票。
AutoMoT(ICML’26)底座是 Qwen3-VL,核心设计是异步双专家(asynchronous Mixture-of-Transformers):一个约 4B 的理解专家负责场景理解,一个约 1.6B 的动作专家负责输出驾驶动作,两者以不同频率异步运行——理解慢而深,动作快而浅,绕开了”每帧都跑全量大模型”的成本。总参数约 5.6B。
成绩:Bench2Drive DS 87.34 / SR 70.00(官方 README),HF 模型卡 DS 89.42 / SR 74.09(权重更新后)。两个口径并存,引用必须注明出处。
第二模型存在的意义是跨架构交叉验证:如果 SimLingo 在 UE5 上的结论能在 AutoMoT 上复现,结论的架构普适性就强一分。但因为 LiDAR 通道的存在,它的渲染敏感度天然更低——渲染结论一律以 SimLingo 为准,AutoMoT 只作佐证,引用其数字必须注明这一点。
LiDAR 测的是几何:激光回波给出点到传感器的真实距离,与渲染器把画面画得多漂亮完全无关。相机测的是外观:像素值由 UE4/UE5 的渲染管线(光栅化/Lumen、材质、后处理)直接决定,这正是本研究操纵的自变量。
对一个双模态模型 ,切换仿真器只改变 的分布, 基本不动。只要动作分支能从几何通道拿到足够信息(比如障碍物的精确位置),渲染域差造成的输入扰动就会在特征融合时被摊薄,表现为:
——同样真实的渲染差异,在双模态模型上测出的驾驶分变化被系统性 attenuate(衰减)向零。UE4/UE5 对比若拿含 LiDAR 的模型当主模型,渲染效果测不出来,不是因为不存在,而是因为被几何通道稀释了。
一个顺理成章的后续实验是去 LiDAR 消融:把 AutoMoT 的几何输入屏蔽,观察渲染敏感度是否回升——能把”稀释”从推断变成实证。
SimLingo 的专家数据远不止”画面 → 动作”配对。它的训练配置里真实开着三个语言监督开关(数据模块的 yaml,白纸黑字):
use_commentary: True # 行驶评论:边开边解说("前方行人,减速")
use_qa: True # 问答对:一问一答("该让行吗?该")
qa_augmentation: True # 问答增广:同一画面换多种问法
route_as: target_point_command # 导航混训:坐标点 + 文字指令两种表达
三种语言监督各有分工:commentary 教模型”边开边说”(可解释输出的来源);qa 把驾驶决策显式化成问答(语境理解的来源);qa_augmentation 对同一场景换问法,防止模型背答案。导航输入同时用坐标点(target_point)和文字指令(“左转""变道”)两种表达混合训练——这就是 SimLingo 能听懂”减速停""慢开""变道”这类指令的原因。“会解释”不是涌现的魔法,是数据工程喂出来的。
这些语言标签不是人工标的:它们由规则专家(PDM-Lite)在采数时利用仿真器真值(周围车距、交通灯状态、意图)自动生成。
语言开关有个隐含前提:特权信息。本项目在 UE5 侧自采数据时,CARLA 0.10 没有 PDM-Lite 这类特权专家,语言标签生成链断了——所以项目微调走的是纯驾驶 bucket(use_commentary: False、use_qa: False 双保险),SimLingo 论文 Table 6 证明纯驾驶训练可行。选型时看着全开的开关,到了自己的数据管线里未必开得起,这是”数据关”的真实分量。
从 HF 镜像(hf-mirror)拉取 Oscar-Huang/AutoMoT(commit fc79b630):14 个文件共 13GB,10 分 41 秒落盘。主权重 model.safetensors 为 13,441,415,278 字节。
第一步是完整性校验:对主权重算 sha256,与 HF LFS 指针文件里的 oid 逐字符比对。一致才敢用——大文件走镜像站,中间任何一环截断或损坏,表面都可能”下载成功”。散列一致是文件无损的唯一硬证据(这是完整性校验,不是防伪;防的是损坏,不是投毒)。
下载完整不等于能正确加载。第二步是 key 审计:把 safetensors 里的参数 key 清单与模型结构逐一对账。AutoMoT 全模型共 2302 个 key,其中 bev_encoder.* 占 1146 个——约一半参数在视觉/BEV 分支,与”动作分支吃 LiDAR 特征”的架构定位互相印证。
审计要点是分清三种账目:
加载器对 missing/unexpected 往往只打印警告不报错,日志一滚而过。“能跑”掩盖着”权重错”是复现失败的经典形态——本项目后来就在 AutoMoT 上踩到 ckpt 与代码跨代际改名(transfuser_proj.* → bev_encoder_proj.*)导致一层随机初始化、驾驶分从 87 掉到 27 的事故(EP12 详述)。
权重目录里有一个 model.safetensors.index.json(分片索引),但它是官方上传时的陈旧残留——里面引用的两个分片文件并不存在。加载器优先读单文件 model.safetensors,索引永远不会被读取。保留勿删(保持与官方目录结构一致),但要心里有数:目录里”长得像被用到”的文件,未必真的被用到。
MindDrive(小米,ECCV’26)官方栈锁定 Python 3.8 + torch 2.4.1 + cu118 + 魔改版 mmcv。这套组合在 RTX 5090(sm_120,要求 torch ≥ 2.7 + CUDA ≥ 12.8)上直接跑不动——老 torch 的二进制里没有新架构的内核。移植就是把整个栈抬到 torch ≥ 2.7:Python 3.10/3.11、重编 CUDA 扩展、逐个修 API 不兼容点。
实测账单:vendored CUDA 扩展用 nvcc 12.9 + TORCH_CUDA_ARCH_LIST=12.0 重编,全程约 24 分钟。
魔改 mmcv 的 C++ 源里,与新 ATen API 唯一不兼容的调用是张量类型查询:
// 老 ATen API(torch 2.4 时代):返回 at::Type 对象,新版本中已移除
auto dtype = dets.type();
// 新 API:直接返回 at::ScalarType 枚举
auto dtype = dets.scalar_type();
一处改名,改完即编过。这类移植的真实成本往往不在代码量,而在定位这一行之前要排掉的编译噪音——几十屏模板报错里找出真正的那一行。
移植是否成功不看”能 import”,看权重能否完整命中:
三关(数据、权重、移植)全过,模型才真正”可用”。很多论文复现失败就死在这里:论文型(架构)是对的,栈(依赖版本、扩展编译、权重装载账目)不对。