1. 为什么选择云服务器部署BEVFusion?

如果你和我一样,是个对自动驾驶感知技术充满好奇的开发者或研究者,肯定对BEVFusion这个多模态融合的“明星”项目不陌生。它能把摄像头和激光雷达的数据巧妙地融合在一起,生成一个鸟瞰视角下的3D感知结果,效果非常惊艳。但说实话,这个项目对硬件的要求,尤其是显存,堪称“硬件杀手”。我最初尝试在本地一台RTX 3060(12GB显存)的机器上折腾,结果连数据预处理那关都过不去,直接显存爆炸。官方建议至少24GB显存,这直接劝退了一大波个人开发者。

这时候,云服务器的优势就体现出来了。像阿里云、AutoDL这类平台,提供了按小时计费的GPU实例,比如拥有24GB显存的NVIDIA A10、RTX 4090,甚至更强大的A100。你不需要一次性投入数万元购买硬件,只需要花几十块钱租用几个小时,就能完成环境的搭建和关键步骤的测试。这特别适合学生、个人研究者或者需要快速验证算法的小团队。云端部署的核心价值,就是用可承受的弹性成本,突破本地硬件的瓶颈。而且,云服务器的环境通常是干净、统一的Linux系统,避免了本地Windows环境下各种驱动、库版本冲突的麻烦事,让部署过程更可控。

当然,在云上操作和在本地的Ubuntu系统里还是有些区别的。比如,你需要通过SSH远程连接,文件传输得用scprsync;云服务器通常没有图形界面,可视化调试得想点别的办法;另外,云盘的读写速度、内网带宽也会影响数据集准备和训练的效率。这份指南就是基于我在阿里云Ubuntu 20.04系统上反复折腾、踩了无数坑之后总结出来的,目标就是帮你把这些“坑”提前填平,让你能更顺畅地在云端跑通BEVFusion。

2. 云端服务器环境初始化与准备

拿到一台崭新的云服务器,第一步不是急着装环境,而是做好基础配置,这能为你后续省下大量时间。我推荐使用Ubuntu 20.04 LTS系统,长期支持,社区资源丰富,和BEVFusion所需的软件版本兼容性最好。

2.1 系统更新与基础工具安装

首先,通过SSH登录你的云服务器。登录后,我习惯先做一次全面的系统更新,并安装一些后续肯定会用到的工具。

sudo apt update
sudo apt upgrade -y
sudo apt install -y wget curl git vim tmux htop screen build-essential cmake g++ gcc make

这里解释几个工具:tmuxscreen会话管理神器。在云服务器上训练模型,动辄几个小时甚至几天,你肯定不希望因为网络波动导致SSH断开,训练进程也跟着挂了。用tmux新建一个会话,让任务在里面跑,即使你关闭终端,任务也会在后台继续运行,下次登录再tmux attach连接回去就行。htop可以让你直观地查看CPU、内存使用情况,方便监控资源。

2.2 驱动与CUDA环境配置

这是最关键的一步。云服务商提供的GPU实例,通常已经预装了NVIDIA驱动和CUDA Toolkit。但你一定要亲自确认版本。运行nvidia-smi命令,查看驱动版本和CUDA版本。BEVFusion(阿里北大版)官方推荐基于PyTorch 1.8.0,这个版本对应的CUDA版本是11.1。

如果nvidia-smi显示的CUDA版本是11.1或更高(如11.4、11.8),一般来说是兼容的,因为CUDA有向下兼容性。但为了绝对稳定,我建议在云平台镜像市场选择预装CUDA 11.1的系统镜像,这是最省事的。如果已经是其他版本,比如CUDA 11.3,你也可以尝试继续,但后面安装PyTorch和mmcv-full时需要选择对应CUDA 11.3的版本,这可能会引入一些不确定性。

接下来安装cuDNN,它是深度学习的加速库。如果你用的是云平台提供的CUDA镜像,cuDNN很可能也已经装好了。可以通过cat /usr/local/cuda/include/cudnn_version.h | grep CUDNN_MAJOR -A 2来检查。如果没有,需要去NVIDIA官网下载对应CUDA 11.1的cuDNN安装包,手动安装。

2.3 配置高效的软件源

在云服务器上,默认的软件源可能速度不快。将APT源和Pip源换成国内镜像,能极大提升包下载速度。

  1. 备份原有源列表sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
  2. 编辑源列表sudo vim /etc/apt/sources.list,将其内容替换为阿里云或清华的Ubuntu 20.04镜像源。
  3. 更新APT缓存:sudo apt update

对于Python的pip,可以创建或修改用户目录下的配置文件 ~/.pip/pip.conf,内容如下:

