
自动驾驶纯视觉感知这几年卷得厉害BEVFormer算是绕不开的一个经典方案。但真正动手在AutoDL上把它跑起来很多人第一步就被环境、数据、显存这些坎拦住了。我这次从零开始把Nuscenes数据集完整训练BEVFormer的全流程走了一遍踩了不少坑也总结出一套能在AutoDL上快速复现的可靠路径分享出来给后面要入坑的朋友参考。先说清楚这套方案能解决什么问题AutoDL平台按小时计费GPU资源灵活非常适合做BEVFormer这种大模型的训练验证但平台自带环境是通用镜像要跑BEVFormer还得自己处理数据格式、依赖版本、训练配置这些细节。这篇文章覆盖从数据集申请下载、环境搭建、配置文件修改到完整训练、报错排查的整个过程适合已经跑通基础目标检测、准备转入BEV感知方向的研究生或算法工程师。1. 整体思路与方案选型1.1 为什么选AutoDL作为训练平台BEVFormer训练对硬件要求不低Nuscenes全量数据集单卡训练显存基本要24GB以上如果本地没有多卡A100或者RTX 3090/4090光准备机器就是一笔不小的开销。AutoDL这类云GPU平台的优势在于可以按需租用训练完就释放成本相对可控。我在AutoDL上选择的是RTX 409024GB显存规格的实例搭配平台提供的PyTorch 2.0 CUDA 11.8基础镜像。之所以不选A100一方面是因为4090性价比更高另一方是因为BEVFormer官方实现基于mmdetection3d框架对GPU型号并没有特殊依赖24GB显存跑base版本足够不需要上80GB的大卡。1.2 环境版本组合的底层逻辑BEVFormer最麻烦的地方在于依赖版本耦合非常紧尤其是mmcv、mmdet、mmseg、mmdet3d这四件套的版本必须严格对齐版本不匹配会直接导致导入报错或算子编译失败。我最终采用的版本组合如下依赖包版本说明Python3.83.10以下兼容性最好PyTorch1.13.1官方推荐版本CUDA11.7与PyTorch配套mmcv-full1.7.0必须1.6以上BEVFormer用到了其中的Deformable Attentionmmdet2.28.13.x版本接口变动太大不推荐mmseg0.30.0和mmdet版本配套mmdet3d1.0.0rc6官方分支指定版本这个组合不是我拍脑袋定的BEVFormer官方仓库的requirements.txt里写得很清楚但直接pip install大概率会装上最新版本导致冲突。稳妥做法是先创建conda环境再按固定顺序安装后面第3章会详细说。1.3 方案对比从头训练还是加载预训练权重这个问题我纠结了很久。BEVFormer有两种启动方式一种是完全从头训练另一种是加载官方提供的nuScenes预训练权重继续训练或微调。从实验角度看如果只是为了验证代码能跑通、熟悉训练流程从头训练几百个iteration就够了如果要做精度对比或下游任务建议直接加载预训练权重。我在AutoDL上先做了200 iter的冒烟测试确认流程无问题再启动完整训练。这样能避免数据或配置问题在长训练跑到一半才暴露白白烧掉几十个小时的GPU费用。2. 环境搭建与依赖安装避坑要点2.1 conda环境创建与PyTorch安装AutoDL镜像自带conda我建议创建一个独立环境不要污染基础环境。# 创建conda环境 conda create -n bevformer python3.8 -y conda activate bevformer # 安装PyTorch 1.13.1 CUDA 11.7 pip install torch1.13.1cu117 torchvision0.14.1cu117 --extra-index-url https://download.pytorch.org/whl/cu117这里注意不要用AutoDL自带的PyTorch 2.0镜像因为后续编译mmcv-full时可能出现算子兼容性问题。实测下来PyTorch 1.13.1是BEVFormer全链路最稳的版本这也是官方CI测试用的版本。2.2 mmcv-full编译的两种方式与取舍mmcv-full是BEVFormer里最关键的依赖负责提供CUDA算子。BEVFormer官方要求mmcv-full版本在1.6.0以上我用的是1.7.0。安装有两种方式方式一直接安装预编译包推荐pip install mmcv-full1.7.0 -f https://download.openmmlab.com/mmcv/dist/cu117/torch1.13.1/index.html这种方式不需要本地编译几分钟就能装完。前提是PyTorch和CUDA版本要和链接里的对应。方式二源码编译安装备用方案如果预编译包安装后出现算子缺失问题比如ImportError: libcudart.so.11.0: cannot open shared object file则需要源码编译git clone https://github.com/open-mmlab/mmcv.git -b v1.7.0 cd mmcv MMCV_WITH_OPS1 pip install -e .源码编译耗时视机器性能而定AutoDL上大约20到40分钟。这里要提醒的是编译前确认gcc版本不低于7.0否则会报internal compiler error。2.3 mmdet、mmseg、mmdet3d安装顺序三个包安装顺序不能乱因为mmdet3d的安装会依赖mmdet和mmseg且版本必须匹配。我按以下顺序执行# 先安装mmdet和mmseg pip install mmdet2.28.1 mmseg0.30.0 # 再安装mmdet3d从源码安装指定版本 git clone https://github.com/open-mmlab/mmdetection3d.git -b v1.0.0rc6 cd mmdetection3d pip install -e .这里的坑在于如果先装mmdet3d再装mmdetpip会主动把mmdet升级到3.x版本导致BEVFormer无法启动。装完后建议用pip list验证一下四个核心包的版本都符合上表。2.4 其他依赖与常见编译报错BEVFormer还依赖一些其他库比如timm、einops、numpy等。有一个关键点numpy版本必须锁定在1.23.5以下新版numpy在PyTorch 1.13下会出现module numpy has no attribute bool一类的报错。执行pip install numpy1.23.5 timm einops yapf0.40.1另外还有一个很隐蔽的坑mmdet3d 1.0.0rc6在编译时会检查torchvision的版本如果版本过高会出现AssertionError: TorchVision not found之类误报。上面安装的0.14.1版本是安全的。3. Nuscenes数据集获取与处理全流程3.1 数据下载官方渠道与磁盘空间规划Nuscenes完整数据集比较大包含1000个场景每个场景约20秒总共约300GB以上。在AutoDL上下载时要格外注意两点第一是AutoDL系统盘一般只有50GB数据必须放到数据盘一般挂载在/root/autodl-tmp第二是数据下载速度受官网限制从官网直接下载非常慢。建议先在本地官网注册并申请下载权限然后获取下载链接再到AutoDL上用wget或aria2c并行下载。整个数据集包括数据内容大小说明trainval约70GB训练集和验证集图像test约46GB测试集图像可选CAN bus约9GB车辆CAN总线数据map约7GB高精地图扩展包标注文件约8GBjson标注如果只是做训练验证trainval加上map和CAN bus就够用了test可以不下载。我在AutoDL数据盘上预留了300GB空间实际使用约120GB包括后续生成的中间文件。3.2 数据集目录结构规范Nuscenes数据必须按照mmdet3d规定的目录结构存放否则后续生成info文件时找不到路径。规范结构如下nuscenes/ ├── maps/ ├── samples/ ├── sweeps/ ├── v1.0-trainval/ ├── can_bus/ ├── lidarseg/ └── (test目录可选)下载完成后先建立一个软链接指向你的数据目录方便多个项目共用同一份数据mkdir -p data/nuscenes ln -s /root/autodl-tmp/nuscenes data/nuscenes3.3 使用官方工具生成pkl标注文件mmdet3d训练需要把Nuscenes的json标注转换成pkl格式这里用到的工具是官方仓库里的create_data.py。在BEVFormer仓库的tools目录下执行python tools/create_data.py nuscenes \ --root-path ./data/nuscenes \ --out-dir ./data/nuscenes \ --extra-tag nuscenes \ --version v1.0-trainval \ --canbus ./data/nuscenes这一步生成的文件包括nuscenes_infos_train.pkl训练集所有帧的传感器标注信息nuscenes_infos_val.pkl验证集标注信息nuscenes_dbinfos_train.pkl用于data augmentation的数据库信息nuscenes_infos_test.pkl测试集信息如果下载了test数据nuscenes_infos_train_mono3d.coco.json单目3D标注格式BEVFormer不强制使用但可以顺带生成生成过程大约需要30到60分钟取决于数据盘IO性能。如果中途报缺失文件多半是下载时漏了某个子目录回到3.1检查。3.4 数据加载验证确认pkl文件可正确读取在正式训练之前先验证数据是否能被正确加载。我写了一个简单的测试脚本import pickle with open(./data/nuscenes/nuscenes_infos_train.pkl, rb) as f: data pickle.load(f) print(len(data[infos])) # 训练集大约28130条 sample data[infos][0] print(sample[lidar_path]) print(sample[cam_sweeps].keys())如果正常输出路径和相机sweep的键名说明数据文件没问题。这里如果报KeyError: cam_sweeps说明你用的create_data.py版本和BEVFormer仓库不一致需要从BEVFormer官方仓库里拉取对应的data_converter脚本。4. 配置文件修改与训练启动4.1 配置文件结构与关键参数解读BEVFormer的训练配置在projects/configs/bevformer/目录下核心文件是bevformer_base.py。这个文件是继承结构先加载基础配置再叠加数据集和模型配置。看懂这个文件是调通训练的前提。几个关键参数的作用如下参数名默认值作用voxel_size[0.512, 0.512, 8]体素分辨率影响BEV网格大小point_cloud_range[-51.2, -51.2, -5, 51.2, 51.2, 3]感知范围正负51.2米bev_h/bev_w200 / 200BEV特征图尺寸num_query900可学习query数量num_classes10检测类别数Nuscenes是10类use_emaFalse是否启用指数滑动平均save_epoch1每隔多少个epoch保存一次ckpt训练策略方面BEVFormer base版本默认训练24个epoch学习率初始为2e-4采用了余弦退火调度。如果只想验证流程建议直接把total_epochs改成1log_config的间隔调小到每10次迭代打印一次。4.2 针对单卡训练的资源配置调整AutoDL租用单张4090时不能直接用官方默认的多卡配置需要手动调整以下参数# 在bevformer_base.py中修改 data dict( samples_per_gpu1, # 单卡batch size设为14090 24GB只能跑1 workers_per_gpu4, ) optimizer dict( typeAdamW, lr2e-4, paramwise_cfgdict(custom_keys{backbone: dict(lr_mult0.1)}), )batch size是最关键的BEVFormer的显存占用大头在BEV特征图和可变形注意力模块上24GB显存跑batch size1已经是极限如果想跑大batch需要A100 80GB或者多卡并行。另外由于用了单卡需要去掉配置文件里的find_unused_parameters相关设置并确保gpu_ids为[0]gpu_ids [0]4.3 启动完整训练命令与日志分析环境配置无误后进入BEVFormer仓库根目录执行训练命令cd /root/autodl-tmp/BEVFormer python tools/train.py projects/configs/bevformer/bevformer_base.py \ --work-dir ./work_dirs/bevformer_base \ --gpus 1启动后观察日志输出重点看以下几个方面模型结构加载确认各模块参数量总参数量约69MBBEVFormer-Base如果显示为0或无法加载多为依赖缺失数据集初始化正常情况下会输出Loading 28130 annotations之类信息耗时约10分钟显存占用用nvidia-smi实时查看训练稳定后显存应在20-23GB之间如果超24GB就会OOM正常启动后日志每10步输出一次loss期望数值在初始阶段大约5到8之间随着训练逐渐下降。如果初始loss直接飙升到几百优先检查学习率是否过大或数据label是否有问题。4.4 checkpoint保存与中断恢复长训练过程中因网络抖动、机器抢占等原因导致中断是很常见的事。BEVFormer支持从ckpt恢复训练python tools/train.py projects/configs/bevformer/bevformer_base.py \ --work-dir ./work_dirs/bevformer_base \ --resume-from ./work_dirs/bevformer_base/epoch_10.pth这里建议把AutoDL的自动快照功能打开但快照只保存系统盘数据盘里的数据不受影响。如果实例被释放了重新创建一个同配置实例、挂载同一数据盘再手动把代码和work_dir同步过来即可不需要重新处理数据。5. 常见问题与排查技巧实录5.1 显存不足导致OOMOOM是最常见的问题尤其是在生成BEV特征时。报错通常长这样RuntimeError: CUDA out of memory. Tried to allocate 2.00 GiB (GPU 0; 23.70 GiB total capacity; ...)排查顺序先用nvidia-smi看显存是否被其他进程占用然后用fuser -v /dev/nvidia*杀掉多余进程如果确认是训练本身超限依次尝试以下方案samples_per_gpu从1改为1且开启cudnn.benchmarkFalse降低bev_h和bev_w到150×150这是最后手段会牺牲精度检查mmcv-full是否开启了磁盘缓存MKL_SERVICE_FORCE_INTEL1等环境变量有时能小幅降低显存4090在batch size1下基本能跑满24GB如果还OOM优先怀疑是不是其他地方改了配置文件导致特征图尺寸变大。5.2 加载预训练权重时的shape mismatch使用官方提供的BEVFormer预训练模型做微调时经常遇到以下报错size mismatch for img_backbone.backbone.conv1.weight: copying a param with shape torch.Size([64, 3, 7, 7]) from checkpoint, the shape in current model is torch.Size([128, 3, 7, 7])这个原因是预训练模型的backbone输入通道数3通道RGB图和配置文件里的num_cams或图像尺寸设置不一致。遇到这个情况用tools/convert_bevformer_checkpoints.py脚本转换权重或者直接忽略backbone权重只加载neck和head部分load_from path/to/checkpoint.pth # 在配置文件中加一行 load_from None # 改为None表示不加载预训练权重如果是刻意忽略backbone用mmcv.runner的load_checkpoint接口并设置strictFalse即可。5.3 CUDA算子版本相关报错BEVFormer的核心算子Deformable Attention在mmcv-full里编译如果版本不对会出现ModuleNotFoundError: No module named mmcv.ops.multi_scale_deformable_attn这是mmcv-full没有正确编译GPU算子导致的。解决方法是执行3.2节的源码编译方式确认编译日志中出现Compiling ops... done字样。还有一种情况是mmcv和mmcv-full装重了需要先卸载再安装pip uninstall mmcv mmcv-full -y pip install mmcv-full1.7.0 -f https://download.openmmlab.com/mmcv/dist/cu117/torch1.13.1/index.html5.4 训练结束后评估精度异常训练24个epoch后在验证集上评估如果mAP非常低比如不到0.1而loss已经收敛问题多半出在数据加载或后处理上。排查方向有确认test配置里的ann_file指向的是nuscenes_infos_val.pkl而不是训练集确认class_names顺序和Nuscenes官方顺序一致默认顺序是car, truck, trailer, bus, construction_vehicle, bicycle, motorcycle, pedestrian, barrier, traffic_cone确认是否加载了ema权重BEVFormer官方实验里开启EMA后精度更高我在调试时发现一个隐蔽问题验证时NMS阈值设太高0.7以上导致大量预测框被滤除mAP掉得厉害。把nms_iou_thr调到0.5后恢复了正常水平。5.5 常见问题速查表症状原因解决方案启动即报No module named mmcv.opsmmcv-full未正确编译源码重编译mmcv-fullsize mismatch加载权重失败配置文件与ckpt结构不一致设置strictFalse或convert脚本CUDA OOMbatch size过大或显存被占用调小batch清理进程numpy bool报错numpy版本过新锁定numpy1.23.5训练loss为NaN学习率过大或数据有脏值降低lr检查标注有无无穷值验证时KeyError: pts_bboxmmdet3d版本与配置文件不匹配升级/降级mmdet3d到rc6pkl文件加载慢磁盘IO瓶颈数据放到SSD数据盘不要放系统盘6. 训练效率优化与后续扩展建议6.1 开启混合精度训练BEVFormer base版本使用FP32训练24GB显存只能跑batch size1但开启AMP自动混合精度后显存占用可以降到18GB左右还能小幅提升训练速度。配置文件里增加fp16 dict(loss_scaledynamic)但需要确认模型中有部分算子不支持FP16尤其是multi_scale_deformable_attn实测下来BEVFormer官方代码是支持AMP的只是精度会有轻微波动。对实验验证场景完全够用。6.2 使用分布式训练加速AutoDL上可以租用多卡实例比如4×4090。修改启动命令bash tools/dist_train.sh projects/configs/bevformer/bevformer_base.py 4 \ --work-dir ./work_dirs/bevformer_base同时把配置里的data.samples_per_gpu改成1这样总batch size变为4。BEVFormer官方在8卡A100上训练24个epoch大约需要40小时单张4090上要明显更久多卡能缩短到可控范围。代价是loss曲线可能会略有波动这是正常的。6.3 数据增强与超参数微调实验如果想进一步提升模型效果可以从几个方向入手use_cbgsTrue开启类别平衡采样对Nuscenes这种类别分布不均的数据集有明显增益rotate_prev_bev对上一帧BEV特征做随机旋转增强时序鲁棒性增大num_query从900到1200能提升密集场景下的小目标召回率但显存会增加做实验时建议用--auto-resume配合的可视化工具追踪不同配置在验证集上的NDSnuScenes检测分数和mAP曲线只留最优配置做长训练。6.4 部署到真实场景的路径训练完模型之后如果要做实车或实机部署BEVFormer官方TensorRT转换需要把模型导出为ONNX再转engine。需要注意的是BEVFormer包含了时序融合的buffer导出时需要把use_temporal标志位设成False或固定bev_embedding维度。这块相对复杂建议先跑通pytorch推理再考虑TensorRT优化。我在实际部署时发现Nuscenes训练出的模型在real-world数据上泛化性需要评估建议针对目标场景采集数据做finetune。根据我的经验如果在AutoDL上从零开始环境搭建大约2小时数据处理1到2小时冒烟测试半小时后续全量训练就是时间问题。关键是把环境版本锁死、数据目录规范处理好后面踩坑的概率会大幅下降。这套流程我已经跑通多次希望对准备入坑BEVFormer的朋友有帮助。