PaddleDetection环境搭建与训练全流程实战指南
1. 为什么选择PaddleDetection而不是其他检测框架如果你正在读这篇文章大概率是准备入坑目标检测或者手头有个实际项目需要快速跑通一个检测模型。我当初选PaddleDetection的原因很直接开箱即用的模型库足够全中文文档友好而且从训练到部署的链路是打通的。这一点对刚接触检测任务的人来说太重要了因为目标检测不像图像分类从数据标注、anchor设计、数据增强到后处理NMS每一步都有坑如果框架本身再不省心很容易在环境阶段就劝退。PaddleDetection是飞桨生态下的目标检测开发套件覆盖了PP-YOLOE、YOLOv3、Faster R-CNN、SOLOv2、Swin Transformer等主流检测和实例分割模型同时提供了从数据准备、模型训练、评估到导出部署的完整工具链。它解决的核心问题是让开发者不用从零手写网络结构和训练循环通过配置文件就能切换模型和数据集。适合的人群包括计算机视觉方向的学生、需要快速验证检测方案的算法工程师、以及想把检测模型落地到实际业务中的开发者。但我要先泼一盆冷水环境搭建这一步官方文档给的是理想路径实际执行时会遇到各种版本冲突、依赖缺失、CUDA不匹配的问题。我前后在三台不同配置的机器上装过PaddleDetection每次都会碰到不一样的情况。所以这篇文章不会只给你一条命令让你复制粘贴而是把每一步背后的逻辑讲清楚让你遇到报错时知道该往哪个方向排查。提示本文基于PaddleDetection 2.x版本系列撰写不同小版本之间API和目录结构可能有差异建议先确认你下载的版本号。2. 环境搭建前的硬件与软件版本决策2.1 先搞清楚你的显卡和CUDA版本这一步很多人会跳过直接pip install paddlepaddle就完事了结果跑训练时发现用的是CPU速度慢到怀疑人生。PaddleDetection的训练几乎必须依赖GPU除非你只是跑一个推理demo看看效果。你需要先确认三件事显卡型号和显存大小显存直接决定了你能用多大的batch size和输入分辨率。6GB显存跑YOLOv3的416输入基本是极限8GB以上会舒服很多。CUDA驱动版本在终端执行nvidia-smi右上角会显示当前驱动支持的CUDA版本。注意这是驱动支持的最高版本不是你实际安装的CUDA版本。cuDNN版本PaddlePaddle的GPU版本对cuDNN有最低版本要求一般CUDA 10.2对应cuDNN 7.6以上CUDA 11.x对应cuDNN 8.x以上。我踩过的一个坑是机器上装了CUDA 11.6但PaddlePaddle当时只支持到CUDA 11.2结果装完GPU版paddle后paddle.utils.run_check()一直报找不到动态库。后来降级CUDA才解决。所以不要盲目追求最新CUDA版本要看飞桨官方文档里明确支持的版本列表。2.2 Python环境隔离别在base环境里乱装我强烈建议用conda创建一个独立环境不要直接在系统Python或base环境里装。原因很简单PaddleDetection依赖的opencv、numpy、pycocotools等库版本要求比较严格和你系统里已有的其他项目很容易冲突。conda create -n paddledet python3.8 -y conda activate paddledet为什么选Python 3.8而不是3.9或3.10因为PaddleDetection 2.x在Python 3.8上的兼容性验证最充分很多预编译的依赖包也是针对3.8构建的。我试过Python 3.10pycocotools编译时直接报错折腾了半天还是退回3.8。2.3 PaddlePaddle安装CPU版还是GPU版这是第一个关键决策点。如果你只是想在本地跑通推理流程、看看模型效果CPU版就够了安装简单不会有CUDA兼容问题。但如果你要训练模型必须装GPU版。GPU版安装命令需要根据你的CUDA版本选择# CUDA 10.2 python -m pip install paddlepaddle-gpu2.4.2 -i https://pypi.tuna.tsinghua.edu.cn/simple # CUDA 11.2 python -m pip install paddlepaddle-gpu2.4.2.post112 -f https://www.paddlepaddle.org.cn/whl/linux/mkl/avx/stable.html安装完成后一定要验证import paddle paddle.utils.run_check()如果输出PaddlePaddle is installed successfully!并且显示了GPU信息说明安装正确。如果只显示CPU信息那说明装的是CPU版或者GPU版没有正确识别到显卡。注意run_check()如果报libcudnn.so找不到大概率是cuDNN路径没有加到LD_LIBRARY_PATH里。可以在~/.bashrc中追加export LD_LIBRARY_PATH/usr/local/cuda/lib64:$LD_LIBRARY_PATH然后source一下。3. PaddleDetection源码获取与依赖安装的完整链路3.1 下载源码的正确姿势PaddleDetection的代码托管在GitHub上国内直接clone可能会很慢。我的做法是先用gitee镜像或者直接下载release压缩包。git clone https://github.com/PaddlePaddle/PaddleDetection.git cd PaddleDetection git checkout release/2.6 # 切换到稳定分支为什么要checkout到release分支而不是直接用develop因为develop分支的代码可能包含未测试的新特性依赖文件也可能和文档不一致。release分支是经过验证的稳定版本适合实际项目使用。下载完成后先看一眼目录结构PaddleDetection/ ├── configs/ # 模型配置文件 ├── ppdet/ # 核心代码 ├── tools/ # 训练、评估、导出脚本 ├── deploy/ # 部署相关 ├── dataset/ # 数据集存放目录需自己创建 └── requirements.txt # 依赖列表3.2 安装依赖时最容易卡住的三个地方直接执行pip install -r requirements.txt看起来很简单但实际执行时大概率会卡在以下三个地方第一个是pycocotools。这个包在Windows上编译需要Visual C Build Tools在Linux上需要cython和numpy先装好。如果报错可以先单独装pip install cython numpy pip install pycocotools第二个是opencv-python。PaddleDetection要求的是opencv-python但如果你系统里已经装了opencv-contrib-python或者opencv-python-headless会产生冲突。建议先卸载再装pip uninstall opencv-python opencv-contrib-python opencv-python-headless -y pip install opencv-python4.5.5.64第三个是PaddleDetection自身的安装。在PaddleDetection根目录下执行pip install -e .这个-e参数是可编辑安装的意思它会把当前目录加入到Python的包搜索路径中这样你修改ppdet目录下的代码后不需要重新安装就能生效。如果你不做这一步直接跑tools/train.py会报ModuleNotFoundError: No module named ppdet。3.3 验证安装是否成功安装完成后用官方提供的一个小测试来验证python tools/infer.py -c configs/yolov3/yolov3_mobilenet_v1_270e_coco.yml \ -o weightshttps://paddledet.bj.bcebos.com/models/yolov3_mobilenet_v1_270e_coco.pdparams \ --infer_imgdemo/000000014439.jpg如果一切正常会在output目录下生成一张带检测框的图片。这一步能跑通说明环境基本没问题了。我遇到过的情况是命令执行后卡在下载权重那里不动。这是因为权重文件托管在远程服务器上网络不稳定时会超时。解决办法是手动下载权重文件放到本地然后用-o weights本地路径指定。4. 跑通第一个训练任务从配置文件到模型收敛4.1 配置文件的结构与继承机制PaddleDetection的配置文件用的是YAML格式而且支持继承。什么意思呢比如yolov3_mobilenet_v1_270e_coco.yml这个文件里可能只有几行_BASE_: [ ../datasets/coco_detection.yml, ../runtime.yml, _base_/optimizer_270e.yml, _base_/yolov3_mobilenet_v1.yml, _base_/yolov3_reader.yml, ]它通过_BASE_字段继承了数据集配置、优化器配置、模型结构配置和数据读取配置。这种设计的好处是你只需要修改差异部分不用把整个配置复制一遍。但坏处是新手容易看晕不知道某个参数到底在哪个文件里定义的。我的建议是先用python tools/train.py -c configs/yolov3/yolov3_mobilenet_v1_270e_coco.yml --eval跑一遍然后在训练日志里找到实际生效的完整配置把它打印出来对照着看。4.2 数据集准备COCO格式还是VOC格式PaddleDetection支持COCO和VOC两种数据格式。COCO格式更通用但标注文件是一个大的jsonVOC格式是每张图对应一个xml更直观。如果你用自己的数据我建议转成COCO格式因为PaddleDetection里大部分预训练模型都是基于COCO训练的用COCO格式可以直接复用数据增强策略和评估指标。数据集目录结构应该是这样的dataset/coco/ ├── annotations/ │ ├── instances_train2017.json │ └── instances_val2017.json ├── train2017/ │ ├── 000000000001.jpg │ └── ... └── val2017/ ├── 000000000002.jpg └── ...然后在配置文件中修改dataset_dir指向这个目录。4.3 启动训练与关键参数解读python tools/train.py -c configs/yolov3/yolov3_mobilenet_v1_270e_coco.yml \ --eval \ -o use_gputrue \ -o TrainReader.batch_size4 \ -o LearningRate.base_lr0.001这里几个参数值得展开说batch_size显存不够时第一个要调的就是它。但注意batch_size减小后学习率也要相应减小否则训练容易震荡。经验公式是new_lr base_lr * new_batch_size / base_batch_size。base_lrYOLOv3在COCO上的默认学习率是0.001对应batch_size8。如果你改成batch_size4学习率建议改成0.0005。--eval每训练一个epoch后在验证集上评估一次。这会增加训练时间但能让你实时看到mAP的变化判断模型是否在正常收敛。训练过程中重点关注loss的变化。正常情况下前几个epoch loss会快速下降然后趋于平缓。如果loss一直不降或者变成nan大概率是学习率太大或者数据有问题。提示训练日志默认保存在output目录下可以用visualdl --logdir output启动VisualDL可视化查看loss曲线和mAP曲线。5. 环境搭建中那些文档不会告诉你的坑5.1 显存明明够却报OOM这个坑我遇到过好几次。明明nvidia-smi显示显存还剩很多但训练时就是报Out of Memory。原因通常是PaddlePaddle默认会申请全部显存而不是按需分配。解决办法是在训练命令中加上-o use_gputrue -o GPUDeviceId0或者在代码中设置import paddle paddle.set_device(gpu:0)另外如果你同时跑了多个训练任务每个任务都会尝试占用显存这时候需要指定不同的GPUDeviceId。5.2 数据增强导致的诡异报错PaddleDetection默认开启了Mosaic、RandomExpand等数据增强。这些增强在COCO数据集上没问题但如果你自己的数据集图片尺寸特别小或者标注框特别密集可能会触发一些边界条件的bug。我遇到过一次所有图片的标注框都被Mosaic拼接到了一起导致小目标完全丢失训练出来的模型对小目标检测效果极差。后来在配置文件中把Mosaic的概率调低问题才解决。TrainReader: sample_transforms: - Decode: {} - Mosaic: prob: 0.5 # 从默认的1.0降到0.55.3 评估指标不涨反降的排查思路训练过程中如果发现mAP不升反降按以下顺序排查检查学习率是否过大loss曲线如果剧烈震荡说明学习率太大。检查数据标注是否有问题用tools/infer.py在训练集上跑几张图看看模型预测的框和真实标注是否对得上。检查是否过拟合如果训练loss持续下降但验证mAP下降说明过拟合了需要增加数据增强或减小模型复杂度。检查类别不平衡如果某些类别的样本特别少模型会偏向预测多的类别。可以用--classwise参数查看每个类别的AP。5.4 导出推理模型时的版本兼容问题训练完成后用tools/export_model.py导出推理模型python tools/export_model.py -c configs/yolov3/yolov3_mobilenet_v1_270e_coco.yml \ -o weightsoutput/yolov3_mobilenet_v1_270e_coco/best_model.pdparams \ --output_dirinference_model导出的模型包含model.pdmodel和model.pdiparams两个文件。注意导出时的PaddlePaddle版本必须和推理时的版本一致否则会报模型格式不兼容。我试过用2.4训练、2.3推理直接报错。所以生产环境中要锁定版本。6. 从跑通到用好几个提升效率的实操建议6.1 用AMP混合精度训练省显存如果你的显卡支持Tensor CoreRTX系列、V100等开启AMP混合精度训练可以节省约30%的显存同时训练速度提升20%左右。在配置文件中加一行use_amp: true或者在命令行中python tools/train.py -c configs/yolov3/yolov3_mobilenet_v1_270e_coco.yml -o use_amptrue但要注意AMP在某些模型上可能会导致训练不稳定如果发现loss异常先关掉AMP试试。6.2 预训练权重的正确加载方式PaddleDetection加载预训练权重有两种方式pretrain_weights和weights。前者是在模型初始化时加载骨干网络的权重后者是加载整个模型的权重继续训练。# 加载骨干网络预训练权重 pretrain_weights: https://paddledet.bj.bcebos.com/models/pretrained/MobileNetV1_pretrained.pdparams # 断点续训 weights: output/yolov3_mobilenet_v1_270e_coco/model_final断点续训时优化器状态和学习率调度器状态也会被恢复所以不用担心学习率重置的问题。6.3 多卡训练的启动方式如果你有多张显卡可以用tools/train_multi_GPU.py启动多卡训练python -m paddle.distributed.launch --gpus 0,1,2,3 tools/train.py \ -c configs/yolov3/yolov3_mobilenet_v1_270e_coco.yml多卡训练时总batch_size 单卡batch_size × 显卡数学习率也要相应放大。但注意学习率不是线性放大的一般按平方根缩放比较稳妥。6.4 日志分析与训练监控训练过程中我习惯用tail -f output/yolov3_mobilenet_v1_270e_coco/train.log实时看日志。重点关注几个指标指标正常范围异常表现可能原因loss持续下降后趋于平稳震荡或nan学习率过大mAP逐步上升不升或下降数据问题或过拟合学习率按调度器变化不变调度器配置错误显存占用稳定持续增长内存泄漏如果发现显存持续增长大概率是数据加载器里有变量没有释放可以尝试减小num_workers或者检查自定义的数据增强代码。7. 一些个人体会PaddleDetection的环境搭建本身不难难的是遇到报错时知道去哪里找答案。我的经验是先看终端报错的最后几行那里通常有具体的错误类型和文件路径然后去PaddleDetection的GitHub Issues里搜关键词大部分坑别人已经踩过了最后才是看官方文档因为文档往往只覆盖理想情况。另外不要在一个环境里同时装多个深度学习框架。我试过在同一个conda环境里装PyTorch和PaddlePaddle结果两者的CUDA库版本冲突折腾了一整天才找到原因。现在我的做法是每个框架一个独立环境互不干扰。最后说一个细节PaddleDetection的配置文件里有很多_BASE_继承修改参数时一定要确认你改的是最终生效的那个文件。我见过有人改了_base_/yolov3_reader.yml里的batch_size但实际训练时用的是yolov3_mobilenet_v1_270e_coco.yml里覆盖的值导致改了没生效。排查方法是在训练日志开头找到打印出来的完整配置以那个为准。