YOLOv5之Focus与6×6卷积的理解

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

前言

最近正在学习 yolov5算法,以 yolov5s模型为例,其中的 focus模块在被改成了一个 kernel_size=6的卷积层,为什么较大的卷积核进行卷积比 focus模块更有效呢?

一、Foucs

1.Focus简介

Foucs模块使将原本的 feature map按下图方式分成四份,再 concat到一起进行一次卷积.

YOLOv5之Focus与6x6卷积的理解
这里是 Focus模块的源码:
class Focus(nn.Module):

    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True):

        super().__init__()
        self.conv = Conv(c1 * 4, c2, k, s, p, g, act)
def forward(self, x):
        return self.conv(torch.cat([x[..., ::2, ::2], x[..., 1::2, ::2],
                            x[..., ::2, 1::2], x[..., 1::2, 1::2]], 1))

为了理解 torch.cat()中拼接部分具体操作,我们需要自己做个小实验验证一下:

import torch
import numpy as np
import torch.nn as nn

a = torch.tensor([[[[0,1],[2,3]],
                [[0,1],[2,3]],
                [[0,1],[2,3]],
                ]])

print(a.size())
print(a[...].size())
print(a[...,:2,:2].size())
print(a[...,::2,::2].size())
print(a[...,::2,::2].size(), '\n', a[...,::2,::2])
print(a[...,1::2,::2].size(), '\n', a[...,1::2,::2])
print(a[...,::2,1::2].size(), '\n', a[...,::2,1::2])
print(a[...,1::2,1::2].size(), '\n', a[...,1::2,1::2])
b = torch.cat([a[...,::2,::2], a[...,1::2,::2]
                ,a[...,::2,1::2], a[...,1::2,1::2]],1)
print(b.size())
print(b)

a.shape[1, 3, 2, 2]变至 [1, 12, 1, 1],通道数增大四倍,w与h缩小两倍.
a[...,::2,::2] 取左上角
a[...,1::2,::2]取左下角
a[...,::2,1::2]取右上角
a[...,1::2,1::2]取右下角
再通过 torch.cat()其在第二个维度上堆叠起来,在对其进行 kernel_size=3,stride=1卷积特征提取.

2.对Focus的疑问

github上有人问过 focus对mAP的影响,原作者是这么回答的

YOLOv5之Focus与6x6卷积的理解
大意是 Foucs()模块是为了减少了 FLOPs并增加计算速度设计的,并不会增加 mAP;另一方面1个 foucs模块代替了 3个yolov3/4层.

我们来计算一下 focus的参数量与计算量(忽略 bias)
F L O P s = ( 3 ∗ 4 ) ∗ 32 ∗ 3 ∗ 3 ∗ 320 ∗ 320 = 353894400 FLOPs = (34)3233320320=353894400 F L OP s =(3 ∗4 )∗32 ∗3 ∗3 ∗320 ∗320 =353894400
P a r a m = 3 ∗ 4 ∗ 32 ∗ 3 ∗ 3 = 3456 Param =343233=3456 P a r am =3 ∗4 ∗32 ∗3 ∗3 =3456
再来计算一下卷积层的参数量与计算量(忽略 bias)
F L O P s = 3 ∗ 32 ∗ 3 ∗ 3 ∗ 320 ∗ 320 = 88473600 FLOPs = 33233320320=88473600 F L OP s =3 ∗32 ∗3 ∗3 ∗320 ∗320 =88473600
P a r a m = 3 ∗ 32 ∗ 3 ∗ 3 = 864 Param =3
3233=864 P a r am =3 ∗32 ∗3 ∗3 =864
一个 Focus的参数量与计算量大约是 conv的4倍,但一个focus结构可以替换3个conv层,所以参数量与计算量都是减少的.

