padding.py 31 KB

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