[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
trusted-host = pypi.tuna.tsinghua.edu.cn

这样,之后所有的pip install命令都会默认从清华源下载,速度飞起。

3. 创建Conda环境与安装核心框架

我强烈建议使用Conda来管理Python环境。BEVFusion的依赖包众多且版本要求严格,用Conda可以创建一个隔离的沙箱,避免污染系统环境,也方便未来清理。

3.1 创建并激活Conda环境

首先安装Miniconda(如果系统没有的话)。然后创建一个名为bevfusion、Python版本为3.8.3的环境。为什么是3.8.3?因为这是经过验证与PyTorch 1.8.0、mmcv-full 1.4.0等组合兼容性最好的版本之一。

conda create -n bevfusion python=3.8.3 -y
conda activate bevfusion

激活环境后,你的命令行提示符前面应该会出现(bevfusion),表示你已经在这个独立环境中了。

3.2 安装PyTorch与TorchVision

这是整个环境的基石。一定要使用Conda命令来安装,因为它能更好地处理CUDA相关的依赖。指定CUDA 11.1的版本。

conda install pytorch==1.8.0 torchvision==0.9.0 torchaudio==0.8.0 cudatoolkit=11.1 -c pytorch -c conda-forge -y

安装完成后,进入Python交互环境验证一下:

import torch
print(torch.__version__)  # 应该输出 1.8.0
print(torch.cuda.is_available())  # 应该输出 True
print(torch.cuda.get_device_name(0))  # 应该输出你的GPU型号,如 A10

如果torch.cuda.is_available()返回False,说明PyTorch没有正确识别到CUDA,需要检查前面的CUDA安装步骤。

3.3 安装MMCV-Full

MMCV是OpenMMLab系列框架(包括MMDetection, MMDetection3D)的基础库。BEVFusion依赖于一个特定版本的mmcv-full(1.4.0),并且必须从源码编译以匹配你的PyTorch和CUDA版本。但幸运的是,OpenMMLab提供了预编译的wheel包。我们直接下载对应版本安装即可,这比从源码编译快得多。

# 注意URL中的 cu111 对应 CUDA 11.1,torch1.8.0 对应 PyTorch 1.8.0, cp38 对应 Python 3.8
wget https://download.openmmlab.com/mmcv/dist/cu111/torch1.8.0/mmcv_full-1.4.0-cp38-cp38-manylinux1_x86_64.whl
pip install mmcv_full-1.4.0-cp38-cp38-manylinux1_x86_64.whl

安装成功后,可以简单测试:python -c "import mmcv; print(mmcv.__version__)",应输出1.4.0

4. 获取代码与编译BEVFusion

环境基础打好了,现在可以把项目代码拿下来,并安装其依赖的其他组件。

4.1 下载BEVFusion源码

使用git clone下载阿里北大版本的BEVFusion代码。这个版本在原始MIT版本上做了不少优化和适配。

git clone https://github.com/ADLab-AutoDrive/BEVFusion.git
cd BEVFusion

4.2 安装MMDetection 2.11.0

BEVFusion使用了MMDetection作为其2D检测部分的基础。我们需要安装一个特定版本(2.11.0)。

# 假设你在BEVFusion根目录
git clone -b v2.11.0 https://github.com/open-mmlab/mmdetection.git mmdetection-2.11.0
cd mmdetection-2.11.0
pip install -r requirements.txt

这里你大概率会遇到两个经典的坑

  1. requirements/optional.txt文件里,有一行sklearn,直接安装会报错。你需要把它改成scikit-learn。可以用命令快速修改:sed -i 's/sklearn/scikit-learn/g' requirements/optional.txt
  2. 安装mmpycocotools时可能会编译失败,提示gcc找不到文件。这是因为cython版本问题。解决方法是先降级安装特定版本的cythonpip install cython==0.29.33,然后再重新安装pip install -r requirements.txt

解决上述问题后,以“开发模式”安装MMDetection:

pip install -v -e .

-e参数代表“可编辑”模式,这样你对MMDetection源码的任何修改都会直接生效,方便调试。

4.3 安装MMDetection3D

接下来安装3D检测框架。回到BEVFusion的上级目录,克隆MMDetection3D的代码。注意,BEVFusion没有指定一个固定的mmdet3d版本,但经过测试,使用其main分支的最新代码(当时对应0.x版本)是可行的。

cd ..  # 回到BEVFusion目录
git clone https://github.com/open-mmlab/mmdetection3d.git
cd mmdetection3d

在运行python setup.py develop之前,我强烈建议你先用国内源安装其运行时依赖,否则很容易卡在下载某个包上。

pip install -r requirements/runtime.txt -i https://pypi.tuna.tsinghua.edu.cn/simple

然后再执行编译安装:

python setup.py develop

4.4 编译BEVFusion本体

现在,回到BEVFusion的根目录,编译它自身。

cd ..  # 回到BEVFusion目录
python setup.py develop

这一步是报错的重灾区。你会看到一大堆关于numpynumballvmlite等包版本不兼容的警告和错误。别慌,这是正常的。关键在于固定几个核心包的版本,其他的包可以按照报错提示进行升级或降级。

根据我的实战经验,下面这几个包的版本必须锁死,它们构成了一个稳定的“基础生态”:

pip install numpy==1.19.5
pip install numba==0.48.0
pip install networkx==2.2
pip install scikit-image==0.19.3
pip install albumentations==1.3.1
pip install nuscenes-devkit==1.1.10
pip install trimesh==2.35.39
pip install pandas==1.4.4

固定好这些之后,再次运行python setup.py develop。如果还有报错,比如提示Package ‘XXX‘ requires ‘yyy<=a.b.c‘, but you‘ll have yyy x.y.z which is incompatible.,就按照提示,用pip install yyy==a.b.c来安装指定版本。耐心一点,通常重复两三次就能成功。

5. 准备nuScenes数据集与数据生成

模型跑起来需要“粮食”,对于BEVFusion来说,粮食就是nuScenes数据集。完整数据集有300GB+,对于云服务器用户,我强烈建议先从Mini版本(约10GB)开始,它能让你快速验证整个流程是否通畅。

5.1 下载与解压数据集

去nuScenes官网注册账号,下载“nuScenes Mini”数据包。你会得到一个压缩文件,比如v1.0-mini.tgz。通过scp命令将它从你的本地上传到云服务器:

# 在你本地机器的终端执行
scp -P <你的SSH端口> /本地路径/v1.0-mini.tgz username@你的服务器IP:/远程路径/

在服务器上,进入BEVFusion目录,创建数据集的标准结构并解压:

mkdir -p data/nuscenes
tar -xzf /远程路径/v1.0-mini.tgz -C data/nuscenes/

解压后,data/nuscenes/目录下应该包含maps, samples, sweeps, v1.0-mini等文件夹。

5.2 生成数据预处理文件

nuScenes的原始数据不能直接用于训练,需要用BEVFusion提供的脚本进行预处理,生成.pkl.bin格式的中间文件。

python tools/create_data.py nuscenes --root-path ./data/nuscenes --version v1.0-mini --out-dir ./data/nuscenes --extra-tag nuscenes

这个命令会运行一段时间,它需要解析所有的传感器数据(图像、点云)、标注信息,并计算一些元数据。如果一切顺利,你会在data/nuscenes目录下看到新生成的nuscenes_infos_train.pklnuscenes_infos_val.pkl以及nuscenes_dbinfos_train.pkl等文件。这是后续所有训练和测试的基石,务必确保这一步没有报错。

6. 模型训练:从预训练模型到完整训练

BEVFusion的训练分为两步:首先是训练一个2D图像检测器作为视觉流的预训练模型,然后才是加载这个预训练权重,进行多模态的端到端训练。对于云服务器用户,显存管理是贯穿始终的主题。

6.1 训练2D图像检测器(预训练模型)

在BEVFusion根目录下的README.md最下方,官方给出了训练命令。第一步是训练一个基于Mask R-CNN和Swin Transformer的2D检测器。

./tools/dist_train.sh configs/bevfusion/mask_rcnn_dbswin-t_fpn_3x_nuim_cocopre.py 1

命令最后的1表示使用1块GPU。如果你租用的是单卡云服务器,这里就是1。直接运行这个命令,99%的概率会爆显存(OOM),即使你的显卡有24GB。因为默认的批次大小(batch size)是针对多卡大显存环境设置的。

你需要修改配置文件configs/bevfusion/mask_rcnn_dbswin-t_fpn_3x_nuim_cocopre.py。找到data字典部分,修改train_dataloader中的参数:

data = dict(
    samples_per_gpu=1,  # 原来是2或4,改为1
    workers_per_gpu=2,  # 数据加载线程数,如果CPU核心少,也可以改为1
    ...
)

samples_per_gpu(即batch size)从默认的4或2改为1,这能显著降低显存消耗。然后再次运行训练命令。训练会持续很多个epoch,在云服务器上,记得使用tmuxscreen将会话挂到后台。训练好的模型权重会保存在work_dirs/mask_rcnn_dbswin-t_fpn_3x_nuim_cocopre/目录下。

6.2 进行BEVFusion端到端训练

有了预训练的2D模型,就可以开始训练完整的BEVFusion了。官方提供了多个配置文件,我们以bevf_pp_2x8_1x_nusc.py为例。同样,你需要先修改批次大小以适应单卡环境。

打开configs/bevfusion/bevf_pp_2x8_1x_nusc.py,修改data部分:

data = dict(
    samples_per_gpu=1,  # 根据显存调整,24G显存A10可以尝试设为1
    workers_per_gpu=2,
    ...
)

还有一个关键修改:你需要告诉模型去哪里加载刚才训练好的2D预训练权重。在配置文件中找到load_from参数,将其指向你训练好的.pth文件路径,例如:

load_from = './work_dirs/mask_rcnn_dbswin-t_fpn_3x_nuim_cocopre/latest.pth'

然后执行训练命令:

./tools/dist_train.sh configs/bevfusion/bevf_pp_2x8_1x_nusc.py 1

在这个过程中,你可能会遇到一些典型的报错和问题:

  • import DCN failed:这是一个已知问题,DCN(可变形卷积)编译可能失败。但好消息是,BEVFusion的代码似乎有回退机制,这个错误通常不影响训练和推理,可以忽略。如果实在想解决,可能需要手动编译DCN插件,过程比较繁琐。
  • ModuleNotFoundError: No module named 'timm':缺少timm库,直接安装指定版本:pip install timm==1.0.15
  • FormatCode() got an unexpected keyword argument 'verify'yapf代码格式化工具的版本问题,安装指定版本:pip install yapf==0.32.0
  • 训练几轮后Loss变成NaN:这是我踩过最大的坑。这通常是梯度爆炸导致的。原因可能是:1) 在显存紧张的情况下,你不仅降低了batch_size,还启用了混合精度训练(fp16),导致数值不稳定;2) 学习率对于小的batch_size来说太高了。

