1. 环境准备:从零搭建飞桨开发环境

想玩转PP-PicoDet这个超轻量级的“小钢炮”目标检测模型,第一步就是把它的“家”——飞桨(PaddlePaddle)环境给搭好。别担心,这个过程我走过很多遍,跟着我的步骤来,避开那些常见的坑,半小时内就能搞定一个干净、可用的深度学习环境。

我强烈推荐使用 Anaconda(或 Miniconda) 来管理你的Python环境。这就像给你的每个AI项目分配一个独立的“房间”,不同项目需要的库版本可能冲突,conda能完美解决这个问题,避免把系统环境搞得一团糟。首先,我们创建一个名为 paddle 的专属环境,并指定Python版本为3.7(这是目前与飞桨各版本兼容性非常好的一个选择)。

# 创建一个新的conda环境,名字叫paddle,Python版本为3.7
conda create -n paddle python=3.7
# 激活这个环境,之后的所有操作都在这个环境里进行
conda activate paddle

激活环境后,命令行提示符前面通常会显示 (paddle),这就表示你已经进入了这个独立的环境。接下来是关键一步:安装PaddlePaddle深度学习框架。这里有个小细节需要注意,飞桨官网提供了非常清晰的安装命令生成器,你需要根据自己电脑的实际情况(是否有NVIDIA GPU、CUDA版本是多少)来选择。假设你有一张支持CUDA 11.2的NVIDIA显卡,那么安装GPU版本的飞桨能极大加速训练过程。

# 使用清华镜像源加速下载,安装PaddlePaddle GPU版本 2.1.3,并配套安装cudatoolkit 11.2
conda install paddlepaddle-gpu==2.1.3 cudatoolkit=11.2 -c https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/Paddle/ -c conda-forge

