res2net.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. # Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. from __future__ import absolute_import
  15. from __future__ import division
  16. from __future__ import print_function
  17. from paddle import fluid
  18. from ppdet.core.workspace import register, serializable
  19. from .nonlocal_helper import add_space_nonlocal
  20. from .resnet import ResNet
  21. __all__ = ['Res2Net', 'Res2NetC5']
  22. @register
  23. @serializable
  24. class Res2Net(ResNet):
  25. """
  26. Res2Net, see https://arxiv.org/abs/1904.01169
  27. Args:
  28. depth (int): Res2Net depth, should be 50, 101, 152, 200.
  29. width (int): Res2Net width
  30. scales (int): Res2Net scale
  31. freeze_at (int): freeze the backbone at which stage
  32. norm_type (str): normalization type, 'bn'/'sync_bn'/'affine_channel'
  33. freeze_norm (bool): freeze normalization layers
  34. norm_decay (float): weight decay for normalization layer weights
  35. variant (str): Res2Net variant, supports 'a', 'b', 'c', 'd' currently
  36. feature_maps (list): index of stages whose feature maps are returned
  37. dcn_v2_stages (list): index of stages who select deformable conv v2
  38. nonlocal_stages (list): index of stages who select nonlocal networks
  39. """
  40. __shared__ = ['norm_type', 'freeze_norm', 'weight_prefix_name']
  41. def __init__(
  42. self,
  43. depth=50,
  44. width=26,
  45. scales=4,
  46. freeze_at=2,
  47. norm_type='bn',
  48. freeze_norm=True,
  49. norm_decay=0.,
  50. variant='b',
  51. feature_maps=[2, 3, 4, 5],
  52. dcn_v2_stages=[],
  53. weight_prefix_name='',
  54. nonlocal_stages=[], ):
  55. super(Res2Net, self).__init__(
  56. depth=depth,
  57. freeze_at=freeze_at,
  58. norm_type=norm_type,
  59. freeze_norm=freeze_norm,
  60. norm_decay=norm_decay,
  61. variant=variant,
  62. feature_maps=feature_maps,
  63. dcn_v2_stages=dcn_v2_stages,
  64. weight_prefix_name=weight_prefix_name,
  65. nonlocal_stages=nonlocal_stages)
  66. assert depth >= 50, "just support depth>=50 in res2net, but got depth=".format(
  67. depth)
  68. # res2net config
  69. self.scales = scales
  70. self.width = width
  71. basic_width = self.width * self.scales
  72. self.num_filters1 = [basic_width * t for t in [1, 2, 4, 8]]
  73. self.num_filters2 = [256 * t for t in [1, 2, 4, 8]]
  74. self.num_filters = [64, 128, 384, 768]
  75. def bottleneck(self,
  76. input,
  77. num_filters1,
  78. num_filters2,
  79. stride,
  80. is_first,
  81. name,
  82. dcn_v2=False):
  83. conv0 = self._conv_norm(
  84. input=input,
  85. num_filters=num_filters1,
  86. filter_size=1,
  87. stride=1,
  88. act='relu',
  89. name=name + '_branch2a')
  90. xs = fluid.layers.split(conv0, self.scales, 1)
  91. ys = []
  92. for s in range(self.scales - 1):
  93. if s == 0 or stride == 2:
  94. ys.append(
  95. self._conv_norm(
  96. input=xs[s],
  97. num_filters=num_filters1 // self.scales,
  98. stride=stride,
  99. filter_size=3,
  100. act='relu',
  101. name=name + '_branch2b_' + str(s + 1),
  102. dcn_v2=dcn_v2))
  103. else:
  104. ys.append(
  105. self._conv_norm(
  106. input=xs[s] + ys[-1],
  107. num_filters=num_filters1 // self.scales,
  108. stride=stride,
  109. filter_size=3,
  110. act='relu',
  111. name=name + '_branch2b_' + str(s + 1),
  112. dcn_v2=dcn_v2))
  113. if stride == 1:
  114. ys.append(xs[-1])
  115. else:
  116. ys.append(
  117. fluid.layers.pool2d(
  118. input=xs[-1],
  119. pool_size=3,
  120. pool_stride=stride,
  121. pool_padding=1,
  122. pool_type='avg'))
  123. conv1 = fluid.layers.concat(ys, axis=1)
  124. conv2 = self._conv_norm(
  125. input=conv1,
  126. num_filters=num_filters2,
  127. filter_size=1,
  128. act=None,
  129. name=name + "_branch2c")
  130. short = self._shortcut(
  131. input, num_filters2, stride, is_first, name=name + "_branch1")
  132. return fluid.layers.elementwise_add(
  133. x=short, y=conv2, act='relu', name=name + ".add.output.5")
  134. def layer_warp(self, input, stage_num):
  135. """
  136. Args:
  137. input (Variable): input variable.
  138. stage_num (int): the stage number, should be 2, 3, 4, 5
  139. Returns:
  140. The last variable in endpoint-th stage.
  141. """
  142. assert stage_num in [2, 3, 4, 5]
  143. stages, block_func = self.depth_cfg[self.depth]
  144. count = stages[stage_num - 2]
  145. ch_out = self.stage_filters[stage_num - 2]
  146. is_first = False if stage_num != 2 else True
  147. dcn_v2 = True if stage_num in self.dcn_v2_stages else False
  148. num_filters1 = self.num_filters1[stage_num - 2]
  149. num_filters2 = self.num_filters2[stage_num - 2]
  150. nonlocal_mod = 1000
  151. if stage_num in self.nonlocal_stages:
  152. nonlocal_mod = self.nonlocal_mod_cfg[
  153. self.depth] if stage_num == 4 else 2
  154. # Make the layer name and parameter name consistent
  155. # with ImageNet pre-trained model
  156. conv = input
  157. for i in range(count):
  158. conv_name = self.na.fix_layer_warp_name(stage_num, count, i)
  159. if self.depth < 50:
  160. is_first = True if i == 0 and stage_num == 2 else False
  161. conv = block_func(
  162. input=conv,
  163. num_filters1=num_filters1,
  164. num_filters2=num_filters2,
  165. stride=2 if i == 0 and stage_num != 2 else 1,
  166. is_first=is_first,
  167. name=conv_name,
  168. dcn_v2=dcn_v2)
  169. # add non local model
  170. dim_in = conv.shape[1]
  171. nonlocal_name = "nonlocal_conv{}".format(stage_num)
  172. if i % nonlocal_mod == nonlocal_mod - 1:
  173. conv = add_space_nonlocal(conv, dim_in, dim_in,
  174. nonlocal_name + '_{}'.format(i),
  175. int(dim_in / 2))
  176. return conv
  177. @register
  178. @serializable
  179. class Res2NetC5(Res2Net):
  180. __doc__ = Res2Net.__doc__
  181. def __init__(self,
  182. depth=50,
  183. width=26,
  184. scales=4,
  185. freeze_at=2,
  186. norm_type='bn',
  187. freeze_norm=True,
  188. norm_decay=0.,
  189. variant='b',
  190. feature_maps=[5],
  191. weight_prefix_name=''):
  192. super(Res2NetC5, self).__init__(depth, width, scales, freeze_at,
  193. norm_type, freeze_norm, norm_decay,
  194. variant, feature_maps)
  195. self.severed_head = True