深圳幻海软件技术有限公司 欢迎您!

目标检测算法——YOLOv5/YOLOv7改进之结合​RepVGG(速度飙升)

2023-02-28

>>>深度学习Tricks,第一时间送达<<<目录RepVGG——极简架构,SOTA性能!!!(一)前沿介绍1.RepVGGBlock模块2.相关实验结果(二)YOLOv5/YOLOv7改进之结合​RepVGG1.配置common.py文件2.配置yolo.py文

>>>深度学习Tricks,第一时间送达<<<

目录

RepVGG——极简架构,SOTA性能!!!

(一)前沿介绍

1.RepVGGBlock模块

2.相关实验结果

(二)YOLOv5/YOLOv7改进之结合​RepVGG

1.配置common.py文件

2.配置yolo.py文件

3.配置yolov5/yolov7_​​RepVGG.yaml文件


RepVGG——极简架构,SOTA性能!!!

(一)前沿介绍

论文题目:RepVGG: Making VGG-style ConvNets Great Again

论文地址:https://arxiv.org/abs/2101.03697

代码地址:https://github.com/DingXiaoH/RepVGG

作者提出了一个简单但功能强大的卷积神经网络架构,该架构推理时候具有类似于VGG的骨干结构,该主体仅由3 x 3卷积和ReLU堆叠组成,而训练时候模型采用多分支拓扑结构。 训练和推理架构的这种解耦是通过结构重参数化技术实现的,因此该模型称为RepVGG。 在ImageNet上,据我们所知,RepVGG的top-1准确性达到80%以上,这是老模型首次实现该精度。 在NVIDIA 1080Ti GPU上,RepVGG模型的运行速度比ResNet-50快83%,比ResNet-101快101%,并且具有更高的精度,与诸如EfficientNet和RegNet的最新模型相比,RepVGG显示出良好的精度-速度权衡。效果对比如下图所示。

该论文主要有以下三点贡献:

1.更快

除了Winograd conv带来的加速之外,FLOPs和速度之间的差异可以归因于两个重要因素,它们对速度有很大影响,但FLOPs并未考虑这些因素:内存访问成本(MAC)和并行度。 另一方面,在相同的FLOPs下,具有高并行度的模型可能比具有低并行度的模型快得多。因此简单的推理结构可以避免多分支的零碎计算。

2.更省内存

如图(A)所示的Residual模块,假设卷积层不改变channel的数量,那么在主分支和shortcut分支上都要保存各自的特征图或者称Activation,那么在add操作前占用的内存大概是输入Activation的两倍,而图(B)的Plain结构占用内存始终不变。

VGG是一个直筒性单路结构,由上述分析可知,单路结构会占有更少的内存,因为不需要保存其中间结果,同时,单路架构非常快,因为并行度高。同样的计算量,大而整的运算效率远超小而碎的运算。

3.更加灵活

作者在论文中提到了模型优化的剪枝问题,对于多分支的模型,结构限制较多剪枝很麻烦,而对于Plain结构的模型就相对灵活很多,剪枝也更加方便。

1.RepVGGBlock模块

2.相关实验结果

(二)YOLOv5/YOLOv7改进之结合​RepVGG

改进方法和其他模块一样,分三步走:

