- 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
- 🍖 原作者:K同学啊 | 接辅导、项目定制
- 🚀 文章来源:K同学的学习圈子
环境配置:
Python-3.11.4 torch-2.0.1+cpu CPU
本周的任务主要是解读yolov5-master/models/yolov5s.yaml文件,在理解的前提下尝试修改该文件的相关参数,然后再修改common.py 与 yolo.py文件来改进网络的结构。
一、参数解读
# Parameters
nc: 80 # number of classes
depth_multiple: 0.33 # model depth multiple
width_multiple: 0.50 # layer channel multiple
1.nc: 80
这是分类任务中的类别数。在训练时,模型将被训练为能够正确分类到这80个类别中的一个。
2.depth_multiple: 0.33
这是模型深度的倍数。它用于控制模型的层数。具体来说,模型的实际深度将是原始深度乘以该倍数。较小的倍数会降低模型的深度,从而减少模型的复杂性。
3.width_multiple: 0.50
这是每个层的通道数的倍数。它用于控制模型的宽度,即每个层的特征图的通道数。较小的倍数会降低模型的宽度,从而减少模型的参数量和计算量。
这些参数可以根据具体任务和资源限制进行调整,以获得更好的性能和效率。
二、锚框(anchors)
锚框(anchors)是目标检测中的重要概念,它们用于在图像中生成候选框以识别目标。锚框的作用是通过定义不同形状和大小的框来捕捉图像中可能存在的目标的位置和尺寸。
下面是代码中提供的锚框及其作用:
yaml
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
anchors(锚框)是一组预定义的边界框,用于检测不同尺度的目标。这里提供了九组锚框的尺寸,分别用于在不同的特征层上检测目标。
这九个anchors在三个feature map中使用,每个feature map的,每个grid_cell都有三个anchor进行预测。分配规则为:
尺度越大的feature map越靠前,相对原图的下采样率越小,感受野越小。所以相对可以预测一些尺度比较小的物体。
尺度越小的feature map越靠后,相对原图的下采样率越大,感受野越大。所以相对可以预测一些尺度比较大的物体。
但并不能确保这三组anchor就适用于所有的数据集,YOLOv5还有anchors进化策略,使用聚类中的k-means和演化计算中的遗传算法(GA),找到与当前数据集最吻合的anchors。
遗传算法通过模拟自然界中生物的遗传进化过程,对优化问题的最优解进行搜索。其工作机理可分为一下几个步骤:
个体编码:将问题空间中的每个解表示为一个个体,通常使用二进制表示法。对于离散型问题,可以将个体表示为一个状态,例如在围棋游戏中,每个状态可以用一个数字表示。
群体的初始化:遗传算法在一个给定的初始进化群体中进行迭代搜索。一般情况下,遗传算法在群体初始化阶段采用的是随机数初始方法。采用生成随机数的方法,对染色体的每一维变量进行初始化赋值。
个体适应度函数:定义每个个体的适应度函数,用于评估个体的质量。适应度函数应该能够反映出问题本身的性质,例如在优化问题中,适应度函数可以是目标函数。
选择操作:根据适应度函数的大小,选择一部分优秀的个体作为下一代种群的基础。常用的选择操作包括锦标赛选择、竞争选择、轮盘赌选择等。
变异操作:对选出的个体进行变异操作,以增加种群的多样性。变异操作可以通过添加随机噪声、交换个体的某些基因等方式实现。
交叉操作:将选出的个体进行交叉操作,将它们的一些基因进行交换或组合,从而产生新的个体。交叉操作可以增加群体的多样性,避免过度拟合。
个体更新:将新生成的个体加入到种群中,并更新种群中个体的基因。更新后的个体会取代原来的个体,成为下一代种群的基础。
重复执行以上步骤,直到达到停止条件为止。遗传算法的工作机理类似于生物进化过程中的自然选择和遗传机制,通过不断迭代和优化来寻找最优解。
三、backbone
# YOLOv5 v6.0 backbone
backbone:
# [from, number, module, args]
[[-1, 1, Conv, [64, 6, 2, 2]], # 0-P1/2
[-1, 1, Conv, [128, 3, 2]], # 1-P2/4
[-1, 3, C3, [128]],
[-1, 1, Conv, [256, 3, 2]], # 3-P3/8
[-1, 6, C3, [256]],
[-1, 1, Conv, [512, 3, 2]], # 5-P4/16
[-1, 9, C3, [512]],
[-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
[-1, 3, C3, [1024]],
[-1, 1, SPPF, [1024, 5]], # 9
]
backbone部分定义了一系列的卷积层和模块,用于从输入图像中提取特征。
from:表示当前模块的输入来自那一层的输出,-1表示来自上—层的输出,层编号由0开始计数。
number:表示当前模块的理论重复次数,实际的重复次数还要由上面的参数 depth_multiple共同决定,该参数影响整体网络模型的深度。
module:模块类名,通过这个类名在common.py中寻找相应的类,进行模块化的搭建网络。
args:是一个list,模块搭建所需参数,channel , kernel_size , stride , padding , bias等。
[-1, 1, Conv, [64, 6, 2, 2]]:表示一个卷积层。-1表示使用默认值(上一层的输出)作为输入通道数,1表示输出通道数为64。Conv表示使用普通卷积操作,[64, 6, 2, 2]是卷积核的参数,分别为输出通道数、卷积核大小、步长和填充 。
[-1, 3, C3, [128]]:表示一个C3模块,C3模块是YOLOv5中定义的一种卷积结构。-1表示使用默认值(上一层的输出)作为输入通道数,3表示重复3次这个模块,C3表示使用C3模块,[128]是模块的参数,表示输出通道数为128。
四、head
# YOLOv5 v6.0 head
head:
[[-1, 1, Conv, [512, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
[[-1, 6], 1, Concat, [1]], # cat backbone P4
[-1, 3, C3, [512, False]], # 13
[-1, 1, Conv, [256, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
[[-1, 4], 1, Concat, [1]], # cat backbone P3
[-1, 3, C3, [256, False]], # 17 (P3/8-small)
[-1, 1, Conv, [256, 3, 2]],
[[-1, 14], 1, Concat, [1]], # cat head P4
[-1, 3, C3, [512, False]], # 20 (P4/16-medium)
[-1, 1, Conv, [512, 3, 2]],
[[-1, 10], 1, Concat, [1]], # cat head P5
[-1, 3, C3, [1024, False]], # 23 (P5/32-large)
[[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
]
五、修改backbone部分
backbone:
# [from, number, module, args]
[[-1, 1, Conv, [64, 6, 2, 2]], # 0-P1/2
[-1, 1, Conv, [128, 3, 2]], # 1-P2/4
[-1, 3, C3, [128]],
[-1, 1, Conv, [256, 3, 2]], # 3-P3/8
[-1, 3, C3, [256]],
[-1, 1, Conv, [512, 3, 2]], # 5-P4/16
[-1, 6, C3, [512]],
[-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
[-1, 3, C3, [1024]],
[-1, 1, SPPF, [1024, 5]], # 9
]