YOLO-v3模型参数anchor设置

本文介绍了YOLO-v3模型中Anchor参数的重要性,解释了Anchor的本质,即SPP思想的逆向,并详细说明了如何根据训练数据计算自定义的Anchor。通过KMeans算法确定Anchor盒子,虽然结果可能因初始点选择而异,但不影响网络最终适应。此外,对比了YOLOv2和YOLOv3中Anchor大小的设定差异。
部署运行你感兴趣的模型镜像

1. 背景知识

在YOLO-v2版本中就引入了anchor box的概念,极大增加了目标检测的性能。但是在训练自己数据的时候还是用模型中原有的anchor设置显然是有点不合适的,那么就涉及到根据自己的训练数据来设置anchor。

那么,首先我们需要知道anchor的本质是什么,本质是SPP(spatial pyramid pooling)思想的逆向。而SPP本身是做什么的呢,就是将不同尺寸的输入resize成为相同尺寸的输出。所以SPP的逆向就是,将相同尺寸的输出,倒推得到不同尺寸的输入。

接下来是anchor的窗口尺寸,这个不难理解,三个面积尺寸( 12 8 2 , 25 6 2 , 51 2 2 128^2,256^2,512^2 128225625122),然后在每个面积尺寸下,取三种不同的长宽比例 ( 1 : 1 , 1 : 2 , 2 : 1 ) (1:1,1:2,2:1) 1:1,1:2,2:1.这样一来,我们得到了一共9种面积尺寸各异的anchor。示意图如下:
在这里插入图片描述
那么anchor在目标检测中是怎么使用的呢?那就先来看Faster R-CNN中的运用,下面是整个网络的结构图:
在这里插入图片描述
利用anchor是从第二列这个位置开始进行处理,这个时候,原始图片已经经过一系列卷积层和池化层以及relu,得到了这里的 feature:51x39x256(256是层数:H,W,C)在这个特征参数的基础上,通过一个3x3的滑动窗口,在这个51x39的区域上进行滑动,stride=1,padding=1,这样一来,滑动得到的就是51x39个3x3的窗口。对于每个3x3的窗口,作者就计算这个滑动窗口的中心点所对应的原始图片的中心点。然后作者假定,这个3x3窗口,是从原始图片上通过SPP池化得到的,而这个池化的区域的面积以及长宽比例,就是一个个的anchor。换句话说,对于每个3x3窗口,作者假定它来自9种不同原始区域的池化,但是这些池化在原始图片中的中心点,都完全一样。这个中心点,就是刚才提到的,3x3窗口中心点所对应的原始图片中的中心点。如此一来,在每个窗口位置,我们都可以根据9个不同长宽比例、不同面积的anchor,逆向推导出它所对应的原始图片中的一个区域,这个区域的尺寸以及坐标,都是已知的。而这个区域,就是我们想要的 proposal。所以我们通过滑动窗口和anchor,成功得到了 51x39x9 个原始图片的proposal。接下来,每个proposal我们只输出6个参数:每个 proposal 和 ground truth 进行比较得到的前景概率和背景概率(2个参数)(对应图上的 cls_score);由于每个 proposal 和 ground truth 位置及尺寸上的差异,从 proposal 通过平移放缩得到 ground truth 需要的4个平移放缩参数(对应图上的 bbox_pred)。

2. Anchor先验参数计算

这里计算训练数据的anchor先验直接使用的是转好的数据,即是已经转好的可直接训练的数据。这里使用的代码参考的是这个仓库kmeans-anchor-boxes。各位可以到仓库里面下载里面的KMeans文件就可以了,这里给出我使用的部分代码:

# -*- coding=utf-8 -*-
import glob
import os
import sys
import xml.etree.ElementTree as ET
import numpy as np
from kmeans import kmeans, avg_iou

# 根文件夹
ROOT_PATH = '/data/DataBase/YOLO_Data/V3_DATA/'
# 聚类的数目
CLUSTERS = 6
# 模型中图像的输入尺寸,默认是一样的
SIZE = 640

# 加载YOLO格式的标注数据
def load_dataset(path):
    jpegimages = os.path.join(path, 'JPEGImages')
    if not os.path.exists(jpegimages):
        print('no JPEGImages folders, program abort')
        sys.exit(0)
    labels_txt = os.path.join(path, 'labels')
    if not os.path.exists(labels_txt):
        print('no labels folders, program abort')
        sys.exit(0)

    label_file = os.listdir(labels_txt)
    print('label count: {}'.format(len(label_file)))
    dataset = []

    for label in label_file:
        with open(os.path.join(labels_txt, label), 'r') as f:
            txt_content = f.readlines()

        for line in txt_content:
            line_split = line.split(' ')
            roi_with = float(line_split[len(line_split)-2])
            roi_height = float(line_split[len(line_split)-1])
            if roi_with == 0 or roi_height == 0:
                continue
            dataset.append([roi_with, roi_height])
            # print([roi_with, roi_height])

    return np.array(dataset)

data = load_dataset(ROOT_PATH)
out = kmeans(data, k=CLUSTERS)

print(out)
print("Accuracy: {:.2f}%".format(avg_iou(data, out) * 100))
print("Boxes:\n {}-{}".format(out[:, 0] * SIZE, out[:, 1] * SIZE))