注意:在实际操作中,由于网络波动,cudatoolkit 这个比较大的包有时会下载失败。如果遇到这种情况,别着急。你可以手动到 conda-forge 的网站(例如 https://conda.anaconda.org/conda-forge/linux-64/)找到对应版本(如 cudatoolkit-11.2.2-he111cf0_8.tar.bz2)的文件,下载到本地,然后用 conda install --use-local /path/to/你的文件.tar.bz2 命令进行本地安装,然后再重新执行上面的飞桨安装命令。

安装完成后,必须验证一下是否成功。打开Python解释器,执行简单的检查命令:

import paddle
paddle.utils.run_check()

如果终端打印出 “PaddlePaddle is installed successfully!” 之类的成功信息,并且显示了你的GPU设备(如果安装了GPU版本),那么恭喜你,飞桨框架已经稳稳地装好了。这一步就像是给新电脑开机,看到logo亮起,心里就踏实了。

1.1 安装目标检测工具箱 PaddleDetection

飞桨框架是我们的基础引擎,而要训练PP-PicoDet模型,我们还需要专门的“汽车组装车间”——PaddleDetection。这是百度官方基于飞桨开发的目标检测开源套件,从数据准备、模型训练、评估到部署,提供了一条龙服务。

首先,我们把它的“蓝图”(源代码)克隆到本地。找一个你习惯的工作目录,执行以下命令:

# 克隆 PaddleDetection 仓库到当前目录
git clone https://github.com/PaddlePaddle/PaddleDetection.git
# 进入项目文件夹
cd PaddleDetection

克隆下来之后,这个项目还需要一些额外的“零部件”(Python依赖库)。项目很贴心地提供了一个 requirements.txt 文件,里面列出了所有必需的库。我们一键安装即可:

# 安装所有必需的Python依赖包
pip install -r requirements.txt

在安装依赖时,你可能会遇到一个常见的报错:No module named ‘Cython‘。这是因为有些底层代码需要Cython来编译。解决起来很简单,手动安装一下Cython就行:pip install Cython。安装完依赖后,我们还需要将PaddleDetection本身以“开发模式”安装到当前Python环境中,这样我们就可以在任何位置直接调用它的模块了。

# 编译并安装 PaddleDetection
python setup.py install

为了确保整个安装过程没问题,我们可以运行一个内置的小测试:

# 运行一个简单的架构测试脚本
python ppdet/modeling/tests/test_architectures.py

如果看到输出里最后有 OK,并且所有测试都通过(Ran X tests in ...),那就说明PaddleDetection已经准备就绪了。现在,你可以迫不及待地先体验一下目标检测的效果了。我们使用一个预训练模型对示例图片进行推理:

# 指定使用第一块GPU(如果有多块卡)
export CUDA_VISIBLE_DEVICES=0
# 使用PP-YOLO模型(与PicoDet同系列)对demo图片进行预测
python tools/infer.py -c configs/ppyolo/ppyolo_r50vd_dcn_1x_coco.yml \
                      -o use_gpu=true weights=https://paddledet.bj.bcebos.com/models/ppyolo_r50vd_dcn_1x_coco.pdparams \
                      --infer_img=demo/000000014439.jpg

命令执行后,会在 output 文件夹下生成一张名为 000000014439.jpg 的新图片,上面用方框标出了模型检测到的所有物体及其类别。看到这个结果,你的环境搭建和工具安装就圆满成功了,我们已经具备了训练和运行一切模型的基础能力。

2. 数据准备与配置文件魔改

环境搭好了,相当于有了厨房和厨具。接下来要做自己的菜(训练自己的模型),首先得准备食材(数据),然后看懂并修改菜谱(配置文件)。这是从“跑通Demo”到“解决自己问题”最关键的一步,我会详细拆解。

PP-PicoDet默认使用 COCO数据集格式。这是一种在目标检测领域非常通用的格式,使用一个JSON文件来管理所有图片的标注信息。如果你的数据已经是COCO格式,那么恭喜你,这一步可以跳过。但大多数情况下,我们手里的数据可能是VOC格式(每个图片对应一个XML文件)、YOLO格式(每个图片对应一个TXT文件),或者干脆就是一堆图片和一份Excel标注表。

以最常见的VOC格式转换为例,假设你的数据集目录结构如下:

dataset/
├── Annotations/  # 存放所有XML标注文件
├── JPEGImages/   # 存放所有训练图片
├── train.txt     # 训练集列表,每行是图片相对路径(如 JPEGImages/001.jpg)
└── val.txt       # 验证集列表

PaddleDetection非常贴心地提供了格式转换脚本。你需要准备一个 label_list.txt 文件,按行写下所有类别的名称(例如:person, car, dog)。然后运行:

# 转换训练集为COCO格式
python tools/x2coco.py \
  --dataset_type voc \
  --voc_anno_dir path/to/dataset/Annotations \
  --voc_anno_list path/to/dataset/train.txt \
  --voc_label_list path/to/dataset/label_list.txt \
  --voc_out_name path/to/dataset/train.json

# 转换验证集
python tools/x2coco.py \
  --dataset_type voc \
  ... # 参数类似,将train.txt和train.json替换为val.txt和val.json

执行成功后,你会得到 train.json 和 val.json 两个文件。现在,你的数据集结构就变成了PaddleDetection喜欢的样式。接下来,就是重头戏——修改配置文件。PaddleDetection采用了一种非常灵活的模块化配置设计,初学者可能会觉得头大,但一旦掌握,你会觉得无比强大和清晰。

2.1 理解与修改核心配置文件

我们以训练一个 picodet_s_416_coco 模型为例。它的主配置文件是 configs/picodet/picodet_s_416_coco.yml。打开它,你会发现它并不长,核心是开头的 _BASE_ 部分:

_BASE_:
  [
    '../datasets/coco_detection.yml', # 数据集配置
    '../runtime.yml',                 # 运行时配置(如GPU、保存间隔)
    '_base_/picodet_esnet.yml',       # 网络结构配置
    '_base_/optimizer_300e.yml',      # 优化器与学习率策略
    '_base_/picodet_416_reader.yml',  # 数据读取与增强配置
  ]
weights: output/picodet_s_416_coco/model_final

这就像一份“菜单索引”,真正的“菜谱细节”在那些被引用的YAML文件里。修改配置的最高原则是:尽量不要直接修改那些被引用的基础文件,而是在主配置文件中进行“覆写”。这样做的好处是,你的修改集中在一处,清晰且不会影响其他模型。

第一步,覆写数据集路径和类别数。 在主配置文件中,添加以下内容来覆盖从 coco_detection.yml 加载的设置:

# 在主配置文件中添加以下内容
metric: COCO
num_classes: 10  # 修改为你的实际类别数,例如10类

TrainDataset:
  !COCODataSet
    image_dir: train2017  # 你的训练图片所在文件夹名
    anno_path: annotations/train.json  # 你的训练标注JSON文件路径
    dataset_dir: /home/your_name/dataset/coco  # 数据集根目录,建议用绝对路径
    data_fields: ['image', 'gt_bbox', 'gt_class', 'is_crowd']

EvalDataset:
  !COCODataSet
    image_dir: val2017
    anno_path: annotations/val.json
    dataset_dir: /home/your_name/dataset/coco

TestDataset:
  !ImageFolder
    anno_path: annotations/val.json  # 测试时也可用验证集标注,或留空
    dataset_dir: /home/your_name/dataset/coco

第二步,调整数据读取和增强参数。 这部分配置来自 _base_/picodet_416_reader.yml。你需要根据你的GPU显存来调整 batch_size。显存不足是新手常遇的“坑”,如果训练时出现“out of memory”错误,首要任务就是减小 batch_size。例如,单张8GB显存的卡,对于416x416的输入,batch_size 设为16或32可能比较安全。

# 在主配置文件中覆写数据读取配置
worker_num: 4  # 数据加载的线程数,通常设为CPU核心数
TrainReader:
  batch_size: 32  # 根据你的GPU显存调整!显存小就调小。
  ...

第三步,调整优化器与学习率。 这是影响模型收敛速度和最终精度的关键。配置文件 _base_/optimizer_300e.yml 默认是为8卡GPU训练设置的。如果你用单卡训练,必须将学习率相应地除以8,否则学习率过大,会导致训练无法收敛,损失值(loss)变成NaN。

# 在主配置文件中覆写优化器配置
epoch: 300  # 总训练轮数,可根据数据集大小调整,小数据集可减少
LearningRate:
  base_lr: 0.00625  # 单卡训练学习率 = 默认0.05 / 8
  schedulers:
    - !CosineDecay
      max_epochs: 300
    - !LinearWarmup
      start_factor: 0.1
      steps: 300  # 热身(warmup)步数

第四步,设置训练时的实用选项。 在 runtime.yml 的基础上,我们可以在主配置里明确一些训练行为。

# 在主配置文件中覆写运行时配置
use_gpu: true
log_iter: 20  # 每20个迭代打印一次日志
save_dir: output  # 模型保存目录
snapshot_epoch: 5  # 每5个epoch保存一次模型快照,并评估一次

把以上这些片段组合到你的主配置文件里,一个针对你自己数据集的训练配置就基本完成了。这个过程就像拼乐高,把需要的模块组合、微调一下,就能搭出想要的形状。配置文件修改是训练自己模型的核心技能,多试几次,你就会越来越熟练。

3. 模型训练、评估与调优实战

配置搞定,终于到了激动人心的训练环节!打开终端,激活你的 paddle 环境,是时候让GPU燃烧起来了。

3.1 启动模型训练

PaddleDetection支持灵活的单卡/多卡训练。对于大多数个人开发者,我们从单卡开始。

# 确保在你的PaddleDetection项目目录下
# 指定使用第0号GPU
export CUDA_VISIBLE_DEVICES=0
# 启动单卡训练,使用我们修改好的配置文件
python tools/train.py -c configs/picodet/picodet_s_416_coco.yml

如果你有幸拥有多张GPU,想加快训练速度,可以使用分布式训练。假设你有4张卡(0,1,2,3):

export CUDA_VISIBLE_DEVICES=0,1,2,3
python -m paddle.distributed.launch --gpus 0,1,2,3 tools/train.py -c configs/picodet/picodet_s_416_coco.yml

更推荐在训练时开启边训练边评估,并记录日志用于可视化,这样能实时监控模型在验证集上的表现,防止过拟合。

python -m paddle.distributed.launch --gpus 0,1,2,3 tools/train.py \
  -c configs/picodet/picodet_s_416_coco.yml \
  --eval \                    # 开启边训练边评估
  --use_vdl=true \            # 启用VisualDL日志记录
  --vdl_log_dir=output/vdl_log  # 指定日志保存目录

训练开始后,终端会滚动输出日志。重点关注两个指标:损失(loss) 和 评估精度(mAP)。loss应该随着训练轮数(epoch)的增加而稳步下降并逐渐趋于平缓。如果loss出现剧烈震荡或变成NaN,通常意味着学习率设置得太高了,请返回第二步检查学习率配置。

3.2 使用VisualDL可视化训练过程

飞桨生态的VisualDL工具就像训练过程的“仪表盘”。在训练命令中我们打开了 --use_vdl,日志已经记录下来了。在另一个终端窗口,运行:

visualdl --logdir output/vdl_log --host 0.0.0.0 --port 8040

然后在浏览器中打开 http://你的机器IP:8040,就能看到一个华丽的监控界面。在这里,你可以看到loss曲线、mAP曲线随训练迭代的变化趋势。通过观察这些曲线,你可以判断模型是否在正常学习、有没有过拟合(训练集loss下降但验证集mAP不升反降)、以及何时可以提前停止训练以节省时间。这个工具对于模型调优至关重要,我每次训练都会开着它。

3.3 模型评估与测试

训练完成后,我们需要用保留的验证集对模型性能做一个正式的“期末考试”。使用 tools/eval.py 脚本:

# 指定要评估的模型权重文件(训练过程中会自动保存最好的模型,通常叫 best_model.pdparams)
python tools/eval.py -c configs/picodet/picodet_s_416_coco.yml \
                     -o weights=output/picodet_s_416_coco/best_model.pdparams

评估结果会输出各类别的AP(平均精度)和整体的mAP(平均精度均值)。mAP是衡量目标检测模型精度的核心指标,数值越高越好。接下来,我们可以用训练好的模型对单张图片或一个文件夹的图片进行推理,直观地看效果:

# 单张图片推理
python tools/infer.py -c configs/picodet/picodet_s_416_coco.yml \
                      -o weights=output/picodet_s_416_coco/best_model.pdparams \
                      --infer_img=path/to/your/test_image.jpg \
                      --draw_threshold=0.5  # 只画出置信度大于0.5的检测框

# 批量推理一个文件夹内的所有图片
python tools/infer.py -c configs/picodet/picodet_s_416_coco.yml \
                      -o weights=output/picodet_s_416_coco/best_model.pdparams \
                      --infer_dir=path/to/your/test_images/ \
                      --output_dir=infer_output/

3.4 效果不理想?试试这些调优“骚操作”

如果你的模型mAP不高,别灰心,调优是AI工程师的日常。除了检查数据标注质量外,可以尝试以下策略:

  1. 使用预训练权重:PP-PicoDet提供了在百万级COCO数据集上预训练的模型。在配置文件中设置 pretrain_weights: https://paddledet.bj.bcebos.com/models/picodet_s_416_coco.pdparams,可以让你在小数据集上快速收敛,几乎总能带来精度提升。
  2. 调整数据增强:如果过拟合(训练集好,验证集差),可以增强数据随机性,如增加随机裁剪、色彩抖动等。如果欠拟合(两者都差),可以适当减少增强强度。
  3. 更换损失函数:在 _base_/picodet_esnet.yml 中,可以尝试将 GIOULoss 改为 DIOULoss,后者对框的位置回归有时更稳定。
  4. 微调学习率策略:如果训练后期loss波动,可以尝试使用 PiecewiseDecay(分段式下降)替代 CosineDecay(余弦下降),或者在训练末尾将学习率再调小一个数量级继续训练几个epoch(即常说的fine-tune)。

模型调优是一个需要耐心和实验的过程,没有银弹。但每一次尝试和观察,都会让你对模型和数据有更深的理解。

4. 模型导出与移动端部署

模型训练评估满意后,它还是一个只能在PaddlePaddle训练环境中运行的“毛坯房”。我们要把它变成可以在各种终端上快速运行的“精装公寓”,这个过程就是模型导出与部署。

4.1 导出为推理模型

训练保存的模型文件(.pdparams)包含了训练所需的全部信息(包括反向传播)。部署时我们只需要前向推理。因此,第一步是将其导出为静态图推理模型。

python tools/export_model.py \
  -c configs/picodet/picodet_s_416_coco.yml \
  -o weights=output/picodet_s_416_coco/best_model.pdparams \
  --output_dir=output_inference/picodet_s_416_coco

执行成功后,在 output_inference/picodet_s_416_coco 目录下,你会看到几个关键文件:

  • model.pdmodel:模型网络结构定义。
  • model.pdiparams:模型权重参数。
  • infer_cfg.yml:模型前、后处理的配置信息(如归一化参数、标签映射)。

这个“推理模型”已经可以在服务器端使用Paddle Inference库进行高效预测了。

4.2 转换为ONNX格式

ONNX是一种开放的模型格式,可以方便地在不同框架(如TensorRT, OpenVINO, NCNN)之间转换和部署。要将Paddle模型转为ONNX,需要安装 paddle2onnx 工具。

pip install paddle2onnx
# 转换模型
paddle2onnx --model_dir output_inference/picodet_s_416_coco \
            --model_filename model.pdmodel \
            --params_filename model.pdiparams \
            --opset_version 11 \
            --save_file picodet_s_416_coco.onnx

现在你得到了一个 picodet_s_416_coco.onnx 文件,它可以在支持ONNX的众多推理引擎上运行,极大地扩展了部署范围。

4.3 模型量化:让模型在端侧飞起来

PP-PicoDet本身已经很轻量,但对于手机、嵌入式设备,我们还想让它更快、更省电。模型量化就是将模型参数从高精度的浮点数(如FP32)转换为低精度的整数(如INT8),从而大幅减少模型体积、提升推理速度,通常只伴随极小的精度损失。

PaddleDetection集成了PaddleSlim量化工具,支持量化感知训练(QAT)和训练后量化(PTQ)。我强烈推荐使用QAT,它在训练过程中模拟量化误差,让模型“提前适应”,最终精度保持得更好。

首先,安装PaddleSlim(注意版本要与PaddlePaddle匹配):

pip install paddleslim==2.1 -i https://pypi.tuna.tsinghua.edu.cn/simple

然后,准备一个量化配置文件(例如复制并修改 configs/slim/quant/picodet_s_quant.yml),主要是指定量化开始轮数、量化位宽等。接着,启动量化训练:

python tools/train.py \
  -c configs/picodet/picodet_s_416_coco.yml \
  --slim_config configs/slim/quant/picodet_s_quant.yml \
  -o pretrain_weights=output/picodet_s_416_coco/best_model.pdparams \
  --eval

量化训练结束后,使用同样的 export_model.py 脚本导出,但加上 --slim_config 参数,导出的就是已经量化好的、更小的推理模型。实测下来,量化后的模型在移动端CPU上的推理速度可以有30%-50%的提升,而mAP可能只下降不到1个百分点,这个交换在移动端场景下通常是非常值得的。

4.4 端侧部署示例:使用Paddle Lite

最终,我们要把模型放到手机(Android/iOS)或嵌入式设备上。这里以Android为例,飞桨提供了 Paddle Lite 这个轻量级推理引擎。

  1. 准备模型:使用上面量化导出的模型,或普通推理模型。
  2. 模型优化:使用Paddle Lite的 opt 工具对模型进行融合、裁剪等优化,生成 .nb 格式的模型文件。
  3. 集成到APP:将Paddle Lite的预测库(.so或.a)和优化后的模型文件放入Android工程。PaddleDetection的 deploy/lite 目录下提供了完整的Demo代码,展示了如何加载模型、预处理图片、运行预测并解析结果。

这个过程涉及一定的Android开发知识,但Paddle Lite的API设计得非常简洁。核心代码片段大致如下(Java示例):

// 1. 创建预测器
PaddlePredictor predictor = PaddlePredictor.createPaddlePredictor(config);

// 2. 准备输入数据(将图片转换为符合模型要求的Tensor)
float[] inputData = ... // 将图片缩放、归一化、排成NCHW格式
Tensor inputTensor = predictor.getInput(0);
inputTensor.resize(inputShape);
inputTensor.setData(inputData);

// 3. 执行预测
predictor.run();

// 4. 获取输出
Tensor outputTensor = predictor.getOutput(0);
float[] results = outputTensor.getFloatData();
// 解析results,得到框的位置、类别和置信度

跟着官方Demo的步骤,你完全可以在一个周末的时间内,把训练好的PP-PicoDet模型集成到一个简单的Android App中,实现实时摄像头目标检测。当你第一次在手机上看到自己训练的模型流畅地识别出物体时,那种成就感是无与伦比的。从环境配置到模型训练,再到最终部署,这条完整的路径走通后,你就真正掌握了将一个AI想法落地到实际应用中的核心能力。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