gelan_backbone.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. import torch
  2. import torch.nn as nn
  3. try:
  4. from .modules import ConvModule, RepGElanLayer, ADown
  5. except:
  6. from modules import ConvModule, RepGElanLayer, ADown
  7. # IN1K pretrained weight
  8. pretrained_urls = {
  9. 's': "https://github.com/yjh0410/YOLO-Tutorial-v2/releases/download/in1k_pretrained_weight/gelan_s_in1k_68.4.pth",
  10. 'c': "https://github.com/yjh0410/YOLO-Tutorial-v2/releases/download/in1k_pretrained_weight/gelan_c_in1k_76.7.pth",
  11. }
  12. # ----------------- GELAN backbone proposed by YOLOv9 -----------------
  13. class GElanBackbone(nn.Module):
  14. def __init__(self, cfg):
  15. super(GElanBackbone, self).__init__()
  16. # ---------- Basic setting ----------
  17. self.model_scale = cfg.model_scale
  18. self.feat_dims = [cfg.backbone_feats["c1"][-1], # 64
  19. cfg.backbone_feats["c2"][-1], # 128
  20. cfg.backbone_feats["c3"][-1], # 256
  21. cfg.backbone_feats["c4"][-1], # 512
  22. cfg.backbone_feats["c5"][-1], # 512
  23. ]
  24. # ---------- Network setting ----------
  25. ## P1/2
  26. self.layer_1 = ConvModule(3, cfg.backbone_feats["c1"][0], kernel_size=3, padding=1, stride=2)
  27. # P2/4
  28. self.layer_2 = nn.Sequential(
  29. ConvModule(cfg.backbone_feats["c1"][0], cfg.backbone_feats["c2"][0], kernel_size=3, padding=1, stride=2),
  30. RepGElanLayer(in_dim = cfg.backbone_feats["c2"][0],
  31. inter_dims = cfg.backbone_feats["c2"][1],
  32. out_dim = cfg.backbone_feats["c2"][2],
  33. num_blocks = cfg.backbone_depth,
  34. shortcut = True,
  35. )
  36. )
  37. # P3/8
  38. self.layer_3 = nn.Sequential(
  39. ADown(cfg.backbone_feats["c2"][2], cfg.backbone_feats["c3"][0]),
  40. RepGElanLayer(in_dim = cfg.backbone_feats["c3"][0],
  41. inter_dims = cfg.backbone_feats["c3"][1],
  42. out_dim = cfg.backbone_feats["c3"][2],
  43. num_blocks = cfg.backbone_depth,
  44. shortcut = True,
  45. )
  46. )
  47. # P4/16
  48. self.layer_4 = nn.Sequential(
  49. ADown(cfg.backbone_feats["c3"][2], cfg.backbone_feats["c4"][0]),
  50. RepGElanLayer(in_dim = cfg.backbone_feats["c4"][0],
  51. inter_dims = cfg.backbone_feats["c4"][1],
  52. out_dim = cfg.backbone_feats["c4"][2],
  53. num_blocks = cfg.backbone_depth,
  54. shortcut = True,
  55. )
  56. )
  57. # P5/32
  58. self.layer_5 = nn.Sequential(
  59. ADown(cfg.backbone_feats["c4"][2], cfg.backbone_feats["c5"][0]),
  60. RepGElanLayer(in_dim = cfg.backbone_feats["c5"][0],
  61. inter_dims = cfg.backbone_feats["c5"][1],
  62. out_dim = cfg.backbone_feats["c5"][2],
  63. num_blocks = cfg.backbone_depth,
  64. shortcut = True,
  65. )
  66. )
  67. # Initialize all layers
  68. self.init_weights()
  69. # Load imagenet pretrained weight
  70. if cfg.use_pretrained:
  71. self.load_pretrained()
  72. def init_weights(self):
  73. """Initialize the parameters."""
  74. for m in self.modules():
  75. if isinstance(m, torch.nn.Conv2d):
  76. m.reset_parameters()
  77. def load_pretrained(self):
  78. url = pretrained_urls[self.model_scale]
  79. if url is not None:
  80. print('Loading backbone pretrained weight from : {}'.format(url))
  81. # checkpoint state dict
  82. checkpoint = torch.hub.load_state_dict_from_url(
  83. url=url, map_location="cpu", check_hash=True)
  84. checkpoint_state_dict = checkpoint.pop("model")
  85. # model state dict
  86. model_state_dict = self.state_dict()
  87. # check
  88. for k in list(checkpoint_state_dict.keys()):
  89. if k in model_state_dict:
  90. shape_model = tuple(model_state_dict[k].shape)
  91. shape_checkpoint = tuple(checkpoint_state_dict[k].shape)
  92. if shape_model != shape_checkpoint:
  93. checkpoint_state_dict.pop(k)
  94. else:
  95. checkpoint_state_dict.pop(k)
  96. print('Unused key: ', k)
  97. # load the weight
  98. self.load_state_dict(checkpoint_state_dict)
  99. else:
  100. print('No pretrained weight for model scale: {}.'.format(self.model_scale))
  101. def forward(self, x):
  102. c1 = self.layer_1(x)
  103. c2 = self.layer_2(c1)
  104. c3 = self.layer_3(c2)
  105. c4 = self.layer_4(c3)
  106. c5 = self.layer_5(c4)
  107. outputs = [c3, c4, c5]
  108. return outputs
  109. if __name__ == '__main__':
  110. import time
  111. from thop import profile
  112. class BaseConfig(object):
  113. def __init__(self) -> None:
  114. self.use_pretrained = True
  115. # # Gelan-C scale
  116. # self.backbone_feats = {
  117. # "c1": [64],
  118. # "c2": [128, [128, 64], 256],
  119. # "c3": [256, [256, 128], 512],
  120. # "c4": [512, [512, 256], 512],
  121. # "c5": [512, [512, 256], 512],
  122. # }
  123. # self.model_scale = "c"
  124. # self.backbone_depth = 1
  125. # Gelan-S scale
  126. self.backbone_feats = {
  127. "c1": [32],
  128. "c2": [64, [64, 32], 64],
  129. "c3": [64, [64, 32], 128],
  130. "c4": [128, [128, 64], 256],
  131. "c5": [256, [256, 128], 256],
  132. }
  133. self.model_scale = "s"
  134. self.backbone_depth = 3
  135. # 定义模型配置文件
  136. cfg = BaseConfig()
  137. # 构建GELAN主干网络
  138. model = GElanBackbone(cfg)
  139. # 随机生成输入数据
  140. x = torch.randn(1, 3, 640, 640)
  141. # 前向推理
  142. outputs = model(x)
  143. # 打印输出中的shape
  144. for out in outputs:
  145. print(out.shape)
  146. # 计算模型的参数量和理论计算量
  147. print('============ Params & FLOPs ============')
  148. flops, params = profile(model, inputs=(x, ), verbose=False)
  149. print('GFLOPs : {:.2f}'.format(flops / 1e9 * 2))
  150. print('Params : {:.2f} M'.format(params / 1e6))