cspresnet.py 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. # Copyright (c) 2021 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. import paddle
  18. import paddle.nn as nn
  19. import paddle.nn.functional as F
  20. from paddle import ParamAttr
  21. from paddle.regularizer import L2Decay
  22. from ppdet.modeling.ops import get_act_fn
  23. from ppdet.core.workspace import register, serializable
  24. from ..shape_spec import ShapeSpec
  25. __all__ = ['CSPResNet', 'BasicBlock', 'EffectiveSELayer', 'ConvBNLayer']
  26. class ConvBNLayer(nn.Layer):
  27. def __init__(self,
  28. ch_in,
  29. ch_out,
  30. filter_size=3,
  31. stride=1,
  32. groups=1,
  33. padding=0,
  34. act=None):
  35. super(ConvBNLayer, self).__init__()
  36. self.conv = nn.Conv2D(
  37. in_channels=ch_in,
  38. out_channels=ch_out,
  39. kernel_size=filter_size,
  40. stride=stride,
  41. padding=padding,
  42. groups=groups,
  43. bias_attr=False)
  44. self.bn = nn.BatchNorm2D(
  45. ch_out,
  46. weight_attr=ParamAttr(regularizer=L2Decay(0.0)),
  47. bias_attr=ParamAttr(regularizer=L2Decay(0.0)))
  48. self.act = get_act_fn(act) if act is None or isinstance(act, (
  49. str, dict)) else act
  50. def forward(self, x):
  51. x = self.conv(x)
  52. x = self.bn(x)
  53. x = self.act(x)
  54. return x
  55. class RepVggBlock(nn.Layer):
  56. def __init__(self, ch_in, ch_out, act='relu'):
  57. super(RepVggBlock, self).__init__()
  58. self.ch_in = ch_in
  59. self.ch_out = ch_out
  60. self.conv1 = ConvBNLayer(
  61. ch_in, ch_out, 3, stride=1, padding=1, act=None)
  62. self.conv2 = ConvBNLayer(
  63. ch_in, ch_out, 1, stride=1, padding=0, act=None)
  64. self.act = get_act_fn(act) if act is None or isinstance(act, (
  65. str, dict)) else act
  66. def forward(self, x):
  67. if hasattr(self, 'conv'):
  68. y = self.conv(x)
  69. else:
  70. y = self.conv1(x) + self.conv2(x)
  71. y = self.act(y)
  72. return y
  73. def convert_to_deploy(self):
  74. if not hasattr(self, 'conv'):
  75. self.conv = nn.Conv2D(
  76. in_channels=self.ch_in,
  77. out_channels=self.ch_out,
  78. kernel_size=3,
  79. stride=1,
  80. padding=1,
  81. groups=1)
  82. kernel, bias = self.get_equivalent_kernel_bias()
  83. self.conv.weight.set_value(kernel)
  84. self.conv.bias.set_value(bias)
  85. self.__delattr__('conv1')
  86. self.__delattr__('conv2')
  87. def get_equivalent_kernel_bias(self):
  88. kernel3x3, bias3x3 = self._fuse_bn_tensor(self.conv1)
  89. kernel1x1, bias1x1 = self._fuse_bn_tensor(self.conv2)
  90. return kernel3x3 + self._pad_1x1_to_3x3_tensor(
  91. kernel1x1), bias3x3 + bias1x1
  92. def _pad_1x1_to_3x3_tensor(self, kernel1x1):
  93. if kernel1x1 is None:
  94. return 0
  95. else:
  96. return nn.functional.pad(kernel1x1, [1, 1, 1, 1])
  97. def _fuse_bn_tensor(self, branch):
  98. if branch is None:
  99. return 0, 0
  100. kernel = branch.conv.weight
  101. running_mean = branch.bn._mean
  102. running_var = branch.bn._variance
  103. gamma = branch.bn.weight
  104. beta = branch.bn.bias
  105. eps = branch.bn._epsilon
  106. std = (running_var + eps).sqrt()
  107. t = (gamma / std).reshape((-1, 1, 1, 1))
  108. return kernel * t, beta - running_mean * gamma / std
  109. class BasicBlock(nn.Layer):
  110. def __init__(self, ch_in, ch_out, act='relu', shortcut=True):
  111. super(BasicBlock, self).__init__()
  112. assert ch_in == ch_out
  113. self.conv1 = ConvBNLayer(ch_in, ch_out, 3, stride=1, padding=1, act=act)
  114. self.conv2 = RepVggBlock(ch_out, ch_out, act=act)
  115. self.shortcut = shortcut
  116. def forward(self, x):
  117. y = self.conv1(x)
  118. y = self.conv2(y)
  119. if self.shortcut:
  120. return paddle.add(x, y)
  121. else:
  122. return y
  123. class EffectiveSELayer(nn.Layer):
  124. """ Effective Squeeze-Excitation
  125. From `CenterMask : Real-Time Anchor-Free Instance Segmentation` - https://arxiv.org/abs/1911.06667
  126. """
  127. def __init__(self, channels, act='hardsigmoid'):
  128. super(EffectiveSELayer, self).__init__()
  129. self.fc = nn.Conv2D(channels, channels, kernel_size=1, padding=0)
  130. self.act = get_act_fn(act) if act is None or isinstance(act, (
  131. str, dict)) else act
  132. def forward(self, x):
  133. x_se = x.mean((2, 3), keepdim=True)
  134. x_se = self.fc(x_se)
  135. return x * self.act(x_se)
  136. class CSPResStage(nn.Layer):
  137. def __init__(self,
  138. block_fn,
  139. ch_in,
  140. ch_out,
  141. n,
  142. stride,
  143. act='relu',
  144. attn='eca'):
  145. super(CSPResStage, self).__init__()
  146. ch_mid = (ch_in + ch_out) // 2
  147. if stride == 2:
  148. self.conv_down = ConvBNLayer(
  149. ch_in, ch_mid, 3, stride=2, padding=1, act=act)
  150. else:
  151. self.conv_down = None
  152. self.conv1 = ConvBNLayer(ch_mid, ch_mid // 2, 1, act=act)
  153. self.conv2 = ConvBNLayer(ch_mid, ch_mid // 2, 1, act=act)
  154. self.blocks = nn.Sequential(*[
  155. block_fn(
  156. ch_mid // 2, ch_mid // 2, act=act, shortcut=True)
  157. for i in range(n)
  158. ])
  159. if attn:
  160. self.attn = EffectiveSELayer(ch_mid, act='hardsigmoid')
  161. else:
  162. self.attn = None
  163. self.conv3 = ConvBNLayer(ch_mid, ch_out, 1, act=act)
  164. def forward(self, x):
  165. if self.conv_down is not None:
  166. x = self.conv_down(x)
  167. y1 = self.conv1(x)
  168. y2 = self.blocks(self.conv2(x))
  169. y = paddle.concat([y1, y2], axis=1)
  170. if self.attn is not None:
  171. y = self.attn(y)
  172. y = self.conv3(y)
  173. return y
  174. @register
  175. @serializable
  176. class CSPResNet(nn.Layer):
  177. __shared__ = ['width_mult', 'depth_mult', 'trt']
  178. def __init__(self,
  179. layers=[3, 6, 6, 3],
  180. channels=[64, 128, 256, 512, 1024],
  181. act='swish',
  182. return_idx=[0, 1, 2, 3, 4],
  183. depth_wise=False,
  184. use_large_stem=False,
  185. width_mult=1.0,
  186. depth_mult=1.0,
  187. trt=False):
  188. super(CSPResNet, self).__init__()
  189. channels = [max(round(c * width_mult), 1) for c in channels]
  190. layers = [max(round(l * depth_mult), 1) for l in layers]
  191. act = get_act_fn(
  192. act, trt=trt) if act is None or isinstance(act,
  193. (str, dict)) else act
  194. if use_large_stem:
  195. self.stem = nn.Sequential(
  196. ('conv1', ConvBNLayer(
  197. 3, channels[0] // 2, 3, stride=2, padding=1, act=act)),
  198. ('conv2', ConvBNLayer(
  199. channels[0] // 2,
  200. channels[0] // 2,
  201. 3,
  202. stride=1,
  203. padding=1,
  204. act=act)), ('conv3', ConvBNLayer(
  205. channels[0] // 2,
  206. channels[0],
  207. 3,
  208. stride=1,
  209. padding=1,
  210. act=act)))
  211. else:
  212. self.stem = nn.Sequential(
  213. ('conv1', ConvBNLayer(
  214. 3, channels[0] // 2, 3, stride=2, padding=1, act=act)),
  215. ('conv2', ConvBNLayer(
  216. channels[0] // 2,
  217. channels[0],
  218. 3,
  219. stride=1,
  220. padding=1,
  221. act=act)))
  222. n = len(channels) - 1
  223. self.stages = nn.Sequential(*[(str(i), CSPResStage(
  224. BasicBlock, channels[i], channels[i + 1], layers[i], 2, act=act))
  225. for i in range(n)])
  226. self._out_channels = channels[1:]
  227. self._out_strides = [4, 8, 16, 32]
  228. self.return_idx = return_idx
  229. def forward(self, inputs):
  230. x = inputs['image']
  231. x = self.stem(x)
  232. outs = []
  233. for idx, stage in enumerate(self.stages):
  234. x = stage(x)
  235. if idx in self.return_idx:
  236. outs.append(x)
  237. return outs
  238. @property
  239. def out_shape(self):
  240. return [
  241. ShapeSpec(
  242. channels=self._out_channels[i], stride=self._out_strides[i])
  243. for i in self.return_idx
  244. ]