
1. 从“知荐”说起为什么多模态轨迹预测值得死磕第一次看到“基于深度卷积网络的自动驾驶多模态轨迹预测”这个题目我脑子里蹦出来的不是论文里的那些公式而是两年前跟一个做量产ADAS的朋友吃饭时他吐槽的一句话“单模态预测就像闭着眼睛猜别人往哪走多模态才是睁开眼发现人家可能往三个方向走但你得同时盯着三个方向。”这句话糙理不糙。轨迹预测这件事本质上解决的是自动驾驶系统“预判”能力的问题。激光雷达、摄像头、毫米波雷达告诉你周围的车现在在哪、速度多少、朝向如何但接下来1到5秒它们会怎么动这是另一回事。而恰恰是这1到5秒的预判决定了你的规划控制模块是平顺跟车还是急刹避让。那为什么非得是“多模态”因为现实交通场景里一个目标的未来轨迹天然就是多峰的。前面那辆白色轿车可能继续直行可能向右变道也可能因为前方障碍物减速——这三种意图在观测时刻都是合理的。如果你只输出一条“平均轨迹”那大概率是一条既不像直行也不像变道的四不像路径规划模块拿到这种输入要么过度保守频繁刹车要么判断失误。“深度卷积网络”在这里扮演的角色是从鸟瞰图Bird‘s Eye ViewBEV或者栅格化的场景表示中提取空间交互特征。卷积的归纳偏置——局部连接、权值共享、平移不变性——天然适合处理这种具有空间结构的数据。车辆之间的相互影响、道路边界的约束、历史轨迹的时序模式都可以通过精心设计的卷积架构来捕获。这个方向适合谁看如果你是做自动驾驶感知或预测模块的工程师这篇内容能帮你理清从问题定义到模型落地的完整链路如果你是刚入行的研究生正在找选题或者复现论文这里面的实操细节和踩坑记录能帮你省下至少两周的试错时间如果你是对多模态融合感兴趣但不在自动驾驶领域轨迹预测这个场景其实是理解“多模态”概念的一个极佳切入点——它比图像描述生成更直观比语音识别更强调时序交互。我下面要聊的不是某篇具体论文的读书笔记而是把“深度卷积网络多模态轨迹预测”这个组合拆开讲清楚每个技术选择背后的逻辑、实操中真正卡人的地方以及那些论文里不会写但工程落地时一定会遇到的坑。2. 核心思路拆解多模态轨迹预测到底在预测什么2.1 问题定义从观测历史到未来分布先把问题说清楚。轨迹预测的输入通常是一段历史观测比如过去2秒内每个时间步通常0.1秒或0.2秒一个采样点每个交通参与者的位置、速度、朝向、类型车、行人、自行车。输出是未来一段时间常见3秒或5秒每个参与者的轨迹。但“输出轨迹”这四个字有歧义。单模态预测输出一条轨迹多模态预测输出K条轨迹每条轨迹附带一个概率值。这个K通常取3、5、6取决于场景复杂度和算力预算。每条轨迹代表一种“意图假设”概率代表这种意图发生的相对可能性。这里有个容易混淆的点多模态预测和多目标预测不是一回事。多模态是同一个目标有多种未来可能多目标是场景里有多个目标需要同时预测。实际系统里两者是叠加的——N个目标每个目标K种模态输出就是N×K条轨迹。计算量随目标数线性增长随模态数线性增长所以K不能太大。2.2 为什么是卷积网络而不是LSTM或Transformer这个问题我被问过很多次。2018年之前轨迹预测的主流是LSTM加社交池化Social Pooling后来Transformer火了很多工作转向注意力机制。但卷积网络在这个任务里始终有一席之地原因有几个。第一空间交互的建模效率。车辆之间的相互影响本质上是空间邻域关系——你主要受前后左右几个车的影响不太可能受50米外一辆车的影响。卷积的局部感受野天然匹配这种空间局部性。堆叠几层之后感受野扩大就能捕获更大范围的交互。相比之下注意力机制需要计算所有目标对之间的关系在目标密集场景下计算冗余明显。第二BEV栅格表示的天然适配。很多工作把场景渲染成BEV图像每个通道代表一种语义车辆位置、道路边界、车道线、可行驶区域等。这种表示下卷积就是最自然的操作。你甚至可以直接用ResNet、EfficientNet这些在ImageNet上预训练过的骨干网络来提取特征迁移学习的红利直接吃。第三计算效率。量产芯片上卷积的优化程度远高于注意力机制。同样算力预算下卷积网络能跑更大的输入分辨率或者更多的模态输出。这不是学术上的优劣问题是工程上的现实约束。当然纯卷积也有局限。时序建模能力弱于LSTM和Transformer长距离依赖捕获需要很深的网络。所以实际工作中常见的是混合架构卷积提空间特征LSTM或注意力提时序特征最后用多头输出生成多模态轨迹。2.3 多模态输出的三种实现路径多模态输出不是简单地在最后一层加K个头就完事了。怎么让K个输出真正代表不同的意图模式而不是K个几乎一样的轨迹这是核心难点。主流做法有三类。第一类锚点轨迹加回归偏移。预先定义K条锚点轨迹比如直行、左变道、右变道、减速、加速网络预测每条锚点的概率和相对于锚点的偏移量。这类似于目标检测里的Anchor Box思路。优点是训练稳定模态不容易坍缩缺点是锚点设计依赖先验场景覆盖不全时性能下降。第二类多模态输出加多样性损失。网络直接输出K条轨迹和对应概率但在损失函数里加一项“多样性正则”惩罚K条轨迹之间过于相似。常见的是Winner-Takes-All损失只对最接近真值的那条轨迹计算回归损失其他轨迹不惩罚同时用分类损失让概率分布合理。这样网络会自然分化出不同模态。第三类条件变分自编码器CVAE。引入隐变量z从先验分布采样解码器根据z和观测历史生成轨迹。不同z采样对应不同模态。优点是理论上能建模连续的多模态分布缺点是训练不稳定容易后验坍缩。实际工程中第一类和第二类用得最多。第一类适合场景相对固定的封闭园区或高速第二类适合城市道路这种意图空间更开放的场景。3. 核心细节解析从数据到网络的完整链路3.1 数据准备那些论文里不会告诉你的脏活轨迹预测的数据集学术界常用的是NGSIM、Argoverse、nuScenes、Waymo Open Motion Dataset。但如果你要做量产落地这些数据集只能用来做预训练和benchmark真正要解决的是自己车队采集的数据。数据清洗的坑极多。我列几个最典型的ID跳变跟踪算法不稳定导致同一个目标的ID中途切换历史轨迹断裂。处理方式是设置一个时间窗口窗口内ID变化超过阈值就丢弃该片段。静止目标停车场里停着的车、路边长时间不动的行人这些目标对预测模型是噪声。通常设置速度阈值比如0.5m/s过滤但要注意区分“等红灯的静止”和“停着的静止”——前者需要预测后者不需要。采样频率不一致不同传感器融合后输出频率可能波动需要重采样到固定频率。线性插值对位置够用但速度要用差分重新计算不能直接插值。坐标系漂移长时间累积的定位误差会导致全局坐标系下的轨迹缓慢漂移。解决方案是每个片段以自车当前位置为原点做局部归一化。数据标注方面轨迹预测不需要人工标注真值直接从跟踪结果里截取。但这里有个隐蔽的坑跟踪结果本身有噪声用带噪的真值训练模型模型会学到跟踪器的偏差。一个缓解办法是对真值轨迹做平滑比如Savitzky-Golay滤波但平滑窗口不能太大否则会抹掉真实的急转弯和急刹车。3.2 场景表示BEV栅格化的参数选择把场景转成BEV栅格图有几个关键参数需要定。分辨率常见0.1m/pixel到0.5m/pixel。0.1m能保留车道线细节但一张100m×100m的场景就是1000×1000像素计算量巨大。0.2m是精度和效率的平衡点100m×100m对应500×500。如果只关注自车周围50m范围250×250的输入对现代GPU来说很轻松。范围以自车为中心前后左右各取多少米。高速场景可以前向取80m、后向取40m、侧向各取20m城市场景需要更均衡前后各50m、侧向各30m。范围太小会丢失远处目标的交互信息太大则引入无关噪声。通道设计每个通道代表一种语义信息。我常用的配置是自车历史轨迹1通道、其他车辆历史轨迹1通道、行人历史轨迹1通道、道路边界1通道、车道线1通道、可行驶区域1通道、交通灯状态1通道。总共7到10个通道。通道不是越多越好每个通道都要有明确的语义否则网络很难学到有效特征。时序堆叠把过去T个时间步的BEV图沿通道维堆叠比如T5每步7通道输入就是35通道。这样卷积核在空间维滑动的同时也能看到时序变化。另一种做法是用3D卷积但计算量更大实际用得少。3.3 网络架构卷积骨干加多模态头一个典型的架构分三部分骨干网络、时序编码器、多模态预测头。骨干网络用ResNet-18或ResNet-34就够了。不需要ResNet-50以上因为BEV图的语义复杂度远低于自然图像太深的网络反而容易过拟合。输入是H×W×C的BEV堆叠图输出是H/32×W/32×512的特征图。这里有个细节下采样倍率不要太大32倍下采样后100m范围只剩3×3的特征图空间信息损失严重。我通常用16倍下采样配合空洞卷积扩大感受野。时序编码器接在骨干网络后面。把每个时间步的特征图展平成一个向量得到T个向量送进单层或双层LSTM隐藏状态维度256。也可以用1D卷积沿时间维滑动效果差不多但并行度更好。输出是融合了时空信息的场景特征向量。多模态预测头有两种设计。一种是共享特征加K个独立MLP头每个头输出一条轨迹和对应概率。另一种是特征加隐变量拼接后再过共享MLP。前者参数量大但训练稳定后者参数量小但容易模态坍缩。我倾向于前者因为轨迹预测的模型规模通常不是瓶颈。输出轨迹的表示方式直接回归未来每个时间步的(x,y)坐标还是回归控制量加速度、角速度再积分直接回归坐标更简单但可能产生不物理的轨迹比如瞬间横向移动。回归控制量物理约束更强但积分误差会累积。折中方案是回归坐标但在损失函数里加物理约束项比如加速度和角速度的平滑惩罚。3.4 损失函数多模态训练的核心难点损失函数设计是多模态轨迹预测最考验功力的地方。我见过太多模型在训练集上损失降得很低但推理时K条轨迹几乎重合这就是模态坍缩。Winner-Takes-AllWTA损失是最常用的。对每个样本计算K条预测轨迹与真值的距离只对距离最小的那条计算回归损失通常是L2或Smooth L1同时对所有K条计算分类损失交叉熵目标是让最准的那条概率最高。这样网络会自然分化不同的头负责不同的意图模式。但WTA有个问题早期训练时如果某个头偶然预测得准梯度会一直强化这个头其他头得不到足够梯度最终退化成单模态。缓解办法是训练初期用较小的K比如K3等模型稳定后再增加到K6。或者用ε-greedy策略以一定概率不只对最优头计算损失也对次优头计算。多样性正则是另一个思路。在损失里加一项惩罚K条轨迹两两之间的平均距离过小。公式大概是L_div -λ * mean(||τ_i - τ_j||)i≠j。λ取0.1到0.5之间。这个正则让轨迹在空间上散开但散得太开又可能偏离合理范围需要调参。概率校准也重要。模型输出的概率应该反映真实的置信度。如果模型说某条轨迹概率0.8那在所有概率0.8的样本里应该有大约80%的真值落在该轨迹附近。实际中模型往往过度自信需要温度缩放Temperature Scaling做后处理校准。4. 实操过程从零搭建一个可用的预测模型4.1 环境配置与依赖安装我用的技术栈是PyTorch 1.12 CUDA 11.3这是经过验证比较稳定的组合。更高版本的PyTorch在混合精度训练时偶发梯度溢出需要额外调参。conda create -n traj_pred python3.8 conda activate traj_pred pip install torch1.12.0cu113 torchvision0.13.0cu113 -f https://download.pytorch.org/whl/torch_stable.html pip install numpy pandas scikit-learn matplotlib tensorboard pip install nuscenes-devkit # 如果用nuScenes数据集数据加载用PyTorch的Dataset和DataLoader但要注意轨迹预测的样本长度可变需要自定义collate_fn做padding。padding用0填充同时在损失计算时用mask忽略padding位置。4.2 数据预处理流水线我以nuScenes数据集为例走一遍完整流程。第一步从nuScenes的devkit里提取每个样本的跟踪标注。nuScenes的标注频率是2Hz对轨迹预测来说太低了需要用插值提升到10Hz。线性插值对位置够用速度用相邻帧差分计算。第二步筛选有效目标。只保留历史观测长度≥2秒、未来预测长度≥3秒的目标。类型只保留车辆和行人自行车和摩托车样本太少单独建模不划算。第三步坐标系归一化。以自车当前位置为原点自车朝向为x轴正方向建立局部坐标系。所有目标的历史和未来轨迹都转到这个坐标系下。这样模型学到的模式与全局位置无关泛化性更好。第四步BEV栅格化。用0.2m/pixel的分辨率范围前后左右各50m得到500×500的栅格。每个通道用不同的渲染方式车辆历史轨迹用高斯核渲染成热力图道路边界用二值线车道线用不同灰度值区分。第五步划分训练集、验证集、测试集。按场景划分而不是按样本划分避免同一场景的样本同时出现在训练和测试集里导致数据泄露。nuScenes有1000个场景我通常用700训练、150验证、150测试。4.3 模型定义与训练循环模型定义的核心代码结构如下import torch import torch.nn as nn import torchvision.models as models class TrajPredictor(nn.Module): def __init__(self, num_modes6, future_steps30, hidden_dim256): super().__init__() # 骨干网络ResNet-18去掉最后的全连接层 resnet models.resnet18(pretrainedTrue) # 修改第一层卷积以接受多通道输入 resnet.conv1 nn.Conv2d(10, 64, kernel_size7, stride2, padding3, biasFalse) self.backbone nn.Sequential(*list(resnet.children())[:-2]) # 时序编码器 self.lstm nn.LSTM(512, hidden_dim, batch_firstTrue, num_layers2) # 多模态预测头 self.mode_heads nn.ModuleList([ nn.Sequential( nn.Linear(hidden_dim, 256), nn.ReLU(), nn.Linear(256, future_steps * 2) ) for _ in range(num_modes) ]) self.prob_head nn.Linear(hidden_dim, num_modes) def forward(self, bev_seq): # bev_seq: (B, T, C, H, W) B, T, C, H, W bev_seq.shape # 逐帧提取空间特征 spatial_feats [] for t in range(T): feat self.backbone(bev_seq[:, t]) # (B, 512, H/32, W/32) feat feat.mean(dim[2, 3]) # 全局平均池化 spatial_feats.append(feat) spatial_feats torch.stack(spatial_feats, dim1) # (B, T, 512) # 时序编码 lstm_out, _ self.lstm(spatial_feats) scene_feat lstm_out[:, -1] # 取最后时刻的隐藏状态 # 多模态输出 trajectories [] for head in self.mode_heads: traj head(scene_feat).view(B, -1, 2) trajectories.append(traj) trajectories torch.stack(trajectories, dim1) # (B, K, future_steps, 2) probs torch.softmax(self.prob_head(scene_feat), dim-1) # (B, K) return trajectories, probs训练循环里几个关键点。优化器用AdamW学习率1e-4权重衰减1e-4。学习率调度用CosineAnnealing从1e-4降到1e-6。Batch size根据显存来16GB显存大概能跑batch size 32。训练100个epoch前10个epoch用warmup把学习率从1e-6线性升到1e-4。WTA损失的具体实现def wta_loss(pred_trajs, pred_probs, gt_traj, gt_mask): # pred_trajs: (B, K, T, 2) # pred_probs: (B, K) # gt_traj: (B, T, 2) # gt_mask: (B, T) 有效位置为1 B, K, T, _ pred_trajs.shape # 计算每条预测轨迹与真值的距离 gt_expanded gt_traj.unsqueeze(1).expand(-1, K, -1, -1) # (B, K, T, 2) mask_expanded gt_mask.unsqueeze(1).expand(-1, K, -1) # (B, K, T) dist torch.norm(pred_trajs - gt_expanded, dim-1) # (B, K, T) dist (dist * mask_expanded).sum(dim-1) / mask_expanded.sum(dim-1) # (B, K) # 找最优模态 best_mode dist.argmin(dim1) # (B,) # 回归损失只对最优模态计算 reg_loss dist[torch.arange(B), best_mode].mean() # 分类损失让最优模态的概率最高 cls_loss F.cross_entropy(pred_probs, best_mode) return reg_loss cls_loss4.4 训练过程监控与调参训练时用TensorBoard监控几个关键指标总损失、回归损失、分类损失、各模态的使用频率最优模态的分布、模态间平均距离。模态使用频率这个指标特别重要。如果6个模态里只有2个被频繁选为最优说明其他4个模态是“死模态”没有学到有效模式。这时候需要增大多样性正则的权重或者减少模态数。模态间平均距离反映多样性程度。太小说明模态坍缩太大说明轨迹发散不物理。我通常让这个值稳定在2到5米之间预测3秒的情况下。学习率是最敏感的。1e-4对大多数配置都合适但如果发现损失震荡降到5e-5。如果损失下降太慢升到2e-4但要配合更长的warmup。5. 常见问题与排查技巧实录5.1 模态坍缩K条轨迹长得一模一样这是最常遇到的问题。现象是推理时输出的K条轨迹几乎重合概率分布也很均匀。原因通常是WTA损失在早期训练时梯度分配不均某个模态偶然获得优势后不断强化。排查步骤先看训练日志里各模态的使用频率如果某个模态占了80%以上基本确认是坍缩。再看模态间距离如果小于1米也是坍缩的迹象。解决方案有三个。第一训练初期用较小的K比如先用K3训练20个epoch等模态分化后再增加到K6。第二在损失里加多样性正则λ从0.1开始逐步增加到0.5。第三用ε-greedy策略以0.1的概率不只对最优模态计算损失也对次优模态计算给其他模态更多梯度。我实测下来组合使用这三个方法效果最好。先用K3训练加λ0.2的多样性正则同时用ε0.1的greedy策略基本不会出现坍缩。5.2 过拟合验证集损失不降反升轨迹预测模型很容易过拟合因为场景的多样性有限模型会记住训练集里的特定模式。判断过拟合的标准训练损失持续下降但验证损失在某个epoch后开始上升。这时候需要早停保存验证损失最低的模型。缓解过拟合的手段数据增强是最有效的。对BEV图做随机旋转±10度、随机平移±2米、随机翻转左右翻转同时交换左右变道模态的标签。另外可以在骨干网络里加Dropoutp0.3和DropBlock。权重衰减从1e-4增加到1e-3也有帮助。还有一个容易被忽视的点模型参数量。ResNet-18有1100万参数对轨迹预测来说偏大。如果数据量少于10万条建议用更小的骨干比如自定义的6层卷积网络参数量控制在200万以内。5.3 推理速度不达标量产芯片上跑不动学术论文里很少提推理速度但量产落地时这是硬指标。通常要求单帧推理在50ms以内20Hz留给预测模块的算力预算可能只有几TOPS。优化手段按性价比排序第一降低BEV分辨率从0.2m/pixel降到0.3m/pixel计算量减少55%。第二减少时序堆叠长度从T5降到T3计算量减少40%。第三用深度可分离卷积替换标准卷积计算量减少70%但精度损失2%到3%。第四模型量化FP32转INT8速度提升2到3倍精度损失1%左右。我通常的组合是0.25m/pixel分辨率 T4 部分层用深度可分离卷积 INT8量化。在典型嵌入式平台上能做到30ms以内精度损失控制在3%以内。5.4 常见问题速查表问题现象可能原因排查方法解决方案模态坍缩WTA梯度分配不均查看模态使用频率小K起步、加多样性正则、ε-greedy验证损失上升过拟合对比训练/验证损失曲线数据增强、Dropout、减小模型推理速度慢输入分辨率过高profile各层耗时降分辨率、减时序长度、量化轨迹不物理直接回归坐标无约束可视化预测轨迹加加速度/角速度平滑惩罚概率不校准模型过度自信画可靠性图温度缩放后处理远处目标预测差感受野不足分析误差随距离分布加空洞卷积、增大输入范围5.5 几个独家避坑技巧第一个真值轨迹的坐标系要和预测轨迹严格一致。我踩过一次坑训练时真值用全局坐标系预测用局部坐标系损失计算时没注意模型训练了几十个epoch才发现loss一直不降。后来统一用局部坐标系loss立刻正常下降。第二个BEV栅格化的渲染方式对性能影响很大。用高斯核渲染车辆历史轨迹时高斯核的方差要随速度自适应调整——速度快的目标方差大一些表示位置不确定性高。固定方差会导致高速目标的轨迹渲染过于尖锐模型学到的特征不鲁棒。第三个多模态概率的输出不要用Softmax后再取log直接用LogSoftmax加NLLLoss数值稳定性更好。我早期用Softmax加CrossEntropy偶尔出现NaN损失换成LogSoftmax后就没再出现过。第四个验证集要按场景难度分层。简单场景高速直行和困难场景城市交叉口的预测误差差好几倍如果验证集里简单场景占多数模型在困难场景上的退化会被平均掉。我通常把验证集按场景类型分成三组分别监控指标。6. 多模态融合的进阶方向与个人体会6.1 从后融合到前融合的演进前面讲的都是基于BEV栅格的后融合方案——感知模块先输出目标轨迹预测模块再基于轨迹做预测。这条路成熟、可解释、模块间解耦但有个根本局限感知误差会直接传导到预测而且感知丢失的目标预测模块完全无能为力。前融合方案把原始传感器数据摄像头图像、激光点云直接送进预测网络让网络自己学习从原始数据到未来轨迹的映射。理论上限更高因为网络可以利用感知模块忽略的细粒度信息比如刹车灯亮灭、行人头部朝向。但工程复杂度也高得多需要多传感器时空对齐、需要更大的模型和更多的数据。我个人的判断是量产落地用后融合预研探索用前融合。后融合的确定性更高出了问题容易定位前融合的潜力更大但离车规级还有距离。6.2 多模态大模型带来的新可能最近多模态大模型很热我试过用视觉语言模型做轨迹预测的zero-shot推理——把BEV图转成自然图像用prompt让模型描述场景并预测轨迹。效果嘛定性看有点意思定量看还差得远。主要问题是数值精度不够大模型输出的是“那辆车可能会向左变道”这样的文本转成具体轨迹坐标时误差很大。但这条路值得关注。大模型的常识推理能力是传统模型不具备的——比如它能理解“前方有校车停靠周围车辆大概率会减速绕行”这种语义层面的交互。未来可能的方向是用大模型做高层意图推理传统模型做底层轨迹回归两者结合。6.3 仿真环境下的闭环验证轨迹预测模型不能只看离线指标minADE、minFDE、MissRate必须做闭环仿真验证。我常用的流程是把预测模型接入CARLA或SUMO仿真器让自车在仿真环境里跑看预测结果如何影响规划控制最终看碰撞率、舒适度、通行效率这些系统级指标。闭环验证经常发现离线指标发现不了的问题。比如模型在离线测试集上minADE很低但闭环跑起来频繁急刹——原因是模型对某些模态的概率估计过于自信规划模块拿到高概率的“直行”预测后没有预留足够的避让空间结果前车突然变道时来不及反应。仿真环境的选择上CARLA的传感器仿真更真实但计算量大SUMO的交通流仿真更高效但感知仿真弱。我通常用SUMO做大规模交通流测试用CARLA做 corner case 的精细验证。6.4 个人实操体会做了两年多轨迹预测最大的体会是这个任务的上限不由模型架构决定而由数据质量和场景覆盖度决定。我见过太多团队在模型结构上反复折腾从LSTM换到Transformer再换到卷积指标提升不到5%。但把数据清洗做好、把长尾场景补全指标能提升20%以上。另一个体会是多模态预测的评估比单模态复杂得多。minADE只关心最准的那条轨迹但实际规划模块需要的是“所有可能模态的合理覆盖”。一条概率0.1但实际发生的轨迹如果模型没预测到就是安全隐患。所以除了minADE我还会看“模态覆盖率”——真值落在任一预测模态一定范围内的样本比例。这个指标更贴近实际需求。最后分享一个训练技巧用课程学习Curriculum Learning。先在高简单场景高速直行、跟车上训练等模型收敛后再加入中等难度场景城市直行、路口转弯最后加入困难场景密集交互、遮挡。这样训练比混合所有场景一起训练收敛更快最终精度也更高。我实测下来课程学习能减少30%的训练时间验证集minADE降低8%左右。这个方向后续还可以往“预测与规划联合优化”走。现在预测和规划是分开训练的预测模型不知道规划模块会怎么用它的输出。如果能把规划模块的损失回传到预测网络让预测网络学会输出“对规划最有用”的轨迹系统级性能应该还有提升空间。我最近在仿真环境里做了一些初步实验联合训练比分开训练的碰撞率降低了15%左右但训练稳定性还需要进一步调。