0


CV 经典主干网络 (Backbone) 系列: CSP-Darknet53

CSP-Darknet53

0. 引言

CSP-Darknet53无论是其作为CV Backbone,还是说它在别的数据集上取得极好的效果。与此同时,它与别的网络的适配能力极强。这些特点都在宣告:CSP-Darknet53的重要性。
关于原理部分的内容请查看这里CV 经典主干网络 (Backbone) 系列: CSPNet

1. 网络结构图

具体网络结构可以参考YOLO V3详解(一):网络结构介绍中使用的工具来进行操作。具体网址和对应的权重文件下载地址如下:
模型可视化工具:https://lutzroeder.github.io/netron/
cfg文件下载网址:https://github.com/WongKinYiu/CrossStagePartialNetworks

得到的部分网络结构图的如下所示。

1.1 输入部分

在这里插入图片描述

1.2 CSP部分结构

在这里插入图片描述

1.3 输出部分

在这里插入图片描述

2. 代码实现

2.1 代码整体实现

通过代码实现CSP-Darknet53。框架为PyTorch,代码整体框架实现如下所示:

  1. classCsDarkNet53(nn.Module):def__init__(self, num_classes):super(CsDarkNet53, self).__init__()
  2. input_channels =32# Network
  3. self.stage1 = Conv2dBatchLeaky(3, input_channels,3,1, activation='mish')
  4. self.stage2 = Stage2(input_channels)
  5. self.stage3 = Stage3(4*input_channels)
  6. self.stage4 = Stage(4*input_channels,8)
  7. self.stage5 = Stage(8*input_channels,8)
  8. self.stage6 = Stage(16*input_channels,4)
  9. self.conv = Conv2dBatchLeaky(32*input_channels,32*input_channels,1,1, activation='mish')
  10. self.avgpool = nn.AdaptiveAvgPool2d((1,1))
  11. self.fc = nn.Linear(1024, num_classes)for m in self.modules():ifisinstance(m, nn.Conv2d):
  12. nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')elifisinstance(m,(nn.BatchNorm2d, nn.GroupNorm)):
  13. nn.init.constant_(m.weight,1)
  14. nn.init.constant_(m.bias,0)defforward(self, x):
  15. stage1 = self.stage1(x)
  16. stage2 = self.stage2(stage1)
  17. stage3 = self.stage3(stage2)
  18. stage4 = self.stage4(stage3)
  19. stage5 = self.stage5(stage4)
  20. stage6 = self.stage6(stage5)
  21. conv = self.conv(stage6)
  22. x = self.avgpool(conv)
  23. x = x.view(-1,1024)
  24. x = self.fc(x)return x

2.2 代码各个阶段实现