再来计算一下 k=6卷积层的参数量与计算量(忽略 bias)
F L O P s = 3 ∗ 32 ∗ 6 ∗ 6 ∗ 320 ∗ 320 = 35389440 FLOPs = 33266320320=35389440 F L OP s =3 ∗32 ∗6 ∗6 ∗320 ∗320 =35389440
P a r a m = 3 ∗ 32 ∗ 6 ∗ 6 = 3456 Param =3
3266=3456 P a r am =3 ∗32 ∗6 ∗6 =3456
所以 k=6卷积层在理论上等价于 focus结构
那么 focus虽然降低了计算成本,但是其采样方式会不会破坏图片的空间信息或者混淆GT框的边界坐标呢?

YOLOv5之Focus与6x6卷积的理解
将空间信息堆叠到通道空间中,可能会减少一个像素的回归信息价值,但对于大多数实例而言回归精度都不会接近一个像素,因此 focus的采样方式并对回归精度产生影响极小.另外focus结构的位置问题,在分类网络中放在后面可能会更有用,但是在目标检测模型中对 mAP@0.5:0.95的影响更大, mAP@0.5影响较小.

对于focus的采样方式是否会破坏原有图像的空间信息,我们只要将focus的采样的4个模块输出来看一看即可.

import cv2
import numpy as np
img = cv2.imread(r'C:/Users/HP/Desktop/p.jpg')

new_img = cv2.resize(img, (320, 320))
cv2.imwrite(r'./0.jpg',new_img)
img = img.transpose(2,1,0)
img = np.expand_dims(img, 0)
print(img.shape)

new_img = img[...,::2,::2]
print(new_img.shape)
new_img = new_img[0]
print('shape',new_img.shape)
new_img = new_img.transpose(2,1,0)
cv2.imwrite(r'./1.jpg',new_img)
new_img = img[...,1::2,::2]
print(new_img.shape)
new_img = new_img[0]
new_img = new_img.transpose(2,1,0)
cv2.imwrite(r'./2.jpg',new_img)
new_img = img[...,::2,::2]
print(new_img.shape)
new_img = new_img[0]
new_img = new_img.transpose(2,1,0)
cv2.imwrite(r'./3.jpg',new_img)
new_img = img[...,1::2,1::2]
print(new_img.shape)
new_img = new_img[0]
new_img = new_img.transpose(2,1,0)
cv2.imwrite(r'./4.jpg',new_img)
img1 = cv2.imread(r'./1.jpg')
img2 = cv2.imread(r'./2.jpg')
img3 = cv2.imread(r'./3.jpg')
img4 = cv2.imread(r'./4.jpg')
h = np.hstack((img1, img2, img3, img4))
cv2.imwrite(r'./5.jpg',h)

原图 3x640x640:

YOLOv5之Focus与6x6卷积的理解
YOLOv5之Focus与6x6卷积的理解
通过两幅图片对比得知,经过 focus下采样得到的特征图并不会丢失特征信息,对语义的影响并不大,且下采样后的每一个像素点的感受野都增大了,与卷积层的下采样方式一样,没有丢失原图的信息.

二.Focus为何又被替换成卷积层

yolov5后期将focus结构又替换成了 k=6的卷积层,我猜想可能是因为这样的方式来代替 3个conv层的原因是在提高了运算速度前提下,运用较大的卷积核增大了感受野,在性能方面可能会获得了一定的提升.

另一方面,考虑到focus的切片处理,与卷积相比,多出了几次运算 concat操作,可能会增加一定的内存开销.

三.Focus是否可以作为一种数据增强的处理方式

Focus可以被看作一种下采样方式,与 transforms.Resize相比哪种方式的效果更好,或是可以在调整图片大小时将两种方式混用,在以后的实验中可以一试.

————————————————————————————————————————————————————————

2022.6.26
更正一下 focus的感受野,与 6x6conv感受野大小相同,并不是 kener_size设为6会增大感受野

YOLOv5之Focus与6x6卷积的理解

Original: https://blog.csdn.net/xiahan_qian/article/details/125086079
Author: 月光下的小白兔
Title: YOLOv5之Focus与6×6卷积的理解

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/706509/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球