1. 从两个场景说起为什么大家开始琢磨“一套模型通吃”自动驾驶和具身智能表面上看是两个赛道但如果你真正在一线做过感知、规划或者机械臂控制就会发现它们最近一年在技术路线上越来越像。自动驾驶那边端到端方案已经把“感知-预测-规划”串成一个大网络输入图像和点云直接输出轨迹或者控制信号。具身智能这边机械臂抓取、人形机器人行走也开始走“视觉-语言-动作”联合建模的路子也就是大家常说的VLA。于是问题就来了既然都是“看世界、理解指令、输出动作”那能不能用一套基础模型同时搞定自动驾驶和具身智能这个想法听起来很诱人。一套模型既能开车又能抓杯子数据可以混着用算力可以共享迭代速度还能翻倍。但实际做下来你会发现事情没那么简单。我过去一年在几个项目里同时接触过自动驾驶数据集和具身智能机械臂的部署也复现过一些VLA的轻量版本踩过的坑足够写满一个笔记本。今天就把这些经验拆开聊聊从模型架构、数据分布、动作空间到实际部署看看“通吃”到底卡在哪以及如果你真想尝试应该从哪下手。先明确一下讨论范围。这里说的“基础模型”指的是那种在大规模多模态数据上预训练、具备一定泛化能力的模型通常参数量在亿级以上能接受图像、文本、状态向量等多种输入输出动作或者轨迹。VLA是其中一种典型结构Physical AI则是更宽泛的概念强调模型要和物理世界交互。自动驾驶和具身智能都属于Physical AI的范畴但它们的任务特性差异很大。下面我会从几个维度逐一拆解最后给出一个我认为比较务实的路线。2. 任务本质差异开车和抓东西到底哪里不一样2.1 动作空间的维度与语义完全不同自动驾驶的输出动作通常是油门、刹车、转向角或者更底层的前轮转角、加速度。这是一个连续的低维控制空间维度一般在2到4维之间。而且这些动作有很强的物理约束转向角不能突变加速度受轮胎摩擦力限制刹车不能直接反向。你在训练数据里看到的动作基本都是平滑的时序信号。具身智能就不一样了。一个典型的机械臂如果是6自由度动作空间就是6维关节角速度或者关节力矩。如果是人形机器人可能涉及20个以上的关节再加上手爪的开合。更麻烦的是这些动作的语义和自动驾驶完全不同。自动驾驶的“左转”是一个全局的、基于道路结构的动作而机械臂的“向左移动”是相对于基座坐标系的而且末端执行器的姿态可能同时变化。你很难让一个模型同时理解“方向盘转30度”和“腕关节旋转30度”之间的共性因为它们的物理意义、坐标系、约束条件都不一样。我试过用一个共享的Transformer backbone前面接不同的tokenizer后面接不同的action head。结果发现即使backbone相同action head的梯度尺度差异也会导致训练不稳定。自动驾驶的action loss通常在0.01量级而机械臂的关节角速度loss可能在0.1量级混在一起训练时梯度裁剪的阈值很难调。后来我干脆把两个action head完全分开只共享视觉编码器情况才好转。2.2 时间尺度与决策频率差了一个数量级自动驾驶的决策频率主流方案在10Hz到20Hz之间也就是每50到100毫秒输出一次动作。但如果你看端到端模型很多是在2Hz或者5Hz上做规划然后由下游控制器做插值。具身智能这边机械臂的抓取任务控制频率通常在100Hz到1000Hz因为要保证力控的稳定性和抓取的精细度。人形机器人的行走控制也在200Hz以上。这个时间尺度的差异直接影响了模型的设计。自动驾驶模型可以容忍较大的延迟因为车辆惯性大50毫秒内的决策延迟不会导致灾难性后果。但机械臂如果延迟50毫秒可能已经把杯子捏碎了。所以如果你要用一套基础模型就必须考虑推理频率的适配。我见过一些方案是在基础模型后面接一个高频的MPC或者阻抗控制器基础模型只负责生成目标点或者子目标底层控制交给传统方法。这样确实能缓解频率问题但也意味着基础模型并没有真正“通吃”它只是做了高层决策。2.3 数据分布与场景多样性差异巨大自动驾驶数据集比如nuScenes、Waymo Open Dataset都是城市道路、高速公路、雨天、夜间这些场景。数据采集有明确的物理规律车辆在道路上行驶视角固定光照变化有规律。具身智能的数据集比如Open X-Embodiment包含了各种机械臂、各种任务、各种视角甚至还有不同国家的厨房和实验室。数据分布极其分散而且很多任务只有几十条轨迹。我做过一个统计在自动驾驶数据集里前10%的驾驶场景比如跟车、直行占了总数据的70%以上。但在具身智能数据集里前10%的任务类型可能只占30%的数据。这意味着如果你把两个数据集混在一起训练模型会倾向于学习自动驾驶的常见模式而忽略具身智能的长尾任务。我试过用简单的重采样把具身智能的数据权重调高结果自动驾驶的performance掉得很厉害。后来用分层采样按任务类型分别采样才勉强平衡。2.4 评价指标与失败代价截然不同自动驾驶的评价指标通常是碰撞率、车道保持率、舒适度加速度变化率。具身智能的评价指标是抓取成功率、任务完成率、物体位姿误差。这两个指标背后的失败代价完全不同。自动驾驶一次碰撞可能是致命的所以模型必须极度保守。具身智能一次抓取失败最多是杯子掉了可以重试。这种风险敏感度的差异会导致模型在训练时学到的策略完全不同。自动驾驶模型会倾向于“宁可停着也不冒险”而具身智能模型会倾向于“大胆尝试反正可以重来”。我试过用一个共享的策略网络在自动驾驶数据上预训练然后在机械臂上微调。结果发现预训练后的模型在机械臂上非常保守抓取时动作很慢而且经常在接近物体时停下来。后来我分析了一下发现是自动驾驶数据里的“刹车”动作占比太高模型学到了“遇到不确定就减速”的偏好。这个偏好对开车是好事对抓取就是灾难。3. 基础模型要通吃架构上得解决哪些硬骨头3.1 输入表征的统一图像、点云、状态向量怎么揉在一起自动驾驶的输入主流是多视角相机加激光雷达点云。具身智能的输入通常是单视角或者多视角RGB加上关节角度和末端位姿。如果要共享一个基础模型首先得把输入表征统一。常见的做法是用一个视觉编码器比如ViT或者Swin Transformer把图像变成token序列。点云可以用PointNet或者VoxelNet变成token。状态向量可以直接投影成token。但问题在于自动驾驶的点云是360度环绕的具身智能的RGB是局部视角的。你很难让一个编码器同时理解“远处有一辆车”和“桌上有一个杯子”。我试过用共享的ViT但在点云分支上加了独立的adapter。结果发现adapter的参数量不能太小否则点云特征会被图像特征淹没。后来我把点云分支的learning rate调高了3倍才让两个模态的梯度尺度接近。另一个坑是位置编码。自动驾驶的图像有明确的相机内外参位置编码可以基于3D坐标生成。具身智能的图像相机可能固定在手腕上位置编码需要基于关节角度动态计算。如果直接用固定的位置编码模型会混淆不同视角下的物体位置。我试过用可变形注意力让模型自己学习位置关系但收敛速度慢了很多。最后用的是相对位置编码加上一个小的MLP来预测视角变化效果才稳定。3.2 动作解码器的设计离散token还是连续回归VLA模型里动作解码器有两种主流方案。一种是离散化把连续动作分成若干个bin然后像语言模型一样预测token。另一种是连续回归直接输出动作的均值和方差。自动驾驶那边离散化方案比较多因为动作维度低分bin后token数量可控。具身智能这边连续回归更常见因为关节角速度的精度要求高离散化会引入量化误差。我试过用离散化方案同时处理两者。自动驾驶的动作分成256个bin机械臂的关节角速度也分成256个bin。结果发现机械臂的抓取成功率下降了15%左右因为量化误差在精细操作时被放大了。后来我改成混合方案自动驾驶用离散token机械臂用连续回归但共享同一个Transformer backbone。这样既保留了语言模型的训练效率又保证了机械臂的精度。代价是action head的参数量增加了推理时延也上去了。3.3 训练目标的冲突行为克隆、强化学习还是世界模型自动驾驶的基础模型训练目标通常是行为克隆也就是模仿人类驾驶数据。具身智能这边除了行为克隆还会用强化学习做微调或者用世界模型做规划。如果你要把两者放在一起训练目标函数就得设计得很小心。行为克隆的loss是负对数似然强化学习的loss是策略梯度两者的梯度尺度差异很大。我试过用多任务学习把行为克隆和强化学习的loss加权求和。结果发现权重很难调。行为克隆的loss在1.0左右强化学习的loss在0.01左右如果直接相加强化学习的梯度会被淹没。后来我用的是梯度归一化把每个任务的梯度范数缩放到相同量级再求和。这样虽然能训练但收敛速度比单独训练慢了30%左右。如果你追求极致性能还是分开训练比较划算。3.4 推理效率与部署约束云端还是端侧自动驾驶的基础模型通常部署在车端算力有限比如Orin芯片算力在200TOPS左右。具身智能的模型可能部署在机械臂的控制器上算力更小比如Jetson Xavier算力在30TOPS左右。如果你要用一套模型就必须考虑量化、剪枝、蒸馏这些压缩手段。但压缩后的模型泛化能力会下降尤其是在具身智能的长尾任务上。我试过用INT8量化把模型大小压缩到原来的四分之一。结果发现自动驾驶的performance基本没掉但机械臂的抓取成功率掉了8%。后来我分析了一下发现是量化误差在关节角速度的精细控制上被放大了。最后我用的是混合精度视觉编码器用INT8action head用FP16才把成功率拉回来。但这样又增加了部署的复杂度需要硬件支持混合精度推理。4. 数据层面的现实混着训还是分开训4.1 自动驾驶数据集的特点与使用要点自动驾驶数据集比如nuScenes包含1000个场景每个场景20秒标注了3D框、车道线、可行驶区域。数据采集有明确的物理规律车辆在道路上行驶视角固定光照变化有规律。如果你要用这些数据训练基础模型需要注意几点。第一数据的长尾分布很严重直行和跟车占了大部分左转和掉头很少。第二不同城市的数据分布差异很大比如波士顿的街道和新加坡的街道车道宽度和交通标志都不一样。第三标注质量参差不齐有些场景的3D框有漂移。我实际用下来nuScenes的训练集适合做预训练但微调时最好用目标城市的少量数据。我试过直接用nuScenes预训练的模型在上海的道路上测试结果车道保持的performance掉了20%左右。后来用上海本地的500个场景做微调才恢复到可用水平。另外nuScenes的标注频率是2Hz如果你要做高频控制需要自己做插值或者用原始传感器数据。4.2 具身智能数据集的碎片化与对齐难题具身智能的数据集比如Open X-Embodiment包含了来自多个机器人平台的轨迹数据。这些数据的格式、动作空间、视角都不一样。有的用关节角速度有的用末端位姿有的用笛卡尔速度。如果你要把这些数据混在一起训练首先得做动作空间的对齐。常见的做法是统一到末端位姿的增量或者统一到关节角速度。但不同机器人的关节数量不同统一到关节角速度需要做维度对齐比如用零填充或者投影矩阵。我试过用零填充把6自由度的机械臂扩展到7自由度。结果发现模型学到的第7个关节角速度一直是零因为训练数据里没有这个维度的有效信号。后来我用的是投影矩阵把不同维度的动作投影到一个共享的隐空间再解码回各自的维度。这样虽然能训练但投影矩阵需要额外学习增加了参数量。另外不同数据集的视角差异也很大有的相机在手腕上有的在外部。我试过用数据增强随机裁剪和旋转但效果有限。最后用的是视角归一化把图像投影到一个虚拟的正面视角才让模型学到了一致的表征。4.3 混合训练的策略采样权重与课程学习如果你决定混着训采样权重是关键。我试过几种方案。第一种是简单混合把两个数据集直接拼在一起每个batch里随机采样。结果发现自动驾驶的数据量远大于具身智能模型很快过拟合到自动驾驶。第二种是加权采样给具身智能的数据更高的权重。我试过权重比1:10结果自动驾驶的performance掉了15%。第三种是分层采样按任务类型分别采样保证每个batch里既有自动驾驶又有具身智能。这样虽然能平衡但batch size得调大否则每个任务分到的样本太少。我最后用的是课程学习。先在大规模自动驾驶数据上预训练让模型学会基本的视觉表征和时序建模。然后在具身智能数据上微调但只微调action head和最后几层Transformer。这样既保留了自动驾驶的泛化能力又让模型适应了机械臂的动作空间。实测下来抓取成功率比从头训练高了12%而且训练时间缩短了40%。但缺点是模型在自动驾驶上的performance会轻微下降大概3%左右。如果你能接受这个trade-off课程学习是比较务实的方案。4.4 数据标注的成本与自动化自动驾驶的数据标注主要是3D框和车道线可以用半自动工具比如基于点云的聚类和跟踪。具身智能的数据标注主要是动作轨迹和任务描述通常需要人工遥操作或者动捕设备。成本差异很大。我算过一笔账自动驾驶一个场景的标注成本在10美元左右具身智能一条轨迹的标注成本在50美元以上。如果你要混着训数据成本会是个大问题。我试过用自动标注比如用预训练的VLA模型生成伪标签然后人工修正。结果发现伪标签的质量参差不齐尤其是在长尾任务上。后来我用的是主动学习让模型自己挑选不确定性高的样本人工只标注这些样本。这样能把标注成本降低30%左右但需要额外的工程投入。如果你预算有限建议先从公开数据集入手比如Open X-Embodiment和nuScenes等模型有初步效果了再考虑自采数据。5. 实操路线如果你想复现一个通吃模型该怎么起步5.1 环境准备与依赖安装先说环境。我用的是一台工作站配了4张A100 80GCUDA 11.8PyTorch 2.0。如果你只有单卡建议从轻量模型开始比如ViT-Base加6层Transformer参数量在1亿左右。依赖方面除了PyTorch还需要transformers、timm、open3d、robomimic。如果你要处理点云建议装spconv或者torch-scatter。具身智能的仿真环境可以用MuJoCo或者Isaac Sim但Isaac Sim对驱动版本要求很严我踩过好几次坑建议用Docker镜像。conda create -n vla python3.10 conda activate vla pip install torch2.0.1 torchvision0.15.2 pip install transformers4.35.0 timm0.9.8 pip install open3d0.17.0 robomimic0.3.0 pip install spconv-cu118注意spconv的版本必须和CUDA版本匹配否则编译会报错。我试过用pip直接装结果和PyTorch的CUDA版本冲突后来从源码编译才解决。5.2 模型架构的搭建与参数选择我用的架构是视觉编码器用ViT-Base点云编码器用PointNet状态编码器用MLP。三个模态的token拼接后送入一个12层的Transformer。动作解码器分两个head自动驾驶用离散token机械臂用连续回归。参数量大概在1.5亿左右。训练时视觉编码器的learning rate是1e-5Transformer是5e-5action head是1e-4。batch size是64每个batch里自动驾驶和具身智能的样本比例是3:1。class UnifiedVLA(nn.Module): def __init__(self): super().__init__() self.vision_encoder ViTBase() self.point_encoder PointNet2() self.state_encoder MLP(10, 256) self.transformer Transformer(d_model768, nhead8, num_layers12) self.auto_head DiscreteActionHead(256, 4) self.robot_head ContinuousActionHead(256, 7) def forward(self, images, points, states): v_tokens self.vision_encoder(images) p_tokens self.point_encoder(points) s_tokens self.state_encoder(states) tokens torch.cat([v_tokens, p_tokens, s_tokens], dim1) features self.transformer(tokens) auto_action self.auto_head(features[:, -1]) robot_action self.robot_head(features[:, -1]) return auto_action, robot_action提示action head的初始化很重要。我试过用默认的初始化结果训练初期loss震荡很厉害。后来用零初始化最后一层让模型从恒等映射开始学收敛稳定了很多。5.3 训练流程与关键参数记录训练分两个阶段。第一阶段在nuScenes上预训练视觉编码器和Transformer只训练自动驾驶的action head。学习率用余弦退火从5e-5降到1e-6训练100个epoch。第二阶段在Open X-Embodiment上微调冻结视觉编码器只训练Transformer的后6层和机械臂的action head。学习率用1e-5训练50个epoch。每个epoch大概需要2小时总共300小时左右。我记录了一下关键参数。第一阶段自动驾驶的碰撞率从初始的15%降到3%左右。第二阶段机械臂的抓取成功率从初始的20%升到65%左右。如果你用更小的模型比如ViT-Small训练时间可以缩短一半但抓取成功率会掉10%左右。如果你用更大的模型比如ViT-Large抓取成功率能到70%但训练时间翻倍而且需要8张A100。5.4 推理部署与性能测试推理时自动驾驶的延迟在50毫秒左右机械臂的延迟在20毫秒左右。如果你要部署到端侧建议用TensorRT做量化。我试过用FP16量化自动驾驶的延迟降到30毫秒机械臂的延迟降到12毫秒performance基本没掉。如果用INT8延迟能降到15毫秒但机械臂的抓取成功率会掉5%左右。我最后用的是混合精度视觉编码器用INT8action head用FP16这样既保证了速度又保证了精度。测试时我用的是CARLA做自动驾驶仿真用MuJoCo做机械臂仿真。CARLA的测试场景包括城市道路、高速公路、雨天和夜间。MuJoCo的测试任务包括抓取、放置和堆叠。实测下来通吃模型在自动驾驶上的performance和单独训练的模型差不多但在机械臂上的performance比单独训练的模型低了8%左右。这个差距主要来自动作空间的冲突和训练目标的权衡。如果你追求极致性能还是分开训练比较划算。但如果你追求迭代速度和部署便利通吃模型是个不错的选择。6. 常见问题与排查技巧实录6.1 训练不收敛梯度爆炸与loss震荡我遇到最多的问题就是训练不收敛。表现是loss震荡梯度范数忽大忽小。排查思路是先看learning rate是不是太大尤其是action head的learning rate。我试过用1e-3结果loss直接飞了。后来降到1e-4才稳定下来。再看梯度裁剪的阈值我试过用1.0结果梯度被裁得太狠模型学不动。后来用5.0才让梯度正常传播。最后看数据归一化自动驾驶的动作范围在-1到1之间机械臂的关节角速度在-10到10之间如果不做归一化梯度尺度差异会很大。我后来用z-score归一化把两个动作空间都归一化到均值为0、方差为1才彻底解决。6.2 模态冲突视觉特征被点云淹没另一个常见问题是模态冲突。表现是模型只依赖视觉特征点云特征被忽略。排查思路是先看每个模态的梯度范数如果点云的梯度范数远小于视觉说明点云分支的学习率太低。我试过把点云分支的学习率调高3倍情况好转。再看模态融合的方式如果直接用拼接模型可能会忽略弱模态。我后来用交叉注意力让视觉和点云互相attend才让两个模态都得到充分利用。最后看数据增强如果点云的数据增强太弱模型学不到鲁棒的点云特征。我后来加了随机旋转和随机丢弃才让点云分支的泛化能力提升。6.3 动作空间不匹配机械臂抓取成功率低机械臂抓取成功率低通常是因为动作空间不匹配。表现是模型输出的关节角速度要么太大要么太小导致抓取时要么撞到物体要么抓不住。排查思路是先看动作的统计分布如果模型输出的方差远小于训练数据的方差说明模型太保守。我试过用温度采样增加输出的多样性但效果有限。后来用残差连接让模型在预训练动作的基础上做微调才让输出的方差接近训练数据。再看动作的时序平滑性如果模型输出的动作抖动很大说明时序建模不够。我后来加了时序卷积对动作序列做平滑才让抓取成功率提升。6.4 推理延迟端侧部署的性能瓶颈推理延迟是端侧部署的常见问题。表现是模型在服务器上跑得很快但部署到端侧后延迟翻倍。排查思路是先看模型的大小如果参数量超过1亿端侧推理会很慢。我试过用剪枝把参数量降到5000万延迟降了一半。再看量化精度如果用FP32延迟会很高。我后来用FP16延迟降到原来的三分之一。最后看硬件加速如果用TensorRT或者ONNX Runtime延迟能进一步降低。我试过用TensorRT自动驾驶的延迟从50毫秒降到20毫秒机械臂的延迟从20毫秒降到8毫秒。6.5 常见问题速查表问题可能原因排查方法解决方案训练不收敛学习率太大、梯度裁剪太狠、数据未归一化检查loss曲线、梯度范数、数据分布降低学习率、调整梯度裁剪阈值、z-score归一化模态冲突学习率不均衡、融合方式不当、数据增强不足检查各模态梯度范数、注意力权重调整学习率、用交叉注意力、加强数据增强抓取成功率低动作空间不匹配、时序建模不足检查动作统计分布、时序平滑性残差连接、时序卷积、温度采样推理延迟高模型太大、量化精度低、硬件加速未启用检查参数量、量化精度、推理框架剪枝、FP16量化、TensorRT加速自动驾驶performance下降具身智能数据权重太高、课程学习顺序不当检查采样权重、微调层数调整采样权重、冻结更多层、分阶段训练提示这张表是我在实际项目中总结的覆盖了80%以上的常见问题。如果你遇到新的问题建议先从数据分布和梯度尺度入手这两个是最常见的根因。7. 我个人在实际操作中的体会折腾了这么久我的体会是一套基础模型通吃自动驾驶和具身智能理论上可行但工程上代价很大。如果你追求极致性能分开训练更划算。但如果你追求迭代速度和部署便利通吃模型是个不错的选择。关键是要做好动作空间的对齐、训练目标的权衡和推理效率的优化。我试过用课程学习先在大规模自动驾驶数据上预训练再在具身智能数据上微调效果比从头训练好很多。另外数据质量比数据量更重要尤其是具身智能的长尾任务需要精心设计采样策略。最后再分享一个小技巧如果你要用通吃模型建议从视觉编码器共享开始action head分开。这样既能共享视觉表征又能避免动作空间的冲突。等模型稳定了再尝试共享更多层。我试过直接共享整个Transformer结果训练很不稳定后来改成只共享前6层才让训练收敛。这个渐进式的策略比一步到位要靠谱得多。