(一)YOLO目标识别模型 ——Darknet53网络结构

(一)YOLO目标识别模型
——Darknet53网络结构

参考

本文链接: https://blog.csdn.net/leiduifan6944/article/details/104857968


文章目录

  • 参考
  • 前言
  • 一、YOLO的主要骨架
  • 二、介绍
    • 1.创建卷积块
    • 2.创建残差单元
    • 2.按照上面结构图写出Darknet53网络结构
  • 总结


前言

YOLO算法的出现,将回归思想引入目标识别处理过程,最终直接输出物体的位置、置信度和类别信息。YOLOv3在结构中模块与模块的衔接采用张量拼接,不同于残差层的add操作。

YOLO的主要骨架采用53个卷积层的Darknet53网络结构。

使用残差(Residual)神经网络的必要性:网络越深,梯度消失的现象就越来越明显,网络的训练效果也不会很好。残差神经网络就是为了在加深网络的情况下又解决梯度消失的问题。残差结构可以不通过卷积,直接从前面一个特征层映射到后面的特征层(跳跃连接),有助于训练,也有助于特征的提取,容易优化。
原文链接:https://blog.csdn.net/weixin_39615182/article/details/109752498


一、YOLO的主要骨架

如图所示为YOLO的主要骨架,即Darknet53网络结构
(一)YOLO目标识别模型 ——Darknet53网络结构_第1张图片

二、介绍

1.创建卷积块

创建卷积类,一次性完成卷积+归一化+激活。

class Conv(nn.Module):
	def __init__(self, c_in, c_out, k, s, p, bias=True):
		"""
		自定义一个卷积块,一次性完成卷积+归一化+激活,这在类似于像DarkNet53这样的深层网络编码上可以节省很多代码
		:param c_in: in_channels
		:param c_out: out_channels
		:param k: kernel_size
		:param s:  stride
		:param p: padding
		:param bias:"""
		super(Conv, self).__init__()
		self.conv = nn.Sequential(
			nn.Conv2d(c_in, c_out, k, s, p),
			nn.BatchNorm2d(c_out),
			nn.LeakyReLU(0.1),
		)

	def forward(self, entry):
		return self.conv(entry)

我们可以看出整个结构中没有使用池化层和全连接层,张量尺度变化是通过改变卷积核的步长(stride)完成,步长表达式为stride=(x,y),其中x表示卷积核的水平滑动步长,y表示卷积核的垂直滑动步长。
其中o为输出特征图的宽度或高度;
其中i为输入特征图的宽度或高度;
其中p为输入特征图的填充大小;
其中k为输入特征图的卷积核的宽度或高度;
若stride=(2,2),即特征图以两倍速度缩小。经历5次缩小后,特征面积缩小为原来的1/2^5,即输入尺寸为x=416x416,输出尺寸就会变为y=13x13;
在这里插入图片描述

2.创建残差单元

代码如下(示例):

class ConvResidual(nn.Module):
	def __init__(self, c_in):		# converlution * 2 + residual
		"""
		自定义残差单元,只需给出通道数,该单元完成两次卷积,并进行加残差后返回相同维度的特征图
		:param c_in: 通道数
		"""
		c = c_in // 2
		super(ConvResidual, self).__init__()
		self.conv = nn.Sequential(
			Conv(c_in, c, 1, 1, 0),		 # kernel_size = 1进行降通道
			Conv(c, c_in, 3, 1, 1),		 # 再用kernel_size = 3把通道升回去
		)

	def forward(self, entry):
		return entry + self.conv(entry)	 # 加残差,既保留原始信息,又融入了提取到的特征
# 采用 1*1 + 3*3 的形式加深网络深度,加强特征抽象

我们可以看出,残差单元并没有改变特征图的通道数和尺寸,只是加强了特征抽象。


2.按照上面结构图写出Darknet53网络结构

代码如下(示例):

class Darknet53(nn.Module):
	def __init__(self):
		super(Darknet53, self).__init__()
		self.conv1 = Conv(3, 32, 3, 1, 1)			# 一个卷积块 = 1层卷积
		self.conv2 = Conv(32, 64, 3, 2, 1)
		self.conv3_4 = ConvResidual(64)				# 一个残差块 = 2层卷积
		self.conv5 = Conv(64, 128, 3, 2, 1)
		self.conv6_9 = nn.Sequential(				# = 4层卷积
			ConvResidual(128),
			ConvResidual(128),
		)
		self.conv10 = Conv(128, 256, 3, 2, 1)
		self.conv11_26 = nn.Sequential(				# = 16层卷积
			ConvResidual(256),
			ConvResidual(256),
			ConvResidual(256),
			ConvResidual(256),
			ConvResidual(256),
			ConvResidual(256),
			ConvResidual(256),
			ConvResidual(256),
		)
		self.conv27 = Conv(256, 512, 3, 2, 1)
		self.conv28_43 = nn.Sequential(				# = 16层卷积
			ConvResidual(512),
			ConvResidual(512),
			ConvResidual(512),
			ConvResidual(512),
			ConvResidual(512),
			ConvResidual(512),
			ConvResidual(512),
			ConvResidual(512),
		)
		self.conv44 = Conv(512, 1024, 3, 2, 1)
		self.conv45_52 = nn.Sequential(				# = 8层卷积
			ConvResidual(1024),
			ConvResidual(1024),
			ConvResidual(1024),
			ConvResidual(1024),
		)

	def forward(self, entry):
		conv1 = self.conv1(entry)
		conv2 = self.conv2(conv1)
		conv3_4 = self.conv3_4(conv2)
		conv5 = self.conv5(conv3_4)
		conv6_9 = self.conv6_9(conv5)
		conv10 = self.conv10(conv6_9)
		conv11_26 = self.conv11_26(conv10)
		conv27 = self.conv27(conv11_26)
		conv28_43 = self.conv28_43(conv27)
		conv44 = self.conv44(conv28_43)
		conv45_52 = self.conv45_52(conv44)
		return conv45_52, conv28_43, conv11_26		# YOLOv3用,所以输出了3次特征

YOLO通过53个卷积层的网络结构Darknet53进行特征提取,得出特征图。


总结

我们知道,当我们将一张图片传进yolo,yolo会将其转化为416×416大小的网格,增加灰度条用于防止失真,之后图片会分成三个网格图片(13×13,26×26,52×52)

yolov3提取多特征层进行目标检测,一共提取三个特征层,三个特征层位于主干特征提取网络darknet53的不同位置,分别位于中间层,中下层,底层,三个特征层的shape分别为(52,52,256)、(26,26,512)、(13,13,1024),这三个特征层后面用于与上采样后的其他特征层堆叠拼接(Concat)。

你可能感兴趣的:(笔记,深度学习,pytorch,神经网络)