在代码中,对各个阶段的具体实现如下所示:

  1. classMish(nn.Module):def__init__(self):super(Mish, self).__init__()defforward(self, x):return x * torch.tanh(F.softplus(x))classConv2dBatchLeaky(nn.Module):"""
  2. This convenience layer groups a 2D convolution, a batchnorm and a leaky ReLU.
  3. """def__init__(self, in_channels, out_channels, kernel_size, stride, activation='leaky', leaky_slope=0.1):super(Conv2dBatchLeaky, self).__init__()# Parameters
  4. self.in_channels = in_channels
  5. self.out_channels = out_channels
  6. self.kernel_size = kernel_size
  7. self.stride = stride
  8. ifisinstance(kernel_size,(list,tuple)):
  9. self.padding =[int(k/2)for k in kernel_size]else:
  10. self.padding =int(kernel_size/2)
  11. self.leaky_slope = leaky_slope
  12. # self.mish = Mish()# Layerif activation =="leaky":
  13. self.layers = nn.Sequential(
  14. nn.Conv2d(self.in_channels, self.out_channels, self.kernel_size, self.stride, self.padding, bias=False),
  15. nn.BatchNorm2d(self.out_channels),
  16. nn.LeakyReLU(self.leaky_slope, inplace=True))elif activation =="mish":
  17. self.layers = nn.Sequential(
  18. nn.Conv2d(self.in_channels, self.out_channels, self.kernel_size, self.stride, self.padding, bias=False),
  19. nn.BatchNorm2d(self.out_channels),
  20. Mish())elif activation =="linear":
  21. self.layers = nn.Sequential(
  22. nn.Conv2d(self.in_channels, self.out_channels, self.kernel_size, self.stride, self.padding, bias=False))def__repr__(self):
  23. s ='{name} ({in_channels}, {out_channels}, kernel_size={kernel_size}, stride={stride}, padding={padding}, negative_slope={leaky_slope})'return s.format(name=self.__class__.__name__,**self.__dict__)defforward(self, x):
  24. x = self.layers(x)return x
  25. classSmallBlock(nn.Module):def__init__(self, nchannels):super().__init__()
  26. self.features = nn.Sequential(
  27. Conv2dBatchLeaky(nchannels, nchannels,1,1, activation='mish'),
  28. Conv2dBatchLeaky(nchannels, nchannels,3,1, activation='mish'))# conv_shortcut'''
  29. 参考 https://github.com/bubbliiiing/yolov4-pytorch
  30. shortcut后不接任何conv
  31. '''# self.active_linear = Conv2dBatchLeaky(nchannels, nchannels, 1, 1, activation='linear')# self.conv_shortcut = Conv2dBatchLeaky(nchannels, nchannels, 1, 1, activation='mish')defforward(self, data):
  32. short_cut = data + self.features(data)# active_linear = self.conv_shortcut(short_cut)return short_cut
  33. # Stage1 conv [256,256,3]->[256,256,32]classStage2(nn.Module):def__init__(self, nchannels):super().__init__()# stage2 32
  34. self.conv1 = Conv2dBatchLeaky(nchannels,2*nchannels,3,2, activation='mish')
  35. self.split0 = Conv2dBatchLeaky(2*nchannels,2*nchannels,1,1, activation='mish')
  36. self.split1 = Conv2dBatchLeaky(2*nchannels,2*nchannels,1,1, activation='mish')
  37. self.conv2 = Conv2dBatchLeaky(2*nchannels, nchannels,1,1, activation='mish')
  38. self.conv3 = Conv2dBatchLeaky(nchannels,2*nchannels,3,1, activation='mish')
  39. self.conv4 = Conv2dBatchLeaky(2*nchannels,2*nchannels,1,1, activation='mish')defforward(self, data):
  40. conv1 = self.conv1(data)
  41. split0 = self.split0(conv1)
  42. split1 = self.split1(conv1)
  43. conv2 = self.conv2(split1)
  44. conv3 = self.conv3(conv2)
  45. shortcut = split1 + conv3
  46. conv4 = self.conv4(shortcut)
  47. route = torch.cat([split0, conv4], dim=1)return route
  48. classStage3(nn.Module):def__init__(self, nchannels):super().__init__()# stage3 128
  49. self.conv1 = Conv2dBatchLeaky(nchannels,int(nchannels/2),1,1, activation='mish')
  50. self.conv2 = Conv2dBatchLeaky(int(nchannels/2), nchannels,3,2, activation='mish')
  51. self.split0 = Conv2dBatchLeaky(nchannels,int(nchannels/2),1,1, activation='mish')
  52. self.split1 = Conv2dBatchLeaky(nchannels,int(nchannels/2),1,1, activation='mish')
  53. self.block1 = SmallBlock(int(nchannels/2))
  54. self.block2 = SmallBlock(int(nchannels/2))
  55. self.conv3 = Conv2dBatchLeaky(int(nchannels/2),int(nchannels/2),1,1, activation='mish')defforward(self, data):
  56. conv1 = self.conv1(data)
  57. conv2 = self.conv2(conv1)
  58. split0 = self.split0(conv2)
  59. split1 = self.split1(conv2)
  60. block1 = self.block1(split1)
  61. block2 = self.block2(block1)
  62. conv3 = self.conv3(block2)
  63. route = torch.cat([split0, conv3], dim=1)return route
  64. # Stage4 Stage5 Stage6classStage(nn.Module):def__init__(self, nchannels, nblocks):super().__init__()# stage4 : 128# stage5 : 256# stage6 : 512
  65. self.conv1 = Conv2dBatchLeaky(nchannels, nchannels,1,1, activation='mish')
  66. self.conv2 = Conv2dBatchLeaky(nchannels,2*nchannels,3,2, activation='mish')
  67. self.split0 = Conv2dBatchLeaky(2*nchannels, nchannels,1,1, activation='mish')
  68. self.split1 = Conv2dBatchLeaky(2*nchannels, nchannels,1,1, activation='mish')
  69. blocks =[]for i inrange(nblocks):
  70. blocks.append(SmallBlock(nchannels))
  71. self.blocks = nn.Sequential(*blocks)
  72. self.conv4 = Conv2dBatchLeaky(nchannels, nchannels,1,1, activation='mish')defforward(self,data):
  73. conv1 = self.conv1(data)
  74. conv2 = self.conv2(conv1)
  75. split0 = self.split0(conv2)
  76. split1 = self.split1(conv2)
  77. blocks = self.blocks(split1)
  78. conv4 = self.conv4(blocks)
  79. route = torch.cat([split0, conv4], dim=1)return route

3. 代码测试

下面使用一个小例子来对代码进行测试。

  1. if __name__ =="__main__":
  2. use_cuda = torch.cuda.is_available()if use_cuda:
  3. device = torch.device("cuda")
  4. cudnn.benchmark =Trueelse:
  5. device = torch.device("cpu")
  6. darknet = CsDarkNet53(num_classes=10)
  7. darknet = darknet.cuda()with torch.no_grad():
  8. darknet.eval()
  9. data = torch.rand(1,3,256,256)
  10. data = data.cuda()try:#print(darknet)
  11. summary(darknet,(3,256,256))print(darknet(data))except Exception as e:print(e)

代码的输出如下所示:

  1. Total params:26,627,434
  2. Trainable params:26,627,434
  3. Non-trainable params:0----------------------------------------------------------------
  4. Input size (MB):0.75
  5. Forward/backward pass size (MB):553.51
  6. Params size (MB):101.58
  7. Estimated Total Size (MB):655.83----------------------------------------------------------------
  8. tensor([[0.1690,0.0798,0.1836,0.2414,0.3855,0.2437,-0.1422,-0.1855,0.1758,-0.2452]], device='cuda:0')

注意:输出中存在框架结构内容,这里没有将其写在博客中

4. 结论

CSP-Darknet53的代码结构结合着对应的代码实现一起看,可以有效帮助大家理解关于原理部分的内容。希望可以帮助到大家!!!
另外,关于代码中存在的一些小的部分可能会在后面进行介绍。


本文转载自: https://blog.csdn.net/qq_36758270/article/details/130395730
版权归原作者 sjx_alo 所有, 如有侵权,请联系我们删除。

“CV 经典主干网络 (Backbone) 系列: CSP-Darknet53”的评论:

还没有评论