0


【YOLOv5/v7改进系列】引入YOLOv9的RepNCSPELAN4

一、导言

YOLOv9的几个主要创新点:

  1. Programmable Gradient Information (PGI):- PGI是一种机制,用于应对深度网络中实现多目标所需要的多种变化。- PGI提供完整的输入信息来计算目标函数,从而获得可靠的梯度信息以更新网络权重。- PGI可以自由选择适合目标任务的损失函数,克服了掩模建模遇到的问题。- PGI机制适用于不同大小的深度神经网络,并且比仅适用于非常深的神经网络的深度监督机制更为通用。
  2. Generalized Efficient Layer Aggregation Network (GELAN):- GELAN是一种基于传统卷积运算符设计的轻量级网络架构,相较于基于深度可分离卷积的设计,GELAN实现了更好的参数利用率。- GELAN的设计同时考虑了参数数量、计算复杂度、准确率和推理速度。- GELAN允许用户根据不同的推理设备选择合适的计算模块。
  3. 理论分析:- 作者们从可逆函数的角度对现有的深度神经网络架构进行了理论分析,通过这个过程成功解释了许多过去难以解释的现象。- 基于这种分析,设计了PGI和辅助可逆分支。
  4. 适用性:- PGI解决了深度监督只能应用于极深神经网络架构的问题,从而使新的轻量级架构能够在日常生活中真正应用。- PGI能有效处理信息瓶颈和信息断裂等问题,并全面提高不同规模模型的准确性。- 结合PGI和GELAN,YOLOv9在MS COCO数据集上的目标检测性能超越了现有实时目标检测器的所有方面。
  5. 实证研究:- 通过消融实验验证了PGI对于主干网络和颈部网络的影响。- 实验结果显示,在不同大小的模型上,PGI都能有效地提升模型性能。

综上所述,YOLOv9通过引入PGI和GELAN这两项创新,在轻量化、效率和准确性方面取得了显著的进步,特别是在信息传递和梯度计算方面有着独特的优势。

二、准备工作