我的解决方案是:首先,在配置文件中注释掉fp16混合精度训练的配置(如果存在的话)。然后,降低优化器的学习率。找到配置文件中的optimizer部分,将lr(学习率)从默认的2e-4改为3e-4甚至1e-4。为了更稳定,还可以加入梯度裁剪

optimizer_config = dict(grad_clip=dict(max_norm=35, norm_type=2))

将这段配置加到optimizer设置后面。经过这些调整,我在24GB显存的A10上,终于能够稳定地完成24个epoch的训练了。

7. 模型测试与云端可视化技巧

训练完成后,或者你想直接测试官方提供的预训练模型,都需要进行测试(推理)步骤。

7.1 运行测试脚本

测试命令的格式如下:

# 基础测试,评估指标
./tools/dist_test.sh configs/bevfusion/bevf_pp_2x8_1x_nusc.py /path/to/your/checkpoint.pth 1 --eval bbox
# 例如,使用我们训练好的模型
./tools/dist_test.sh configs/bevfusion/bevf_pp_2x8_1x_nusc.py work_dirs/bevf_pp_2x8_1x_nusc/epoch_12.pth 1 --eval bbox

这个命令会在验证集上运行模型,并输出mAP、NDS等3D检测的关键指标。这是衡量模型性能的标准方式。