1.配置common.py文件

  1. #RepVGGBlock
  2. class RepVGGBlock(nn.Module):
  3. def __init__(self, in_channels, out_channels, kernel_size=3,
  4. stride=1, padding=1, dilation=1, groups=1, padding_mode='zeros', deploy=False, use_se=False):
  5. super(RepVGGBlock, self).__init__()
  6. self.deploy = deploy
  7. self.groups = groups
  8. self.in_channels = in_channels
  9. padding_11 = padding - kernel_size // 2
  10. self.nonlinearity = nn.SiLU()
  11. # self.nonlinearity = nn.ReLU()
  12. if use_se:
  13. self.se = SEBlock(out_channels, internal_neurons=out_channels // 16)
  14. else:
  15. self.se = nn.Identity()
  16. if deploy:
  17. self.rbr_reparam = nn.Conv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=kernel_size,
  18. stride=stride,
  19. padding=padding, dilation=dilation, groups=groups, bias=True,
  20. padding_mode=padding_mode)
  21. else:
  22. self.rbr_identity = nn.BatchNorm2d(
  23. num_features=in_channels) if out_channels == in_channels and stride == 1 else None
  24. self.rbr_dense = conv_bn(in_channels=in_channels, out_channels=out_channels, kernel_size=kernel_size,
  25. stride=stride, padding=padding, groups=groups)
  26. self.rbr_1x1 = conv_bn(in_channels=in_channels, out_channels=out_channels, kernel_size=1, stride=stride,
  27. padding=padding_11, groups=groups)
  28. # print('RepVGG Block, identity = ', self.rbr_identity)
  29. def get_equivalent_kernel_bias(self):
  30. kernel3x3, bias3x3 = self._fuse_bn_tensor(self.rbr_dense)
  31. kernel1x1, bias1x1 = self._fuse_bn_tensor(self.rbr_1x1)
  32. kernelid, biasid = self._fuse_bn_tensor(self.rbr_identity)
  33. return kernel3x3 + self._pad_1x1_to_3x3_tensor(kernel1x1) + kernelid, bias3x3 + bias1x1 + biasid
  34. def _pad_1x1_to_3x3_tensor(self, kernel1x1):
  35. if kernel1x1 is None:
  36. return 0
  37. else:
  38. return torch.nn.functional.pad(kernel1x1, [1, 1, 1, 1])
  39. def _fuse_bn_tensor(self, branch):
  40. if branch is None:
  41. return 0, 0
  42. if isinstance(branch, nn.Sequential):
  43. kernel = branch.conv.weight
  44. running_mean = branch.bn.running_mean
  45. running_var = branch.bn.running_var
  46. gamma = branch.bn.weight
  47. beta = branch.bn.bias
  48. eps = branch.bn.eps
  49. else:
  50. assert isinstance(branch, nn.BatchNorm2d)
  51. if not hasattr(self, 'id_tensor'):
  52. input_dim = self.in_channels // self.groups
  53. kernel_value = np.zeros((self.in_channels, input_dim, 3, 3), dtype=np.float32)
  54. for i in range(self.in_channels):
  55. kernel_value[i, i % input_dim, 1, 1] = 1
  56. self.id_tensor = torch.from_numpy(kernel_value).to(branch.weight.device)
  57. kernel = self.id_tensor
  58. running_mean = branch.running_mean
  59. running_var = branch.running_var
  60. gamma = branch.weight
  61. beta = branch.bias
  62. eps = branch.eps
  63. std = (running_var + eps).sqrt()
  64. t = (gamma / std).reshape(-1, 1, 1, 1)
  65. return kernel * t, beta - running_mean * gamma / std
  66. def forward(self, inputs):
  67. if hasattr(self, 'rbr_reparam'):
  68. return self.nonlinearity(self.se(self.rbr_reparam(inputs)))
  69. if self.rbr_identity is None:
  70. id_out = 0
  71. else:
  72. id_out = self.rbr_identity(inputs)
  73. return self.nonlinearity(self.se(self.rbr_dense(inputs) + self.rbr_1x1(inputs) + id_out))
  74. def fusevggforward(self, x):
  75. return self.nonlinearity(self.rbr_dense(x))

2.配置yolo.py文件

加入RepVGGBlock模块。

3.配置yolov5/yolov7_​​RepVGG.yaml文件

  1. # anchors
  2. anchors:
  3. - [10,13, 16,30, 33,23] # P3/8
  4. - [30,61, 62,45, 59,119] # P4/16
  5. - [116,90, 156,198, 373,326] # P5/32
  6. # YOLOv5 backbone
  7. backbone:
  8. # [from, number, module, args]
  9. [[-1, 1, RepVGGBlock, [64, 3, 2]], # 0-P1/2
  10. [-1, 1, RepVGGBlock, [64, 3, 2]], # 1-P2/4
  11. [-1, 1, RepVGGBlock, [64, 3, 1]], # 2-P2/4
  12. [-1, 1, RepVGGBlock, [128, 3, 2]], # 3-P3/8
  13. [-1, 3, RepVGGBlock, [128, 3, 1]],
  14. [-1, 1, RepVGGBlock, [256, 3, 2]], # 5-P4/16
  15. [-1, 13, RepVGGBlock, [256, 3, 1]],
  16. [-1, 1, RepVGGBlock, [512, 3, 2]], # 7-P4/16
  17. ]
  18. # YOLOv5 head
  19. head:
  20. [[-1, 1, Conv, [256, 1, 1]],
  21. [-1, 1, nn.Upsample, [None, 2, 'nearest']],
  22. [[-1, 6], 1, Concat, [1]], # cat backbone P4
  23. [-1, 1, C3, [256, False]], # 11
  24. [-1, 1, Conv, [128, 1, 1]],
  25. [-1, 1, nn.Upsample, [None, 2, 'nearest']],
  26. [[-1, 4], 1, Concat, [1]], # cat backbone P3
  27. [-1, 1, C3, [128, False]], # 15 (P3/8-small)
  28. [-1, 1, Conv, [128, 3, 2]],
  29. [[-1, 12], 1, Concat, [1]], # cat head P4
  30. [-1, 1, C3, [256, False]], # 18 (P4/16-medium)
  31. [-1, 1, Conv, [256, 3, 2]],
  32. [[-1, 8], 1, Concat, [1]], # cat head P5
  33. [-1, 1, C3, [512, False]], # 21 (P5/32-large)
  34. [[15, 18, 21], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
  35. ]

关于YOLO算法改进及论文投稿可关注并留言博主的CSDN/QQ

>>>一起交流!互相学习!共同进步!<<<

文章知识点与官方知识档案匹配,可进一步学习相关知识
算法技能树首页概览38749 人正在系统学习中
哆啦C梦
QQ名片