mobilenet_v2.py 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. # copyright (c) 2021 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. import math
  15. import numpy as np
  16. import paddle
  17. from paddle import ParamAttr
  18. import paddle.nn as nn
  19. import paddle.nn.functional as F
  20. from paddle.nn import Conv2D, BatchNorm, Linear, Dropout
  21. from paddle.nn import AdaptiveAvgPool2D, MaxPool2D, AvgPool2D
  22. from paddleseg.cvlibs import manager
  23. import ppmatting
  24. MODEL_URLS = {
  25. "MobileNetV2_x0_25":
  26. "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/MobileNetV2_x0_25_pretrained.pdparams",
  27. "MobileNetV2_x0_5":
  28. "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/MobileNetV2_x0_5_pretrained.pdparams",
  29. "MobileNetV2_x0_75":
  30. "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/MobileNetV2_x0_75_pretrained.pdparams",
  31. "MobileNetV2":
  32. "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/MobileNetV2_pretrained.pdparams",
  33. "MobileNetV2_x1_5":
  34. "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/MobileNetV2_x1_5_pretrained.pdparams",
  35. "MobileNetV2_x2_0":
  36. "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/MobileNetV2_x2_0_pretrained.pdparams"
  37. }
  38. __all__ = ["MobileNetV2"]
  39. class ConvBNLayer(nn.Layer):
  40. def __init__(self,
  41. num_channels,
  42. filter_size,
  43. num_filters,
  44. stride,
  45. padding,
  46. channels=None,
  47. num_groups=1,
  48. name=None,
  49. use_cudnn=True):
  50. super(ConvBNLayer, self).__init__()
  51. self._conv = Conv2D(
  52. in_channels=num_channels,
  53. out_channels=num_filters,
  54. kernel_size=filter_size,
  55. stride=stride,
  56. padding=padding,
  57. groups=num_groups,
  58. weight_attr=ParamAttr(name=name + "_weights"),
  59. bias_attr=False)
  60. self._batch_norm = BatchNorm(
  61. num_filters,
  62. param_attr=ParamAttr(name=name + "_bn_scale"),
  63. bias_attr=ParamAttr(name=name + "_bn_offset"),
  64. moving_mean_name=name + "_bn_mean",
  65. moving_variance_name=name + "_bn_variance")
  66. def forward(self, inputs, if_act=True):
  67. y = self._conv(inputs)
  68. y = self._batch_norm(y)
  69. if if_act:
  70. y = F.relu6(y)
  71. return y
  72. class InvertedResidualUnit(nn.Layer):
  73. def __init__(self, num_channels, num_in_filter, num_filters, stride,
  74. filter_size, padding, expansion_factor, name):
  75. super(InvertedResidualUnit, self).__init__()
  76. num_expfilter = int(round(num_in_filter * expansion_factor))
  77. self._expand_conv = ConvBNLayer(
  78. num_channels=num_channels,
  79. num_filters=num_expfilter,
  80. filter_size=1,
  81. stride=1,
  82. padding=0,
  83. num_groups=1,
  84. name=name + "_expand")
  85. self._bottleneck_conv = ConvBNLayer(
  86. num_channels=num_expfilter,
  87. num_filters=num_expfilter,
  88. filter_size=filter_size,
  89. stride=stride,
  90. padding=padding,
  91. num_groups=num_expfilter,
  92. use_cudnn=False,
  93. name=name + "_dwise")
  94. self._linear_conv = ConvBNLayer(
  95. num_channels=num_expfilter,
  96. num_filters=num_filters,
  97. filter_size=1,
  98. stride=1,
  99. padding=0,
  100. num_groups=1,
  101. name=name + "_linear")
  102. def forward(self, inputs, ifshortcut):
  103. y = self._expand_conv(inputs, if_act=True)
  104. y = self._bottleneck_conv(y, if_act=True)
  105. y = self._linear_conv(y, if_act=False)
  106. if ifshortcut:
  107. y = paddle.add(inputs, y)
  108. return y
  109. class InvresiBlocks(nn.Layer):
  110. def __init__(self, in_c, t, c, n, s, name):
  111. super(InvresiBlocks, self).__init__()
  112. self._first_block = InvertedResidualUnit(
  113. num_channels=in_c,
  114. num_in_filter=in_c,
  115. num_filters=c,
  116. stride=s,
  117. filter_size=3,
  118. padding=1,
  119. expansion_factor=t,
  120. name=name + "_1")
  121. self._block_list = []
  122. for i in range(1, n):
  123. block = self.add_sublayer(
  124. name + "_" + str(i + 1),
  125. sublayer=InvertedResidualUnit(
  126. num_channels=c,
  127. num_in_filter=c,
  128. num_filters=c,
  129. stride=1,
  130. filter_size=3,
  131. padding=1,
  132. expansion_factor=t,
  133. name=name + "_" + str(i + 1)))
  134. self._block_list.append(block)
  135. def forward(self, inputs):
  136. y = self._first_block(inputs, ifshortcut=False)
  137. for block in self._block_list:
  138. y = block(y, ifshortcut=True)
  139. return y
  140. @manager.BACKBONES.add_component
  141. class MobileNet(nn.Layer):
  142. def __init__(self,
  143. input_channels=3,
  144. scale=1.0,
  145. pretrained=None,
  146. prefix_name=""):
  147. super(MobileNet, self).__init__()
  148. self.scale = scale
  149. bottleneck_params_list = [
  150. (1, 16, 1, 1),
  151. (6, 24, 2, 2),
  152. (6, 32, 3, 2),
  153. (6, 64, 4, 2),
  154. (6, 96, 3, 1),
  155. (6, 160, 3, 2),
  156. (6, 320, 1, 1),
  157. ]
  158. self.conv1 = ConvBNLayer(
  159. num_channels=input_channels,
  160. num_filters=int(32 * scale),
  161. filter_size=3,
  162. stride=2,
  163. padding=1,
  164. name=prefix_name + "conv1_1")
  165. self.block_list = []
  166. i = 1
  167. in_c = int(32 * scale)
  168. for layer_setting in bottleneck_params_list:
  169. t, c, n, s = layer_setting
  170. i += 1
  171. block = self.add_sublayer(
  172. prefix_name + "conv" + str(i),
  173. sublayer=InvresiBlocks(
  174. in_c=in_c,
  175. t=t,
  176. c=int(c * scale),
  177. n=n,
  178. s=s,
  179. name=prefix_name + "conv" + str(i)))
  180. self.block_list.append(block)
  181. in_c = int(c * scale)
  182. self.out_c = int(1280 * scale) if scale > 1.0 else 1280
  183. self.conv9 = ConvBNLayer(
  184. num_channels=in_c,
  185. num_filters=self.out_c,
  186. filter_size=1,
  187. stride=1,
  188. padding=0,
  189. name=prefix_name + "conv9")
  190. self.feat_channels = [int(i * scale) for i in [16, 24, 32, 96, 1280]]
  191. self.pretrained = pretrained
  192. self.init_weight()
  193. def forward(self, inputs):
  194. feat_list = []
  195. y = self.conv1(inputs, if_act=True)
  196. block_index = 0
  197. for block in self.block_list:
  198. y = block(y)
  199. if block_index in [0, 1, 2, 4]:
  200. feat_list.append(y)
  201. block_index += 1
  202. y = self.conv9(y, if_act=True)
  203. feat_list.append(y)
  204. return feat_list
  205. def init_weight(self):
  206. ppmatting.utils.load_pretrained_model(self, self.pretrained)
  207. @manager.BACKBONES.add_component
  208. def MobileNetV2(**kwargs):
  209. model = MobileNet(scale=1.0, **kwargs)
  210. return model