相关文章推荐
被表白的眼镜  ·  nltk - Python VADER ...·  1 年前    · 
憨厚的大熊猫  ·  使用 ShellExecute ...·  1 年前    · 

ultralytics的yolov3源码解读(Pytorch)-网络结构1

前言

最近看了yolo系列的论文,并想着着手自己实现一下,由于目前实现yolo1和2的意义不大,直接从yolo3开始即可;于是找到了ultralytics的代码,在阅读的过程中发现有很多的细节,于是写下来,记录一下自己学习的历程;由于本人只是一个入门小白,如有错误,欢迎大家纠正赐教。

首先是代码地址:

我clone时候的时间是2021/11/24,以下所有的代码也都基于此。

个人认为理解yolov3代码应该主要从三个大方面入手,然后考虑再其他的细节

  • 网络结构
  • 损失函数
  • 数据集的制作,加载读取

网络结构总览

网络上比较清晰明了的是这张图:

可以看出主要部分由DBL模块,ResUnit模块,resn模块,普通conv卷积构成。各个模块的构成图中也比较清晰,在此不再赘述。

粗略看一下

在ultralytics的代码中并没有直接写出,在代码中使用YAML文件来描述网络的结构(/models/yolov3.yaml),他的backbone描述如下

head描述如下

关于这些描述,简单的理解是每一行都是一个单独的模块,有四个变量from,number,module,args。这里先给出其粗略解释(后面会详细讲):

  • from:这个模块的输入数据从哪里来
  • number:这个模块有几个
  • module:这是一个什么样的模块
  • args:构建这个模块的参数

我们可以看出在yolov3中存在有Conv,Bottleneck,nn.Upsample, Contact,Detect,这几个模块。那么如何与我们最初的那张网络结构图对应起来呢?

细看一下

我们从源码中找一下这几个模块的定义(model/common.py)

Conv

首先这个Conv区别于nn.Conv

作者将普通卷积层,BN层和激活函数层集成起来形成了Conv模块,其参数不难理解;参数p决定了这个模块卷积时的填充方式,act则决定了是否调用激活函数,如果为True那么使用SiLU,如果为False则不做任何处理,当然这里可以传入一些其他的module,那么就使结果经过这个模块计算后再返回。这个模块即可对应头图的DBL模块。

Bottleneck

这一个模块我初见它是在ResNet中,被称为瓶颈层,常常被用到比较深层的网络当中。这一部分可以参考其他博主的文章。

回到代码当中,作者写的bottleneck是这样的

如果shortcut为True并且输入和输出的通道数相等则将输入和经过两层Conv的的输出拼接起来。对应了头图中的ResUnit也就是残差块。

nn.Upsample

pytorch原生的上采样层,不多赘述。对应头图中的上采样

Contact

这个模块比较简单,和nn.cat并无太大区别。阅读源码读者应该能轻松理解:

其他

在头图中的模块resn就是Conv+Bottleneck*N,这样我们将yolov3网络会用到的模块几个捋过一遍了, 还有一点是没有讲到的,在网络的最后一层是有三个普通卷积层来detect的,在源码中作者将这个三个集成为一个Detect层。

总结+预告

本篇总体透过YAML看了yolov3的网络结构,将其对应到了一张网络结构图上,以及查看了几个模块的实现。下一篇我会写最后的Detect层的实现,yolov3是怎么组合这几个模块,这个YAML文件是如何解析,from,args的详细解释。

发布于 2021-11-24 21:14

文章被以下专栏收录