序言

v5出来这么久,一直搜不到网上对Focus的理解,还想着白嫖一下结论,但是发现搜出来的都是一知半解,讲的全都是Focus做了什么,愣是没说为什么要这么做。没办法只好自己花点时间深入学习一下,本人也记录一下本人对Focus模块的一些理解,如果有理解错误的地方,还请评论区告知。

一、Focus模块的原理

Focus模块在v5中是图片进入backbone前,对图片进行切片操作,具体操作是在一张图片中每隔一个像素拿到一个值,类似于邻近下采样,这样就拿到了四张图片,四张图片互补,长的差不多,但是没有信息丢失,这样一来,将W、H信息就集中到了通道空间,输入通道扩充了4倍,即拼接起来的图片相对于原先的RGB三通道模式变成了12个通道,最后将得到的新图片再经过卷积操作,最终得到了没有信息丢失情况下的二倍下采样特征图。

以yolov5s为例,原始的640 × 640 × 3的图像输入Focus结构,采用切片操作,先变成320 × 320 × 12的特征图,再经过一次卷积操作,最终变成320 × 320 × 32的特征图。切片操作如下:

具体代码实现:

class Focus(nn.Module):# Focus wh information into c-spacedef __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True):  # ch_in, ch_out, kernel, stride, padding, groupssuper(Focus, self).__init__()self.conv = Conv(c1 * 4, c2, k, s, p, g, act)      # 这里输入通道变成了4倍def forward(self, x):  # x(b,c,w,h) -> y(b,4c,w/2,h/2)return self.conv(torch.cat([x[..., ::2, ::2], x[..., 1::2, ::2], x[..., ::2, 1::2], x[..., 1::2, 1::2]], 1))

二、Focus的作用

在讨论Focus的作用之前,先了解两个概念:

参数数量(params):关系到模型大小,单位通常是M,通常参数用float32表示,所以模型大小是参数数量的4倍。

计算量(FLOPs):即浮点运算数,可以用来衡量算法/模型的复杂度,这关系到算法速度,大模型的单位通常为G,小模型单位通常为M;通常只考虑乘加操作的数量,而且只考虑Conv和FC等参数层的计算量,忽略BN和PReLU等,一般情况下,Conv和FC层也会忽略仅纯加操作的计算量,如bias偏置加和shoutcut残差加等,目前技术有BN和CNN可以不加bias。

params计算公式

Kh × Kw × Cin × Cout

FLOPs计算公式

Kh × Kw × Cin × Cout × H × W = 即(当前层filter × 输出的feature map)= params × H × W

总所周知,图片在经过Focus模块后,最直观的是起到了下采样的作用,但是和常用的卷积下采样有些不一样,可以对Focus的计算量和普通卷积的下采样计算量进行做个对比:

在yolov5s的网络结构中,可以看到,Focus模块的卷积核是3 × 3,输出通道是32:

那么做个对比:

普通下采样:即将一张640 × 640 × 3的图片输入3 × 3的卷积中,步长为2,输出通道32,下采样后得到320 × 320 × 32的特征图,那么普通卷积下采样理论的计算量为:

FLOPs(conv) = 3 × 3 × 3 × 32 × 320 × 320 = 88473600(不考虑bias情况下)
params参数量(conv) = 3 × 3 × 3 × 32 +32 +32 = 928 (后面两个32分别为bias和BN层参数)

Focus:将640 × 640 × 3的图像输入Focus结构,采用切片操作,先变成320 × 320 × 12的特征图,再经过3 × 3的卷积操作,输出通道32,最终变成320 × 320 × 32的特征图,那么Focus理论的计算量为:

FLOPs(Focus) = 3 × 3 × 12 × 32 × 320 × 320 = 353894400(不考虑bias情况下)
params参数量(Focus)= 3 × 3 × 12 × 32 +32 +32 =3520 (为了呼应上图输出的参数量,将后面两个32分别为bias和BN层的参数考虑进去,通常这两个占比比较小可以忽略)

可以明显的看到,Focus的计算量和参数量要比普通卷积要多一些,是普通卷积的4倍,但是下采样时没有信息的丢失。(结论已修改,请看后续更新)

综上所述,其实就可以得出结论,Focus的作用无非是使图片在下采样的过程中,不带来信息丢失的情况下,将W、H的信息集中到通道上,再使用3 × 3的卷积对其进行特征提取,使得特征提取得更加的充分。虽然增加了一点点的计算量,但是为后续的特征提取保留了更完整的图片下采样信息。


2021-07-01更新:作者有在issues中提到Focus是为了提速,和mAP无关,但是也没有说是什么原理,我也是一知半解,本文也仅从计算量和参数量去分析该模块,如果有看懂作者这样作法的同学望评论区告知。

2021-08-16更新:作者终于在issues上做了具体的解答,和之前分析的思路一样,都是从计算量参数量出发,不同的是,在作者解答之前我们并不知道作者改进的出发点是什么,也就是不清楚他在何结构上进行的改进,文中我理解为只是对一层普通下采样卷积做的改进,实际上有三层,所以经过改进后参数量其实还是变少了的,也确实达到了提速的效果,具体内容可以结合本文分析过程和作者给的issues结合起来看。

