You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

pooling.py 12 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. # Copyright 2020 Huawei Technologies Co., Ltd
  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. # ============================================================================
  15. """pooling"""
  16. from mindspore.ops import operations as P
  17. from mindspore.ops import functional as F
  18. from mindspore._checkparam import Validator as validator
  19. from ... import context
  20. from ..cell import Cell
  21. from ..._checkparam import Rel
  22. class _PoolNd(Cell):
  23. """N-D AvgPool"""
  24. def __init__(self, kernel_size, stride, pad_mode):
  25. super(_PoolNd, self).__init__()
  26. self.pad_mode = validator.check_string('pad_mode', pad_mode.upper(), ['VALID', 'SAME'], self.cls_name)
  27. def _check_int_or_tuple(arg_name, arg_value):
  28. validator.check_value_type(arg_name, arg_value, [int, tuple], self.cls_name)
  29. error_msg = f'For \'{self.cls_name}\' the {arg_name} should be an positive int number or ' \
  30. f'a tuple of two positive int numbers, but got {arg_value}'
  31. if isinstance(arg_value, int):
  32. if arg_value <= 0:
  33. raise ValueError(error_msg)
  34. elif len(arg_value) == 2:
  35. for item in arg_value:
  36. if isinstance(item, int) and item > 0:
  37. continue
  38. raise ValueError(error_msg)
  39. else:
  40. raise ValueError(error_msg)
  41. return arg_value
  42. self.kernel_size = _check_int_or_tuple('kernel_size', kernel_size)
  43. self.stride = _check_int_or_tuple('stride', stride)
  44. def construct(self, *inputs):
  45. pass
  46. def extend_repr(self):
  47. return 'kernel_size={kernel_size}, stride={stride}, pad_mode={pad_mode}'.format(**self.__dict__)
  48. class MaxPool2d(_PoolNd):
  49. r"""
  50. Max pooling operation for temporal data.
  51. Applies a 2D max pooling over an input Tensor which can be regarded as a composition of 2D planes.
  52. Typically the input is of shape :math:`(N_{in}, C_{in}, H_{in}, W_{in})`, MaxPool2d outputs
  53. regional maximum in the :math:`(H_{in}, W_{in})`-dimension. Given kernel size
  54. :math:`ks = (h_{ker}, w_{ker})` and stride :math:`s = (s_0, s_1)`, the operation is as follows.
  55. .. math::
  56. \text{output}(N_i, C_j, h, w) = \max_{m=0, \ldots, h_{ker}-1} \max_{n=0, \ldots, w_{ker}-1}
  57. \text{input}(N_i, C_j, s_0 \times h + m, s_1 \times w + n)
  58. Note:
  59. pad_mode for training only supports "same" and "valid".
  60. Args:
  61. kernel_size (Union[int, tuple[int]]): The size of kernel used to take the max value,
  62. is an int number that represents height and width are both kernel_size,
  63. or a tuple of two int numbers that represent height and width respectively.
  64. Default: 1.
  65. stride (Union[int, tuple[int]]): The distance of kernel moving, an int number that represents
  66. the height and width of movement are both strides, or a tuple of two int numbers that
  67. represent height and width of movement respectively. Default: 1.
  68. pad_mode (str): The optional values for pad mode, is "same" or "valid", not case sensitive.
  69. Default: "valid".
  70. - same: Adopts the way of completion. Output height and width will be the same as
  71. the input. Total number of padding will be calculated for horizontal and vertical
  72. direction and evenly distributed to top and bottom, left and right if possible.
  73. Otherwise, the last extra padding will be done from the bottom and the right side.
  74. - valid: Adopts the way of discarding. The possibly largest height and width of output
  75. will be return without padding. Extra pixels will be discarded.
  76. Inputs:
  77. - **input** (Tensor) - Tensor of shape :math:`(N, C_{in}, H_{in}, W_{in})`.
  78. Outputs:
  79. Tensor of shape :math:`(N, C_{out}, H_{out}, W_{out})`.
  80. Examples:
  81. >>> pool = nn.MaxPool2d(kernel_size=3, stride=1)
  82. >>> x = Tensor(np.random.randint(0, 10, [1, 2, 4, 4]), mindspore.float32)
  83. [[[[1. 5. 5. 1.]
  84. [0. 3. 4. 8.]
  85. [4. 2. 7. 6.]
  86. [4. 9. 0. 1.]]
  87. [[3. 6. 2. 6.]
  88. [4. 4. 7. 8.]
  89. [0. 0. 4. 0.]
  90. [1. 8. 7. 0.]]]]
  91. >>> output = pool(x)
  92. >>> output.shape()
  93. (1, 2, 2, 2)
  94. >>> output
  95. [[[[7. 8.]
  96. [9. 9.]]
  97. [[7. 8.]
  98. [8. 8.]]]]
  99. """
  100. def __init__(self, kernel_size=1, stride=1, pad_mode="valid"):
  101. super(MaxPool2d, self).__init__(kernel_size, stride, pad_mode)
  102. self.max_pool = P.MaxPool(ksize=self.kernel_size,
  103. strides=self.stride,
  104. padding=self.pad_mode)
  105. self.max_pool_with_arg_max = P.MaxPoolWithArgmax(ksize=self.kernel_size,
  106. strides=self.stride,
  107. padding=self.pad_mode)
  108. self.is_tbe = context.get_context("device_target") == "Ascend"
  109. def construct(self, x):
  110. if self.is_tbe and self.training:
  111. out = self.max_pool_with_arg_max(x)[0]
  112. else:
  113. out = self.max_pool(x)
  114. return out
  115. class AvgPool2d(_PoolNd):
  116. r"""
  117. Average pooling for temporal data.
  118. Applies a 2D average pooling over an input Tensor which can be regarded as a composition of 2D input planes.
  119. Typically the input is of shape :math:`(N_{in}, C_{in}, H_{in}, W_{in})`, AvgPool2d outputs
  120. regional average in the :math:`(H_{in}, W_{in})`-dimension. Given kernel size
  121. :math:`ks = (h_{ker}, w_{ker})` and stride :math:`s = (s_0, s_1)`, the operation is as follows.
  122. .. math::
  123. \text{output}(N_i, C_j, h, w) = \frac{1}{h_{ker} * w_{ker}} \sum_{m=0}^{h_{ker}-1} \sum_{n=0}^{w_{ker}-1}
  124. \text{input}(N_i, C_j, s_0 \times h + m, s_1 \times w + n)
  125. Note:
  126. pad_mode for training only supports "same" and "valid".
  127. Args:
  128. kernel_size (Union[int, tuple[int]]): The size of kernel used to take the average value,
  129. is an int number that represents height and width are both kernel_size,
  130. or a tuple of two int numbers that represent height and width respectively.
  131. Default: 1.
  132. stride (Union[int, tuple[int]]): The distance of kernel moving, an int number that represents
  133. the height and width of movement are both strides, or a tuple of two int numbers that
  134. represent height and width of movement respectively. Default: 1.
  135. pad_mode (str): The optional values for pad mode, is "same" or "valid", not case sensitive.
  136. Default: "valid".
  137. - same: Adopts the way of completion. Output height and width will be the same as
  138. the input. Total number of padding will be calculated for horizontal and vertical
  139. direction and evenly distributed to top and bottom, left and right if possible.
  140. Otherwise, the last extra padding will be done from the bottom and the right side.
  141. - valid: Adopts the way of discarding. The possibly largest height and width of output
  142. will be return without padding. Extra pixels will be discarded.
  143. Inputs:
  144. - **input** (Tensor) - Tensor of shape :math:`(N, C_{in}, H_{in}, W_{in})`.
  145. Outputs:
  146. Tensor of shape :math:`(N, C_{out}, H_{out}, W_{out})`.
  147. Examples:
  148. >>> pool = nn.AvgPool2d(kernel_size=3, strides=1)
  149. >>> x = Tensor(np.random.randint(0, 10, [1, 2, 4, 4]), mindspore.float32)
  150. [[[[5. 5. 9. 9.]
  151. [8. 4. 3. 0.]
  152. [2. 7. 1. 2.]
  153. [1. 8. 3. 3.]]
  154. [[6. 8. 2. 4.]
  155. [3. 0. 2. 1.]
  156. [0. 8. 9. 7.]
  157. [2. 1. 4. 9.]]]]
  158. >>> output = pool(x)
  159. >>> output.shape()
  160. (1, 2, 2, 2)
  161. >>> output
  162. [[[[4.888889 4.4444447]
  163. [4.111111 3.4444444]]
  164. [[4.2222223 4.5555553]
  165. [3.2222223 4.5555553]]]]
  166. """
  167. def __init__(self,
  168. kernel_size=1,
  169. stride=1,
  170. pad_mode="valid"):
  171. super(AvgPool2d, self).__init__(kernel_size, stride, pad_mode)
  172. self.avg_pool = P.AvgPool(ksize=self.kernel_size,
  173. strides=self.stride,
  174. padding=self.pad_mode)
  175. def construct(self, x):
  176. return self.avg_pool(x)
  177. class AvgPool1d(_PoolNd):
  178. r"""
  179. Average pooling for temporal data.
  180. Applies a 1D average pooling over an input Tensor which can be regarded as a composition of 1D input planes.
  181. Typically the input is of shape :math:`(N_{in}, C_{in}, H_{in}, W_{in})`, AvgPool1d outputs
  182. regional average in the :math:`(W_{in})`-dimension. Given kernel size
  183. :math:`ks = w_{ker}` and stride :math:`s = s_0`, the operation is as follows.
  184. .. math::
  185. \text{output}(N_i, C_j, h_k, w) = \frac{1}{w_{ker}} \sum_{n=0}^{w_{ker}-1}
  186. \text{input}(N_i, C_j, h_k, s_0 \times w + n)
  187. Note:
  188. pad_mode for training only supports "same" and "valid".
  189. Args:
  190. kernel_size (int): The size of kernel window used to take the average value, Default: 1.
  191. stride (int): The distance of kernel moving, an int number that represents
  192. the width of movement is strides, Default: 1.
  193. pad_mode (str): The optional values for pad mode, is "same" or "valid", not case sensitive.
  194. Default: "valid".
  195. - same: Adopts the way of completion. Output height and width will be the same as
  196. the input. Total number of padding will be calculated for horizontal and vertical
  197. direction and evenly distributed to top and bottom, left and right if possible.
  198. Otherwise, the last extra padding will be done from the bottom and the right side.
  199. - valid: Adopts the way of discarding. The possibly largest height and width of output
  200. will be return without padding. Extra pixels will be discarded.
  201. Inputs:
  202. - **input** (Tensor) - Tensor of shape :math:`(N, C_{in}, H_{in}, W_{in})`.
  203. Outputs:
  204. Tensor of shape :math:`(N, C_{out}, H_{out}, W_{out})`.
  205. Examples:
  206. >>> pool = nn.AvgPool1d(kernel_size=3, strides=1)
  207. >>> x = Tensor(np.random.randint(0, 10, [1, 2, 4, 4]), mindspore.float32)
  208. >>> output = pool(x)
  209. >>> output.shape()
  210. (1, 2, 4, 2)
  211. """
  212. def __init__(self,
  213. kernel_size=1,
  214. stride=1,
  215. pad_mode="valid"):
  216. super(AvgPool1d, self).__init__(kernel_size, stride, pad_mode)
  217. validator.check_value_type('kernel_size', kernel_size, [int], self.cls_name)
  218. validator.check_value_type('stride', stride, [int], self.cls_name)
  219. self.pad_mode = validator.check_string('pad_mode', pad_mode.upper(), ['VALID', 'SAME'], self.cls_name)
  220. validator.check_integer("kernel_size", kernel_size, 1, Rel.GE, self.cls_name)
  221. validator.check_integer("stride", stride, 1, Rel.GE, self.cls_name)
  222. self.kernel_size = (1, kernel_size)
  223. self.stride = (1, stride)
  224. self.avg_pool = P.AvgPool(ksize=self.kernel_size,
  225. strides=self.stride,
  226. padding=self.pad_mode)
  227. self.shape = F.shape
  228. self.reduce_mean = P.ReduceMean(keep_dims=True)
  229. self.slice = P.Slice()
  230. def construct(self, x):
  231. batch, channel, high, width = self.shape(x)
  232. if width == self.kernel_size[1]:
  233. x = self.reduce_mean(x, 3)
  234. elif width - self.kernel_size[1] < self.stride[1]:
  235. x = self.slice(x, (0, 0, 0, 0), (batch, channel, high, self.kernel_size[1]))
  236. x = self.reduce_mean(x, 3)
  237. else:
  238. x = self.avg_pool(x)
  239. return x