resnext101_wsl.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. import paddle
  2. from paddle import ParamAttr
  3. import paddle.nn as nn
  4. import paddle.nn.functional as F
  5. from paddle.nn import Conv2D, BatchNorm, Linear, Dropout
  6. from paddle.nn import AdaptiveAvgPool2D, MaxPool2D, AvgPool2D
  7. from paddle.nn.initializer import Uniform
  8. from paddlex.ppcls.utils.save_load import load_dygraph_pretrain, load_dygraph_pretrain_from_url
  9. MODEL_URLS = {
  10. "ResNeXt101_32x8d_wsl":
  11. "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/ResNeXt101_32x8d_wsl_pretrained.pdparams",
  12. "ResNeXt101_32x16d_wsl":
  13. "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/ResNeXt101_32x16_wsl_pretrained.pdparams",
  14. "ResNeXt101_32x32d_wsl":
  15. "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/ResNeXt101_32x32d_wsl_pretrained.pdparams",
  16. "ResNeXt101_32x48d_wsl":
  17. "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/ResNeXt101_32x48d_wsl_pretrained.pdparams",
  18. }
  19. __all__ = list(MODEL_URLS.keys())
  20. class ConvBNLayer(nn.Layer):
  21. def __init__(self,
  22. input_channels,
  23. output_channels,
  24. filter_size,
  25. stride=1,
  26. groups=1,
  27. act=None,
  28. name=None):
  29. super(ConvBNLayer, self).__init__()
  30. if "downsample" in name:
  31. conv_name = name + ".0"
  32. else:
  33. conv_name = name
  34. self._conv = Conv2D(
  35. in_channels=input_channels,
  36. out_channels=output_channels,
  37. kernel_size=filter_size,
  38. stride=stride,
  39. padding=(filter_size - 1) // 2,
  40. groups=groups,
  41. weight_attr=ParamAttr(name=conv_name + ".weight"),
  42. bias_attr=False)
  43. if "downsample" in name:
  44. bn_name = name[:9] + "downsample.1"
  45. else:
  46. if "conv1" == name:
  47. bn_name = "bn" + name[-1]
  48. else:
  49. bn_name = (name[:10] if name[7:9].isdigit() else name[:9]
  50. ) + "bn" + name[-1]
  51. self._bn = BatchNorm(
  52. num_channels=output_channels,
  53. act=act,
  54. param_attr=ParamAttr(name=bn_name + ".weight"),
  55. bias_attr=ParamAttr(name=bn_name + ".bias"),
  56. moving_mean_name=bn_name + ".running_mean",
  57. moving_variance_name=bn_name + ".running_var")
  58. def forward(self, inputs):
  59. x = self._conv(inputs)
  60. x = self._bn(x)
  61. return x
  62. class ShortCut(nn.Layer):
  63. def __init__(self, input_channels, output_channels, stride, name=None):
  64. super(ShortCut, self).__init__()
  65. self.input_channels = input_channels
  66. self.output_channels = output_channels
  67. self.stride = stride
  68. if input_channels != output_channels or stride != 1:
  69. self._conv = ConvBNLayer(
  70. input_channels,
  71. output_channels,
  72. filter_size=1,
  73. stride=stride,
  74. name=name)
  75. def forward(self, inputs):
  76. if self.input_channels != self.output_channels or self.stride != 1:
  77. return self._conv(inputs)
  78. return inputs
  79. class BottleneckBlock(nn.Layer):
  80. def __init__(self, input_channels, output_channels, stride, cardinality,
  81. width, name):
  82. super(BottleneckBlock, self).__init__()
  83. self._conv0 = ConvBNLayer(
  84. input_channels,
  85. output_channels,
  86. filter_size=1,
  87. act="relu",
  88. name=name + ".conv1")
  89. self._conv1 = ConvBNLayer(
  90. output_channels,
  91. output_channels,
  92. filter_size=3,
  93. act="relu",
  94. stride=stride,
  95. groups=cardinality,
  96. name=name + ".conv2")
  97. self._conv2 = ConvBNLayer(
  98. output_channels,
  99. output_channels // (width // 8),
  100. filter_size=1,
  101. act=None,
  102. name=name + ".conv3")
  103. self._short = ShortCut(
  104. input_channels,
  105. output_channels // (width // 8),
  106. stride=stride,
  107. name=name + ".downsample")
  108. def forward(self, inputs):
  109. x = self._conv0(inputs)
  110. x = self._conv1(x)
  111. x = self._conv2(x)
  112. y = self._short(inputs)
  113. y = paddle.add(x, y)
  114. y = F.relu(y)
  115. return y
  116. class ResNeXt101WSL(nn.Layer):
  117. def __init__(self, layers=101, cardinality=32, width=48, class_num=1000):
  118. super(ResNeXt101WSL, self).__init__()
  119. self.class_num = class_num
  120. self.layers = layers
  121. self.cardinality = cardinality
  122. self.width = width
  123. self.scale = width // 8
  124. self.depth = [3, 4, 23, 3]
  125. self.base_width = cardinality * width
  126. num_filters = [self.base_width * i
  127. for i in [1, 2, 4, 8]] # [256, 512, 1024, 2048]
  128. self._conv_stem = ConvBNLayer(
  129. 3, 64, 7, stride=2, act="relu", name="conv1")
  130. self._pool = MaxPool2D(kernel_size=3, stride=2, padding=1)
  131. self._conv1_0 = BottleneckBlock(
  132. 64,
  133. num_filters[0],
  134. stride=1,
  135. cardinality=self.cardinality,
  136. width=self.width,
  137. name="layer1.0")
  138. self._conv1_1 = BottleneckBlock(
  139. num_filters[0] // (width // 8),
  140. num_filters[0],
  141. stride=1,
  142. cardinality=self.cardinality,
  143. width=self.width,
  144. name="layer1.1")
  145. self._conv1_2 = BottleneckBlock(
  146. num_filters[0] // (width // 8),
  147. num_filters[0],
  148. stride=1,
  149. cardinality=self.cardinality,
  150. width=self.width,
  151. name="layer1.2")
  152. self._conv2_0 = BottleneckBlock(
  153. num_filters[0] // (width // 8),
  154. num_filters[1],
  155. stride=2,
  156. cardinality=self.cardinality,
  157. width=self.width,
  158. name="layer2.0")
  159. self._conv2_1 = BottleneckBlock(
  160. num_filters[1] // (width // 8),
  161. num_filters[1],
  162. stride=1,
  163. cardinality=self.cardinality,
  164. width=self.width,
  165. name="layer2.1")
  166. self._conv2_2 = BottleneckBlock(
  167. num_filters[1] // (width // 8),
  168. num_filters[1],
  169. stride=1,
  170. cardinality=self.cardinality,
  171. width=self.width,
  172. name="layer2.2")
  173. self._conv2_3 = BottleneckBlock(
  174. num_filters[1] // (width // 8),
  175. num_filters[1],
  176. stride=1,
  177. cardinality=self.cardinality,
  178. width=self.width,
  179. name="layer2.3")
  180. self._conv3_0 = BottleneckBlock(
  181. num_filters[1] // (width // 8),
  182. num_filters[2],
  183. stride=2,
  184. cardinality=self.cardinality,
  185. width=self.width,
  186. name="layer3.0")
  187. self._conv3_1 = BottleneckBlock(
  188. num_filters[2] // (width // 8),
  189. num_filters[2],
  190. stride=1,
  191. cardinality=self.cardinality,
  192. width=self.width,
  193. name="layer3.1")
  194. self._conv3_2 = BottleneckBlock(
  195. num_filters[2] // (width // 8),
  196. num_filters[2],
  197. stride=1,
  198. cardinality=self.cardinality,
  199. width=self.width,
  200. name="layer3.2")
  201. self._conv3_3 = BottleneckBlock(
  202. num_filters[2] // (width // 8),
  203. num_filters[2],
  204. stride=1,
  205. cardinality=self.cardinality,
  206. width=self.width,
  207. name="layer3.3")
  208. self._conv3_4 = BottleneckBlock(
  209. num_filters[2] // (width // 8),
  210. num_filters[2],
  211. stride=1,
  212. cardinality=self.cardinality,
  213. width=self.width,
  214. name="layer3.4")
  215. self._conv3_5 = BottleneckBlock(
  216. num_filters[2] // (width // 8),
  217. num_filters[2],
  218. stride=1,
  219. cardinality=self.cardinality,
  220. width=self.width,
  221. name="layer3.5")
  222. self._conv3_6 = BottleneckBlock(
  223. num_filters[2] // (width // 8),
  224. num_filters[2],
  225. stride=1,
  226. cardinality=self.cardinality,
  227. width=self.width,
  228. name="layer3.6")
  229. self._conv3_7 = BottleneckBlock(
  230. num_filters[2] // (width // 8),
  231. num_filters[2],
  232. stride=1,
  233. cardinality=self.cardinality,
  234. width=self.width,
  235. name="layer3.7")
  236. self._conv3_8 = BottleneckBlock(
  237. num_filters[2] // (width // 8),
  238. num_filters[2],
  239. stride=1,
  240. cardinality=self.cardinality,
  241. width=self.width,
  242. name="layer3.8")
  243. self._conv3_9 = BottleneckBlock(
  244. num_filters[2] // (width // 8),
  245. num_filters[2],
  246. stride=1,
  247. cardinality=self.cardinality,
  248. width=self.width,
  249. name="layer3.9")
  250. self._conv3_10 = BottleneckBlock(
  251. num_filters[2] // (width // 8),
  252. num_filters[2],
  253. stride=1,
  254. cardinality=self.cardinality,
  255. width=self.width,
  256. name="layer3.10")
  257. self._conv3_11 = BottleneckBlock(
  258. num_filters[2] // (width // 8),
  259. num_filters[2],
  260. stride=1,
  261. cardinality=self.cardinality,
  262. width=self.width,
  263. name="layer3.11")
  264. self._conv3_12 = BottleneckBlock(
  265. num_filters[2] // (width // 8),
  266. num_filters[2],
  267. stride=1,
  268. cardinality=self.cardinality,
  269. width=self.width,
  270. name="layer3.12")
  271. self._conv3_13 = BottleneckBlock(
  272. num_filters[2] // (width // 8),
  273. num_filters[2],
  274. stride=1,
  275. cardinality=self.cardinality,
  276. width=self.width,
  277. name="layer3.13")
  278. self._conv3_14 = BottleneckBlock(
  279. num_filters[2] // (width // 8),
  280. num_filters[2],
  281. stride=1,
  282. cardinality=self.cardinality,
  283. width=self.width,
  284. name="layer3.14")
  285. self._conv3_15 = BottleneckBlock(
  286. num_filters[2] // (width // 8),
  287. num_filters[2],
  288. stride=1,
  289. cardinality=self.cardinality,
  290. width=self.width,
  291. name="layer3.15")
  292. self._conv3_16 = BottleneckBlock(
  293. num_filters[2] // (width // 8),
  294. num_filters[2],
  295. stride=1,
  296. cardinality=self.cardinality,
  297. width=self.width,
  298. name="layer3.16")
  299. self._conv3_17 = BottleneckBlock(
  300. num_filters[2] // (width // 8),
  301. num_filters[2],
  302. stride=1,
  303. cardinality=self.cardinality,
  304. width=self.width,
  305. name="layer3.17")
  306. self._conv3_18 = BottleneckBlock(
  307. num_filters[2] // (width // 8),
  308. num_filters[2],
  309. stride=1,
  310. cardinality=self.cardinality,
  311. width=self.width,
  312. name="layer3.18")
  313. self._conv3_19 = BottleneckBlock(
  314. num_filters[2] // (width // 8),
  315. num_filters[2],
  316. stride=1,
  317. cardinality=self.cardinality,
  318. width=self.width,
  319. name="layer3.19")
  320. self._conv3_20 = BottleneckBlock(
  321. num_filters[2] // (width // 8),
  322. num_filters[2],
  323. stride=1,
  324. cardinality=self.cardinality,
  325. width=self.width,
  326. name="layer3.20")
  327. self._conv3_21 = BottleneckBlock(
  328. num_filters[2] // (width // 8),
  329. num_filters[2],
  330. stride=1,
  331. cardinality=self.cardinality,
  332. width=self.width,
  333. name="layer3.21")
  334. self._conv3_22 = BottleneckBlock(
  335. num_filters[2] // (width // 8),
  336. num_filters[2],
  337. stride=1,
  338. cardinality=self.cardinality,
  339. width=self.width,
  340. name="layer3.22")
  341. self._conv4_0 = BottleneckBlock(
  342. num_filters[2] // (width // 8),
  343. num_filters[3],
  344. stride=2,
  345. cardinality=self.cardinality,
  346. width=self.width,
  347. name="layer4.0")
  348. self._conv4_1 = BottleneckBlock(
  349. num_filters[3] // (width // 8),
  350. num_filters[3],
  351. stride=1,
  352. cardinality=self.cardinality,
  353. width=self.width,
  354. name="layer4.1")
  355. self._conv4_2 = BottleneckBlock(
  356. num_filters[3] // (width // 8),
  357. num_filters[3],
  358. stride=1,
  359. cardinality=self.cardinality,
  360. width=self.width,
  361. name="layer4.2")
  362. self._avg_pool = AdaptiveAvgPool2D(1)
  363. self._out = Linear(
  364. num_filters[3] // (width // 8),
  365. class_num,
  366. weight_attr=ParamAttr(name="fc.weight"),
  367. bias_attr=ParamAttr(name="fc.bias"))
  368. def forward(self, inputs):
  369. x = self._conv_stem(inputs)
  370. x = self._pool(x)
  371. x = self._conv1_0(x)
  372. x = self._conv1_1(x)
  373. x = self._conv1_2(x)
  374. x = self._conv2_0(x)
  375. x = self._conv2_1(x)
  376. x = self._conv2_2(x)
  377. x = self._conv2_3(x)
  378. x = self._conv3_0(x)
  379. x = self._conv3_1(x)
  380. x = self._conv3_2(x)
  381. x = self._conv3_3(x)
  382. x = self._conv3_4(x)
  383. x = self._conv3_5(x)
  384. x = self._conv3_6(x)
  385. x = self._conv3_7(x)
  386. x = self._conv3_8(x)
  387. x = self._conv3_9(x)
  388. x = self._conv3_10(x)
  389. x = self._conv3_11(x)
  390. x = self._conv3_12(x)
  391. x = self._conv3_13(x)
  392. x = self._conv3_14(x)
  393. x = self._conv3_15(x)
  394. x = self._conv3_16(x)
  395. x = self._conv3_17(x)
  396. x = self._conv3_18(x)
  397. x = self._conv3_19(x)
  398. x = self._conv3_20(x)
  399. x = self._conv3_21(x)
  400. x = self._conv3_22(x)
  401. x = self._conv4_0(x)
  402. x = self._conv4_1(x)
  403. x = self._conv4_2(x)
  404. x = self._avg_pool(x)
  405. x = paddle.squeeze(x, axis=[2, 3])
  406. x = self._out(x)
  407. return x
  408. def _load_pretrained(pretrained, model, model_url, use_ssld=False):
  409. if pretrained is False:
  410. pass
  411. elif pretrained is True:
  412. load_dygraph_pretrain_from_url(model, model_url, use_ssld=use_ssld)
  413. elif isinstance(pretrained, str):
  414. load_dygraph_pretrain(model, pretrained)
  415. else:
  416. raise RuntimeError(
  417. "pretrained type is not available. Please use `string` or `boolean` type."
  418. )
  419. def ResNeXt101_32x8d_wsl(pretrained=False, use_ssld=False, **kwargs):
  420. model = ResNeXt101WSL(cardinality=32, width=8, **kwargs)
  421. _load_pretrained(
  422. pretrained,
  423. model,
  424. MODEL_URLS["ResNeXt101_32x8d_wsl"],
  425. use_ssld=use_ssld)
  426. return model
  427. def ResNeXt101_32x16d_wsl(pretrained=False, use_ssld=False, **kwargs):
  428. model = ResNeXt101WSL(cardinality=32, width=16, **kwargs)
  429. _load_pretrained(
  430. pretrained,
  431. model,
  432. MODEL_URLS["ResNeXt101_32x16d_wsl"],
  433. use_ssld=use_ssld)
  434. return model
  435. def ResNeXt101_32x32d_wsl(pretrained=False, use_ssld=False, **kwargs):
  436. model = ResNeXt101WSL(cardinality=32, width=32, **kwargs)
  437. _load_pretrained(
  438. pretrained,
  439. model,
  440. MODEL_URLS["ResNeXt101_32x32d_wsl"],
  441. use_ssld=use_ssld)
  442. return model
  443. def ResNeXt101_32x48d_wsl(pretrained=False, use_ssld=False, **kwargs):
  444. model = ResNeXt101WSL(cardinality=32, width=48, **kwargs)
  445. _load_pretrained(
  446. pretrained,
  447. model,
  448. MODEL_URLS["ResNeXt101_32x48d_wsl"],
  449. use_ssld=use_ssld)
  450. return model