最后

千呼万唤始出来的结论,终于解开了我这么长时间的疑惑,虽然之前文中的结论和作者实际的结论是相反的;主要原因还是因为不知道作者改进的出发点在哪里,所以分析过程虽然是对的,但是结论却是反着了;知道了改进的出发点后,再把过程重新梳理一下,就很好理解了。最后也感谢大家的讨论

yolov5中的Focus模块的理解相关推荐

  1. 关于Autosar中的NM模块的理解

    关于Autosar中的NM模块的理解 本篇文章主要介绍AutoSar中关于NM模块的理解. 阅读本篇文章希望达到的目的: 1. NM(网络管理)是用来做什么的: 2. AutoSar中网络管理的原理: ...

  2. python threading模块的方法_Python THREADING模块中的JOIN()方法深入理解

    看了oschina上的两个代码,受益匪浅.其中对join()方法不理解,看python官网文档的介绍: join([timeout]):等待直到进程结束.这将阻塞正在调用的线程,直到被调用join() ...

  3. spring(7)---深入理解Spring核心技术——Spring中的各模块详解

    深入理解Spring核心技术--Spring中的各模块详解 Spring框架的两个基本概念IOC容器和AOP,相信大家现在对Spring中的这两个部分的基本概念有了一定的认识,好了,那么今天我们就来正 ...

  4. 深入理解python中的select模块

    简介 Python中的select模块专注于I/O多路复用,提供了select poll epoll三个方法(其中后两个在Linux中可用,windows仅支持select),另外也提供了kqueue ...

  5. python select模块_深入理解python中的select模块

    简介 Python中的select模块专注于I/O多路复用,提供了select  poll  epoll三个方法(其中后两个在Linux中可用,windows仅支持select),另外也提供了kque ...

  6. YOLOv5 网络组件与激活函数 代码理解笔记

    前言 最近在看YOLOv5 第6个版本的代码,记录了一下笔记,分享一下.首先看了网络结构.网络组件,对应代码models\common.py.然后看了激活函数,对应代码utils\activation ...

  7. Focus模块代码解析

    Focus模块代码解析 这就是Focus结构想干的事情.把一个特征图:W * H * C 变到 W/2 * H/2 * C*4.取像素点的过程就是隔一个格子取一个点(横竖都间隔一个). 在YOLOv5 ...

  8. 详解YOLOv5中的Bottleneck

    深度学习入门小菜鸟,希望像做笔记记录自己学的东西,也希望能帮助到同样入门的人,更希望大佬们帮忙纠错啦~侵权立删. 目录 一.背景知识 -- 残差结构 二.Bottleneck和building blo ...

  9. 深度神经网络中的Inception模块介绍

    深度神经网络(Deep Neural Networks, DNN)或深度卷积网络中的Inception模块是由Google的Christian Szegedy等人提出,包括Inception-v1.I ...

最新文章

  1. python3.6.0安装教程-CentOS7安装Python3.6
  2. TCP/IP 某些最常见的错误原因码 (errno)列表
  3. 设计一个算法找一条从迷宫入口到出口的最短路径。_我花了一夜用数据结构给女朋友写个H5走迷宫游戏...
  4. 如何在ASP.NET Core中使用SignalR构建与Angular通信的实时通信应用程序
  5. Spring Security用户认证和权限控制(默认实现)
  6. 大数据_Hbase_面试题0001
  7. 【绝迹篇】RSA加密算法(私钥加签公钥验签)
  8. 最新python中文手册_python中文手册下载
  9. 如何使用CANape实现XCP/CCP“Measurement测量”和“Calibration标定”变量
  10. navicat 软件查询mysql表,限制显示条数
  11. 打通C到B,“能者多劳”的小冰
  12. 基于频域的数字图像水印算法设计
  13. 学生如何提高专业英文阅读能力(转自施一公博客)
  14. 共享网络隐藏计算机,把电脑变成无线路由器,wifi共享大师隐藏ssid-
  15. 女生做软件测试工作怎么样?
  16. 我的世界电脑版服务器区块怎么显示,我的世界区块显示指令 | 手游网游页游攻略大全...
  17. 实现radio单选框单击取消选中状态
  18. 小程序开发报错 使用wx.reLaunch跳转报错 Expected updated data but get first rendering data如何解决 ???
  19. bga封装扇出过孔_手把手教你BGA元器件如何扇出?-EDA/PCB-与非网
  20. Java GPS 经纬度 相关操作

热门文章

  1. 2021最新版JAVA开发面试那些事儿~(结尾有字节、华为面试内容)
  2. 关于等号数量判断的问题
  3. 码蹄集 - MT2140 - 双端队列
  4. 机器人餐厅 机器人包饺子卖技又卖萌
  5. 【Python】python | 升级pip | pycharm升级pip
  6. Amandroid安装与使用
  7. 世界上第一台电子计算机ENIAC诞辰60周年--(1946.2.15-2006.2.15)
  8. 软件测试人员棘手的问题,软件测试的棘手问题:如何避免重复提交缺陷
  9. 思科服务器连接无线打印机,介绍思科模拟器网络打印机怎样操作安装
  10. 写一份制作核反应堆的计划书