当前位置:   article > 正文

YOLOv8添加DCNv2可变形卷积_c2f_dcn

c2f_dcn

最近比较火的可变形卷积(Deformable Convolutional Networks(DCN))被称为目标检测改进网络结构的中涨点神器,确实在yolov8中加入DCN3可以涨3到4个点,尤其是它对小目标检测效果较好。下面是对DCNv2添加记录一下

首先我们要在nn/models/文件夹下block.py文件中加入以下代码

  1. class DCNv2(nn.Module):
  2. def __init__(self, in_channels, out_channels, kernel_size, stride=1,
  3. padding=1, dilation=1, groups=1, deformable_groups=1):
  4. super(DCNv2, self).__init__()
  5. self.in_channels = in_channels
  6. self.out_channels = out_channels
  7. self.kernel_size = (kernel_size, kernel_size)
  8. self.stride = (stride, stride)
  9. self.padding = (padding, padding)
  10. self.dilation = (dilation, dilation)
  11. self.groups = groups
  12. self.deformable_groups = deformable_groups
  13. self.weight = nn.Parameter(
  14. torch.empty(out_channels, in_channels, *self.kernel_size)
  15. )
  16. self.bias = nn.Parameter(torch.empty(out_channels))
  17. out_channels_offset_mask = (self.deformable_groups * 3 *
  18. self.kernel_size[0] * self.kernel_size[1])
  19. self.conv_offset_mask = nn.Conv2d(
  20. self.in_channels,
  21. out_channels_offset_mask,
  22. kernel_size=self.kernel_size,
  23. stride=self.stride,
  24. padding=self.padding,
  25. bias=True,
  26. )
  27. self.bn = nn.BatchNorm2d(out_channels)
  28. self.act = Conv.default_act
  29. self.reset_parameters()
  30. def forward(self, x):
  31. offset_mask = self.conv_offset_mask(x)
  32. o1, o2, mask = torch.chunk(offset_mask, 3, dim=1)
  33. offset = torch.cat((o1, o2), dim=1)
  34. mask = torch.sigmoid(mask)
  35. x = torch.ops.torchvision.deform_conv2d(
  36. x,
  37. self.weight,
  38. offset,
  39. mask,
  40. self.bias,
  41. self.stride[0], self.stride[1],
  42. self.padding[0], self.padding[1],
  43. self.dilation[0], self.dilation[1],
  44. self.groups,
  45. self.deformable_groups,
  46. True
  47. )
  48. x = self.bn(x)
  49. x = self.act(x)
  50. return x
  51. def reset_parameters(self):
  52. n = self.in_channels
  53. for k in self.kernel_size:
  54. n *= k
  55. std = 1. / math.sqrt(n)
  56. self.weight.data.uniform_(-std, std)
  57. self.bias.data.zero_()
  58. self.conv_offset_mask.weight.data.zero_()
  59. self.conv_offset_mask.bias.data.zero_()
  60. class Bottleneck_DCN(nn.Module):
  61. # Standard bottleneck with DCN
  62. def __init__(self, c1, c2, shortcut=True, g=1, k=(3, 3), e=0.5): # ch_in, ch_out, shortcut, groups, kernels, expand
  63. super().__init__()
  64. c_ = int(c2 * e) # hidden channels
  65. if k[0] == 3:
  66. self.cv1 = DCNv2(c1, c_, k[0], 1)
  67. else:
  68. self.cv1 = Conv(c1, c_, k[0], 1)
  69. if k[1] == 3:
  70. self.cv2 = DCNv2(c_, c2, k[1], 1, groups=g)
  71. else:
  72. self.cv2 = Conv(c_, c2, k[1], 1, g=g)
  73. self.add = shortcut and c1 == c2
  74. def forward(self, x):
  75. return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))
  76. class C2f_DCN(nn.Module):
  77. # CSP Bottleneck with 2 convolutions
  78. def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion
  79. super().__init__()
  80. self.c = int(c2 * e) # hidden channels
  81. self.cv1 = Conv(c1, 2 * self.c, 1, 1)
  82. self.cv2 = Conv((2 + n) * self.c, c2, 1) # optional act=FReLU(c2)
  83. self.m = nn.ModuleList(Bottleneck_DCN(self.c, self.c, shortcut, g, k=(3, 3), e=1.0) for _ in range(n))
  84. def forward(self, x):
  85. y = list(self.cv1(x).split((self.c, self.c), 1))
  86. y.extend(m(y[-1]) for m in self.m)
  87. return self.cv2(torch.cat(y, 1))

然后在tasks.py文件

这三处()里都加上C2f_DCN,接着在modules文件夹下的__init__.py

 

 来declare一下,否则会导入失败,至此已经差不多就ok了,现在只需要在yaml中你想要更改的网络结构的地方改一下就行,然后就可以训练了,如果不确定可以在训练的时候看一下print的网络结构即可。

下面是DCNv3的代码,操作跟上述有些不同,需要去GitHub上下载ops_dcnv3模块,然后进行编译,具体怎么弄可以私信我,如果我有时间的话,因为DCNv3配置起来还是比较麻烦的

  1. class DCNV3_YoLo(nn.Module):
  2. def __init__(self, inc, ouc, k=1, s=1, p=None, g=1, d=1, act=True):
  3. super().__init__()
  4. self.conv = Conv(inc, ouc, k=1)
  5. self.dcnv3 = DCNv3(ouc, kernel_size=k, stride=s, group=g, dilation=d)
  6. self.bn = nn.BatchNorm2d(ouc)
  7. self.act = Conv.default_act
  8. def forward(self, x):
  9. x = self.conv(x)
  10. x = x.permute(0, 2, 3, 1)
  11. x = self.dcnv3(x)
  12. x = x.permute(0, 3, 1, 2)
  13. x = self.act(self.bn(x))
  14. return x
  15. class Bottleneck_DCNV3(nn.Module):
  16. # Standard bottleneck
  17. def __init__(self, c1, c2, shortcut=True, g=1, k=(3, 3), e=0.5): # ch_in, ch_out, shortcut, groups, kernels, expand
  18. super().__init__()
  19. c_ = int(c2 * e) # hidden channels
  20. self.cv1 = Conv(c1, c_, k[0], 1)
  21. self.cv2 = DCNV3_YoLo(c_, c2, k[1], 1, g=g)
  22. self.add = shortcut and c1 == c2
  23. def forward(self, x):
  24. return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))
  25. class DCNV3(nn.Module):
  26. # CSP Bottleneck with 2 convolutions
  27. def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion
  28. super().__init__()
  29. self.c = int(c2 * e) # hidden channels
  30. self.cv1 = Conv(c1, 2 * self.c, 1, 1)
  31. self.cv2 = Conv((2 + n) * self.c, c2, 1) # optional act=FReLU(c2)
  32. self.m = nn.ModuleList(Bottleneck_DCNV3(self.c, self.c, shortcut, g, k=(3, 3), e=1.0) for _ in range(n))
  33. def forward(self, x):
  34. y = list(self.cv1(x).chunk(2, 1))
  35. y.extend(m(y[-1]) for m in self.m)
  36. return self.cv2(torch.cat(y, 1))
  37. def forward_split(self, x):
  38. y = list(self.cv1(x).split((self.c, self.c), 1))
  39. y.extend(m(y[-1]) for m in self.m)
  40. return self.cv2(torch.cat(y, 1))

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/93845
推荐阅读
相关标签
  

闽ICP备14008679号