当前位置:   article > 正文

YOLOv8改进RepNCSPELAN4(结合YOLOv9二创)_repncspelan4改进yolov8

repncspelan4改进yolov8
  1. import torch
  2. import torch.nn as nn
  3. import torch.nn.functional as F
  4. import numpy as np
  5. class RepConvN(nn.Module):
  6. """RepConv is a basic rep-style block, including training and deploy status
  7. This code is based on https://github.com/DingXiaoH/RepVGG/blob/main/repvgg.py
  8. """
  9. default_act = nn.SiLU() # default activation
  10. def __init__(self, c1, c2, k=3, s=1, p=1, g=1, d=1, act=True, bn=False, deploy=False):
  11. super().__init__()
  12. assert k == 3 and p == 1
  13. self.g = g
  14. self.c1 = c1
  15. self.c2 = c2
  16. self.act = self.default_act if act is True else act if isinstance(act, nn.Module) else nn.Identity()
  17. self.bn = None
  18. self.conv1 = Conv(c1, c2, k, s, p=p, g=g, act=False)
  19. self.conv2 = Conv(c1, c2, 1, s, p=(p - k // 2), g=g, act=False)
  20. def forward_fuse(self, x):
  21. """Forward process"""
  22. return self.act(self.conv(x))
  23. def forward(self, x):
  24. """Forward process"""
  25. if hasattr(self, 'conv'):
  26. return self.forward_fuse(x)
  27. id_out = 0 if self.bn is None else self.bn(x)
  28. return self.act(self.conv1(x) + self.conv2(x) + id_out)
  29. def get_equivalent_kernel_bias(self):
  30. kernel3x3, bias3x3 = self._fuse_bn_tensor(self.conv1)
  31. kernel1x1, bias1x1 = self._fuse_bn_tensor(self.conv2)
  32. kernelid, biasid = self._fuse_bn_tensor(self.bn)
  33. return kernel3x3 + self._pad_1x1_to_3x3_tensor(kernel1x1) + kernelid, bias3x3 + bias1x1 + biasid
  34. def _avg_to_3x3_tensor(self, avgp):
  35. channels = self.c1
  36. groups = self.g
  37. kernel_size = avgp.kernel_size
  38. input_dim = channels // groups
  39. k = torch.zeros((channels, input_dim, kernel_size, kernel_size))
  40. k[np.arange(channels), np.tile(np.arange(input_dim), groups), :, :] = 1.0 / kernel_size ** 2
  41. return k
  42. def _pad_1x1_to_3x3_tensor(self, kernel1x1):
  43. if kernel1x1 is None:
  44. return 0
  45. else:
  46. return torch.nn.functional.pad(kernel1x1, [1, 1, 1, 1])
  47. def _fuse_bn_tensor(self, branch):
  48. if branch is None:
  49. return 0, 0
  50. if isinstance(branch, Conv):
  51. kernel = branch.conv.weight
  52. running_mean = branch.bn.running_mean
  53. running_var = branch.bn.running_var
  54. gamma = branch.bn.weight
  55. beta = branch.bn.bias
  56. eps = branch.bn.eps
  57. elif isinstance(branch, nn.BatchNorm2d):
  58. if not hasattr(self, 'id_tensor'):
  59. input_dim = self.c1 // self.g
  60. kernel_value = np.zeros((self.c1, input_dim, 3, 3), dtype=np.float32)
  61. for i in range(self.c1):
  62. kernel_value[i, i % input_dim, 1, 1] = 1
  63. self.id_tensor = torch.from_numpy(kernel_value).to(branch.weight.device)
  64. kernel = self.id_tensor
  65. running_mean = branch.running_mean
  66. running_var = branch.running_var
  67. gamma = branch.weight
  68. beta = branch.bias
  69. eps = branch.eps
  70. std = (running_var + eps).sqrt()
  71. t = (gamma / std).reshape(-1, 1, 1, 1)
  72. return kernel * t, beta - running_mean * gamma / std
  73. def switch_to_deploy(self):
  74. if hasattr(self, 'conv'):
  75. return
  76. kernel, bias = self.get_equivalent_kernel_bias()
  77. self.conv = nn.Conv2d(in_channels=self.conv1.conv.in_channels,
  78. out_channels=self.conv1.conv.out_channels,
  79. kernel_size=self.conv1.conv.kernel_size,
  80. stride=self.conv1.conv.stride,
  81. padding=self.conv1.conv.padding,
  82. dilation=self.conv1.conv.dilation,
  83. groups=self.conv1.conv.groups,
  84. bias=True).requires_grad_(False)
  85. self.conv.weight.data = kernel
  86. self.conv.bias.data = bias
  87. for para in self.parameters():
  88. para.detach_()
  89. self.__delattr__('conv1')
  90. self.__delattr__('conv2')
  91. if hasattr(self, 'nm'):
  92. self.__delattr__('nm')
  93. if hasattr(self, 'bn'):
  94. self.__delattr__('bn')
  95. if hasattr(self, 'id_tensor'):
  96. self.__delattr__('id_tensor')
  97. class RepNBottleneck(nn.Module):
  98. # Standard bottleneck
  99. def __init__(self, c1, c2, shortcut=True, g=1, k=(3, 3), e=0.5): # ch_in, ch_out, shortcut, kernels, groups, expand
  100. super().__init__()
  101. c_ = int(c2 * e) # hidden channels
  102. self.cv1 = RepConvN(c1, c_, k[0], 1)
  103. self.cv2 = Conv(c_, c2, k[1], 1, g=g)
  104. self.add = shortcut and c1 == c2
  105. def forward(self, x):
  106. return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))
  107. class RepNCSP(nn.Module):
  108. # CSP Bottleneck with 3 convolutions
  109. def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion
  110. super().__init__()
  111. c_ = int(c2 * e) # hidden channels
  112. self.cv1 = Conv(c1, c_, 1, 1)
  113. self.cv2 = Conv(c1, c_, 1, 1)
  114. self.cv3 = Conv(2 * c_, c2, 1) # optional act=FReLU(c2)
  115. self.m = nn.Sequential(*(RepNBottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n)))
  116. def forward(self, x):
  117. return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), 1))
  118. class RepNCSPELAN4(nn.Module):
  119. # csp-elan
  120. def __init__(self, c1, c2, c3, c4, c5=1): # ch_in, ch_out, number, shortcut, groups, expansion
  121. super().__init__()
  122. self.c = c3//2
  123. self.cv1 = Conv(c1, c3, 1, 1)
  124. self.cv2 = nn.Sequential(RepNCSP(c3//2, c4, c5), Conv(c4, c4, 3, 1))
  125. self.cv3 = nn.Sequential(RepNCSP(c4, c4, c5), Conv(c4, c4, 3, 1))
  126. self.cv4 = Conv(c3+(2*c4), c2, 1, 1)
  127. def forward(self, x):
  128. y = list(self.cv1(x).chunk(2, 1))
  129. y.extend((m(y[-1])) for m in [self.cv2, self.cv3])
  130. return self.cv4(torch.cat(y, 1))
  131. def forward_split(self, x):
  132. y = list(self.cv1(x).split((self.c, self.c), 1))
  133. y.extend(m(y[-1]) for m in [self.cv2, self.cv3])
  134. return self.cv4(torch.cat(y, 1))
  1. # Ultralytics YOLO
    声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/710609
    推荐阅读
    相关标签