从零开始:YOLOv4 目标检测实战指南 (环境配置、训练到优化全流程)

本篇博客将带你一步步从零开始,完成 YOLOv4 的环境配置、数据集准备与训练,并涵盖常见的优化和问题解决。本文将以 Darknet 框架下的 YOLOv4 实现为主,因为它是由 YOLOv4 原作者团队维护和优化的官方版本,能够提供最原汁原味的体验和性能。

我们将涵盖以下内容:

  1. 环境配置详解:Python、CUDA、cuDNN、GCC、Make 等前置依赖,以及 Darknet 的编译。
  2. 数据集准备与预处理:目标检测数据集的格式要求、常用标注工具、数据文件组织。
  3. 参数配置与训练流程:核心配置文件详解、迁移学习、训练命令、日志解读。
  4. 常见问题及解决方案:编译错误、CUDA 问题、数据路径错误、训练过程中的 NaN 等。
  5. 超参数调优技巧:学习率策略、Batch Size、数据增强等对训练效果的影响。
  6. 性能评估与可视化分析:mAP 计算、检测结果可视化。

重要提示: 训练深度学习模型,尤其是 YOLOv4 这样参数量较大的模型,通常需要一块性能较好的 NVIDIA GPU。本文的环境配置部分将重点介绍如何在 Linux 系统下配置 CUDA 环境,这是 GPU 训练的基石。

1. 环境配置详解

这是进行深度学习训练的第一步,也是最容易遇到问题的一步。耐心、仔细是关键。

操作系统:

推荐使用 Linux (如 Ubuntu 18.04 或 20.04)。虽然 Darknet 也可以在 Windows 上编译,但在 Linux 环境下配置 CUDA 和各种库更加方便和稳定。

硬件要求:

  • GPU: NVIDIA GPU 是必须的,显存越大越好 (建议 8GB 或以上)。
  • CPU: 性能适中即可。
  • 内存: 建议 16GB 或以上。
  • 硬盘空间: 需要足够的空间存储数据集、预训练权重和训练过程中生成的权重文件 (几十 GB 到几百 GB 不等)。

前置依赖:

在安装 Darknet 之前,你需要安装一些基础的开发工具和库。

  • GCC/G++: C/C++ 编译器。通常 Linux 发行版自带。
  • Make: 构建工具。通常 Linux 发行版自带。
  • CMake: 用于构建软件的工具。 Bash

    sudo apt update
    sudo apt install cmake
    
  • Python: 推荐安装 Python 3.6 或更高版本。Anaconda 或 Miniconda 是管理 Python 环境的好选择。 Bash

    # 使用 Miniconda 为例
    wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
    bash Miniconda3-latest-Linux-x86_64.sh
    # 按照提示安装
    # 创建并激活虚拟环境 (可选但强烈推荐)
    conda create -n yolov4_env python=3.8
    conda activate yolov4_env
    # 安装一些常用库
    pip install numpy opencv-python matplotlib
    
  • CUDA Toolkit: NVIDIA 提供的并行计算平台,是 GPU 加速的关键。版本选择取决于你的 GPU 型号和操作系统。务必检查你的显卡支持的最高 CUDA 版本。 可以在 NVIDIA 官网查找兼容性。
    • 安装步骤: 访问 NVIDIA CUDA Toolkit Archive (CUDA Toolkit Archive | NVIDIA Developer) 下载对应版本的安装包 (选择 runfile 方式通常更灵活)。
    • 重要: 安装时可以选择不安驱动,如果你已经通过其他方式安装了驱动。如果选择安装驱动,务必确认安装的驱动版本与你的显卡兼容
    • 安装完成后: 将 CUDA 的 bin 目录添加到系统环境变量 PATH 中,将 lib64 目录添加到 LD_LIBRARY_PATH 中。通常在 ~/.bashrc 文件中添加: Bash

      export PATH=/usr/local/cuda/bin:$PATH
      export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH
      
      然后执行 source ~/.bashrc 使其生效。
    • 验证安装: 打开新的终端,运行 nvcc -V。如果显示 CUDA 版本信息,则安装成功。
  • cuDNN: NVIDIA 深度学习加速库。它依赖于 CUDA。cuDNN 版本必须与 CUDA 版本兼容。
    • 下载: 访问 NVIDIA cuDNN Download (https://developer.nvidia.com/cudnn/downloads) 下载对应 CUDA 版本的 cuDNN (需要注册 NVIDIA 开发者账号)。下载 cuDNN Library for Linux 的 tar 文件。
    • 安装: 解压下载的文件,将 include 目录下的头文件复制到 CUDA 的 include 目录,将 lib64 目录下的库文件复制到 CUDA 的 lib64 目录。 Bash

      tar -xvf cudnn-*-archive.tar.xz
      sudo cp cuda/include/cudnn.h /usr/local/cuda/include/
      sudo cp cuda/lib64/libcudnn* /usr/local/cuda/lib64/
      sudo chmod a+r /usr/local/cuda/lib64/libcudnn*
      
    • 验证安装: 可以运行 CUDA 提供的示例 (deviceQuery, bandwidthTest) 来验证 CUDA 和驱动,cuDNN 通常没有独立的验证程序,但如果后续 Darknet 编译开启 cuDNN 成功,则说明安装正确。
  • OpenCV: 用于图像处理和可视化的库。Darknet 可以选择性地使用 OpenCV 来进行图像加载和结果可视化。 Bash

    sudo apt install libopencv-dev
    

安装 Darknet:

我们将使用 AlexeyAB 维护的 Darknet 开源项目,它是目前最活跃和功能最完善的 Darknet 版本。

  1. 克隆仓库: Bash

    git clone https://github.com/AlexeyAB/darknet.git
    cd darknet
    
  2. 修改 Makefile: 这是编译 Darknet 的关键步骤。根据你的需求和环境修改 Makefile 文件。使用任意文本编辑器打开 Makefile: Bash

    # 开启 GPU 支持 (必须)
    GPU=1
    # 开启 cuDNN 加速 (强烈推荐)
    CUDNN=1
    # 开启 OpenCV 支持 (推荐,用于可视化)
    OPENCV=1
    # 开启 LIBSO 支持 (可选,用于编译为动态库,方便 Python 调用)
    # LIBSO=1
    
    # 根据你的 CUDA 版本设置 ARCH (Compute Capability)
    # 如果不确定,可以运行 nvidia-smi 查看 GPU 型号,然后到 NVIDIA 官网查询对应的 Compute Capability
    # 例如,对于 RTX 30系列,ARCH=86
    # 如果是较旧的显卡,可能需要设置多个 ARCH,例如 ARCH=61 75
    # 或者尝试不设置 ARCH,让 make 自动检测 (有时会出错)
    # ARCH= -gencode arch=compute_61,code=[sm_61,compute_61] \
    #       -gencode arch=compute_75,code=[sm_75,compute_75]
    # ... (找到 ARCH 相关的行,根据注释或你的显卡修改)
    
    # 如果使用了 CUDNN_HALF=1,需要 GPU 支持 FP16 (通常是 Volta 及更新架构)
    # CUDNN_HALF=1
    
    # 如果使用了 OPENCV=1,确保 PKG_CONFIG_PATH 包含了你的 OpenCV 安装路径
    # (如果使用 apt 安装,通常不需要额外设置)
    
    保存并关闭 Makefile
  3. 编译: Bash

    make
    
    编译过程可能需要几分钟到十几分钟,取决于你的 CPU 性能。如果一切顺利,你会看到编译成功的提示,并在 darknet 目录下生成可执行文件 darknet

验证安装:

  • 运行 ./darknet,如果能看到 Darknet 的使用说明,说明编译成功。
  • 运行一个简单的测试 (需要下载预训练权重,后面会介绍): Bash

    wget https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v3_optimal/yolov4.weights
    

1 ./darknet detector test cfg/coco.data cfg/yolov4.cfg yolov4.weights data/dog.jpg # 如果能看到检测结果图片 predictions.jpg,说明环境配置和 Darknet 基本功能正常 ```  

1. github.com 

github.com

2. 数据集准备与预处理

训练目标检测模型需要大量的标注数据。每个数据样本包含一张图片和其中所有目标的位置和类别信息。

数据集格式 (YOLO Darknet 格式):

Darknet 期望的标注格式是针对每张图片生成一个同名的 .txt 文件。例如,图片文件是 image.jpg,对应的标注文件就是 image.txt

.txt 文件中,每一行代表图片中的一个目标,格式如下:

<class_id> <center_x> <center_y> <width> <height>
  • <class_id>: 目标的类别 ID,从 0 开始计数。例如,如果你有 "cat" 和 "dog" 两个类别,"cat" 是 0,"dog" 是 1。
  • <center_x>, <center_y>, <width>, <height>: 这些都是 归一化 的浮点数,范围在 [0.0, 1.0] 之间。
    • <center_x>: 目标框中心的 X 坐标,除以图片宽度进行归一化。
    • <center_y>: 目标框中心的 Y 坐标,除以图片高度进行归一化。
    • <width>: 目标框的宽度,除以图片宽度进行归一化。
    • <height>: 目标框的高度,除以图片高度进行归一化。

例子:

如果一张 640x480 的图片中有一个目标框,左上角坐标 (100, 50),右下角坐标 (300, 450),类别 ID 是 0 (猫)。

  • 中心 X: (100 + 300) / 2 = 200
  • 中心 Y: (50 + 450) / 2 = 250
  • 宽度: 300 - 100 = 200
  • 高度: 450 - 50 = 400

归一化后:

  • <center_x>: 200 / 640 = 0.3125
  • <center_y>: 250 / 480 = 0.5208
  • <width>: 200 / 640 = 0.3125
  • <height>: 400 / 480 = 0.8333

则对应的 .txt 文件中的一行就是:

0 0.3125 0.5208 0.3125 0.8333

常用标注工具:

如果你有自己的图片需要从头标注,可以使用以下工具:

  • LabelImg: (推荐) 开源的图形界面标注工具,支持多种格式输出 (包括 YOLO)。安装和使用都很方便。
  • VGG Image Annotator (VIA): 基于 Web 的标注工具。
  • Makesense.ai: 在线标注工具。

数据集文件组织:

通常将数据集组织成以下结构:

your_dataset/
├── images/       # 存放所有图片文件 (.jpg, .png等)
│   ├── image1.jpg
│   ├── image2.png
│   └── ...
└── labels/       # 存放所有标注文件 (.txt),与 images 下的文件一一对应且同名
    ├── image1.txt
    ├── image2.txt
    └── ...

创建数据文件:

Darknet 需要几个文件来了解你的数据集:

  1. .names 文件: 包含所有类别的名称,每行一个。例如 obj.names:
    cat
    dog
    person
    
    注意顺序要和你的标注中的 <class_id> 对应。
  2. .data 文件: 告诉 Darknet 数据集的相关信息。例如 obj.data:
    classes = 3           # 类别数量
    train = data/train.txt  # 训练图片列表文件路径
    valid = data/val.txt    # 验证图片列表文件路径 (可选)
    names = data/obj.names  # .names 文件路径
    backup = /path/to/backup/weights/  # 训练过程中保存权重文件的目录
    # eval=coco             # 评估方式 (可选,通常不需要设置)
    
  3. 训练图片列表 (train.txt): 包含所有用于训练的图片文件的绝对路径或相对路径,每行一个。
  4. 验证图片列表 (val.txt): (可选) 包含所有用于验证的图片文件的路径,格式同 train.txt。用于在训练过程中评估模型性能。

你可以编写一个简单的 Python 脚本来生成 train.txtval.txt 文件,将 images 目录下的图片路径随机划分到这两个文件中。

Python

import os
import random

image_dir = 'your_dataset/images/'
train_file = 'data/train.txt'
val_file = 'data/val.txt'
split_ratio = 0.9 # 90% 训练,10% 验证

image_list = [os.path.join(image_dir, img) for img in os.listdir(image_dir) if img.endswith(('.jpg', '.png', '.jpeg'))]
random.shuffle(image_list)

train_count = int(len(image_list) * split_ratio)
train_list = image_list[:train_count]
val_list = image_list[train_count:]

with open(train_file, 'w') as f:
    for img_path in train_list:
        f.write(img_path + '\n')

with open(val_file, 'w') as f:
    for img_path in val_list:
        f.write(img_path + '\n')

print(f"Generated {train_file} with {len(train_list)} images")
print(f"Generated {val_file} with {len(val_list)} images")

将上述 Python 脚本放在 darknet 目录下,修改 image_dir 路径,运行即可生成 data/train.txtdata/val.txt (确保 darknet 目录下有 data 文件夹)。

3. 参数配置与训练流程详解

训练 YOLOv4 需要配置模型结构、训练参数以及指定数据集信息。

模型配置文件 (.cfg):

YOLOv4 的模型结构和许多训练参数都定义在 .cfg 文件中,例如 cfg/yolov4.cfg。你需要根据你的数据集修改这个文件。

找到文件末尾的 [yolo] 层及其前面的 [convolutional] 层。对于每个 [yolo] 层 (通常有 3 个,对应不同尺度的检测):

  • [convolutional] 层 (在 [yolo] 前): 修改 filters 参数。其值应为 (classes + 5) * 3

    • classes: 你的数据集的类别数量。
    • 5: 表示边界框的 (center_x, center_y, width, height) 和目标性得分 (objectness score)。
    • 3: 表示该层对应的 Anchor 数量 (YOLOv4 在每个检测层使用 3 个 Anchor)。 例如,如果你的数据集有 3 个类别,则 filters = (3 + 5) * 3 = 24
  • [yolo] 层: 修改 classes 参数为你的类别数量。 修改 anchors 参数。这一步非常重要! 默认的 anchors 是在 COCO 数据集上聚类得到的,你需要根据你的数据集重新聚类生成适合你的目标的 anchors。

    如何生成 Anchors: Darknet 提供了工具来根据你的数据集计算最佳的 anchors。运行以下命令:

    Bash

    ./darknet detector calc_anchors data/obj.data -cfg cfg/yolov4.cfg -num_of_clusters 9 -width 416 -height 416
    # data/obj.data: 你的数据文件
    # cfg/yolov4.cfg: 你的配置文件
    # num_of_clusters: Anchor 数量 (通常 YOLOv4 使用 9 个)
    # width/height: 你训练时将使用的输入图片尺寸 (比如 416x416)
    

    该命令会输出计算得到的 9 个 anchors (9个数值对)。将这些数值复制粘贴到 cfg/yolov4.cfg 中所有 [yolo] 层的 anchors 参数后面,并删除原有的 anchors。确保格式正确,例如:anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326 (注意逗号和空格)。

其他重要参数 (在文件顶部):

  • batch: 训练时使用的图片数量。越大越稳定,但越耗显存。
  • subdivisions: 将一个 batch 分割成多少份送入 GPU。实际送入 GPU 的图片数量是 batch / subdivisions。这是为了在显存不足时模拟大 batch size。例如 batch=64, subdivisions=16,则每次送入 4 张图片。
  • width, height: 网络输入的图片尺寸。通常是 32 的倍数,例如 416x416, 608x608。更大的尺寸通常精度更高,但速度更慢且需要更多显存。
  • learning_rate: 初始学习率。
  • policy: 学习率衰减策略 (如 steps, polynomial, exponential)。
  • steps, scales: 与 policy=steps 配合使用,定义在哪些迭代次数 (steps) 将学习率乘以对应的因子 (scales) 进行衰减。
  • max_batches: 总共训练的迭代次数。建议设置为 classes * 2000,但不小于 6000。
  • burn_in: 在前 burn_in 迭代内,学习率会从一个很小的值逐渐增加到初始学习率。
  • mosaic, cutmix: 数据增强技术,默认开启 (1)。
  • hue, saturation, exposure: 颜色抖动参数。
  • random: 是否使用随机尺寸输入进行训练 (每 10 个迭代随机改变一次输入尺寸,范围从 width/32*32width,步长为 32)。默认开启 (1)。这有助于提高模型的鲁棒性。

迁移学习 (Transfer Learning):

从预训练权重开始训练可以大大缩短训练时间并提高性能,尤其是在数据集较小的情况下。

  1. 下载预训练权重: 下载在大型数据集 (如 COCO 或 ImageNet) 上预训练的 YOLOv4 权重。
    • 在 ImageNet 上预训练的权重 (只包含 backbone): yolov4.conv.137 (约 160MB) Bash

      wget https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v3_optimal/yolov4.conv.137
      
    • 在 COCO 上预训练的完整权重: yolov4.weights (约 245MB) Bash

      wget https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v4_pre/yolov4.weights
      
    建议使用 yolov4.conv.137 从头开始在你的数据集上训练,因为 yolov4.weights 是在 80 个类别的 COCO 上训练的,直接在少量类别的数据集上微调可能会遇到类别不匹配的问题 (虽然 Darknet 也能处理,但从 conv 权重开始更规范)。

开始训练:

使用 Darknet 的 detector train 命令开始训练。

Bash

./darknet detector train data/obj.data cfg/yolov4.cfg yolov4.conv.137 -map
# data/obj.data: 你的数据文件路径
# cfg/yolov4.cfg: 你的配置文件路径
# yolov4.conv.137: 用于迁移学习的预训练权重文件路径 (如果是从头训练,可以省略或使用一个较小的 backbone 权重如 darknet53.conv.74)
# -map: (可选) 在训练过程中定期计算验证集上的 mAP (Mean Average Precision),用于监控训练效果。这会稍微降低训练速度。

训练开始后,你会看到类似以下的输出:

...
Loading weights from yolov4.conv.137...Done!
Learning Rate: 0.00261
Batch Size: 64, Subdivisions: 16
...
Epoch   Iteration   Region Avg IOU   Class Avg IOU   Object Avg IOU    Total Avg IOU  Recall  Precision   Avg Loss   Rate
   1         100           0.7580          0.9032          0.7890           0.8167    0.88    0.91       0.543210   0.001000
   1         200           0.7801          0.9115          0.8103           0.8340    0.90    0.93       0.487654   0.002610
...
Saving weights to /path/to/backup/weights/yolov4_xxxx.weights
  • Iteration: 当前的训练迭代次数。
  • Region Avg IOU: 预测框与真实框的平均 IoU。
  • Class Avg IOU: 预测框中正确分类的目标的平均 IoU。
  • Object Avg IOU: 预测框中包含目标的平均 IoU。
  • Total Avg IOU: 整体平均 IoU。
  • Recall: 召回率。
  • Precision: 精确率。
  • Avg Loss: 平均损失值。这是监控训练是否收敛的重要指标,应随着训练进行逐渐下降。
  • Rate: 当前的学习率。

Darknet 会定期在 backup 目录 (在 .data 文件中指定) 下保存权重文件 (.weights),通常是每 100 次迭代保存一次 .weights 文件,以及每 1000 次迭代保存一次完整的 .weights 文件。

中断与恢复训练:

如果你需要中断训练 (例如关机或显存不足),可以直接关闭终端。下次训练时,使用以下命令从保存的最新权重文件继续:

Bash

./darknet detector train data/obj.data cfg/yolov4.cfg /path/to/backup/weights/yolov4_last.weights -map
# 将 yolov4_last.weights 替换为你想要恢复的权重文件路径

Darknet 会查找指定权重文件同目录下的 _last.weights 文件作为最新的保存点。

4. 常见问题及解决方案

在 YOLOv4 训练过程中,可能会遇到各种问题。以下是一些常见问题及其解决方法:

  • 编译错误 (尤其是 CUDA 相关):
    • 问题: undefined reference to 'cudaFree' 或其他 CUDA 函数。
    • 原因: CUDA Toolkit 或驱动安装不正确,或者 Makefile 中的 CUDA 路径配置错误。
    • 解决方案: 重新安装 CUDA Toolkit,确保 PATHLD_LIBRARY_PATH 包含正确的 CUDA 路径。检查 Makefile 中的 GPUCUDNN 是否开启,以及 ARCH 是否与你的显卡兼容。
    • 问题: fatal error: cudnn.h: No such file or directory
    • 原因: cuDNN 没有正确安装或复制到 CUDA 目录。
    • 解决方案: 检查 cuDNN 文件是否正确复制到 /usr/local/cuda/include/usr/local/cuda/lib64。确保文件权限正确 (chmod a+r ...)。
    • 问题: undefined reference to 'cv::' 或其他 OpenCV 函数。
    • 原因: OpenCV 没有正确安装,或者 Makefile 中的 OPENCV 没有开启。
    • 解决方案: 安装 libopencv-dev,确保 OPENCV=1 在 Makefile 中。
  • CUDA/cuDNN 版本不兼容:
    • 问题: 运行时报 CUDA 或 cuDNN 相关错误,提示版本不匹配。
    • 原因: 安装的 CUDA Toolkit、cuDNN 和 NVIDIA 驱动之间版本不兼容。
    • 解决方案: 仔细查阅 NVIDIA 官方文档,确认你的 GPU、驱动、CUDA 和 cuDNN 之间的兼容性,然后安装对应的版本。通常建议先安装驱动,再安装兼容的 CUDA 和 cuDNN。
  • 数据集路径错误:
    • 问题: Couldn't open file data/obj.dataCannot load image data/train.txt 中的图片。
    • 原因: .data 文件中指定的路径错误,或者 train.txt/val.txt 中指定的图片路径错误。
    • 解决方案: 仔细检查 obj.data 文件中的 train, valid, names, backup 路径是否正确,以及 train.txt/val.txt 文件中的图片路径是否准确。使用绝对路径可以避免相对路径带来的问题。
  • 配置文件错误 (.cfg):
    • 问题: Error in cfg file... 或训练开始后立即崩溃。
    • 原因: .cfg 文件中有语法错误,或者修改 filters, classes, anchors 时计算或复制错误。
    • 解决方案: 仔细检查你修改的 [convolutional][yolo] 层中的 filters, classes, anchors 参数是否正确。filters 必须是 (classes + 5) * 3。确保 anchors 格式正确。
  • 训练过程中出现 NaN Loss:
    • 问题: 训练输出的 Avg Loss 突然变成 nan
    • 原因: 学习率过高、数据异常 (标注错误、图片损坏) 或模型不稳定。
    • 解决方案:
      • 降低学习率: 初始学习率可能过高,尝试减小一点。
      • 检查数据集: 检查训练集中是否有标注错误、空白标注文件、损坏的图片或尺寸极小的图片。
      • 减小 Batch Size: 减小 batchsubdivisions
      • 从上一个稳定权重恢复: 从出现 NaN 之前的最后一个正常权重文件恢复训练。
      • 关闭或调整数据增强: 有时过于激进的数据增强可能导致问题。
  • 显存不足 (Out of Memory):
    • 问题: 训练过程中报 CUDA 内存错误。
    • 原因: Batch size 或输入图片尺寸过大,超过了 GPU 显存容量。
    • 解决方案:
      • 减小 batch 和/或 增大 subdivisions: 实际送入 GPU 的图片数量是 batch / subdivisions,减小这个值可以降低显存占用。
      • 减小输入图片尺寸: 修改 .cfg 文件中的 widthheight
      • 开启 CUDNN_HALF=1: 如果你的 GPU 支持 FP16,开启这个选项可以减少显存使用 (需要修改 Makefile 并重新编译)。

5. 超参数调优技巧

超参数的选择对模型的训练效果至关重要。调优是一个需要经验和耐心的过程。

以下是一些关键的超参数和调优技巧:

  • 学习率 (learning_rate, policy, steps, scales):
    • 学习率是影响训练收敛速度和最终性能的最重要参数之一。
    • 通常从一个较小的初始学习率开始 (0.0010.00261 是常见的起始值)。
    • 使用学习率衰减策略 (policy=steps) 是必要的,可以在训练后期减小学习率,帮助模型更稳定地收敛到最优解。stepsscales 需要根据 max_batches 合理设置。例如,在总迭代次数的 80% 和 90% 进行两次衰减,每次衰减因子为 0.1 (scales=0.1,0.1)。
    • 如果训练初期 loss 下降缓慢,可以尝试增大初始学习率。如果 loss 震荡或出现 NaN,说明学习率可能过高,需要减小。
  • Batch Size (batch, subdivisions):
    • Batch size 越大,梯度估计越准确,训练通常越稳定,也更容易收敛到更好的局部最优解。但受限于显存。
    • 尽量使用你能负担的最大 Batch size。如果显存不足,可以通过增大 subdivisions 来模拟大 Batch size。
  • 输入图片尺寸 (width, height):
    • 更大的输入尺寸通常能提高对小目标的检测能力,从而提高精度。
    • 缺点是需要更多显存,推理速度也会变慢。
    • 可以先使用较小的尺寸 (如 416x416) 进行快速实验,确定其他参数后,再尝试更大的尺寸 (如 608x608) 进行最终训练。
    • random=1 (随机尺寸训练) 是一个很有效的正则化手段,能提高模型对不同尺寸目标的鲁棒性。
  • Anchors:
    • Anchors 的选择对模型的收敛速度和性能有很大影响。务必根据你的数据集重新聚类生成。
  • 数据增强 (mosaic, cutmix, hue, saturation, exposure 等):
    • 数据增强是提高模型泛化能力的重要手段。Darknet 内置了多种数据增强方法。
    • mosaiccutmix 是很有效的增强技术,通常建议开启。
    • 颜色抖动参数 (hue, saturation, exposure) 可以适度调整,模拟不同的光照条件。
    • 如果数据集较小,可以考虑使用更强的数据增强。如果数据集很大,可以适度减弱。
  • 优化器参数:
    • Darknet 使用 SGD 优化器。.cfg 文件中的 momentum (动量) 和 decay (权重衰减) 是重要的优化器参数。默认值通常工作良好,一般不需要大幅调整。decay 用于防止过拟合,较大的 decay 会惩罚大的权重。
  • 训练迭代次数 (max_batches):
    • 训练到 loss 收敛并且验证集性能不再提升即可停止。设置过大的 max_batches 只会浪费计算资源,甚至可能导致过拟合。
    • 监控训练日志中的 Avg Loss-map 选项输出的 mAP 来判断何时停止。

调优策略:

  1. 从基础开始: 使用推荐的默认参数和在 ImageNet 上预训练的 yolov4.conv.137 开始训练。
  2. 监控指标: 密切关注训练日志中的 Avg Loss 和验证集上的 mAP。
  3. 一次调整少量参数: 避免一次修改太多超参数,否则很难判断哪个修改起作用了。
  4. 学习率优先: 通常先从学习率开始调优。
  5. Batch Size 限制: 在显存允许范围内选择最大的 Batch Size 或通过 subdivisions 模拟。
  6. Anchor 聚类: 务必为你的数据集重新计算 anchors。
  7. 数据增强: 根据数据集大小和特性调整数据增强参数。
  8. 耐心和实验: 超参数调优是一个实验过程,需要耐心尝试不同的组合。

6. 性能评估与可视化分析

训练完成后,你需要评估模型的性能并可视化检测结果。

性能评估 (mAP):

mAP (Mean Average Precision) 是目标检测中最常用的评估指标,它综合考虑了模型的准确率和召回率。Darknet 可以方便地计算 mAP。

修改 obj.data 文件,确保 valid 路径指向你的验证集图片列表文件。

运行以下命令计算 mAP:

Bash

./darknet detector map data/obj.data cfg/yolov4.cfg /path/to/your_trained_weights.weights
# data/obj.data: 你的数据文件
# cfg/yolov4.cfg: 你的配置文件
# /path/to/your_trained_weights.weights: 你训练好的权重文件路径 (通常选择验证集上 mAP 最高或 loss 最低的权重)

输出会显示不同 IoU 阈值下的 Average Precision (AP) 以及它们的平均值 (mAP)。例如:

...
Calculating mAP (mean average precision)...
For class_id = 0 name = cat: AP@0.50 = 0.856789
For class_id = 1 name = dog: AP@0.50 = 0.923456
For class_id = 2 name = person: AP@0.50 = 0.891234
 avg mAP@0.50 = 0.890493
...
  • AP@0.50: 在 IoU 阈值为 0.5 时的平均精确率。
  • avg mAP@0.50: 所有类别在 IoU 阈值为 0.5 时的平均 mAP。

通常,avg mAP@0.50 是最重要的评估指标。一些比赛或研究也会关注更高 IoU 阈值下的 mAP (如 mAP@0.75 或 mAP@0.5:0.95,表示在 IoU 从 0.5 到 0.95 以 0.05 为步长的多个阈值下的平均 mAP)。

可视化分析:

将模型应用到新的图片或视频上,直观地查看检测结果。

检测单张图片:

Bash

./darknet detector test data/obj.data cfg/yolov4.cfg /path/to/your_trained_weights.weights /path/to/your_image.jpg
# data/obj.data: 你的数据文件
# cfg/yolov4.cfg: 你的配置文件
# /path/to/your_trained_weights.weights: 训练好的权重文件路径
# /path/to/your_image.jpg: 要检测的图片路径
# -thresh 0.5: (可选) 设置置信度阈值,只显示置信度高于该值的检测框 (默认通常是 0.25)

检测结果会保存在 predictions.jpg 文件中。

检测视频:

Bash

./darknet detector demo data/obj.data cfg/yolov4.cfg /path/to/your_trained_weights.weights /path/to/your_video.mp4 -thresh 0.5 -out_filename results.avi
# ... (前面参数同上)
# /path/to/your_video.mp4: 要检测的视频文件路径
# -out_filename results.avi: (可选) 将检测结果保存为视频文件

这会在窗口中实时显示检测结果。

绘制 loss/mAP 曲线:

Darknet 的训练日志包含了每次迭代的 loss 和 mAP 信息。你可以编写一个 Python 脚本来解析日志文件,并使用 Matplotlib 等库绘制 loss 曲线和 mAP 曲线,以便更直观地分析训练过程。

Python

import matplotlib.pyplot as plt

def parse_log(log_file):
    iterations = []
    losses = []
    ious = []
    maps = [] # 如果使用了 -map 选项

    with open(log_file, 'r') as f:
        for line in f:
            if 'Iteration' in line and 'Avg Loss' in line:
                parts = line.split()
                iterations.append(int(parts[1]))
                losses.append(float(parts[-2]))
                ious.append(float(parts[5])) # Region Avg IOU

            if 'avg mAP@0.50' in line: # 如果使用了 -map 选项
                parts = line.split()
                # 找到 avg mAP 值,注意日志格式可能略有不同
                try:
                    map_val = float(parts[-1])
                    maps.append((iterations[-1], map_val)) # 记录迭代次数和mAP
                except (ValueError, IndexError):
                    pass # 处理解析错误

    return iterations, losses, ious, maps

# 修改为你的日志文件路径
log_file = 'path/to/your_darknet_train.log'
iterations, losses, ious, maps = parse_log(log_file)

# 绘制 Loss 和 IOU 曲线
plt.figure(figsize=(12, 5))
plt.subplot(1, 2, 1)
plt.plot(iterations, losses)
plt.xlabel('Iteration')
plt.ylabel('Average Loss')
plt.title('Training Loss Curve')

plt.subplot(1, 2, 2)
plt.plot(iterations, ious)
plt.xlabel('Iteration')
plt.ylabel('Region Avg IOU')
plt.title('Training Region Avg IOU Curve')

plt.tight_layout()
plt.show()

# 绘制 mAP 曲线 (如果解析到 mAP 数据)
if maps:
    map_iterations, map_values = zip(*maps)
    plt.figure(figsize=(6, 5))
    plt.plot(map_iterations, map_values)
    plt.xlabel('Iteration')
    plt.ylabel('mAP@0.50')
    plt.title('Validation mAP Curve')
    plt.show()

将上述脚本保存为 .py 文件,修改 log_file 路径并运行,即可看到训练过程的曲线图。

结论

通过本篇博客,你应该已经了解了 YOLOv4 在 Darknet 框架下的环境配置、数据集准备、模型训练、问题解决、超参数调优以及性能评估的全流程。从实际动手的角度出发,我们详细讲解了每一个步骤,并提供了相应的命令和代码示例。

YOLOv4 是一个强大的目标检测模型,掌握其训练过程是进行目标检测项目的基础。希望这篇博客能够帮助你成功地在自己的数据集上训练出高性能的 YOLOv4 模型。

记住,深度学习模型的训练是一个不断尝试和优化的过程。耐心、细致地检查每一步,并结合训练日志进行分析,你一定能取得好结果。

下一步:

  • 尝试在更大的数据集或更复杂的场景下训练 YOLOv4。
  • 探索 YOLOv4 的其他变种 (如 YOLOv4-tiny) 或更新的模型 (如 YOLOv5, YOLOv7, YOLOv8)。
  • 将训练好的模型部署到实际应用中 (如使用 Darknet 的 C++ API 或将其转换为其他框架格式如 ONNX)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值