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.

sliding_window.py 4.6 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. # -*- coding: utf-8 -*-
  2. from typing import Tuple, Union
  3. from ..functional import sliding_window, sliding_window_transpose
  4. from .module import Module
  5. class SlidingWindow(Module):
  6. r"""Apply a sliding window to input tensor and copy content in the window to
  7. corresponding output location. Assume input shape is :math:`(N, C, IH, IW)`,
  8. then output shape would be :math:`(N, C, OH, OW, window_h, window_w)` where
  9. :math:`(OH, OW)` would be computed from padding, stride, window and
  10. :math:`(IH, IW)`, as in convolution. For each output location, we have;
  11. .. math::
  12. out_{n, c, oh, ow, wh, ww} &= src_{n, c, ih+wh, iw+ww} \\
  13. \text{where } & ih=-pad_h+oh \times stride_h + (wh-1) \times (dilation_h-1) \\
  14. & iw=-pad_w+ow \times stride_w + (ww-1) \times (dilation_w-1)
  15. Args:
  16. kernel_size: the size of the window to take a max over.
  17. padding: implicit zero padding to be added on both sides. Default: 0
  18. stride: the stride of the window. Default: 1
  19. dilation: the dilation of the window. Default: 1
  20. Example:
  21. >>> import numpy as np
  22. >>> inp = Tensor(np.arange(30).reshape(1,1,5,6))
  23. >>> op = M.SlidingWindow(kernel_size=3, padding=1, stride=2, dilation=2)
  24. >>> out = op(inp)
  25. >>> print(out.numpy())
  26. [[[[[[ 0 0 0]
  27. [ 0 7 9]
  28. [ 0 19 21]]
  29. <BLANKLINE>
  30. [[ 0 0 0]
  31. [ 7 9 11]
  32. [19 21 23]]]
  33. <BLANKLINE>
  34. <BLANKLINE>
  35. [[[ 0 7 9]
  36. [ 0 19 21]
  37. [ 0 0 0]]
  38. <BLANKLINE>
  39. [[ 7 9 11]
  40. [19 21 23]
  41. [ 0 0 0]]]]]]
  42. """
  43. def __init__(
  44. self,
  45. kernel_size: Union[int, Tuple[int, int]],
  46. padding: Union[int, Tuple[int, int]] = 0,
  47. stride: Union[int, Tuple[int, int]] = 1,
  48. dilation: Union[int, Tuple[int, int]] = 1,
  49. **kwargs
  50. ):
  51. super(SlidingWindow, self).__init__(**kwargs)
  52. self.kernel_size = kernel_size
  53. self.padding = padding
  54. self.stride = stride
  55. self.dilation = dilation
  56. def forward(self, inp):
  57. return sliding_window(
  58. inp, self.kernel_size, self.padding, self.stride, self.dilation
  59. )
  60. class SlidingWindowTranspose(Module):
  61. r"""Opposite opration of SlidingWindow, sum over the sliding windows on the
  62. corresponding input location. Given an input of the size
  63. :math:`(N, C, IH, IW, window_h, window_w)` and :attr:`output_size`, the
  64. output shape would be :math:`(N, C, output\_size_{h}, output\_size_{w})` and the
  65. arguments must satisfy
  66. .. math::
  67. \text{IH} = \lfloor \frac{\text{output_size}_{h} + 2 * \text{padding}_{h} -
  68. \text{dilation}_{h} * (\text{kernel_size}_{h} - 1) - 1}{\text{stride}_{h}} + 1 \rfloor
  69. .. math::
  70. \text{IW} = \lfloor \frac{\text{output_size}_{w} + 2 * \text{padding}_{w} -
  71. \text{dilation}_{w} * (\text{kernel_size}_{w} - 1) - 1}{\text{stride}_{w}} + 1 \rfloor
  72. For each output location, we have:
  73. .. math::
  74. \text{out}_{n, c, oh, ow} = \sum_{n,c,oh,ow=location(n, c, ih, iw, wh, ww)}\text{src}_{n, c, ih, iw, wh, ww}
  75. .. math::
  76. \text{location}(n, c, ih, iw, wh, ww) &= (n, c, oh+wh, ow+ww) \\
  77. \text{where } & oh=-pad_h+ih \times stride_h + (wh-1) \times (dilation_h-1) \\
  78. & ow=-pad_w+iw \times stride_w + (ww-1) \times (dilation_w-1)
  79. Args:
  80. output_size: the size of the output tensor.
  81. kernel_size: the size of the window to take a max over.
  82. padding: implicit zero padding to be added on both sides. Default: 0
  83. stride: the stride of the window. Default: 1
  84. dilation: the dilation of the window. Default: 1
  85. """
  86. def __init__(
  87. self,
  88. output_size: Union[int, Tuple[int, int]],
  89. kernel_size: Union[int, Tuple[int, int]],
  90. padding: Union[int, Tuple[int, int]] = 0,
  91. stride: Union[int, Tuple[int, int]] = 1,
  92. dilation: Union[int, Tuple[int, int]] = 1,
  93. **kwargs
  94. ):
  95. super(SlidingWindowTranspose, self).__init__(**kwargs)
  96. self.output_size = output_size
  97. self.kernel_size = kernel_size
  98. self.padding = padding
  99. self.stride = stride
  100. self.dilation = dilation
  101. def forward(self, inp):
  102. return sliding_window_transpose(
  103. inp,
  104. self.output_size,
  105. self.kernel_size,
  106. self.padding,
  107. self.stride,
  108. self.dilation,
  109. )