ratios = np.around(out[:, 0] / out[:, 1], decimals=2).tolist()
print("Ratios:\n {}".format(sorted(ratios)))

经过运行之后得到一组如下数据:

[[0.21203704 0.02708333]
 [0.34351852 0.09375   ]
 [0.35185185 0.06388889]
 [0.29513889 0.06597222]
 [0.24652778 0.06597222]
 [0.24861111 0.05347222]]
Accuracy: 89.58%
Boxes:
 [135.7037037  219.85185185 225.18518519 188.88888889 157.77777778
 159.11111111]-[17.33333333 60.         40.88888889 42.22222222 42.22222222 34.22222222]

其中的Boxes就是得到的anchor参数,以上面给出的计算结果为例,最后的anchor参数设置为

anchors = 135,17,  219,60,  225,40,  188,42,  157,42,  159,34

由于KMeans算法的结果对于初始点的选取敏感,因而每次运行的结果并不相同,只有Accuracy结果比较稳定点。至于那个anchor参数好,只有自己去尝试了。但是在使用的时候,没改过anchor经过一段时间的训练之后网络也能够适应,至于会不会对检测的精度有影响,暂时还没验证,-_-||。。。

为什么YOLOv2和YOLOv3的anchor大小有明显区别?
在YOLOv2中,作者用最后一层feature map的相对大小来定义anchor大小。也就是说,在YOLOv2中,最后一层feature map大小为13X13(不同输入尺寸的图像最后的feature map也不一样的),相对的anchor大小范围就在(0x0,13x13],如果一个anchor大小是9x9,那么其在原图上的实际大小是288x288。

而在YOLOv3中,作者又改用相对于原图的大小来定义anchor,anchor的大小为(0x0,input_w x input_h]。所以,在两份cfg文件中,anchor的大小有明显的区别。如下是作者自己的解释:

So YOLOv2 I made some design choice errors, I made the anchor box size be relative to the feature size in the last layer. Since the network was down-sampling by 32. This means it was relative to 32 pixels so an anchor of 9x9 was actually 288px x 288px.
In YOLOv3 anchor sizes are actual pixel values. this simplifies a lot of stuff and was only a little bit harder to implement
https://github.com/pjreddie/darknet/issues/555#issuecomment-376190325

3. 参考

  1. K-means 计算 anchor boxes

您可能感兴趣的与本文相关的镜像

Yolo-v5

Yolo-v5

Yolo

YOLO(You Only Look Once)是一种流行的物体检测和图像分割模型,由华盛顿大学的Joseph Redmon 和Ali Farhadi 开发。 YOLO 于2015 年推出,因其高速和高精度而广受欢迎

### YOLO-V3用于林业病虫害目标检测的实现方法 #### 数据集准备 YOLO-V3的目标检测任务依赖于高质量的数据集。根据已有描述,AI识虫数据集中提供了2183张图片,分为训练集、验证集和测试集[^2]。这些数据涵盖了7种不同的昆虫种类,分别为Boerner、Leconte、Linnaeus、acuminatus、armandi、coleoptera和linnaeus。为了顺利开展实验,需确保数据已解压并存储在`insects`目录下。 #### 基础概念理解 在实施YOLO-V3之前,了解一些基本的概念至关重要。边界框(Bounding Box)、锚框(Anchor Boxes)以及交并比(Intersection over Union, IoU)是目标检测中的核心要素[^1]。边界框定义了目标的位置和大小;锚框则是预先设定的一组参考框,帮助模型更高效地定位目标;IoU用来衡量预测框与真实框之间的重叠程度。 #### 模型架构解析 YOLO-V3是一种单阶段检测算法,它利用单一神经网络来同时生成候选区域并预测物体类别及其位置[^1]。具体而言,该模型通过Darknet-53作为骨干网络提取特征,并采用多尺度预测机制,在不同分辨率层面上捕捉目标信息。这种设计使得YOLO-V3能够有效识别各种尺寸的目标。 以下是基于PyTorch框架的一个简单代码示例,展示如何加载预训练权重并对自定义数据集进行微调: ```python import torch from torchvision import transforms from yolov3.models import Darknet from yolov3.utils.datasets import ListDataset from yolov3.utils.utils import non_max_suppression # 加载YOLOv3模型配置文件 config_path = 'yolov3.cfg' weights_path = 'yolov3.weights' model = Darknet(config_path) model.load_darknet_weights(weights_path) # 定义数据转换操作 transform = transforms.Compose([ transforms.Resize((416, 416)), transforms.ToTensor(), ]) # 创建ListDataset实例读取本地图片路径列表 train_dataset = ListDataset('path/to/train.txt', transform=transform) dataloader = torch.utils.data.DataLoader(train_dataset, batch_size=8, shuffle=True) # 微调过程省略... ``` #### 训练与评估流程 针对林业病虫害数据集的具体情况,可以按照以下方式调整超参数并执行训练: - 设置学习率初始值较低(如0.001),随着迭代次数增加逐步衰减; - 使用交叉熵损失函数结合L1平滑损失优化分类与回归部分的表现; - 验证过程中引入mAP指标评价模型性能优劣。 最后一步涉及部署环节,即将经过充分训练后的模型导出为可移植格式以便实际应用场景下的快速推理运算。
评论 79
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值