yolov7_af_backbone.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. import torch
  2. import torch.nn as nn
  3. try:
  4. from .yolov7_af_basic import BasicConv, MDown, ELANLayer
  5. except:
  6. from yolov7_af_basic import BasicConv, MDown, ELANLayer
  7. # ELANNet
  8. class Yolov7TBackbone(nn.Module):
  9. def __init__(self, cfg):
  10. super(Yolov7TBackbone, self).__init__()
  11. # ---------------- Basic parameters ----------------
  12. self.model_scale = cfg.scale
  13. self.bk_act = cfg.bk_act
  14. self.bk_norm = cfg.bk_norm
  15. self.bk_depthwise = cfg.bk_depthwise
  16. self.elan_depth = 1
  17. self.feat_dims = [round(64 * cfg.width), round(128 * cfg.width),
  18. round(256 * cfg.width), round(512 * cfg.width), round(1024 * cfg.width)]
  19. # ---------------- Model parameters ----------------
  20. self.layer_1 = self.make_stem(3, self.feat_dims[0])
  21. self.layer_2 = self.make_block(self.feat_dims[0], self.feat_dims[1], expansion=0.5)
  22. self.layer_3 = self.make_block(self.feat_dims[1], self.feat_dims[2], expansion=0.5)
  23. self.layer_4 = self.make_block(self.feat_dims[2], self.feat_dims[3], expansion=0.5)
  24. self.layer_5 = self.make_block(self.feat_dims[3], self.feat_dims[4], expansion=0.5)
  25. # Initialize all layers
  26. self.init_weights()
  27. def init_weights(self):
  28. """Initialize the parameters."""
  29. for m in self.modules():
  30. if isinstance(m, torch.nn.Conv2d):
  31. # In order to be consistent with the source code,
  32. # reset the Conv2d initialization parameters
  33. m.reset_parameters()
  34. def make_stem(self, in_dim, out_dim):
  35. stem = BasicConv(in_dim, out_dim, kernel_size=6, padding=2, stride=2,
  36. act_type=self.bk_act, norm_type=self.bk_norm, depthwise=self.bk_depthwise)
  37. return stem
  38. def make_block(self, in_dim, out_dim, expansion=0.5):
  39. block = nn.Sequential(
  40. nn.MaxPool2d((2, 2), stride=2),
  41. ELANLayer(in_dim, out_dim,
  42. expansion=expansion, num_blocks=self.elan_depth,
  43. act_type=self.bk_act, norm_type=self.bk_norm, depthwise=self.bk_depthwise),
  44. )
  45. return block
  46. def forward(self, x):
  47. c1 = self.layer_1(x)
  48. c2 = self.layer_2(c1)
  49. c3 = self.layer_3(c2)
  50. c4 = self.layer_4(c3)
  51. c5 = self.layer_5(c4)
  52. outputs = [c3, c4, c5]
  53. return outputs
  54. class Yolov7LBackbone(nn.Module):
  55. def __init__(self, cfg):
  56. super(Yolov7LBackbone, self).__init__()
  57. # ---------------- Basic parameters ----------------
  58. self.model_scale = cfg.scale
  59. self.bk_act = cfg.bk_act
  60. self.bk_norm = cfg.bk_norm
  61. self.bk_depthwise = cfg.bk_depthwise
  62. self.elan_depth = 2
  63. self.feat_dims = [round(64 * cfg.width), round(128 * cfg.width), round(256 * cfg.width),
  64. round(512 * cfg.width), round(1024 * cfg.width), round(1024 * cfg.width)]
  65. # ---------------- Model parameters ----------------
  66. self.layer_1 = self.make_stem(3, self.feat_dims[0])
  67. self.layer_2 = self.make_block(self.feat_dims[0], self.feat_dims[1], self.feat_dims[2], expansion=0.5, conv_downsample=True)
  68. self.layer_3 = self.make_block(self.feat_dims[2], self.feat_dims[2], self.feat_dims[3], expansion=0.5)
  69. self.layer_4 = self.make_block(self.feat_dims[3], self.feat_dims[3], self.feat_dims[4], expansion=0.5)
  70. self.layer_5 = self.make_block(self.feat_dims[4], self.feat_dims[4], self.feat_dims[5], expansion=0.25)
  71. # Initialize all layers
  72. self.init_weights()
  73. def init_weights(self):
  74. """Initialize the parameters."""
  75. for m in self.modules():
  76. if isinstance(m, torch.nn.Conv2d):
  77. # In order to be consistent with the source code,
  78. # reset the Conv2d initialization parameters
  79. m.reset_parameters()
  80. def make_stem(self, in_dim, out_dim):
  81. stem = nn.Sequential(
  82. BasicConv(in_dim, out_dim//2, kernel_size=3, padding=1, stride=1,
  83. act_type=self.bk_act, norm_type=self.bk_norm, depthwise=self.bk_depthwise),
  84. BasicConv(out_dim//2, out_dim, kernel_size=3, padding=1, stride=2,
  85. act_type=self.bk_act, norm_type=self.bk_norm, depthwise=self.bk_depthwise),
  86. BasicConv(out_dim, out_dim, kernel_size=3, padding=1, stride=1,
  87. act_type=self.bk_act, norm_type=self.bk_norm, depthwise=self.bk_depthwise)
  88. )
  89. return stem
  90. def make_block(self, in_dim, out_dim_1, out_dim_2, expansion=0.5, conv_downsample=False):
  91. if conv_downsample:
  92. block = nn.Sequential(
  93. BasicConv(in_dim, out_dim_1, kernel_size=3, padding=1, stride=2,
  94. act_type=self.bk_act, norm_type=self.bk_norm, depthwise=self.bk_depthwise),
  95. ELANLayer(out_dim_1, out_dim_2,
  96. expansion=expansion, num_blocks=self.elan_depth,
  97. act_type=self.bk_act, norm_type=self.bk_norm, depthwise=self.bk_depthwise),
  98. )
  99. else:
  100. block = nn.Sequential(
  101. MDown(in_dim, out_dim_1,
  102. act_type=self.bk_act, norm_type=self.bk_norm, depthwise=self.bk_depthwise),
  103. ELANLayer(out_dim_1, out_dim_2,
  104. expansion=expansion, num_blocks=self.elan_depth,
  105. act_type=self.bk_act, norm_type=self.bk_norm, depthwise=self.bk_depthwise),
  106. )
  107. return block
  108. def forward(self, x):
  109. c1 = self.layer_1(x)
  110. c2 = self.layer_2(c1)
  111. c3 = self.layer_3(c2)
  112. c4 = self.layer_4(c3)
  113. c5 = self.layer_5(c4)
  114. outputs = [c3, c4, c5]
  115. return outputs
  116. if __name__ == '__main__':
  117. import time
  118. from thop import profile
  119. class BaseConfig(object):
  120. def __init__(self) -> None:
  121. self.bk_act = 'silu'
  122. self.bk_norm = 'BN'
  123. self.bk_depthwise = False
  124. self.width = 1.0
  125. self.depth = 0.34
  126. self.scale = "l"
  127. cfg = BaseConfig()
  128. model = Yolov7LBackbone(cfg)
  129. x = torch.randn(1, 3, 640, 640)
  130. t0 = time.time()
  131. outputs = model(x)
  132. t1 = time.time()
  133. print('Time: ', t1 - t0)
  134. for out in outputs:
  135. print(out.shape)
  136. x = torch.randn(1, 3, 640, 640)
  137. print('==============================')
  138. flops, params = profile(model, inputs=(x, ), verbose=False)
  139. print('==============================')
  140. print('GFLOPs : {:.2f}'.format(flops / 1e9 * 2))
  141. print('Params : {:.2f} M'.format(params / 1e6))