padding.py 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830
  1. # mypy: allow-untyped-defs
  2. from collections.abc import Sequence
  3. import torch.nn.functional as F
  4. from torch import Tensor
  5. from torch.nn.common_types import _size_2_t, _size_4_t, _size_6_t
  6. from .module import Module
  7. from .utils import _ntuple, _pair, _quadruple
  8. # TODO: grad_output size asserts in THNN
  9. __all__ = [
  10. "CircularPad1d",
  11. "CircularPad2d",
  12. "CircularPad3d",
  13. "ConstantPad1d",
  14. "ConstantPad2d",
  15. "ConstantPad3d",
  16. "ReflectionPad1d",
  17. "ReflectionPad2d",
  18. "ReflectionPad3d",
  19. "ReplicationPad1d",
  20. "ReplicationPad2d",
  21. "ReplicationPad3d",
  22. "ZeroPad1d",
  23. "ZeroPad2d",
  24. "ZeroPad3d",
  25. ]
  26. class _CircularPadNd(Module):
  27. __constants__ = ["padding"]
  28. padding: Sequence[int]
  29. def _check_input_dim(self, input):
  30. raise NotImplementedError
  31. def forward(self, input: Tensor) -> Tensor:
  32. self._check_input_dim(input)
  33. return F.pad(input, self.padding, "circular")
  34. def extra_repr(self) -> str:
  35. return f"{self.padding}"
  36. class CircularPad1d(_CircularPadNd):
  37. r"""Pads the input tensor using circular padding of the input boundary.
  38. Tensor values at the beginning of the dimension are used to pad the end,
  39. and values at the end are used to pad the beginning. If negative padding is
  40. applied then the ends of the tensor get removed.
  41. For `N`-dimensional padding, use :func:`torch.nn.functional.pad()`.
  42. Args:
  43. padding (int, tuple): the size of the padding. If is `int`, uses the same
  44. padding in all boundaries. If a 2-`tuple`, uses
  45. (:math:`\text{padding\_left}`, :math:`\text{padding\_right}`)
  46. Note that padding size should be less than or equal to the corresponding input dimension.
  47. Shape:
  48. - Input: :math:`(C, W_{in})` or :math:`(N, C, W_{in})`.
  49. - Output: :math:`(C, W_{out})` or :math:`(N, C, W_{out})`, where
  50. :math:`W_{out} = W_{in} + \text{padding\_left} + \text{padding\_right}`
  51. Examples::
  52. >>> # xdoctest: +IGNORE_WANT("not sure why xdoctest is choking on this")
  53. >>> m = nn.CircularPad1d(2)
  54. >>> input = torch.arange(8, dtype=torch.float).reshape(1, 2, 4)
  55. >>> input
  56. tensor([[[0., 1., 2., 3.],
  57. [4., 5., 6., 7.]]])
  58. >>> m(input)
  59. tensor([[[2., 3., 0., 1., 2., 3., 0., 1.],
  60. [6., 7., 4., 5., 6., 7., 4., 5.]]])
  61. >>> # using different paddings for different sides
  62. >>> m = nn.CircularPad1d((3, 1))
  63. >>> m(input)
  64. tensor([[[1., 2., 3., 0., 1., 2., 3., 0.],
  65. [5., 6., 7., 4., 5., 6., 7., 4.]]])
  66. """
  67. padding: tuple[int, int]
  68. def __init__(self, padding: _size_2_t) -> None:
  69. super().__init__()
  70. self.padding = _pair(padding)
  71. def _check_input_dim(self, input) -> None:
  72. if input.dim() != 2 and input.dim() != 3:
  73. raise ValueError(f"expected 2D or 3D input (got {input.dim()}D input)")
  74. class CircularPad2d(_CircularPadNd):
  75. r"""Pads the input tensor using circular padding of the input boundary.
  76. Tensor values at the beginning of the dimension are used to pad the end,
  77. and values at the end are used to pad the beginning. If negative padding is
  78. applied then the ends of the tensor get removed.
  79. For `N`-dimensional padding, use :func:`torch.nn.functional.pad()`.
  80. Args:
  81. padding (int, tuple): the size of the padding. If is `int`, uses the same
  82. padding in all boundaries. If a 4-`tuple`, uses (:math:`\text{padding\_left}`,
  83. :math:`\text{padding\_right}`, :math:`\text{padding\_top}`, :math:`\text{padding\_bottom}`)
  84. Note that padding size should be less than or equal to the corresponding input dimension.
  85. Shape:
  86. - Input: :math:`(N, C, H_{in}, W_{in})` or :math:`(C, H_{in}, W_{in})`.
  87. - Output: :math:`(N, C, H_{out}, W_{out})` or :math:`(C, H_{out}, W_{out})`, where
  88. :math:`H_{out} = H_{in} + \text{padding\_top} + \text{padding\_bottom}`
  89. :math:`W_{out} = W_{in} + \text{padding\_left} + \text{padding\_right}`
  90. Examples::
  91. >>> m = nn.CircularPad2d(2)
  92. >>> input = torch.arange(9, dtype=torch.float).reshape(1, 1, 3, 3)
  93. >>> input
  94. tensor([[[[0., 1., 2.],
  95. [3., 4., 5.],
  96. [6., 7., 8.]]]])
  97. >>> m(input)
  98. tensor([[[[4., 5., 3., 4., 5., 3., 4.],
  99. [7., 8., 6., 7., 8., 6., 7.],
  100. [1., 2., 0., 1., 2., 0., 1.],
  101. [4., 5., 3., 4., 5., 3., 4.],
  102. [7., 8., 6., 7., 8., 6., 7.],
  103. [1., 2., 0., 1., 2., 0., 1.],
  104. [4., 5., 3., 4., 5., 3., 4.]]]])
  105. >>> # using different paddings for different sides
  106. >>> m = nn.CircularPad2d((1, 1, 2, 0))
  107. >>> m(input)
  108. tensor([[[[5., 3., 4., 5., 3.],
  109. [8., 6., 7., 8., 6.],
  110. [2., 0., 1., 2., 0.],
  111. [5., 3., 4., 5., 3.],
  112. [8., 6., 7., 8., 6.]]]])
  113. """
  114. padding: tuple[int, int, int, int]
  115. def __init__(self, padding: _size_4_t) -> None:
  116. super().__init__()
  117. self.padding = _quadruple(padding)
  118. def _check_input_dim(self, input) -> None:
  119. if input.dim() != 3 and input.dim() != 4:
  120. raise ValueError(f"expected 3D or 4D input (got {input.dim()}D input)")
  121. class CircularPad3d(_CircularPadNd):
  122. r"""Pads the input tensor using circular padding of the input boundary.
  123. Tensor values at the beginning of the dimension are used to pad the end,
  124. and values at the end are used to pad the beginning. If negative padding is
  125. applied then the ends of the tensor get removed.
  126. For `N`-dimensional padding, use :func:`torch.nn.functional.pad()`.
  127. Args:
  128. padding (int, tuple): the size of the padding. If is `int`, uses the same
  129. padding in all boundaries. If a 6-`tuple`, uses
  130. (:math:`\text{padding\_left}`, :math:`\text{padding\_right}`,
  131. :math:`\text{padding\_top}`, :math:`\text{padding\_bottom}`,
  132. :math:`\text{padding\_front}`, :math:`\text{padding\_back}`)
  133. Note that padding size should be less than or equal to the corresponding input dimension.
  134. Shape:
  135. - Input: :math:`(N, C, D_{in}, H_{in}, W_{in})` or :math:`(C, D_{in}, H_{in}, W_{in})`.
  136. - Output: :math:`(N, C, D_{out}, H_{out}, W_{out})` or :math:`(C, D_{out}, H_{out}, W_{out})`,
  137. where
  138. :math:`D_{out} = D_{in} + \text{padding\_front} + \text{padding\_back}`
  139. :math:`H_{out} = H_{in} + \text{padding\_top} + \text{padding\_bottom}`
  140. :math:`W_{out} = W_{in} + \text{padding\_left} + \text{padding\_right}`
  141. Examples::
  142. >>> # xdoctest: +IGNORE_WANT("non-deterministic")
  143. >>> m = nn.CircularPad3d(3)
  144. >>> input = torch.randn(16, 3, 8, 320, 480)
  145. >>> output = m(input)
  146. >>> # using different paddings for different sides
  147. >>> m = nn.CircularPad3d((3, 3, 6, 6, 1, 1))
  148. >>> output = m(input)
  149. """
  150. padding: tuple[int, int, int, int, int, int]
  151. def __init__(self, padding: _size_6_t) -> None:
  152. super().__init__()
  153. self.padding = _ntuple(6)(padding)
  154. def _check_input_dim(self, input) -> None:
  155. if input.dim() != 4 and input.dim() != 5:
  156. raise ValueError(f"expected 4D or 5D input (got {input.dim()}D input)")
  157. class _ConstantPadNd(Module):
  158. __constants__ = ["padding", "value"]
  159. value: float
  160. padding: Sequence[int]
  161. def __init__(self, value: float) -> None:
  162. super().__init__()
  163. self.value = value
  164. def forward(self, input: Tensor) -> Tensor:
  165. return F.pad(input, self.padding, "constant", self.value)
  166. def extra_repr(self) -> str:
  167. return f"padding={self.padding}, value={self.value}"
  168. class ConstantPad1d(_ConstantPadNd):
  169. r"""Pads the input tensor boundaries with a constant value.
  170. For `N`-dimensional padding, use :func:`torch.nn.functional.pad()`.
  171. Args:
  172. padding (int, tuple): the size of the padding. If is `int`, uses the same
  173. padding in both boundaries. If a 2-`tuple`, uses
  174. (:math:`\text{padding\_left}`, :math:`\text{padding\_right}`)
  175. Shape:
  176. - Input: :math:`(C, W_{in})` or :math:`(N, C, W_{in})`.
  177. - Output: :math:`(C, W_{out})` or :math:`(N, C, W_{out})`, where
  178. :math:`W_{out} = W_{in} + \text{padding\_left} + \text{padding\_right}`
  179. Examples::
  180. >>> # xdoctest: +IGNORE_WANT("non-deterministic")
  181. >>> m = nn.ConstantPad1d(2, 3.5)
  182. >>> input = torch.randn(1, 2, 4)
  183. >>> input
  184. tensor([[[-1.0491, -0.7152, -0.0749, 0.8530],
  185. [-1.3287, 1.8966, 0.1466, -0.2771]]])
  186. >>> m(input)
  187. tensor([[[ 3.5000, 3.5000, -1.0491, -0.7152, -0.0749, 0.8530, 3.5000,
  188. 3.5000],
  189. [ 3.5000, 3.5000, -1.3287, 1.8966, 0.1466, -0.2771, 3.5000,
  190. 3.5000]]])
  191. >>> m = nn.ConstantPad1d(2, 3.5)
  192. >>> input = torch.randn(1, 2, 3)
  193. >>> input
  194. tensor([[[ 1.6616, 1.4523, -1.1255],
  195. [-3.6372, 0.1182, -1.8652]]])
  196. >>> m(input)
  197. tensor([[[ 3.5000, 3.5000, 1.6616, 1.4523, -1.1255, 3.5000, 3.5000],
  198. [ 3.5000, 3.5000, -3.6372, 0.1182, -1.8652, 3.5000, 3.5000]]])
  199. >>> # using different paddings for different sides
  200. >>> m = nn.ConstantPad1d((3, 1), 3.5)
  201. >>> m(input)
  202. tensor([[[ 3.5000, 3.5000, 3.5000, 1.6616, 1.4523, -1.1255, 3.5000],
  203. [ 3.5000, 3.5000, 3.5000, -3.6372, 0.1182, -1.8652, 3.5000]]])
  204. """
  205. padding: tuple[int, int]
  206. def __init__(self, padding: _size_2_t, value: float) -> None:
  207. super().__init__(value)
  208. self.padding = _pair(padding)
  209. class ConstantPad2d(_ConstantPadNd):
  210. r"""Pads the input tensor boundaries with a constant value.
  211. For `N`-dimensional padding, use :func:`torch.nn.functional.pad()`.
  212. Args:
  213. padding (int, tuple): the size of the padding. If is `int`, uses the same
  214. padding in all boundaries. If a 4-`tuple`, uses (:math:`\text{padding\_left}`,
  215. :math:`\text{padding\_right}`, :math:`\text{padding\_top}`, :math:`\text{padding\_bottom}`)
  216. Shape:
  217. - Input: :math:`(N, C, H_{in}, W_{in})` or :math:`(C, H_{in}, W_{in})`.
  218. - Output: :math:`(N, C, H_{out}, W_{out})` or :math:`(C, H_{out}, W_{out})`, where
  219. :math:`H_{out} = H_{in} + \text{padding\_top} + \text{padding\_bottom}`
  220. :math:`W_{out} = W_{in} + \text{padding\_left} + \text{padding\_right}`
  221. Examples::
  222. >>> # xdoctest: +IGNORE_WANT("non-deterministic")
  223. >>> m = nn.ConstantPad2d(2, 3.5)
  224. >>> input = torch.randn(1, 2, 2)
  225. >>> input
  226. tensor([[[ 1.6585, 0.4320],
  227. [-0.8701, -0.4649]]])
  228. >>> m(input)
  229. tensor([[[ 3.5000, 3.5000, 3.5000, 3.5000, 3.5000, 3.5000],
  230. [ 3.5000, 3.5000, 3.5000, 3.5000, 3.5000, 3.5000],
  231. [ 3.5000, 3.5000, 1.6585, 0.4320, 3.5000, 3.5000],
  232. [ 3.5000, 3.5000, -0.8701, -0.4649, 3.5000, 3.5000],
  233. [ 3.5000, 3.5000, 3.5000, 3.5000, 3.5000, 3.5000],
  234. [ 3.5000, 3.5000, 3.5000, 3.5000, 3.5000, 3.5000]]])
  235. >>> # using different paddings for different sides
  236. >>> m = nn.ConstantPad2d((3, 0, 2, 1), 3.5)
  237. >>> m(input)
  238. tensor([[[ 3.5000, 3.5000, 3.5000, 3.5000, 3.5000],
  239. [ 3.5000, 3.5000, 3.5000, 3.5000, 3.5000],
  240. [ 3.5000, 3.5000, 3.5000, 1.6585, 0.4320],
  241. [ 3.5000, 3.5000, 3.5000, -0.8701, -0.4649],
  242. [ 3.5000, 3.5000, 3.5000, 3.5000, 3.5000]]])
  243. """
  244. __constants__ = ["padding", "value"]
  245. padding: tuple[int, int, int, int]
  246. def __init__(self, padding: _size_4_t, value: float) -> None:
  247. super().__init__(value)
  248. self.padding = _quadruple(padding)
  249. class ConstantPad3d(_ConstantPadNd):
  250. r"""Pads the input tensor boundaries with a constant value.
  251. For `N`-dimensional padding, use :func:`torch.nn.functional.pad()`.
  252. Args:
  253. padding (int, tuple): the size of the padding. If is `int`, uses the same
  254. padding in all boundaries. If a 6-`tuple`, uses
  255. (:math:`\text{padding\_left}`, :math:`\text{padding\_right}`,
  256. :math:`\text{padding\_top}`, :math:`\text{padding\_bottom}`,
  257. :math:`\text{padding\_front}`, :math:`\text{padding\_back}`)
  258. Shape:
  259. - Input: :math:`(N, C, D_{in}, H_{in}, W_{in})` or :math:`(C, D_{in}, H_{in}, W_{in})`.
  260. - Output: :math:`(N, C, D_{out}, H_{out}, W_{out})` or
  261. :math:`(C, D_{out}, H_{out}, W_{out})`, where
  262. :math:`D_{out} = D_{in} + \text{padding\_front} + \text{padding\_back}`
  263. :math:`H_{out} = H_{in} + \text{padding\_top} + \text{padding\_bottom}`
  264. :math:`W_{out} = W_{in} + \text{padding\_left} + \text{padding\_right}`
  265. Examples::
  266. >>> m = nn.ConstantPad3d(3, 3.5)
  267. >>> input = torch.randn(16, 3, 10, 20, 30)
  268. >>> output = m(input)
  269. >>> # using different paddings for different sides
  270. >>> m = nn.ConstantPad3d((3, 3, 6, 6, 0, 1), 3.5)
  271. >>> output = m(input)
  272. """
  273. padding: tuple[int, int, int, int, int, int]
  274. def __init__(self, padding: _size_6_t, value: float) -> None:
  275. super().__init__(value)
  276. self.padding = _ntuple(6)(padding)
  277. class _ReflectionPadNd(Module):
  278. __constants__ = ["padding"]
  279. padding: Sequence[int]
  280. def forward(self, input: Tensor) -> Tensor:
  281. return F.pad(input, self.padding, "reflect")
  282. def extra_repr(self) -> str:
  283. return f"{self.padding}"
  284. class ReflectionPad1d(_ReflectionPadNd):
  285. r"""Pads the input tensor using the reflection of the input boundary.
  286. For `N`-dimensional padding, use :func:`torch.nn.functional.pad()`.
  287. Args:
  288. padding (int, tuple): the size of the padding. If is `int`, uses the same
  289. padding in all boundaries. If a 2-`tuple`, uses
  290. (:math:`\text{padding\_left}`, :math:`\text{padding\_right}`)
  291. Note that padding size should be less than the corresponding input dimension.
  292. Shape:
  293. - Input: :math:`(C, W_{in})` or :math:`(N, C, W_{in})`.
  294. - Output: :math:`(C, W_{out})` or :math:`(N, C, W_{out})`, where
  295. :math:`W_{out} = W_{in} + \text{padding\_left} + \text{padding\_right}`
  296. Examples::
  297. >>> m = nn.ReflectionPad1d(2)
  298. >>> # xdoctest: +IGNORE_WANT("other tests seem to modify printing styles")
  299. >>> input = torch.arange(8, dtype=torch.float).reshape(1, 2, 4)
  300. >>> input
  301. tensor([[[0., 1., 2., 3.],
  302. [4., 5., 6., 7.]]])
  303. >>> m(input)
  304. tensor([[[2., 1., 0., 1., 2., 3., 2., 1.],
  305. [6., 5., 4., 5., 6., 7., 6., 5.]]])
  306. >>> # using different paddings for different sides
  307. >>> m = nn.ReflectionPad1d((3, 1))
  308. >>> m(input)
  309. tensor([[[3., 2., 1., 0., 1., 2., 3., 2.],
  310. [7., 6., 5., 4., 5., 6., 7., 6.]]])
  311. """
  312. padding: tuple[int, int]
  313. def __init__(self, padding: _size_2_t) -> None:
  314. super().__init__()
  315. self.padding = _pair(padding)
  316. class ReflectionPad2d(_ReflectionPadNd):
  317. r"""Pads the input tensor using the reflection of the input boundary.
  318. For `N`-dimensional padding, use :func:`torch.nn.functional.pad()`.
  319. Args:
  320. padding (int, tuple): the size of the padding. If is `int`, uses the same
  321. padding in all boundaries. If a 4-`tuple`, uses (:math:`\text{padding\_left}`,
  322. :math:`\text{padding\_right}`, :math:`\text{padding\_top}`, :math:`\text{padding\_bottom}`)
  323. Note that padding size should be less than the corresponding input dimension.
  324. Shape:
  325. - Input: :math:`(N, C, H_{in}, W_{in})` or :math:`(C, H_{in}, W_{in})`.
  326. - Output: :math:`(N, C, H_{out}, W_{out})` or :math:`(C, H_{out}, W_{out})` where
  327. :math:`H_{out} = H_{in} + \text{padding\_top} + \text{padding\_bottom}`
  328. :math:`W_{out} = W_{in} + \text{padding\_left} + \text{padding\_right}`
  329. Examples::
  330. >>> # xdoctest: +IGNORE_WANT("not sure why xdoctest is choking on this")
  331. >>> m = nn.ReflectionPad2d(2)
  332. >>> input = torch.arange(9, dtype=torch.float).reshape(1, 1, 3, 3)
  333. >>> input
  334. tensor([[[[0., 1., 2.],
  335. [3., 4., 5.],
  336. [6., 7., 8.]]]])
  337. >>> m(input)
  338. tensor([[[[8., 7., 6., 7., 8., 7., 6.],
  339. [5., 4., 3., 4., 5., 4., 3.],
  340. [2., 1., 0., 1., 2., 1., 0.],
  341. [5., 4., 3., 4., 5., 4., 3.],
  342. [8., 7., 6., 7., 8., 7., 6.],
  343. [5., 4., 3., 4., 5., 4., 3.],
  344. [2., 1., 0., 1., 2., 1., 0.]]]])
  345. >>> # using different paddings for different sides
  346. >>> m = nn.ReflectionPad2d((1, 1, 2, 0))
  347. >>> m(input)
  348. tensor([[[[7., 6., 7., 8., 7.],
  349. [4., 3., 4., 5., 4.],
  350. [1., 0., 1., 2., 1.],
  351. [4., 3., 4., 5., 4.],
  352. [7., 6., 7., 8., 7.]]]])
  353. """
  354. padding: tuple[int, int, int, int]
  355. def __init__(self, padding: _size_4_t) -> None:
  356. super().__init__()
  357. self.padding = _quadruple(padding)
  358. class ReflectionPad3d(_ReflectionPadNd):
  359. r"""Pads the input tensor using the reflection of the input boundary.
  360. For `N`-dimensional padding, use :func:`torch.nn.functional.pad()`.
  361. Args:
  362. padding (int, tuple): the size of the padding. If is `int`, uses the same
  363. padding in all boundaries. If a 6-`tuple`, uses
  364. (:math:`\text{padding\_left}`, :math:`\text{padding\_right}`,
  365. :math:`\text{padding\_top}`, :math:`\text{padding\_bottom}`,
  366. :math:`\text{padding\_front}`, :math:`\text{padding\_back}`)
  367. Note that padding size should be less than the corresponding input dimension.
  368. Shape:
  369. - Input: :math:`(N, C, D_{in}, H_{in}, W_{in})` or :math:`(C, D_{in}, H_{in}, W_{in})`.
  370. - Output: :math:`(N, C, D_{out}, H_{out}, W_{out})` or :math:`(C, D_{out}, H_{out}, W_{out})`,
  371. where
  372. :math:`D_{out} = D_{in} + \text{padding\_front} + \text{padding\_back}`
  373. :math:`H_{out} = H_{in} + \text{padding\_top} + \text{padding\_bottom}`
  374. :math:`W_{out} = W_{in} + \text{padding\_left} + \text{padding\_right}`
  375. Examples::
  376. >>> # xdoctest: +IGNORE_WANT("not sure why xdoctest is choking on this")
  377. >>> m = nn.ReflectionPad3d(1)
  378. >>> input = torch.arange(8, dtype=torch.float).reshape(1, 1, 2, 2, 2)
  379. >>> m(input)
  380. tensor([[[[[7., 6., 7., 6.],
  381. [5., 4., 5., 4.],
  382. [7., 6., 7., 6.],
  383. [5., 4., 5., 4.]],
  384. [[3., 2., 3., 2.],
  385. [1., 0., 1., 0.],
  386. [3., 2., 3., 2.],
  387. [1., 0., 1., 0.]],
  388. [[7., 6., 7., 6.],
  389. [5., 4., 5., 4.],
  390. [7., 6., 7., 6.],
  391. [5., 4., 5., 4.]],
  392. [[3., 2., 3., 2.],
  393. [1., 0., 1., 0.],
  394. [3., 2., 3., 2.],
  395. [1., 0., 1., 0.]]]]])
  396. """
  397. padding: tuple[int, int, int, int, int, int]
  398. def __init__(self, padding: _size_6_t) -> None:
  399. super().__init__()
  400. self.padding = _ntuple(6)(padding)
  401. class _ReplicationPadNd(Module):
  402. __constants__ = ["padding"]
  403. padding: Sequence[int]
  404. def forward(self, input: Tensor) -> Tensor:
  405. return F.pad(input, self.padding, "replicate")
  406. def extra_repr(self) -> str:
  407. return f"{self.padding}"
  408. class ReplicationPad1d(_ReplicationPadNd):
  409. r"""Pads the input tensor using replication of the input boundary.
  410. For `N`-dimensional padding, use :func:`torch.nn.functional.pad()`.
  411. Args:
  412. padding (int, tuple): the size of the padding. If is `int`, uses the same
  413. padding in all boundaries. If a 2-`tuple`, uses
  414. (:math:`\text{padding\_left}`, :math:`\text{padding\_right}`)
  415. Note that the output dimensions must remain positive.
  416. Shape:
  417. - Input: :math:`(C, W_{in})` or :math:`(N, C, W_{in})`.
  418. - Output: :math:`(C, W_{out})` or :math:`(N, C, W_{out})`, where
  419. :math:`W_{out} = W_{in} + \text{padding\_left} + \text{padding\_right}`
  420. Examples::
  421. >>> # xdoctest: +IGNORE_WANT("not sure why xdoctest is choking on this")
  422. >>> m = nn.ReplicationPad1d(2)
  423. >>> input = torch.arange(8, dtype=torch.float).reshape(1, 2, 4)
  424. >>> input
  425. tensor([[[0., 1., 2., 3.],
  426. [4., 5., 6., 7.]]])
  427. >>> m(input)
  428. tensor([[[0., 0., 0., 1., 2., 3., 3., 3.],
  429. [4., 4., 4., 5., 6., 7., 7., 7.]]])
  430. >>> # using different paddings for different sides
  431. >>> m = nn.ReplicationPad1d((3, 1))
  432. >>> m(input)
  433. tensor([[[0., 0., 0., 0., 1., 2., 3., 3.],
  434. [4., 4., 4., 4., 5., 6., 7., 7.]]])
  435. """
  436. padding: tuple[int, int]
  437. def __init__(self, padding: _size_2_t) -> None:
  438. super().__init__()
  439. self.padding = _pair(padding)
  440. class ReplicationPad2d(_ReplicationPadNd):
  441. r"""Pads the input tensor using replication of the input boundary.
  442. For `N`-dimensional padding, use :func:`torch.nn.functional.pad()`.
  443. Args:
  444. padding (int, tuple): the size of the padding. If is `int`, uses the same
  445. padding in all boundaries. If a 4-`tuple`, uses (:math:`\text{padding\_left}`,
  446. :math:`\text{padding\_right}`, :math:`\text{padding\_top}`, :math:`\text{padding\_bottom}`)
  447. Note that the output dimensions must remain positive.
  448. Shape:
  449. - Input: :math:`(N, C, H_{in}, W_{in})` or :math:`(C, H_{in}, W_{in})`.
  450. - Output: :math:`(N, C, H_{out}, W_{out})` or :math:`(C, H_{out}, W_{out})`, where
  451. :math:`H_{out} = H_{in} + \text{padding\_top} + \text{padding\_bottom}`
  452. :math:`W_{out} = W_{in} + \text{padding\_left} + \text{padding\_right}`
  453. Examples::
  454. >>> m = nn.ReplicationPad2d(2)
  455. >>> # xdoctest: +IGNORE_WANT("non-deterministic")
  456. >>> input = torch.arange(9, dtype=torch.float).reshape(1, 1, 3, 3)
  457. >>> input
  458. tensor([[[[0., 1., 2.],
  459. [3., 4., 5.],
  460. [6., 7., 8.]]]])
  461. >>> m(input)
  462. tensor([[[[0., 0., 0., 1., 2., 2., 2.],
  463. [0., 0., 0., 1., 2., 2., 2.],
  464. [0., 0., 0., 1., 2., 2., 2.],
  465. [3., 3., 3., 4., 5., 5., 5.],
  466. [6., 6., 6., 7., 8., 8., 8.],
  467. [6., 6., 6., 7., 8., 8., 8.],
  468. [6., 6., 6., 7., 8., 8., 8.]]]])
  469. >>> # using different paddings for different sides
  470. >>> m = nn.ReplicationPad2d((1, 1, 2, 0))
  471. >>> m(input)
  472. tensor([[[[0., 0., 1., 2., 2.],
  473. [0., 0., 1., 2., 2.],
  474. [0., 0., 1., 2., 2.],
  475. [3., 3., 4., 5., 5.],
  476. [6., 6., 7., 8., 8.]]]])
  477. """
  478. padding: tuple[int, int, int, int]
  479. def __init__(self, padding: _size_4_t) -> None:
  480. super().__init__()
  481. self.padding = _quadruple(padding)
  482. class ReplicationPad3d(_ReplicationPadNd):
  483. r"""Pads the input tensor using replication of the input boundary.
  484. For `N`-dimensional padding, use :func:`torch.nn.functional.pad()`.
  485. Args:
  486. padding (int, tuple): the size of the padding. If is `int`, uses the same
  487. padding in all boundaries. If a 6-`tuple`, uses
  488. (:math:`\text{padding\_left}`, :math:`\text{padding\_right}`,
  489. :math:`\text{padding\_top}`, :math:`\text{padding\_bottom}`,
  490. :math:`\text{padding\_front}`, :math:`\text{padding\_back}`)
  491. Note that the output dimensions must remain positive.
  492. Shape:
  493. - Input: :math:`(N, C, D_{in}, H_{in}, W_{in})` or :math:`(C, D_{in}, H_{in}, W_{in})`.
  494. - Output: :math:`(N, C, D_{out}, H_{out}, W_{out})` or :math:`(C, D_{out}, H_{out}, W_{out})`,
  495. where
  496. :math:`D_{out} = D_{in} + \text{padding\_front} + \text{padding\_back}`
  497. :math:`H_{out} = H_{in} + \text{padding\_top} + \text{padding\_bottom}`
  498. :math:`W_{out} = W_{in} + \text{padding\_left} + \text{padding\_right}`
  499. Examples::
  500. >>> # xdoctest: +IGNORE_WANT("non-deterministic")
  501. >>> m = nn.ReplicationPad3d(3)
  502. >>> input = torch.randn(16, 3, 8, 320, 480)
  503. >>> output = m(input)
  504. >>> # using different paddings for different sides
  505. >>> m = nn.ReplicationPad3d((3, 3, 6, 6, 1, 1))
  506. >>> output = m(input)
  507. """
  508. padding: tuple[int, int, int, int, int, int]
  509. def __init__(self, padding: _size_6_t) -> None:
  510. super().__init__()
  511. self.padding = _ntuple(6)(padding)
  512. class ZeroPad1d(ConstantPad1d):
  513. r"""Pads the input tensor boundaries with zero.
  514. For `N`-dimensional padding, use :func:`torch.nn.functional.pad()`.
  515. Args:
  516. padding (int, tuple): the size of the padding. If is `int`, uses the same
  517. padding in both boundaries. If a 2-`tuple`, uses
  518. (:math:`\text{padding\_left}`, :math:`\text{padding\_right}`)
  519. Shape:
  520. - Input: :math:`(C, W_{in})` or :math:`(N, C, W_{in})`.
  521. - Output: :math:`(C, W_{out})` or :math:`(N, C, W_{out})`, where
  522. :math:`W_{out} = W_{in} + \text{padding\_left} + \text{padding\_right}`
  523. Examples::
  524. >>> # xdoctest: +IGNORE_WANT("non-deterministic")
  525. >>> m = nn.ZeroPad1d(2)
  526. >>> input = torch.randn(1, 2, 4)
  527. >>> input
  528. tensor([[[-1.0491, -0.7152, -0.0749, 0.8530],
  529. [-1.3287, 1.8966, 0.1466, -0.2771]]])
  530. >>> m(input)
  531. tensor([[[ 0.0000, 0.0000, -1.0491, -0.7152, -0.0749, 0.8530, 0.0000,
  532. 0.0000],
  533. [ 0.0000, 0.0000, -1.3287, 1.8966, 0.1466, -0.2771, 0.0000,
  534. 0.0000]]])
  535. >>> m = nn.ZeroPad1d(2)
  536. >>> input = torch.randn(1, 2, 3)
  537. >>> input
  538. tensor([[[ 1.6616, 1.4523, -1.1255],
  539. [-3.6372, 0.1182, -1.8652]]])
  540. >>> m(input)
  541. tensor([[[ 0.0000, 0.0000, 1.6616, 1.4523, -1.1255, 0.0000, 0.0000],
  542. [ 0.0000, 0.0000, -3.6372, 0.1182, -1.8652, 0.0000, 0.0000]]])
  543. >>> # using different paddings for different sides
  544. >>> m = nn.ZeroPad1d((3, 1))
  545. >>> m(input)
  546. tensor([[[ 0.0000, 0.0000, 0.0000, 1.6616, 1.4523, -1.1255, 0.0000],
  547. [ 0.0000, 0.0000, 0.0000, -3.6372, 0.1182, -1.8652, 0.0000]]])
  548. """
  549. padding: tuple[int, int]
  550. def __init__(self, padding: _size_2_t) -> None:
  551. super().__init__(padding, 0.0)
  552. def extra_repr(self) -> str:
  553. """
  554. Return the extra representation of the module.
  555. """
  556. return f"{self.padding}"
  557. class ZeroPad2d(ConstantPad2d):
  558. r"""Pads the input tensor boundaries with zero.
  559. For `N`-dimensional padding, use :func:`torch.nn.functional.pad()`.
  560. Args:
  561. padding (int, tuple): the size of the padding. If is `int`, uses the same
  562. padding in all boundaries. If a 4-`tuple`, uses (:math:`\text{padding\_left}`,
  563. :math:`\text{padding\_right}`, :math:`\text{padding\_top}`, :math:`\text{padding\_bottom}`)
  564. Shape:
  565. - Input: :math:`(N, C, H_{in}, W_{in})` or :math:`(C, H_{in}, W_{in})`.
  566. - Output: :math:`(N, C, H_{out}, W_{out})` or :math:`(C, H_{out}, W_{out})`, where
  567. :math:`H_{out} = H_{in} + \text{padding\_top} + \text{padding\_bottom}`
  568. :math:`W_{out} = W_{in} + \text{padding\_left} + \text{padding\_right}`
  569. Examples::
  570. >>> # xdoctest: +IGNORE_WANT("non-deterministic")
  571. >>> m = nn.ZeroPad2d(2)
  572. >>> input = torch.randn(1, 1, 3, 3)
  573. >>> input
  574. tensor([[[[-0.1678, -0.4418, 1.9466],
  575. [ 0.9604, -0.4219, -0.5241],
  576. [-0.9162, -0.5436, -0.6446]]]])
  577. >>> m(input)
  578. tensor([[[[ 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],
  579. [ 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],
  580. [ 0.0000, 0.0000, -0.1678, -0.4418, 1.9466, 0.0000, 0.0000],
  581. [ 0.0000, 0.0000, 0.9604, -0.4219, -0.5241, 0.0000, 0.0000],
  582. [ 0.0000, 0.0000, -0.9162, -0.5436, -0.6446, 0.0000, 0.0000],
  583. [ 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],
  584. [ 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000]]]])
  585. >>> # using different paddings for different sides
  586. >>> m = nn.ZeroPad2d((1, 1, 2, 0))
  587. >>> m(input)
  588. tensor([[[[ 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],
  589. [ 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],
  590. [ 0.0000, -0.1678, -0.4418, 1.9466, 0.0000],
  591. [ 0.0000, 0.9604, -0.4219, -0.5241, 0.0000],
  592. [ 0.0000, -0.9162, -0.5436, -0.6446, 0.0000]]]])
  593. """
  594. padding: tuple[int, int, int, int]
  595. def __init__(self, padding: _size_4_t) -> None:
  596. super().__init__(padding, 0.0)
  597. def extra_repr(self) -> str:
  598. """
  599. Return the extra representation of the module.
  600. """
  601. return f"{self.padding}"
  602. class ZeroPad3d(ConstantPad3d):
  603. r"""Pads the input tensor boundaries with zero.
  604. For `N`-dimensional padding, use :func:`torch.nn.functional.pad()`.
  605. Args:
  606. padding (int, tuple): the size of the padding. If is `int`, uses the same
  607. padding in all boundaries. If a 6-`tuple`, uses
  608. (:math:`\text{padding\_left}`, :math:`\text{padding\_right}`,
  609. :math:`\text{padding\_top}`, :math:`\text{padding\_bottom}`,
  610. :math:`\text{padding\_front}`, :math:`\text{padding\_back}`)
  611. Shape:
  612. - Input: :math:`(N, C, D_{in}, H_{in}, W_{in})` or :math:`(C, D_{in}, H_{in}, W_{in})`.
  613. - Output: :math:`(N, C, D_{out}, H_{out}, W_{out})` or
  614. :math:`(C, D_{out}, H_{out}, W_{out})`, where
  615. :math:`D_{out} = D_{in} + \text{padding\_front} + \text{padding\_back}`
  616. :math:`H_{out} = H_{in} + \text{padding\_top} + \text{padding\_bottom}`
  617. :math:`W_{out} = W_{in} + \text{padding\_left} + \text{padding\_right}`
  618. Examples::
  619. >>> m = nn.ZeroPad3d(3)
  620. >>> input = torch.randn(16, 3, 10, 20, 30)
  621. >>> output = m(input)
  622. >>> # using different paddings for different sides
  623. >>> m = nn.ZeroPad3d((3, 3, 6, 6, 0, 1))
  624. >>> output = m(input)
  625. """
  626. padding: tuple[int, int, int, int, int, int]
  627. def __init__(self, padding: _size_6_t) -> None:
  628. super().__init__(padding, 0.0)
  629. def extra_repr(self) -> str:
  630. """
  631. Return the extra representation of the module.
  632. """
  633. return f"{self.padding}"