hourglass.py 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. # Copyright (c) 2020 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 paddle.fluid.param_attr import ParamAttr
  19. from paddle.fluid.initializer import Uniform
  20. from ppdet.core.workspace import register
  21. __all__ = ['Hourglass']
  22. def kaiming_init(input, filter_size):
  23. fan_in = input.shape[1]
  24. std = (1.0 / (fan_in * filter_size * filter_size))**0.5
  25. return Uniform(0. - std, std)
  26. def _conv_norm(x,
  27. k,
  28. out_dim,
  29. stride=1,
  30. pad=0,
  31. groups=None,
  32. with_bn=True,
  33. bn_act=None,
  34. ind=None,
  35. name=None):
  36. conv_name = "_conv" if ind is None else "_conv" + str(ind)
  37. bn_name = "_bn" if ind is None else "_bn" + str(ind)
  38. conv = fluid.layers.conv2d(
  39. input=x,
  40. filter_size=k,
  41. num_filters=out_dim,
  42. stride=stride,
  43. padding=pad,
  44. groups=groups,
  45. param_attr=ParamAttr(
  46. name=name + conv_name + "_weight", initializer=kaiming_init(x, k)),
  47. bias_attr=ParamAttr(
  48. name=name + conv_name + "_bias", initializer=kaiming_init(x, k))
  49. if not with_bn else False,
  50. name=name + '_output')
  51. if with_bn:
  52. pattr = ParamAttr(name=name + bn_name + '_weight')
  53. battr = ParamAttr(name=name + bn_name + '_bias')
  54. out = fluid.layers.batch_norm(
  55. input=conv,
  56. act=bn_act,
  57. name=name + '_bn_output',
  58. param_attr=pattr,
  59. bias_attr=battr,
  60. moving_mean_name=name + bn_name + '_running_mean',
  61. moving_variance_name=name + bn_name +
  62. '_running_var') if with_bn else conv
  63. else:
  64. out = fluid.layers.relu(conv)
  65. return out
  66. def residual_block(x, out_dim, k=3, stride=1, name=None):
  67. p = (k - 1) // 2
  68. conv1 = _conv_norm(
  69. x, k, out_dim, pad=p, stride=stride, bn_act='relu', ind=1, name=name)
  70. conv2 = _conv_norm(conv1, k, out_dim, pad=p, ind=2, name=name)
  71. skip = _conv_norm(
  72. x, 1, out_dim, stride=stride,
  73. name=name + '_skip') if stride != 1 or x.shape[1] != out_dim else x
  74. return fluid.layers.elementwise_add(
  75. x=skip, y=conv2, act='relu', name=name + "_add")
  76. def fire_block(x, out_dim, sr=2, stride=1, name=None):
  77. conv1 = _conv_norm(x, 1, out_dim // sr, ind=1, name=name)
  78. conv_1x1 = fluid.layers.conv2d(
  79. conv1,
  80. filter_size=1,
  81. num_filters=out_dim // 2,
  82. stride=stride,
  83. param_attr=ParamAttr(
  84. name=name + "_conv_1x1_weight", initializer=kaiming_init(conv1, 1)),
  85. bias_attr=False,
  86. name=name + '_conv_1x1')
  87. conv_3x3 = fluid.layers.conv2d(
  88. conv1,
  89. filter_size=3,
  90. num_filters=out_dim // 2,
  91. stride=stride,
  92. padding=1,
  93. groups=out_dim // sr,
  94. param_attr=ParamAttr(
  95. name=name + "_conv_3x3_weight", initializer=kaiming_init(conv1, 3)),
  96. bias_attr=False,
  97. name=name + '_conv_3x3',
  98. use_cudnn=False)
  99. conv2 = fluid.layers.concat(
  100. [conv_1x1, conv_3x3], axis=1, name=name + '_conv2')
  101. pattr = ParamAttr(name=name + '_bn2_weight')
  102. battr = ParamAttr(name=name + '_bn2_bias')
  103. bn2 = fluid.layers.batch_norm(
  104. input=conv2,
  105. name=name + '_bn2',
  106. param_attr=pattr,
  107. bias_attr=battr,
  108. moving_mean_name=name + '_bn2_running_mean',
  109. moving_variance_name=name + '_bn2_running_var')
  110. if stride == 1 and x.shape[1] == out_dim:
  111. return fluid.layers.elementwise_add(
  112. x=bn2, y=x, act='relu', name=name + "_add_relu")
  113. else:
  114. return fluid.layers.relu(bn2, name="_relu")
  115. def make_layer(x, in_dim, out_dim, modules, block, name=None):
  116. layers = block(x, out_dim, name=name + '_0')
  117. for i in range(1, modules):
  118. layers = block(layers, out_dim, name=name + '_' + str(i))
  119. return layers
  120. def make_hg_layer(x, in_dim, out_dim, modules, block, name=None):
  121. layers = block(x, out_dim, stride=2, name=name + '_0')
  122. for i in range(1, modules):
  123. layers = block(layers, out_dim, name=name + '_' + str(i))
  124. return layers
  125. def make_layer_revr(x, in_dim, out_dim, modules, block, name=None):
  126. for i in range(modules - 1):
  127. x = block(x, in_dim, name=name + '_' + str(i))
  128. layers = block(x, out_dim, name=name + '_' + str(modules - 1))
  129. return layers
  130. def make_unpool_layer(x, dim, name=None):
  131. pattr = ParamAttr(name=name + '_weight', initializer=kaiming_init(x, 4))
  132. battr = ParamAttr(name=name + '_bias', initializer=kaiming_init(x, 4))
  133. layer = fluid.layers.conv2d_transpose(
  134. input=x,
  135. num_filters=dim,
  136. filter_size=4,
  137. stride=2,
  138. padding=1,
  139. param_attr=pattr,
  140. bias_attr=battr)
  141. return layer
  142. @register
  143. class Hourglass(object):
  144. """
  145. Hourglass Network, see https://arxiv.org/abs/1603.06937
  146. Args:
  147. stack (int): stack of hourglass, 2 by default
  148. dims (list): dims of each level in hg_module
  149. modules (list): num of modules in each level
  150. """
  151. __shared__ = ['stack']
  152. def __init__(self,
  153. stack=2,
  154. dims=[256, 256, 384, 384, 512],
  155. modules=[2, 2, 2, 2, 4],
  156. block_name='fire'):
  157. super(Hourglass, self).__init__()
  158. self.stack = stack
  159. assert len(dims) == len(modules), \
  160. "Expected len of dims equal to len of modules, Receiced len of "\
  161. "dims: {}, len of modules: {}".format(len(dims), len(modules))
  162. self.dims = dims
  163. self.modules = modules
  164. self.num_level = len(dims) - 1
  165. block_dict = {'fire': fire_block}
  166. self.block = block_dict[block_name]
  167. def __call__(self, input, name='hg'):
  168. inter = self.pre(input, name + '_pre')
  169. cnvs = []
  170. for ind in range(self.stack):
  171. hg = self.hg_module(
  172. inter,
  173. self.num_level,
  174. self.dims,
  175. self.modules,
  176. name=name + '_hgs_' + str(ind))
  177. cnv = _conv_norm(
  178. hg,
  179. 3,
  180. 256,
  181. bn_act='relu',
  182. pad=1,
  183. name=name + '_cnvs_' + str(ind))
  184. cnvs.append(cnv)
  185. if ind < self.stack - 1:
  186. inter = _conv_norm(
  187. inter, 1, 256, name=name + '_inters__' +
  188. str(ind)) + _conv_norm(
  189. cnv, 1, 256, name=name + '_cnvs__' + str(ind))
  190. inter = fluid.layers.relu(inter)
  191. inter = residual_block(
  192. inter, 256, name=name + '_inters_' + str(ind))
  193. return cnvs
  194. def pre(self, x, name=None):
  195. conv = _conv_norm(
  196. x, 7, 128, stride=2, pad=3, bn_act='relu', name=name + '_0')
  197. res1 = residual_block(conv, 256, stride=2, name=name + '_1')
  198. res2 = residual_block(res1, 256, stride=2, name=name + '_2')
  199. return res2
  200. def hg_module(self,
  201. x,
  202. n=4,
  203. dims=[256, 256, 384, 384, 512],
  204. modules=[2, 2, 2, 2, 4],
  205. make_up_layer=make_layer,
  206. make_hg_layer=make_hg_layer,
  207. make_low_layer=make_layer,
  208. make_hg_layer_revr=make_layer_revr,
  209. make_unpool_layer=make_unpool_layer,
  210. name=None):
  211. curr_mod = modules[0]
  212. next_mod = modules[1]
  213. curr_dim = dims[0]
  214. next_dim = dims[1]
  215. up1 = make_up_layer(
  216. x, curr_dim, curr_dim, curr_mod, self.block, name=name + '_up1')
  217. max1 = x
  218. low1 = make_hg_layer(
  219. max1, curr_dim, next_dim, curr_mod, self.block, name=name + '_low1')
  220. low2 = self.hg_module(
  221. low1,
  222. n - 1,
  223. dims[1:],
  224. modules[1:],
  225. make_up_layer=make_up_layer,
  226. make_hg_layer=make_hg_layer,
  227. make_low_layer=make_low_layer,
  228. make_hg_layer_revr=make_hg_layer_revr,
  229. make_unpool_layer=make_unpool_layer,
  230. name=name + '_low2') if n > 1 else make_low_layer(
  231. low1,
  232. next_dim,
  233. next_dim,
  234. next_mod,
  235. self.block,
  236. name=name + '_low2')
  237. low3 = make_hg_layer_revr(
  238. low2, next_dim, curr_dim, curr_mod, self.block, name=name + '_low3')
  239. up2 = make_unpool_layer(low3, curr_dim, name=name + '_up2')
  240. merg = fluid.layers.elementwise_add(x=up1, y=up2, name=name + '_merg')
  241. return merg