赞
踩
1.解释参数
当修改yolov8的网络结构时基本都会遇到将新的模块导入tasks.py里的问题,就是加入判断分支elif m is 啥啥啥模块,基本都有c1、c2和args这3个参数。
以Conv所在的判断分支代码为例解释:
if m in (Classify, Conv, ConvTranspose, ..., C3x, RepC3): c1, c2 = ch[f], args[0] if c2 != nc: c2 = make_divisible(min(c2, max_channels) * width, 8) args = [c1, c2, *args[1:]]
yaml文件里backbone部分第一个Conv对应的参数:
- [-1, 1, Conv, [64, 3, 2]]
c1表示这个模块的输入通道数,经常看到的组合是c1=ch[f],其中ch[f]就是上个模块的输出通道数,因此c1=ch[f]的意思就是大家都熟知的将上个模块的输出通道数作为这个模块的输入通道数。
c2那就是这个模块的输出通道数喽,说c2之前要先弄懂args。
初始的args就是backbone部分每个模块里的第4个参数,在这里那可不就是args=[64, 3, 2]嘛,那c2=args[0]=64就显而易见了,由代码可见还要改变输出通道数c2的值,这就跟不同大小的模型n、s、m等联系起来了。
这里的width就是yaml文件里的width_multiple用于调节模型大小,函数make_divisible(x, 8)的作用就是找个一个能被8整除的最小的整数x,所以make_divisible(8, 8)=8,make_divisible(15, 8)=16,make_divisible(17, 8)=24。然后yaml文件里还可设置max_channels,用于限制通道数的。
当采用yolov8n模型时那c2=make_divisible(min(64, 1024) * 0.25, 8)=16了。
可以看到args最后也重新赋值了,由上解释可知args[1:]=[3, 2],前面加个*的作用就是去掉中括号[],那最终args=[3, 16, 3, 2],不加*就是args=[3, 16, [3, 2]],显然是要加*的,因为要将得到的参数args=[3, 16, 3, 2]传入conv.py里的Conv类,3、2分别表示卷积核的尺寸是3*3和步幅为2。
2.使用参数
conv.py里有yolov8自带的注意力机制CBAM,部分代码如下:
class CBAM(nn.Module): """Convolutional Block Attention Module.""" def __init__(self, c1, kernel_size=7): # ch_in, kernels
可以看到调用CBAM只需输入2个参数c1和kernel_size,输入通道c1是由上个模块的输出通道决定的,因此可设为c1=ch[f]。kernel_size是由用户自定义为7或3的,因此yaml文件如果这样写- [ -1, 1, CBAM, [kernel_size] ],kernel_size=3或7,那args=[ c1, *args[0:] ]或args=[ c1, args[0] ]都可行,完整代码即:
elif m is CBAM: c1 = ch[f] # args = [c1, *args[0:]] args = [c1, args[0]]
顺带介绍一种改法
别人论文上差不多是这么个改法(是7还是3不清楚,我的是3比7好)mAP50升了0.8%,我的就可怜的0.1%,悲催啊!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。