squeezenet.py 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  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 paddle
  15. import paddle.nn.functional as F
  16. from paddle import nn
  17. from paddle.base.param_attr import ParamAttr
  18. from paddle.nn import AdaptiveAvgPool2D, Conv2D, Dropout, MaxPool2D
  19. from paddle.utils.download import get_weights_path_from_url
  20. __all__ = []
  21. model_urls = {
  22. 'squeezenet1_0': (
  23. 'https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/SqueezeNet1_0_pretrained.pdparams',
  24. '30b95af60a2178f03cf9b66cd77e1db1',
  25. ),
  26. 'squeezenet1_1': (
  27. 'https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/SqueezeNet1_1_pretrained.pdparams',
  28. 'a11250d3a1f91d7131fd095ebbf09eee',
  29. ),
  30. }
  31. class MakeFireConv(nn.Layer):
  32. def __init__(self, input_channels, output_channels, filter_size, padding=0):
  33. super().__init__()
  34. self._conv = Conv2D(
  35. input_channels,
  36. output_channels,
  37. filter_size,
  38. padding=padding,
  39. weight_attr=ParamAttr(),
  40. bias_attr=ParamAttr(),
  41. )
  42. def forward(self, x):
  43. x = self._conv(x)
  44. x = F.relu(x)
  45. return x
  46. class MakeFire(nn.Layer):
  47. def __init__(
  48. self,
  49. input_channels,
  50. squeeze_channels,
  51. expand1x1_channels,
  52. expand3x3_channels,
  53. ):
  54. super().__init__()
  55. self._conv = MakeFireConv(input_channels, squeeze_channels, 1)
  56. self._conv_path1 = MakeFireConv(squeeze_channels, expand1x1_channels, 1)
  57. self._conv_path2 = MakeFireConv(
  58. squeeze_channels, expand3x3_channels, 3, padding=1
  59. )
  60. def forward(self, inputs):
  61. x = self._conv(inputs)
  62. x1 = self._conv_path1(x)
  63. x2 = self._conv_path2(x)
  64. return paddle.concat([x1, x2], axis=1)
  65. class SqueezeNet(nn.Layer):
  66. """SqueezeNet model from
  67. `"SqueezeNet: AlexNet-level accuracy with 50x fewer parameters and <0.5MB model size"
  68. <https://arxiv.org/pdf/1602.07360.pdf>`_.
  69. Args:
  70. version (str): Version of SqueezeNet, which can be "1.0" or "1.1".
  71. num_classes (int, optional): Output dim of last fc layer. If num_classes <= 0, last fc layer
  72. will not be defined. Default: 1000.
  73. with_pool (bool, optional): Use pool before the last fc layer or not. Default: True.
  74. Returns:
  75. :ref:`api_paddle_nn_Layer`. An instance of SqueezeNet model.
  76. Examples:
  77. .. code-block:: python
  78. >>> import paddle
  79. >>> from paddle.vision.models import SqueezeNet
  80. >>> # build v1.0 model
  81. >>> model = SqueezeNet(version='1.0')
  82. >>> # build v1.1 model
  83. >>> # model = SqueezeNet(version='1.1')
  84. >>> x = paddle.rand([1, 3, 224, 224])
  85. >>> out = model(x)
  86. >>> print(out.shape)
  87. [1, 1000]
  88. """
  89. def __init__(self, version, num_classes=1000, with_pool=True):
  90. super().__init__()
  91. self.version = version
  92. self.num_classes = num_classes
  93. self.with_pool = with_pool
  94. supported_versions = ['1.0', '1.1']
  95. assert (
  96. version in supported_versions
  97. ), f"supported versions are {supported_versions} but input version is {version}"
  98. if self.version == "1.0":
  99. self._conv = Conv2D(
  100. 3,
  101. 96,
  102. 7,
  103. stride=2,
  104. weight_attr=ParamAttr(),
  105. bias_attr=ParamAttr(),
  106. )
  107. self._pool = MaxPool2D(kernel_size=3, stride=2, padding=0)
  108. self._conv1 = MakeFire(96, 16, 64, 64)
  109. self._conv2 = MakeFire(128, 16, 64, 64)
  110. self._conv3 = MakeFire(128, 32, 128, 128)
  111. self._conv4 = MakeFire(256, 32, 128, 128)
  112. self._conv5 = MakeFire(256, 48, 192, 192)
  113. self._conv6 = MakeFire(384, 48, 192, 192)
  114. self._conv7 = MakeFire(384, 64, 256, 256)
  115. self._conv8 = MakeFire(512, 64, 256, 256)
  116. else:
  117. self._conv = Conv2D(
  118. 3,
  119. 64,
  120. 3,
  121. stride=2,
  122. padding=1,
  123. weight_attr=ParamAttr(),
  124. bias_attr=ParamAttr(),
  125. )
  126. self._pool = MaxPool2D(kernel_size=3, stride=2, padding=0)
  127. self._conv1 = MakeFire(64, 16, 64, 64)
  128. self._conv2 = MakeFire(128, 16, 64, 64)
  129. self._conv3 = MakeFire(128, 32, 128, 128)
  130. self._conv4 = MakeFire(256, 32, 128, 128)
  131. self._conv5 = MakeFire(256, 48, 192, 192)
  132. self._conv6 = MakeFire(384, 48, 192, 192)
  133. self._conv7 = MakeFire(384, 64, 256, 256)
  134. self._conv8 = MakeFire(512, 64, 256, 256)
  135. self._drop = Dropout(p=0.5, mode="downscale_in_infer")
  136. self._conv9 = Conv2D(
  137. 512, num_classes, 1, weight_attr=ParamAttr(), bias_attr=ParamAttr()
  138. )
  139. self._avg_pool = AdaptiveAvgPool2D(1)
  140. def forward(self, inputs):
  141. x = self._conv(inputs)
  142. x = F.relu(x)
  143. x = self._pool(x)
  144. if self.version == "1.0":
  145. x = self._conv1(x)
  146. x = self._conv2(x)
  147. x = self._conv3(x)
  148. x = self._pool(x)
  149. x = self._conv4(x)
  150. x = self._conv5(x)
  151. x = self._conv6(x)
  152. x = self._conv7(x)
  153. x = self._pool(x)
  154. x = self._conv8(x)
  155. else:
  156. x = self._conv1(x)
  157. x = self._conv2(x)
  158. x = self._pool(x)
  159. x = self._conv3(x)
  160. x = self._conv4(x)
  161. x = self._pool(x)
  162. x = self._conv5(x)
  163. x = self._conv6(x)
  164. x = self._conv7(x)
  165. x = self._conv8(x)
  166. if self.num_classes > 0:
  167. x = self._drop(x)
  168. x = self._conv9(x)
  169. if self.with_pool:
  170. x = F.relu(x)
  171. x = self._avg_pool(x)
  172. x = paddle.squeeze(x, axis=[2, 3])
  173. return x
  174. def _squeezenet(arch, version, pretrained, **kwargs):
  175. model = SqueezeNet(version, **kwargs)
  176. if pretrained:
  177. assert (
  178. arch in model_urls
  179. ), f"{arch} model do not have a pretrained model now, you should set pretrained=False"
  180. weight_path = get_weights_path_from_url(
  181. model_urls[arch][0], model_urls[arch][1]
  182. )
  183. param = paddle.load(weight_path)
  184. model.set_dict(param)
  185. return model
  186. def squeezenet1_0(pretrained=False, **kwargs):
  187. """SqueezeNet v1.0 model from
  188. `"SqueezeNet: AlexNet-level accuracy with 50x fewer parameters and <0.5MB model size"
  189. <https://arxiv.org/pdf/1602.07360.pdf>`_.
  190. Args:
  191. pretrained (bool, optional): Whether to load pre-trained weights. If True, returns a model pre-trained
  192. on ImageNet. Default: False.
  193. **kwargs (optional): Additional keyword arguments. For details, please refer to :ref:`SqueezeNet <api_paddle_vision_models_SqueezeNet>`.
  194. Returns:
  195. :ref:`api_paddle_nn_Layer`. An instance of SqueezeNet v1.0 model.
  196. Examples:
  197. .. code-block:: python
  198. >>> import paddle
  199. >>> from paddle.vision.models import squeezenet1_0
  200. >>> # build model
  201. >>> model = squeezenet1_0()
  202. >>> # build model and load imagenet pretrained weight
  203. >>> # model = squeezenet1_0(pretrained=True)
  204. >>> x = paddle.rand([1, 3, 224, 224])
  205. >>> out = model(x)
  206. >>> print(out.shape)
  207. [1, 1000]
  208. """
  209. return _squeezenet('squeezenet1_0', '1.0', pretrained, **kwargs)
  210. def squeezenet1_1(pretrained=False, **kwargs):
  211. """SqueezeNet v1.1 model from
  212. `"SqueezeNet: AlexNet-level accuracy with 50x fewer parameters and <0.5MB model size"
  213. <https://arxiv.org/pdf/1602.07360.pdf>`_.
  214. Args:
  215. pretrained (bool, optional): Whether to load pre-trained weights. If True, returns a model pre-trained
  216. on ImageNet. Default: False.
  217. **kwargs (optional): Additional keyword arguments. For details, please refer to :ref:`SqueezeNet <api_paddle_vision_models_SqueezeNet>`.
  218. Returns:
  219. :ref:`api_paddle_nn_Layer`. An instance of SqueezeNet v1.1 model.
  220. Examples:
  221. .. code-block:: python
  222. >>> import paddle
  223. >>> from paddle.vision.models import squeezenet1_1
  224. >>> # build model
  225. >>> model = squeezenet1_1()
  226. >>> # build model and load imagenet pretrained weight
  227. >>> # model = squeezenet1_1(pretrained=True)
  228. >>> x = paddle.rand([1, 3, 224, 224])
  229. >>> out = model(x)
  230. >>> print(out.shape)
  231. [1, 1000]
  232. """
  233. return _squeezenet('squeezenet1_1', '1.1', pretrained, **kwargs)