一、课题背景和开发环境
📌第Y3周:yolov5s.yaml文件解读📌
- 语言:Python3、Pytorch
- 📌本周任务:将yolov5s网络模型中第4层的
C3*2
修改为C3*1
,第6层的C3*3
修改我C3*2
。 - 💫任务提示:仅需修改
./models/yolov5s.yaml
文件
YOLOv5配置了4种不同大小的网络模型,分别是YOLOv5s
、YOLOv5m
、YOLOv5l
、YOLOv5x
,其中YOLOv5s
是网络深度和宽度最小但检测速度最快的模型,其他3中模型都是在YOLOv5s
的基础上不断加深、加宽网络使得网络规模扩大,在增强模型检测性能的同时增加了计算资源和速度消耗。出于对检测精度、模型大小、检测速度的综合考量,本文选择YOLOv5s
作为研究对象进行介绍。
./models/yolov5s.yaml
文件是YOLOv5s
网络结构的定义文件,如果你想改进算法的网络结构,需先修改该文件中的相关参数,然后再修改./models/common.py
与./models/yolo.py
中的相关代码。
开发环境
- 电脑系统:Windows 10
- 语言环境:Python 3.8.2
- 编译器:无(直接在cmd.exe内运行)
- 深度学习环境:Pytorch 1.8.1+cu111
- 显卡及显存:NVIDIA GeForce GTX 1660 Ti 12G
- CUDA版本:Release 10.2, V10.2.89(
cmd
输入nvcc -V
或nvcc --version
指令可查看) - YOLOv5开源地址:YOLOv5开源地址
- 数据:🔗水果检测
二、参数配置
# Parameters
nc: 80 # number of classes
depth_multiple: 0.33 # model depth multiple 控制模型深度
width_multiple: 0.50 # layer channel multiple 控制COnv通道channel个数(卷积核数量)
- depth_multiple:控制子模块数量,
= int(number*depth)
,该参数与任务有关- width_multiple:控制卷积核的数量,
= int(number*width)
通过这两个参数可以实现不同复杂度的模型设计。YOLOv5s
、YOLOv5m
、YOLOv5l
、YOLOv5x
这四个模型的区别仅在于depth_multiple
与width_multiple
这两个参数不同。
三、anchors配置
anchors:
- [10,13, 16,30, 33,23] # P3/8 ,检测小目标,每两个尺寸参数一组,共三组
- [30,61, 62,45, 59,119] # P4/16,检测中目标,共三组
- [116,90, 156,198, 373,326] # P5/32,检测大目标,共三组
小 目标
3
组:[10, 13], [16, 30], [33, 23]
中 目标3
组:[30, 61], [62, 45], [59,119]
大 目标3
组:[116,90], [156,198], [373,326]
YOLOv5初始化了9个anchor,在3个Detect层(3个feature map)中使用,每个feature map的每个grid_cell都有3个anchor进行预测。分配规则是:尺度越大的feature map越靠前,相对原图的下采样率越小,感受野越小,则相对可以预测一些尺度比较小的物体,所有分配到定anchor越小;尺度越小的feature map越靠后,相对原图的下采样率越大,感受野越大,则相对可以预测一些尺寸比较大的物体,所有分配到的anchor也越大。即可以在小特征图(feature map)上检测大目标,也可以在大特征图上检测小目标。
YOLOv5根据工程经验得到了这么3组anchors(9对尺寸参数),对于很多数据集而言已经很合适了。但也不能保证这3组anchor就适用于所有数据集,所以YOLOv5还有一个anchor进化的策略:使用k-means
和遗传进化算法,找到与当前数据集最吻合的anchors。
k-means:对当前数据集中所有的标注信息中的目标框的尺寸做聚类,输出9对anchors的值。下面是我找到的一段聚类输出anchors的代码。
yolo_kmeans.py
import numpy as np
def wh_iou(wh1, wh2):
# Returns the nxm IoU matrix. wh1 is nx2, wh2 is mx2
wh1 = wh1[:, None] # [N,1,2]
wh2 = wh2[None] # [1,M,2]
inter = np.minimum(wh1, wh2).prod(2) # [N,M]
return inter / (wh1.prod(2) + wh2.prod(2) - inter) # iou = inter / (area1 + area2 - inter)
def k_means(boxes, k, dist=np.median):
"""
yolo k-means methods
refer: https://github.com/qqwweee/keras-yolo3/blob/master/kmeans.py
Args:
boxes: 需要聚类的bboxes
k: 簇数(聚成几类)
dist: 更新簇坐标的方法(默认使用中位数,比均值效果略好)
"""
box_number = boxes.shape[0]
last_nearest = np.zeros((box_number,))
# 在所有的bboxes中随机挑选k个作为簇的中心。
clusters