7.2 在无显示器的云服务器上实现可视化

我们更想直观地看到检测结果。官方测试命令加上--show--show-dir参数可以保存可视化结果。但这里有个大坑:默认的可视化代码使用open3d库进行3D点云渲染,而open3d需要真正的图形显示设备(如显示器),这在无图形界面的云服务器上会报错。

有两种解决思路:

  1. 修改源码,使用Matplotlib进行2D/3D可视化:这是更通用的方法。你需要找到BEVFusion或MMDetection3D中负责可视化的代码(通常是mmdet3d/models/detectors/mvx_two_stage.py中的show_results方法或类似的函数),将其中的open3d调用替换为matplotlib的绘图代码。这需要一些编程工作,但一劳永逸。
  2. 使用虚拟显示缓冲区(Xvfb):这是一种“欺骗”程序,让它认为有显示器的方法。首先安装Xvfb:sudo apt install xvfb。然后,在运行测试命令前,先启动一个虚拟显示:
    Xvfb :99 -screen 0 1024x768x24 &
    export DISPLAY=:99
    
    然后再运行带--show的测试命令。这样,open3d的渲染窗口会在虚拟缓冲区中运行,并将结果保存为图片。完成后,你可以用scp将图片下载到本地查看。

我个人的经验是,对于快速调试,方法2更快捷。但对于需要定制化可视化效果,方法1更灵活。可视化结果通常是3D的边界框叠加在点云上,你可以清晰地看到模型对车辆、行人等目标的检测效果。

整个流程走下来,从租用服务器到最终看到可视化结果,虽然步骤繁多,但每一步都有迹可循。核心思路就是:利用云服务的弹性算力,通过Conda严格隔离环境,锁定关键版本避免冲突,根据显存动态调整训练配置,并巧用工具解决云端可视化难题。希望这份结合了具体操作和原理分析的指南,能帮你少走弯路,成功在云端驾驭BEVFusion这个强大的模型。如果在实践过程中遇到新的问题,不妨去项目的GitHub Issues里搜搜看,很可能已经有先驱者提供了解决方案。

更多推荐