dpn.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. # copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve.
  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 numpy as np
  18. import sys
  19. import paddle
  20. from paddle import ParamAttr
  21. import paddle.nn as nn
  22. from paddle.nn import Conv2D, BatchNorm, Linear
  23. from paddle.nn import AdaptiveAvgPool2D, MaxPool2D, AvgPool2D
  24. from paddle.nn.initializer import Uniform
  25. import math
  26. __all__ = [
  27. "DPN",
  28. "DPN68",
  29. "DPN92",
  30. "DPN98",
  31. "DPN107",
  32. "DPN131",
  33. ]
  34. class ConvBNLayer(nn.Layer):
  35. def __init__(self,
  36. num_channels,
  37. num_filters,
  38. filter_size,
  39. stride=1,
  40. pad=0,
  41. groups=1,
  42. act="relu",
  43. name=None):
  44. super(ConvBNLayer, self).__init__()
  45. self._conv = Conv2D(
  46. in_channels=num_channels,
  47. out_channels=num_filters,
  48. kernel_size=filter_size,
  49. stride=stride,
  50. padding=pad,
  51. groups=groups,
  52. weight_attr=ParamAttr(name=name + "_weights"),
  53. bias_attr=False)
  54. self._batch_norm = BatchNorm(
  55. num_filters,
  56. act=act,
  57. param_attr=ParamAttr(name=name + '_bn_scale'),
  58. bias_attr=ParamAttr(name + '_bn_offset'),
  59. moving_mean_name=name + '_bn_mean',
  60. moving_variance_name=name + '_bn_variance')
  61. def forward(self, input):
  62. y = self._conv(input)
  63. y = self._batch_norm(y)
  64. return y
  65. class BNACConvLayer(nn.Layer):
  66. def __init__(self,
  67. num_channels,
  68. num_filters,
  69. filter_size,
  70. stride=1,
  71. pad=0,
  72. groups=1,
  73. act="relu",
  74. name=None):
  75. super(BNACConvLayer, self).__init__()
  76. self.num_channels = num_channels
  77. self._batch_norm = BatchNorm(
  78. num_channels,
  79. act=act,
  80. param_attr=ParamAttr(name=name + '_bn_scale'),
  81. bias_attr=ParamAttr(name + '_bn_offset'),
  82. moving_mean_name=name + '_bn_mean',
  83. moving_variance_name=name + '_bn_variance')
  84. self._conv = Conv2D(
  85. in_channels=num_channels,
  86. out_channels=num_filters,
  87. kernel_size=filter_size,
  88. stride=stride,
  89. padding=pad,
  90. groups=groups,
  91. weight_attr=ParamAttr(name=name + "_weights"),
  92. bias_attr=False)
  93. def forward(self, input):
  94. y = self._batch_norm(input)
  95. y = self._conv(y)
  96. return y
  97. class DualPathFactory(nn.Layer):
  98. def __init__(self,
  99. num_channels,
  100. num_1x1_a,
  101. num_3x3_b,
  102. num_1x1_c,
  103. inc,
  104. G,
  105. _type='normal',
  106. name=None):
  107. super(DualPathFactory, self).__init__()
  108. self.num_1x1_c = num_1x1_c
  109. self.inc = inc
  110. self.name = name
  111. kw = 3
  112. kh = 3
  113. pw = (kw - 1) // 2
  114. ph = (kh - 1) // 2
  115. # type
  116. if _type == 'proj':
  117. key_stride = 1
  118. self.has_proj = True
  119. elif _type == 'down':
  120. key_stride = 2
  121. self.has_proj = True
  122. elif _type == 'normal':
  123. key_stride = 1
  124. self.has_proj = False
  125. else:
  126. print("not implemented now!!!")
  127. sys.exit(1)
  128. data_in_ch = sum(num_channels) if isinstance(num_channels,
  129. list) else num_channels
  130. if self.has_proj:
  131. self.c1x1_w_func = BNACConvLayer(
  132. num_channels=data_in_ch,
  133. num_filters=num_1x1_c + 2 * inc,
  134. filter_size=(1, 1),
  135. pad=(0, 0),
  136. stride=(key_stride, key_stride),
  137. name=name + "_match")
  138. self.c1x1_a_func = BNACConvLayer(
  139. num_channels=data_in_ch,
  140. num_filters=num_1x1_a,
  141. filter_size=(1, 1),
  142. pad=(0, 0),
  143. name=name + "_conv1")
  144. self.c3x3_b_func = BNACConvLayer(
  145. num_channels=num_1x1_a,
  146. num_filters=num_3x3_b,
  147. filter_size=(kw, kh),
  148. pad=(pw, ph),
  149. stride=(key_stride, key_stride),
  150. groups=G,
  151. name=name + "_conv2")
  152. self.c1x1_c_func = BNACConvLayer(
  153. num_channels=num_3x3_b,
  154. num_filters=num_1x1_c + inc,
  155. filter_size=(1, 1),
  156. pad=(0, 0),
  157. name=name + "_conv3")
  158. def forward(self, input):
  159. # PROJ
  160. if isinstance(input, list):
  161. data_in = paddle.concat([input[0], input[1]], axis=1)
  162. else:
  163. data_in = input
  164. if self.has_proj:
  165. c1x1_w = self.c1x1_w_func(data_in)
  166. data_o1, data_o2 = paddle.split(
  167. c1x1_w, num_or_sections=[self.num_1x1_c, 2 * self.inc], axis=1)
  168. else:
  169. data_o1 = input[0]
  170. data_o2 = input[1]
  171. c1x1_a = self.c1x1_a_func(data_in)
  172. c3x3_b = self.c3x3_b_func(c1x1_a)
  173. c1x1_c = self.c1x1_c_func(c3x3_b)
  174. c1x1_c1, c1x1_c2 = paddle.split(
  175. c1x1_c, num_or_sections=[self.num_1x1_c, self.inc], axis=1)
  176. # OUTPUTS
  177. summ = paddle.add(x=data_o1, y=c1x1_c1)
  178. dense = paddle.concat([data_o2, c1x1_c2], axis=1)
  179. # tensor, channels
  180. return [summ, dense]
  181. class DPN(nn.Layer):
  182. def __init__(self, layers=68, class_dim=1000):
  183. super(DPN, self).__init__()
  184. self._class_dim = class_dim
  185. args = self.get_net_args(layers)
  186. bws = args['bw']
  187. inc_sec = args['inc_sec']
  188. rs = args['r']
  189. k_r = args['k_r']
  190. k_sec = args['k_sec']
  191. G = args['G']
  192. init_num_filter = args['init_num_filter']
  193. init_filter_size = args['init_filter_size']
  194. init_padding = args['init_padding']
  195. self.k_sec = k_sec
  196. self.conv1_x_1_func = ConvBNLayer(
  197. num_channels=3,
  198. num_filters=init_num_filter,
  199. filter_size=init_filter_size,
  200. stride=2,
  201. pad=init_padding,
  202. act='relu',
  203. name="conv1")
  204. self.pool2d_max = MaxPool2D(kernel_size=3, stride=2, padding=1)
  205. num_channel_dpn = init_num_filter
  206. self.dpn_func_list = []
  207. #conv2 - conv5
  208. match_list, num = [], 0
  209. for gc in range(4):
  210. bw = bws[gc]
  211. inc = inc_sec[gc]
  212. R = (k_r * bw) // rs[gc]
  213. if gc == 0:
  214. _type1 = 'proj'
  215. _type2 = 'normal'
  216. match = 1
  217. else:
  218. _type1 = 'down'
  219. _type2 = 'normal'
  220. match = match + k_sec[gc - 1]
  221. match_list.append(match)
  222. self.dpn_func_list.append(
  223. self.add_sublayer(
  224. "dpn{}".format(match),
  225. DualPathFactory(
  226. num_channels=num_channel_dpn,
  227. num_1x1_a=R,
  228. num_3x3_b=R,
  229. num_1x1_c=bw,
  230. inc=inc,
  231. G=G,
  232. _type=_type1,
  233. name="dpn" + str(match))))
  234. num_channel_dpn = [bw, 3 * inc]
  235. for i_ly in range(2, k_sec[gc] + 1):
  236. num += 1
  237. if num in match_list:
  238. num += 1
  239. self.dpn_func_list.append(
  240. self.add_sublayer(
  241. "dpn{}".format(num),
  242. DualPathFactory(
  243. num_channels=num_channel_dpn,
  244. num_1x1_a=R,
  245. num_3x3_b=R,
  246. num_1x1_c=bw,
  247. inc=inc,
  248. G=G,
  249. _type=_type2,
  250. name="dpn" + str(num))))
  251. num_channel_dpn = [
  252. num_channel_dpn[0], num_channel_dpn[1] + inc
  253. ]
  254. out_channel = sum(num_channel_dpn)
  255. self.conv5_x_x_bn = BatchNorm(
  256. num_channels=sum(num_channel_dpn),
  257. act="relu",
  258. param_attr=ParamAttr(name='final_concat_bn_scale'),
  259. bias_attr=ParamAttr('final_concat_bn_offset'),
  260. moving_mean_name='final_concat_bn_mean',
  261. moving_variance_name='final_concat_bn_variance')
  262. self.pool2d_avg = AdaptiveAvgPool2D(1)
  263. stdv = 0.01
  264. self.out = Linear(
  265. out_channel,
  266. class_dim,
  267. weight_attr=ParamAttr(
  268. initializer=Uniform(-stdv, stdv), name="fc_weights"),
  269. bias_attr=ParamAttr(name="fc_offset"))
  270. def forward(self, input):
  271. conv1_x_1 = self.conv1_x_1_func(input)
  272. convX_x_x = self.pool2d_max(conv1_x_1)
  273. dpn_idx = 0
  274. for gc in range(4):
  275. convX_x_x = self.dpn_func_list[dpn_idx](convX_x_x)
  276. dpn_idx += 1
  277. for i_ly in range(2, self.k_sec[gc] + 1):
  278. convX_x_x = self.dpn_func_list[dpn_idx](convX_x_x)
  279. dpn_idx += 1
  280. conv5_x_x = paddle.concat(convX_x_x, axis=1)
  281. conv5_x_x = self.conv5_x_x_bn(conv5_x_x)
  282. y = self.pool2d_avg(conv5_x_x)
  283. y = paddle.flatten(y, start_axis=1, stop_axis=-1)
  284. y = self.out(y)
  285. return y
  286. def get_net_args(self, layers):
  287. if layers == 68:
  288. k_r = 128
  289. G = 32
  290. k_sec = [3, 4, 12, 3]
  291. inc_sec = [16, 32, 32, 64]
  292. bw = [64, 128, 256, 512]
  293. r = [64, 64, 64, 64]
  294. init_num_filter = 10
  295. init_filter_size = 3
  296. init_padding = 1
  297. elif layers == 92:
  298. k_r = 96
  299. G = 32
  300. k_sec = [3, 4, 20, 3]
  301. inc_sec = [16, 32, 24, 128]
  302. bw = [256, 512, 1024, 2048]
  303. r = [256, 256, 256, 256]
  304. init_num_filter = 64
  305. init_filter_size = 7
  306. init_padding = 3
  307. elif layers == 98:
  308. k_r = 160
  309. G = 40
  310. k_sec = [3, 6, 20, 3]
  311. inc_sec = [16, 32, 32, 128]
  312. bw = [256, 512, 1024, 2048]
  313. r = [256, 256, 256, 256]
  314. init_num_filter = 96
  315. init_filter_size = 7
  316. init_padding = 3
  317. elif layers == 107:
  318. k_r = 200
  319. G = 50
  320. k_sec = [4, 8, 20, 3]
  321. inc_sec = [20, 64, 64, 128]
  322. bw = [256, 512, 1024, 2048]
  323. r = [256, 256, 256, 256]
  324. init_num_filter = 128
  325. init_filter_size = 7
  326. init_padding = 3
  327. elif layers == 131:
  328. k_r = 160
  329. G = 40
  330. k_sec = [4, 8, 28, 3]
  331. inc_sec = [16, 32, 32, 128]
  332. bw = [256, 512, 1024, 2048]
  333. r = [256, 256, 256, 256]
  334. init_num_filter = 128
  335. init_filter_size = 7
  336. init_padding = 3
  337. else:
  338. raise NotImplementedError
  339. net_arg = {
  340. 'k_r': k_r,
  341. 'G': G,
  342. 'k_sec': k_sec,
  343. 'inc_sec': inc_sec,
  344. 'bw': bw,
  345. 'r': r
  346. }
  347. net_arg['init_num_filter'] = init_num_filter
  348. net_arg['init_filter_size'] = init_filter_size
  349. net_arg['init_padding'] = init_padding
  350. return net_arg
  351. def DPN68(**args):
  352. model = DPN(layers=68, **args)
  353. return model
  354. def DPN92(**args):
  355. model = DPN(layers=92, **args)
  356. return model
  357. def DPN98(**args):
  358. model = DPN(layers=98, **args)
  359. return model
  360. def DPN107(**args):
  361. model = DPN(layers=107, **args)
  362. return model
  363. def DPN131(**args):
  364. model = DPN(layers=131, **args)
  365. return model