首先在YOLOv5/v7的models文件夹下新建文件repncspelan4.py,导入如下代码

  1. from models.common import *
  2. # https://arxiv.org/pdf/2402.13616
  3. class RepConvN(nn.Module):
  4. """RepConv is a basic rep-style block, including training and deploy status
  5. This code is based on https://github.com/DingXiaoH/RepVGG/blob/main/repvgg.py
  6. """
  7. default_act = nn.LeakyReLU() # default activation
  8. def __init__(self, c1, c2, k=3, s=1, p=1, g=1, d=1, act=True, bn=False, deploy=False):
  9. super().__init__()
  10. assert k == 3 and p == 1
  11. self.g = g
  12. self.c1 = c1
  13. self.c2 = c2
  14. self.act = self.default_act if act is True else act if isinstance(act, nn.Module) else nn.Identity()
  15. self.bn = None
  16. self.conv1 = Conv(c1, c2, k, s, p=p, g=g, act=False)
  17. self.conv2 = Conv(c1, c2, 1, s, p=(p - k // 2), g=g, act=False)
  18. def forward_fuse(self, x):
  19. """Forward process"""
  20. return self.act(self.conv(x))
  21. def forward(self, x):
  22. """Forward process"""
  23. id_out = 0 if self.bn is None else self.bn(x)
  24. return self.act(self.conv1(x) + self.conv2(x) + id_out)
  25. def get_equivalent_kernel_bias(self):
  26. kernel3x3, bias3x3 = self._fuse_bn_tensor(self.conv1)
  27. kernel1x1, bias1x1 = self._fuse_bn_tensor(self.conv2)
  28. kernelid, biasid = self._fuse_bn_tensor(self.bn)
  29. return kernel3x3 + self._pad_1x1_to_3x3_tensor(kernel1x1) + kernelid, bias3x3 + bias1x1 + biasid
  30. def _avg_to_3x3_tensor(self, avgp):
  31. channels = self.c1
  32. groups = self.g
  33. kernel_size = avgp.kernel_size
  34. input_dim = channels // groups
  35. k = torch.zeros((channels, input_dim, kernel_size, kernel_size))
  36. k[np.arange(channels), np.tile(np.arange(input_dim), groups), :, :] = 1.0 / kernel_size ** 2
  37. return k
  38. def _pad_1x1_to_3x3_tensor(self, kernel1x1):
  39. if kernel1x1 is None:
  40. return 0
  41. else:
  42. return torch.nn.functional.pad(kernel1x1, [1, 1, 1, 1])
  43. def _fuse_bn_tensor(self, branch):
  44. if branch is None:
  45. return 0, 0
  46. if isinstance(branch, Conv):
  47. kernel = branch.conv.weight
  48. running_mean = branch.bn.running_mean
  49. running_var = branch.bn.running_var
  50. gamma = branch.bn.weight
  51. beta = branch.bn.bias
  52. eps = branch.bn.eps
  53. elif isinstance(branch, nn.BatchNorm2d):
  54. if not hasattr(self, 'id_tensor'):
  55. input_dim = self.c1 // self.g
  56. kernel_value = np.zeros((self.c1, input_dim, 3, 3), dtype=np.float32)
  57. for i in range(self.c1):
  58. kernel_value[i, i % input_dim, 1, 1] = 1
  59. self.id_tensor = torch.from_numpy(kernel_value).to(branch.weight.device)
  60. kernel = self.id_tensor
  61. running_mean = branch.running_mean
  62. running_var = branch.running_var
  63. gamma = branch.weight
  64. beta = branch.bias
  65. eps = branch.eps
  66. std = (running_var + eps).sqrt()
  67. t = (gamma / std).reshape(-1, 1, 1, 1)
  68. return kernel * t, beta - running_mean * gamma / std
  69. def fuse_convs(self):
  70. if hasattr(self, 'conv'):
  71. return
  72. kernel, bias = self.get_equivalent_kernel_bias()
  73. self.conv = nn.Conv2d(in_channels=self.conv1.conv.in_channels,
  74. out_channels=self.conv1.conv.out_channels,
  75. kernel_size=self.conv1.conv.kernel_size,
  76. stride=self.conv1.conv.stride,
  77. padding=self.conv1.conv.padding,
  78. dilation=self.conv1.conv.dilation,
  79. groups=self.conv1.conv.groups,
  80. bias=True).requires_grad_(False)
  81. self.conv.weight.data = kernel
  82. self.conv.bias.data = bias
  83. for para in self.parameters():
  84. para.detach_()
  85. self.__delattr__('conv1')
  86. self.__delattr__('conv2')
  87. if hasattr(self, 'nm'):
  88. self.__delattr__('nm')
  89. if hasattr(self, 'bn'):
  90. self.__delattr__('bn')
  91. if hasattr(self, 'id_tensor'):
  92. self.__delattr__('id_tensor')
  93. class RepNBottleneck(nn.Module):
  94. # Standard bottleneck
  95. def __init__(self, c1, c2, shortcut=True, g=1, k=(3, 3), e=0.5): # ch_in, ch_out, shortcut, kernels, groups, expand
  96. super().__init__()
  97. c_ = int(c2 * e) # hidden channels
  98. self.cv1 = RepConvN(c1, c_, k[0], 1)
  99. self.cv2 = Conv(c_, c2, k[1], 1, g=g)
  100. self.add = shortcut and c1 == c2
  101. def forward(self, x):
  102. return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))
  103. class RepNCSP(nn.Module):
  104. # CSP Bottleneck with 3 convolutions
  105. def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion
  106. super().__init__()
  107. c_ = int(c2 * e) # hidden channels
  108. self.cv1 = Conv(c1, c_, 1, 1)
  109. self.cv2 = Conv(c1, c_, 1, 1)
  110. self.cv3 = Conv(2 * c_, c2, 1) # optional act=FReLU(c2)
  111. self.m = nn.Sequential(*(RepNBottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n)))
  112. def forward(self, x):
  113. return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), 1))
  114. class RepNCSPELAN4(nn.Module):
  115. # csp-elan
  116. def __init__(self, c1, c2, c3, c4, c5=1): # ch_in, ch_out, number, shortcut, groups, expansion
  117. super().__init__()
  118. self.c = c3 // 2
  119. self.cv1 = Conv(c1, c3, 1, 1)
  120. self.cv2 = nn.Sequential(RepNCSP(c3 // 2, c4, c5), Conv(c4, c4, 3, 1))
  121. self.cv3 = nn.Sequential(RepNCSP(c4, c4, c5), Conv(c4, c4, 3, 1))
  122. self.cv4 = Conv(c3 + (2 * c4), c2, 1, 1)
  123. def forward(self, x):
  124. y = list(self.cv1(x).chunk(2, 1))
  125. y.extend((m(y[-1])) for m in [self.cv2, self.cv3])
  126. return self.cv4(torch.cat(y, 1))
  127. def forward_split(self, x):
  128. y = list(self.cv1(x).split((self.c, self.c), 1))
  129. y.extend(m(y[-1]) for m in [self.cv2, self.cv3])
  130. return self.cv4(torch.cat(y, 1))

其次在在YOLOv5/v7项目文件下的models/yolo.py中在文件首部添加代码

  1. from models.repncspelan4 import RepNCSPELAN4

并搜索def parse_model(d, ch)

定位到如下行添加以下代码

  1. RepNCSPELAN4,

三、YOLOv7-tiny改进工作

完成二后,在YOLOv7项目文件下的models文件夹下创建新的文件yolov7-tiny-repncspelan4.yaml,导入如下代码。

  1. # parameters
  2. nc: 80 # number of classes
  3. depth_multiple: 1.0 # model depth multiple
  4. width_multiple: 1.0 # layer channel multiple
  5. # anchors
  6. anchors:
  7. - [10,13, 16,30, 33,23] # P3/8
  8. - [30,61, 62,45, 59,119] # P4/16
  9. - [116,90, 156,198, 373,326] # P5/32
  10. # yolov7-tiny backbone
  11. backbone:
  12. # [from, number, module, args] c2, k=1, s=1, p=None, g=1, act=True
  13. [[-1, 1, Conv, [32, 3, 2, None, 1, nn.LeakyReLU(0.1)]], # 0-P1/2
  14. [-1, 1, Conv, [64, 3, 2, None, 1, nn.LeakyReLU(0.1)]], # 1-P2/4
  15. [-1, 1, Conv, [32, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  16. [-2, 1, Conv, [32, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  17. [-1, 1, Conv, [32, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  18. [-1, 1, Conv, [32, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  19. [[-1, -2, -3, -4], 1, Concat, [1]],
  20. [-1, 1, Conv, [64, 1, 1, None, 1, nn.LeakyReLU(0.1)]], # 7
  21. [-1, 1, MP, []], # 8-P3/8
  22. [-1, 1, Conv, [64, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  23. [-2, 1, Conv, [64, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  24. [-1, 1, Conv, [64, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  25. [-1, 1, Conv, [64, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  26. [[-1, -2, -3, -4], 1, Concat, [1]],
  27. [-1, 1, Conv, [128, 1, 1, None, 1, nn.LeakyReLU(0.1)]], # 14
  28. [-1, 1, MP, []], # 15-P4/16
  29. [-1, 1, Conv, [128, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  30. [-2, 1, Conv, [128, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  31. [-1, 1, Conv, [128, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  32. [-1, 1, Conv, [128, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  33. [[-1, -2, -3, -4], 1, Concat, [1]],
  34. [-1, 1, Conv, [256, 1, 1, None, 1, nn.LeakyReLU(0.1)]], # 21
  35. [-1, 1, MP, []], # 22-P5/32
  36. [-1, 1, Conv, [256, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  37. [-2, 1, Conv, [256, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  38. [-1, 1, Conv, [256, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  39. [-1, 1, Conv, [256, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  40. [[-1, -2, -3, -4], 1, Concat, [1]],
  41. [-1, 1, Conv, [512, 1, 1, None, 1, nn.LeakyReLU(0.1)]], # 28
  42. ]
  43. # yolov7-tiny head
  44. head:
  45. [[-1, 1, Conv, [256, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  46. [-2, 1, Conv, [256, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  47. [-1, 1, SP, [5]],
  48. [-2, 1, SP, [9]],
  49. [-3, 1, SP, [13]],
  50. [[-1, -2, -3, -4], 1, Concat, [1]],
  51. [-1, 1, Conv, [256, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  52. [[-1, -7], 1, Concat, [1]],
  53. [-1, 1, Conv, [256, 1, 1, None, 1, nn.LeakyReLU(0.1)]], # 37
  54. [-1, 1, Conv, [128, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  55. [-1, 1, nn.Upsample, [None, 2, 'nearest']],
  56. [21, 1, Conv, [128, 1, 1, None, 1, nn.LeakyReLU(0.1)]], # route backbone P4
  57. [[-1, -2], 1, Concat, [1]],
  58. [-1, 1, Conv, [64, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  59. [-2, 1, Conv, [64, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  60. [-1, 1, Conv, [64, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  61. [-1, 1, Conv, [64, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  62. [[-1, -2, -3, -4], 1, Concat, [1]],
  63. [-1, 1, Conv, [128, 1, 1, None, 1, nn.LeakyReLU(0.1)]], # 47
  64. [-1, 1, Conv, [64, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  65. [-1, 1, nn.Upsample, [None, 2, 'nearest']],
  66. [14, 1, Conv, [64, 1, 1, None, 1, nn.LeakyReLU(0.1)]], # route backbone P3
  67. [[-1, -2], 1, Concat, [1]],
  68. [-1, 1, Conv, [32, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  69. [-2, 1, Conv, [32, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  70. [-1, 1, Conv, [32, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  71. [-1, 1, Conv, [32, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  72. [[-1, -2, -3, -4], 1, Concat, [1]],
  73. [-1, 1, Conv, [64, 1, 1, None, 1, nn.LeakyReLU(0.1)]], # 57
  74. [-1, 1, Conv, [128, 3, 2, None, 1, nn.LeakyReLU(0.1)]],
  75. [[-1, 47], 1, Concat, [1]],
  76. [-1, 1, Conv, [64, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  77. [-2, 1, Conv, [64, 1, 1, None, 1, nn.LeakyReLU(0.1)]],
  78. [-1, 1, Conv, [64, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  79. [-1, 1, Conv, [64, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  80. [[-1, -2, -3, -4], 1, Concat, [1]],
  81. [-1, 1, Conv, [128, 1, 1, None, 1, nn.LeakyReLU(0.1)]], # 65
  82. [-1, 1, Conv, [256, 3, 2, None, 1, nn.LeakyReLU(0.1)]],
  83. [[-1, 37], 1, Concat, [1]], # 67
  84. [-1, 1, RepNCSPELAN4, [256, 128, 64, 1]],# 68
  85. [57, 1, Conv, [128, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  86. [65, 1, Conv, [256, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  87. [68, 1, Conv, [512, 3, 1, None, 1, nn.LeakyReLU(0.1)]],
  88. [[69,70,71], 1, IDetect, [nc, anchors]], # Detect(P3, P4, P5)
  89. ]
  1. from n params module arguments
  2. 0 -1 1 928 models.common.Conv [3, 32, 3, 2, None, 1, LeakyReLU(negative_slope=0.1)]
  3. 1 -1 1 18560 models.common.Conv [32, 64, 3, 2, None, 1, LeakyReLU(negative_slope=0.1)]
  4. 2 -1 1 2112 models.common.Conv [64, 32, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  5. 3 -2 1 2112 models.common.Conv [64, 32, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  6. 4 -1 1 9280 models.common.Conv [32, 32, 3, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  7. 5 -1 1 9280 models.common.Conv [32, 32, 3, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  8. 6 [-1, -2, -3, -4] 1 0 models.common.Concat [1]
  9. 7 -1 1 8320 models.common.Conv [128, 64, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  10. 8 -1 1 0 models.common.MP []
  11. 9 -1 1 4224 models.common.Conv [64, 64, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  12. 10 -2 1 4224 models.common.Conv [64, 64, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  13. 11 -1 1 36992 models.common.Conv [64, 64, 3, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  14. 12 -1 1 36992 models.common.Conv [64, 64, 3, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  15. 13 [-1, -2, -3, -4] 1 0 models.common.Concat [1]
  16. 14 -1 1 33024 models.common.Conv [256, 128, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  17. 15 -1 1 0 models.common.MP []
  18. 16 -1 1 16640 models.common.Conv [128, 128, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  19. 17 -2 1 16640 models.common.Conv [128, 128, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  20. 18 -1 1 147712 models.common.Conv [128, 128, 3, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  21. 19 -1 1 147712 models.common.Conv [128, 128, 3, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  22. 20 [-1, -2, -3, -4] 1 0 models.common.Concat [1]
  23. 21 -1 1 131584 models.common.Conv [512, 256, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  24. 22 -1 1 0 models.common.MP []
  25. 23 -1 1 66048 models.common.Conv [256, 256, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  26. 24 -2 1 66048 models.common.Conv [256, 256, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  27. 25 -1 1 590336 models.common.Conv [256, 256, 3, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  28. 26 -1 1 590336 models.common.Conv [256, 256, 3, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  29. 27 [-1, -2, -3, -4] 1 0 models.common.Concat [1]
  30. 28 -1 1 525312 models.common.Conv [1024, 512, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  31. 29 -1 1 131584 models.common.Conv [512, 256, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  32. 30 -2 1 131584 models.common.Conv [512, 256, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  33. 31 -1 1 0 models.common.SP [5]
  34. 32 -2 1 0 models.common.SP [9]
  35. 33 -3 1 0 models.common.SP [13]
  36. 34 [-1, -2, -3, -4] 1 0 models.common.Concat [1]
  37. 35 -1 1 262656 models.common.Conv [1024, 256, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  38. 36 [-1, -7] 1 0 models.common.Concat [1]
  39. 37 -1 1 131584 models.common.Conv [512, 256, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  40. 38 -1 1 33024 models.common.Conv [256, 128, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  41. 39 -1 1 0 torch.nn.modules.upsampling.Upsample [None, 2, 'nearest']
  42. 40 21 1 33024 models.common.Conv [256, 128, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  43. 41 [-1, -2] 1 0 models.common.Concat [1]
  44. 42 -1 1 16512 models.common.Conv [256, 64, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  45. 43 -2 1 16512 models.common.Conv [256, 64, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  46. 44 -1 1 36992 models.common.Conv [64, 64, 3, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  47. 45 -1 1 36992 models.common.Conv [64, 64, 3, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  48. 46 [-1, -2, -3, -4] 1 0 models.common.Concat [1]
  49. 47 -1 1 33024 models.common.Conv [256, 128, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  50. 48 -1 1 8320 models.common.Conv [128, 64, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  51. 49 -1 1 0 torch.nn.modules.upsampling.Upsample [None, 2, 'nearest']
  52. 50 14 1 8320 models.common.Conv [128, 64, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  53. 51 [-1, -2] 1 0 models.common.Concat [1]
  54. 52 -1 1 4160 models.common.Conv [128, 32, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  55. 53 -2 1 4160 models.common.Conv [128, 32, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  56. 54 -1 1 9280 models.common.Conv [32, 32, 3, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  57. 55 -1 1 9280 models.common.Conv [32, 32, 3, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  58. 56 [-1, -2, -3, -4] 1 0 models.common.Concat [1]
  59. 57 -1 1 8320 models.common.Conv [128, 64, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  60. 58 -1 1 73984 models.common.Conv [64, 128, 3, 2, None, 1, LeakyReLU(negative_slope=0.1)]
  61. 59 [-1, 47] 1 0 models.common.Concat [1]
  62. 60 -1 1 16512 models.common.Conv [256, 64, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  63. 61 -2 1 16512 models.common.Conv [256, 64, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  64. 62 -1 1 36992 models.common.Conv [64, 64, 3, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  65. 63 -1 1 36992 models.common.Conv [64, 64, 3, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  66. 64 [-1, -2, -3, -4] 1 0 models.common.Concat [1]
  67. 65 -1 1 33024 models.common.Conv [256, 128, 1, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  68. 66 -1 1 295424 models.common.Conv [128, 256, 3, 2, None, 1, LeakyReLU(negative_slope=0.1)]
  69. 67 [-1, 37] 1 0 models.common.Concat [1]
  70. 68 -1 1 262016 models.repncspelan4.RepNCSPELAN4 [512, 256, 128, 64, 1]
  71. 69 57 1 73984 models.common.Conv [64, 128, 3, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  72. 70 65 1 295424 models.common.Conv [128, 256, 3, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  73. 71 68 1 1180672 models.common.Conv [256, 512, 3, 1, None, 1, LeakyReLU(negative_slope=0.1)]
  74. 72 [69, 70, 71] 1 17132 models.yolo.IDetect [1, [[10, 13, 16, 30, 33, 23], [30, 61, 62, 45, 59, 119], [116, 90, 156, 198, 373, 326]], [128, 256, 512]]
  75. Model Summary: 318 layers, 5718412 parameters, 5718412 gradients, 12.9 GFLOPS

运行后若打印出如上文本代表改进成功。

四、YOLOv5s改进工作

完成二后,在YOLOv5项目文件下的models文件夹下创建新的文件yolov5s-repncspelan4.yaml,导入如下代码。

  1. # Parameters
  2. nc: 1 # number of classes
  3. depth_multiple: 0.33 # model depth multiple
  4. width_multiple: 0.25 # layer channel multiple
  5. anchors:
  6. - [10,13, 16,30, 33,23] # P3/8
  7. - [30,61, 62,45, 59,119] # P4/16
  8. - [116,90, 156,198, 373,326] # P5/32
  9. # YOLOv5 v6.0 backbone
  10. backbone:
  11. # [from, number, module, args]
  12. [[-1, 1, Conv, [64, 6, 2, 2]], # 0-P1/2
  13. [-1, 1, Conv, [128, 3, 2]], # 1-P2/4
  14. [-1, 3, C3, [128]],
  15. [-1, 1, Conv, [256, 3, 2]], # 3-P3/8
  16. [-1, 6, C3, [256]],
  17. [-1, 1, Conv, [512, 3, 2]], # 5-P4/16
  18. [-1, 9, C3, [512]],
  19. [-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
  20. [-1, 3, C3, [1024]],
  21. [-1, 1, SPPF, [1024, 5]], # 9
  22. ]
  23. # YOLOv5 v6.0 head
  24. head:
  25. [[-1, 1, Conv, [512, 1, 1]],
  26. [-1, 1, nn.Upsample, [None, 2, 'nearest']],
  27. [[-1, 6], 1, Concat, [1]], # cat backbone P4
  28. [-1, 3, C3, [512, False]], # 13
  29. [-1, 1, Conv, [256, 1, 1]],
  30. [-1, 1, nn.Upsample, [None, 2, 'nearest']],
  31. [[-1, 4], 1, Concat, [1]], # cat backbone P3
  32. [-1, 3, C3, [256, False]], # 17 (P3/8-small)
  33. [-1, 1, Conv, [256, 3, 2]],
  34. [[-1, 14], 1, Concat, [1]], # cat head P4
  35. [-1, 3, C3, [512, False]], # 20 (P4/16-medium)
  36. [-1, 1, Conv, [512, 3, 2]],
  37. [[-1, 10], 1, Concat, [1]], # cat head P5
  38. [-1, 1, RepNCSPELAN4, [1024, 512, 256, 1]], # 23 (P5/32-large)
  39. [[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
  40. ]
  1. from n params module arguments
  2. 0 -1 1 3520 models.common.Conv [3, 32, 6, 2, 2]
  3. 1 -1 1 18560 models.common.Conv [32, 64, 3, 2]
  4. 2 -1 1 18816 models.common.C3 [64, 64, 1]
  5. 3 -1 1 73984 models.common.Conv [64, 128, 3, 2]
  6. 4 -1 2 115712 models.common.C3 [128, 128, 2]
  7. 5 -1 1 295424 models.common.Conv [128, 256, 3, 2]
  8. 6 -1 3 625152 models.common.C3 [256, 256, 3]
  9. 7 -1 1 1180672 models.common.Conv [256, 512, 3, 2]
  10. 8 -1 1 1182720 models.common.C3 [512, 512, 1]
  11. 9 -1 1 656896 models.common.SPPF [512, 512, 5]
  12. 10 -1 1 131584 models.common.Conv [512, 256, 1, 1]
  13. 11 -1 1 0 torch.nn.modules.upsampling.Upsample [None, 2, 'nearest']
  14. 12 [-1, 6] 1 0 models.common.Concat [1]
  15. 13 -1 1 361984 models.common.C3 [512, 256, 1, False]
  16. 14 -1 1 33024 models.common.Conv [256, 128, 1, 1]
  17. 15 -1 1 0 torch.nn.modules.upsampling.Upsample [None, 2, 'nearest']
  18. 16 [-1, 4] 1 0 models.common.Concat [1]
  19. 17 -1 1 90880 models.common.C3 [256, 128, 1, False]
  20. 18 -1 1 147712 models.common.Conv [128, 128, 3, 2]
  21. 19 [-1, 14] 1 0 models.common.Concat [1]
  22. 20 -1 1 296448 models.common.C3 [256, 256, 1, False]
  23. 21 -1 1 590336 models.common.Conv [256, 256, 3, 2]
  24. 22 [-1, 10] 1 0 models.common.Concat [1]
  25. 23 -1 1 2857472 models.repncspelan4.RepNCSPELAN4 [512, 512, 512, 256, 1]
  26. 24 [17, 20, 23] 1 16182 models.yolo.Detect [1, [[10, 13, 16, 30, 33, 23], [30, 61, 62, 45, 59, 119], [116, 90, 156, 198, 373, 326]], [128, 256, 512]]
  27. Model Summary: 323 layers, 8697078 parameters, 8697078 gradients, 17.3 GFLOPs

运行后若打印出如上文本代表改进成功。

五、YOLOv5n改进工作

完成二后,在YOLOv5项目文件下的models文件夹下创建新的文件yolov5n-repncspelan4.yaml,导入如下代码。

  1. # Parameters
  2. nc: 1 # number of classes
  3. depth_multiple: 0.33 # model depth multiple
  4. width_multiple: 0.25 # layer channel multiple
  5. anchors:
  6. - [10,13, 16,30, 33,23] # P3/8
  7. - [30,61, 62,45, 59,119] # P4/16
  8. - [116,90, 156,198, 373,326] # P5/32
  9. # YOLOv5 v6.0 backbone
  10. backbone:
  11. # [from, number, module, args]
  12. [[-1, 1, Conv, [64, 6, 2, 2]], # 0-P1/2
  13. [-1, 1, Conv, [128, 3, 2]], # 1-P2/4
  14. [-1, 3, C3, [128]],
  15. [-1, 1, Conv, [256, 3, 2]], # 3-P3/8
  16. [-1, 6, C3, [256]],
  17. [-1, 1, Conv, [512, 3, 2]], # 5-P4/16
  18. [-1, 9, C3, [512]],
  19. [-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
  20. [-1, 3, C3, [1024]],
  21. [-1, 1, SPPF, [1024, 5]], # 9
  22. ]
  23. # YOLOv5 v6.0 head
  24. head:
  25. [[-1, 1, Conv, [512, 1, 1]],
  26. [-1, 1, nn.Upsample, [None, 2, 'nearest']],
  27. [[-1, 6], 1, Concat, [1]], # cat backbone P4
  28. [-1, 3, C3, [512, False]], # 13
  29. [-1, 1, Conv, [256, 1, 1]],
  30. [-1, 1, nn.Upsample, [None, 2, 'nearest']],
  31. [[-1, 4], 1, Concat, [1]], # cat backbone P3
  32. [-1, 3, C3, [256, False]], # 17 (P3/8-small)
  33. [-1, 1, Conv, [256, 3, 2]],
  34. [[-1, 14], 1, Concat, [1]], # cat head P4
  35. [-1, 3, C3, [512, False]], # 20 (P4/16-medium)
  36. [-1, 1, Conv, [512, 3, 2]],
  37. [[-1, 10], 1, Concat, [1]], # cat head P5
  38. [-1, 1, RepNCSPELAN4, [1024, 512, 256, 1]], # 23 (P5/32-large)
  39. [[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
  40. ]
  1. from n params module arguments
  2. 0 -1 1 1760 models.common.Conv [3, 16, 6, 2, 2]
  3. 1 -1 1 4672 models.common.Conv [16, 32, 3, 2]
  4. 2 -1 1 4800 models.common.C3 [32, 32, 1]
  5. 3 -1 1 18560 models.common.Conv [32, 64, 3, 2]
  6. 4 -1 2 29184 models.common.C3 [64, 64, 2]
  7. 5 -1 1 73984 models.common.Conv [64, 128, 3, 2]
  8. 6 -1 3 156928 models.common.C3 [128, 128, 3]
  9. 7 -1 1 295424 models.common.Conv [128, 256, 3, 2]
  10. 8 -1 1 296448 models.common.C3 [256, 256, 1]
  11. 9 -1 1 164608 models.common.SPPF [256, 256, 5]
  12. 10 -1 1 33024 models.common.Conv [256, 128, 1, 1]
  13. 11 -1 1 0 torch.nn.modules.upsampling.Upsample [None, 2, 'nearest']
  14. 12 [-1, 6] 1 0 models.common.Concat [1]
  15. 13 -1 1 90880 models.common.C3 [256, 128, 1, False]
  16. 14 -1 1 8320 models.common.Conv [128, 64, 1, 1]
  17. 15 -1 1 0 torch.nn.modules.upsampling.Upsample [None, 2, 'nearest']
  18. 16 [-1, 4] 1 0 models.common.Concat [1]
  19. 17 -1 1 22912 models.common.C3 [128, 64, 1, False]
  20. 18 -1 1 36992 models.common.Conv [64, 64, 3, 2]
  21. 19 [-1, 14] 1 0 models.common.Concat [1]
  22. 20 -1 1 74496 models.common.C3 [128, 128, 1, False]
  23. 21 -1 1 147712 models.common.Conv [128, 128, 3, 2]
  24. 22 [-1, 10] 1 0 models.common.Concat [1]
  25. 23 -1 1 2463744 models.repncspelan4.RepNCSPELAN4 [256, 256, 512, 256, 1]
  26. 24 [17, 20, 23] 1 8118 models.yolo.Detect [1, [[10, 13, 16, 30, 33, 23], [30, 61, 62, 45, 59, 119], [116, 90, 156, 198, 373, 326]], [64, 128, 256]]
  27. Model Summary: 323 layers, 3932566 parameters, 3932566 gradients, 6.0 GFLOPs
六、RepNCSPELAN4的优点
  1. RepNCSPELAN4

是一个复合模块,结合了CSP (Cross Stage Partial Networks) 和 ELAN (Efficient Layer Aggregation Network) 的设计理念,旨在构建一个高效且参数利用率高的网络结构。下面是

  1. RepNCSPELAN4

模块的一些关键优点:

1. 参数利用率高
  • RepNCSPELAN4 使用了两个 RepNCSP 模块,它们通过将输入通道分割成两部分并分别处理,然后将结果合并,这种方式能够更高效地利用通道信息。
  • RepNCSP 内部使用了 RepNBottleneck,这是一种基于可重复卷积的瓶颈结构,它可以在训练时学习到更复杂的特征表示,而在部署时简化为单一的卷积层,减少了计算量。
2. 计算效率
  • 通过使用 RepConvNRepNBottleneck,模块能够在不牺牲精度的情况下减少前向传播的时间成本。
  • RepConvN 可以在训练阶段使用多个卷积核,而在部署阶段转换为一个等效的单个卷积核,这提高了推理速度。
3. 深度与宽度的灵活配置
  • RepNCSPELAN4 支持通道分割和并行处理,这意味着可以通过调整通道数和重复的 RepNCSP 层数来适应不同的计算资源和任务需求。
  • 通过调整 c5 参数(即 RepNCSP 中的重复次数),可以根据需要增加或减少模块的深度。
4. 特征融合
  • RepNCSPELAN4 在其 forward 方法中将输入通道分成两个部分,并分别通过 RepNCSP 处理,最后再合并。这样的设计有助于更好地聚合多尺度特征,增强模型对不同大小目标的识别能力。
5. 易于扩展
  • 该模块易于集成到更大的网络结构中,例如作为骨干网络的一部分,或者作为头部网络中的组件。
6. 训练和部署的一致性
  • 由于 RepConvN 在训练和部署阶段表现的一致性,使得整个网络更容易优化并且避免了在不同阶段之间切换带来的性能损失。
7. 灵活的前向传播模式
  • 提供了 forward_split 方法,这为开发者提供了更多的灵活性,可以在需要时使用不同的通道分割策略。

通过这些设计特点,

  1. RepNCSPELAN4

能够在保持高精度的同时,实现高效的计算性能,使其成为实时目标检测任务的理想选择。

七、注意

第二步在YOLOv5/v7的models文件夹下新建文件repncspelan4.py的激活函数是YOLOv7-tiny的LeakyReLU,

  1. default_act = nn.LeakyReLU() # default activation

使用YOLOv7、YOLOv5时需要更改为SiLU()

  1. default_act = nn.SiLU()

运行后打印如上代码说明改进成功。

更多文章产出中,主打简洁和准确,欢迎关注我,共同探讨!


本文转载自: https://blog.csdn.net/2401_84870184/article/details/140782817
版权归原作者 拿下Nahida 所有, 如有侵权,请联系我们删除。

“【YOLOv5/v7改进系列】引入YOLOv9的RepNCSPELAN4”的评论:

还没有评论