pytorch实现DarkNet53网络
DarkNet53网络结构
DarkNet53网络结构如下图所示,主要由两个基本单元组成,一个卷积单元
Convolutional,一个残差单元Residual
- Convolutional由一个卷积层一个BN层和一个leakRelu层组成
- Residual单元完成两次卷积,并进行加残差后返回相同维度的特征图
DarkNet53网络总共由52个卷积层,最后还有一个1x1的卷积层将前52层提取到的特征进行融合和输出
pytorch实现
Convolutional单元
一个Convolutional单元中由一个卷积层一个BN层和一个leakRelu层组成
class Convolutional(nn.Module):
def __init__(self, c_in, c_out, k, s, p, bias=False):
"""
自定义一个卷积块,实现卷积+归一化+激活
:param c_in: 输入通道数
:param c_out: 输出通道数
:param k: 卷积核尺寸
:param s: 卷积核的步距
:param p: padding
:param bias: 偏置,使用BN层时设置为False
"""
super(Convolutional, self).__init__()
self.conv = nn.Sequential(
nn.Conv2d(c_in, c_out, k, s, p, bias),
nn.BatchNorm2d(c_out),
nn.LeakyReLU(0.1),
)
def forward(self, x):
return self.conv(x)
Residual单元
一个Residual单元里有一个11的卷积层和一个33的卷积层,11的卷积层将输入通道数降低一半,再用33的卷积层将输入通道数升回到原来的通道数,在前向传播中,最终输出的既保留原始信息,又融入了提取到的特征
class ConvResidual(nn.Module):
def __init__(self, c_in):
"""
自定义残差单元,只需给出通道数,该单元完成两次卷积,并进行加残差后返回相同维度的特征图
:param c_in: 输入通道数
"""
c = c_in // 2
super(ConvResidual, self).__init__()
self.conv = nn.Sequential(
Convolutional(c_in, c, 1, 1, 0),
Convolutional(c, c_in, 3, 1, 1),
)
def forward(self, x):
return x + self.conv(x)
实现DarkNet53网络
实现了这两个基本单元,就可以按照上图的网络结构,搭建DarkNet53网络,
class Darknet53(nn.Module):
def __init__(self):
super(Darknet53, self).__init__()
self.conv1 = Convolutional(3, 32, 3, 1, 1)
self.conv2 = Convolutional(32, 64, 3, 2, 1)
self.conv3_4 = ConvResidual(64)
self.conv5 = Convolutional(64, 128, 3, 2, 1)
self.conv6_9 = nn.Sequential(
ConvResidual(128),
ConvResidual(128),
)
self.conv10 = Convolutional(128, 256, 3, 2, 1)
self.conv11_26 = nn.Sequential(
ConvResidual(256),
ConvResidual(256),
ConvResidual(256),
ConvResidual(256),
ConvResidual(256),
ConvResidual(256),
ConvResidual(256),
ConvResidual(256),
)
self.conv27 = Convolutional(256, 512, 3, 2, 1)
self.conv28_43 = nn.Sequential(
ConvResidual(512),
ConvResidual(512),
ConvResidual(512),
ConvResidual(512),
ConvResidual(512),
ConvResidual(512),
ConvResidual(512),
ConvResidual(512),
)
self.conv44 = Convolutional(512, 1024, 3, 2, 1)
self.conv45_52 = nn.Sequential(
ConvResidual(1024),
ConvResidual(1024),
ConvResidual(1024),
ConvResidual(1024),
)
def forward(self, x):
conv1 = self.conv1(x)
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