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.

conv.py 34 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946
  1. # MegEngine is Licensed under the Apache License, Version 2.0 (the "License")
  2. #
  3. # Copyright (c) 2014-2021 Megvii Inc. All rights reserved.
  4. #
  5. # Unless required by applicable law or agreed to in writing,
  6. # software distributed under the License is distributed on an
  7. # "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  8. from abc import abstractmethod
  9. from typing import Tuple, Union
  10. import numpy as np
  11. from ..functional import (
  12. conv1d,
  13. conv2d,
  14. conv3d,
  15. conv_transpose2d,
  16. conv_transpose3d,
  17. deformable_conv2d,
  18. local_conv2d,
  19. relu,
  20. )
  21. from ..tensor import Parameter
  22. from ..utils.tuple_function import _pair, _pair_nonzero, _triple, _triple_nonzero
  23. from . import init
  24. from .module import Module
  25. class _ConvNd(Module):
  26. """base class for convolution modules, including transposed conv"""
  27. def __init__(
  28. self,
  29. in_channels: int,
  30. out_channels: int,
  31. kernel_size: Union[int, Tuple[int, int]],
  32. stride: Union[int, Tuple[int, int]],
  33. padding: Union[int, Tuple[int, int]],
  34. dilation: Union[int, Tuple[int, int]],
  35. groups: int,
  36. bias: bool = True,
  37. **kwargs
  38. ):
  39. super().__init__(**kwargs)
  40. if in_channels % groups != 0:
  41. raise ValueError("in_channels must be divisible by groups")
  42. if out_channels % groups != 0:
  43. raise ValueError("out_channels must be divisible by groups")
  44. self.in_channels = in_channels
  45. self.out_channels = out_channels
  46. self.kernel_size = kernel_size
  47. self.stride = stride
  48. self.padding = padding
  49. self.dilation = dilation
  50. self.groups = groups
  51. self.weight = Parameter(np.zeros(self._infer_weight_shape(), dtype=np.float32))
  52. self.bias = None
  53. if bias:
  54. self.bias = Parameter(np.zeros(self._infer_bias_shape(), dtype=np.float32))
  55. self.reset_parameters()
  56. @abstractmethod
  57. def _get_fanin(self):
  58. pass
  59. def reset_parameters(self) -> None:
  60. fanin = self._get_fanin()
  61. std = np.sqrt(1 / fanin)
  62. init.normal_(self.weight, 0.0, std)
  63. if self.bias is not None:
  64. init.zeros_(self.bias)
  65. @abstractmethod
  66. def _infer_weight_shape(self):
  67. pass
  68. @abstractmethod
  69. def _infer_bias_shape(self):
  70. pass
  71. def _module_info_string(self):
  72. s = "{in_channels}, {out_channels}, kernel_size={kernel_size}"
  73. if self.stride != (1,) * len(self.stride):
  74. s += ", stride={stride}"
  75. if self.padding != (0,) * len(self.padding):
  76. s += ", padding={padding}"
  77. if self.dilation != (1,) * len(self.dilation):
  78. s += ", dilation={dilation}"
  79. if self.groups != 1:
  80. s += ", groups={groups}"
  81. if self.bias is None:
  82. s += ", bias=False"
  83. return s.format(**self.__dict__)
  84. class Conv1d(_ConvNd):
  85. r"""Applies a 1D convolution over an input tensor.
  86. For instance, given an input of the size :math:`(N, C_{\text{in}}, H)`,
  87. this layer generates an output of the size
  88. :math:`(N, C_{\text{out}}, H_{\text{out}})` through the
  89. process described as below:
  90. .. math::
  91. \text{out}(N_i, C_{\text{out}_j}) = \text{bias}(C_{\text{out}_j}) +
  92. \sum_{k = 0}^{C_{\text{in}} - 1} \text{weight}(C_{\text{out}_j}, k) \star \text{input}(N_i, k)
  93. where :math:`\star` is the valid 1D cross-correlation operator,
  94. :math:`N` is batch size, :math:`C` denotes number of channels, and
  95. :math:`H` is length of 1D data element.
  96. When `groups == in_channels` and `out_channels == K * in_channels`,
  97. where K is a positive integer, this operation is also known as depthwise
  98. convolution.
  99. In other words, for an input of size :math:`(N, C_{in}, H_{in})`,
  100. a depthwise convolution with a depthwise multiplier `K`, can be constructed
  101. by arguments :math:`(in\_channels=C_{in}, out\_channels=C_{in} \times K, ..., groups=C_{in})`.
  102. Args:
  103. in_channels: number of input channels.
  104. out_channels: number of output channels.
  105. kernel_size: size of weight on spatial dimensions.
  106. stride: stride of the 1D convolution operation.
  107. padding: size of the paddings added to the input on both sides of its
  108. spatial dimensions. Only zero-padding is supported. Default: 0
  109. dilation: dilation of the 1D convolution operation. Default: 1
  110. groups: number of groups to divide input and output channels into,
  111. so as to perform a "grouped convolution". When ``groups`` is not 1,
  112. ``in_channels`` and ``out_channels`` must be divisible by ``groups``,
  113. and the shape of weight should be ``(groups, out_channel // groups,
  114. in_channels // groups, kernel_size)``. Default: 1
  115. bias: whether to add a bias onto the result of convolution. Default: True
  116. conv_mode: Supports `cross_correlation`. Default: `cross_correlation`
  117. compute_mode: When set to "default", no special requirements will be
  118. placed on the precision of intermediate results. When set to "float32",
  119. "float32" would be used for accumulator and intermediate result, but only
  120. effective when input and output are of float16 dtype.
  121. Note:
  122. * ``weight`` usually has shape ``(out_channels, in_channels, kernel_size)`` ,
  123. if groups is not 1, shape will be ``(groups, out_channels // groups, in_channels // groups, kernel_size)``
  124. * ``bias`` usually has shape ``(1, out_channels, 1)``
  125. Examples:
  126. .. testcode::
  127. import numpy as np
  128. import megengine as mge
  129. import megengine.module as M
  130. m = M.Conv1d(in_channels=3, out_channels=1, kernel_size=3)
  131. inp = mge.tensor(np.arange(0, 24).astype("float32").reshape(2, 3, 4))
  132. oup = m(inp)
  133. print(oup.numpy().shape)
  134. Outputs:
  135. .. testoutput::
  136. (2, 1, 2)
  137. """
  138. def __init__(
  139. self,
  140. in_channels: int,
  141. out_channels: int,
  142. kernel_size: int,
  143. stride: int = 1,
  144. padding: int = 0,
  145. dilation: int = 1,
  146. groups: int = 1,
  147. bias: bool = True,
  148. conv_mode: str = "cross_correlation",
  149. compute_mode: str = "default",
  150. **kwargs
  151. ):
  152. kernel_size = kernel_size
  153. stride = stride
  154. padding = padding
  155. dilation = dilation
  156. self.conv_mode = conv_mode
  157. self.compute_mode = compute_mode
  158. super().__init__(
  159. in_channels,
  160. out_channels,
  161. kernel_size,
  162. stride,
  163. padding,
  164. dilation,
  165. groups,
  166. bias,
  167. **kwargs,
  168. )
  169. def _get_fanin(self):
  170. kh = self.kernel_size
  171. ic = self.in_channels
  172. return kh * ic
  173. def _infer_weight_shape(self):
  174. group = self.groups
  175. ichl = self.in_channels
  176. ochl = self.out_channels
  177. kh = self.kernel_size
  178. if group == 1:
  179. # Assume format is NCH(W=1)
  180. return (ochl, ichl, kh)
  181. assert (
  182. ichl % group == 0 and ochl % group == 0
  183. ), "invalid config: in_channels={} out_channels={} group={}".format(
  184. ichl, ochl, group
  185. )
  186. # Assume format is NCH(W=1)
  187. return (group, ochl // group, ichl // group, kh)
  188. def _infer_bias_shape(self):
  189. # Assume format is NCH(W=1)
  190. return (1, self.out_channels, 1)
  191. def calc_conv(self, inp, weight, bias):
  192. return conv1d(
  193. inp,
  194. weight,
  195. bias,
  196. self.stride,
  197. self.padding,
  198. self.dilation,
  199. self.groups,
  200. self.conv_mode,
  201. self.compute_mode,
  202. )
  203. def forward(self, inp):
  204. return self.calc_conv(inp, self.weight, self.bias)
  205. class Conv2d(_ConvNd):
  206. r"""Applies a 2D convolution over an input tensor.
  207. For instance, given an input of the size :math:`(N, C_{\text{in}}, H, W)`,
  208. this layer generates an output of the size
  209. :math:`(N, C_{\text{out}}, H_{\text{out}}, W_{\text{out}})` through the
  210. process described as below:
  211. .. math::
  212. \text{out}(N_i, C_{\text{out}_j}) = \text{bias}(C_{\text{out}_j}) +
  213. \sum_{k = 0}^{C_{\text{in}} - 1} \text{weight}(C_{\text{out}_j}, k) \star \text{input}(N_i, k)
  214. where :math:`\star` is the valid 2D cross-correlation operator,
  215. :math:`N` is batch size, :math:`C` denotes number of channels,
  216. :math:`H` is height of input planes in pixels, and :math:`W` is
  217. width in pixels.
  218. In general, output feature maps' shapes can be inferred as follows:
  219. input: :math:`(N, C_{\text{in}}, H_{\text{in}}, W_{\text{in}})`
  220. output: :math:`(N, C_{\text{out}}, H_{\text{out}}, W_{\text{out}})` where
  221. .. math::
  222. \text{H}_{out} = \lfloor \frac{\text{H}_{in} + 2 * \text{padding[0]} -
  223. \text{dilation[0]} * (\text{kernel_size[0]} - 1) - 1}{\text{stride[0]}} + 1 \rfloor
  224. .. math::
  225. \text{W}_{out} = \lfloor \frac{\text{W}_{in} + 2 * \text{padding[1]} -
  226. \text{dilation[1]} * (\text{kernel_size[1]} - 1) - 1}{\text{stride[1]}} + 1 \rfloor
  227. When `groups == in_channels` and `out_channels == K * in_channels`,
  228. where K is a positive integer, this operation is also known as depthwise
  229. convolution.
  230. In other words, for an input of size :math:`(N, C_{in}, H_{in}, W_{in})`,
  231. a depthwise convolution with a depthwise multiplier `K`, can be constructed
  232. by arguments :math:`(in\_channels=C_{in}, out\_channels=C_{in} \times K, ..., groups=C_{in})`.
  233. Args:
  234. in_channels: number of input channels.
  235. out_channels: number of output channels.
  236. kernel_size: size of weight on spatial dimensions. If kernel_size is
  237. an :class:`int`, the actual kernel size would be
  238. ``(kernel_size, kernel_size)``.
  239. stride: stride of the 2D convolution operation. Default: 1
  240. padding: size of the paddings added to the input on both sides of its
  241. spatial dimensions. Only zero-padding is supported. Default: 0
  242. dilation: dilation of the 2D convolution operation. Default: 1
  243. groups: number of groups into which the input and output channels are divided,
  244. so as to perform a ``grouped convolution``. When ``groups`` is not 1,
  245. ``in_channels`` and ``out_channels`` must be divisible by ``groups``,
  246. and the shape of weight should be ``(groups, out_channel // groups,
  247. in_channels // groups, height, width)``. Default: 1
  248. bias: whether to add a bias onto the result of convolution. Default: True
  249. conv_mode: Supports `cross_correlation`. Default: `cross_correlation`
  250. compute_mode: When set to "default", no special requirements will be
  251. placed on the precision of intermediate results. When set to "float32",
  252. "float32" would be used for accumulator and intermediate result, but only
  253. effective when input and output are of float16 dtype.
  254. Note:
  255. * ``weight`` usually has shape ``(out_channels, in_channels, height, width)`` ,
  256. if groups is not 1, shape will be ``(groups, out_channels // groups, in_channels // groups, height, width)``
  257. * ``bias`` usually has shape ``(1, out_channels, *1)``
  258. Examples:
  259. .. testcode::
  260. import numpy as np
  261. import megengine as mge
  262. import megengine.module as M
  263. m = M.Conv2d(in_channels=3, out_channels=1, kernel_size=3)
  264. inp = mge.tensor(np.arange(0, 96).astype("float32").reshape(2, 3, 4, 4))
  265. oup = m(inp)
  266. print(oup.numpy().shape)
  267. Outputs:
  268. .. testoutput::
  269. (2, 1, 2, 2)
  270. """
  271. def __init__(
  272. self,
  273. in_channels: int,
  274. out_channels: int,
  275. kernel_size: Union[int, Tuple[int, int]],
  276. stride: Union[int, Tuple[int, int]] = 1,
  277. padding: Union[int, Tuple[int, int]] = 0,
  278. dilation: Union[int, Tuple[int, int]] = 1,
  279. groups: int = 1,
  280. bias: bool = True,
  281. conv_mode: str = "cross_correlation",
  282. compute_mode: str = "default",
  283. **kwargs
  284. ):
  285. kernel_size = _pair_nonzero(kernel_size)
  286. stride = _pair_nonzero(stride)
  287. padding = _pair(padding)
  288. dilation = _pair_nonzero(dilation)
  289. self.conv_mode = conv_mode
  290. self.compute_mode = compute_mode
  291. super().__init__(
  292. in_channels,
  293. out_channels,
  294. kernel_size,
  295. stride,
  296. padding,
  297. dilation,
  298. groups,
  299. bias,
  300. **kwargs,
  301. )
  302. def _get_fanin(self):
  303. kh, kw = self.kernel_size
  304. ic = self.in_channels
  305. return kh * kw * ic
  306. def _infer_weight_shape(self):
  307. group = self.groups
  308. ichl = self.in_channels
  309. ochl = self.out_channels
  310. kh, kw = self.kernel_size
  311. if group == 1:
  312. # Assume format is NCHW
  313. return (ochl, ichl, kh, kw)
  314. assert (
  315. ichl % group == 0 and ochl % group == 0
  316. ), "invalid config: in_channels={} out_channels={} group={}".format(
  317. ichl, ochl, group
  318. )
  319. # Assume format is NCHW
  320. return (group, ochl // group, ichl // group, kh, kw)
  321. def _infer_bias_shape(self):
  322. # Assume format is NCHW
  323. return (1, self.out_channels, 1, 1)
  324. def calc_conv(self, inp, weight, bias):
  325. return conv2d(
  326. inp,
  327. weight,
  328. bias,
  329. self.stride,
  330. self.padding,
  331. self.dilation,
  332. self.groups,
  333. self.conv_mode,
  334. self.compute_mode,
  335. )
  336. def forward(self, inp):
  337. return self.calc_conv(inp, self.weight, self.bias)
  338. class Conv3d(_ConvNd):
  339. r"""Applies a 3D convolution over an input tensor.
  340. For instance, given an input of the size :math:`(N, C_{\text{in}}, T, H, W)`,
  341. this layer generates an output of the size
  342. :math:`(N, C_{\text{out}}, T_{\text{out}}, H_{\text{out}}, W_{\text{out}})` through the
  343. process described as below:
  344. .. math::
  345. \text{out}(N_i, C_{\text{out}_j}) = \text{bias}(C_{\text{out}_j}) +
  346. \sum_{k = 0}^{C_{\text{in}} - 1} \text{weight}(C_{\text{out}_j}, k) \star \text{input}(N_i, k)
  347. where :math:`\star` is the valid 3D cross-correlation operator,
  348. :math:`N` is batch size, :math:`C` denotes number of channels.
  349. When `groups == in_channels` and `out_channels == K * in_channels`,
  350. where K is a positive integer, this operation is also known as depthwise
  351. convolution.
  352. In other words, for an input of size :math:`(N, C_{in}, T_{int}, H_{in}, W_{in})`,
  353. a depthwise convolution with a depthwise multiplier `K`, can be constructed
  354. by arguments :math:`(in\_channels=C_{in}, out\_channels=C_{in} \times K, ..., groups=C_{in})`.
  355. Args:
  356. in_channels: number of input channels.
  357. out_channels: number of output channels.
  358. kernel_size: size of weight on spatial dimensions. If kernel_size is
  359. an :class:`int`, the actual kernel size would be
  360. `(kernel_size, kernel_size, kernel_size)`.
  361. stride: stride of the 3D convolution operation. Default: 1
  362. padding: size of the paddings added to the input on both sides of its
  363. spatial dimensions. Only zero-padding is supported. Default: 0
  364. dilation: dilation of the 3D convolution operation. Default: 1
  365. groups: number of groups into which the input and output channels are divided,
  366. so as to perform a ``grouped convolution``. When ``groups`` is not 1,
  367. ``in_channels`` and ``out_channels`` must be divisible by ``groups``,
  368. and the shape of weight should be ``(groups, out_channel // groups,
  369. in_channels // groups, depth, height, width)``. Default: 1
  370. bias: whether to add a bias onto the result of convolution. Default: True
  371. conv_mode: Supports `cross_correlation`. Default: `cross_correlation`
  372. Note:
  373. * ``weight`` usually has shape ``(out_channels, in_channels, depth, height, width)`` ,
  374. if groups is not 1, shape will be ``(groups, out_channels // groups, in_channels // groups, depth, height, width)``
  375. * ``bias`` usually has shape ``(1, out_channels, *1)``
  376. Examples:
  377. .. testcode::
  378. import numpy as np
  379. import megengine as mge
  380. import megengine.module as M
  381. m = M.Conv3d(in_channels=3, out_channels=1, kernel_size=3)
  382. inp = mge.tensor(np.arange(0, 384).astype("float32").reshape(2, 3, 4, 4, 4))
  383. oup = m(inp)
  384. print(oup.numpy().shape)
  385. Outputs:
  386. .. testoutput::
  387. (2, 1, 2, 2, 2)
  388. """
  389. def __init__(
  390. self,
  391. in_channels: int,
  392. out_channels: int,
  393. kernel_size: Union[int, Tuple[int, int, int]],
  394. stride: Union[int, Tuple[int, int, int]] = 1,
  395. padding: Union[int, Tuple[int, int, int]] = 0,
  396. dilation: Union[int, Tuple[int, int, int]] = 1,
  397. groups: int = 1,
  398. bias: bool = True,
  399. conv_mode: str = "cross_correlation",
  400. ):
  401. kernel_size = _triple_nonzero(kernel_size)
  402. stride = _triple_nonzero(stride)
  403. padding = _triple(padding)
  404. dilation = _triple_nonzero(dilation)
  405. self.conv_mode = conv_mode
  406. super().__init__(
  407. in_channels,
  408. out_channels,
  409. kernel_size,
  410. stride,
  411. padding,
  412. dilation,
  413. groups,
  414. bias,
  415. )
  416. def _get_fanin(self):
  417. kt, kh, kw = self.kernel_size
  418. ic = self.in_channels
  419. return kt * kh * kw * ic
  420. def _infer_weight_shape(self):
  421. group = self.groups
  422. ichl = self.in_channels
  423. ochl = self.out_channels
  424. kt, kh, kw = self.kernel_size
  425. if group == 1:
  426. # Assume format is NCTHW
  427. return (ochl, ichl, kt, kh, kw)
  428. assert (
  429. ichl % group == 0 and ochl % group == 0
  430. ), "invalid config: in_channels={} out_channels={} group={}".format(
  431. ichl, ochl, group
  432. )
  433. # Assume format is NCTHW
  434. return (group, ochl // group, ichl // group, kt, kh, kw)
  435. def _infer_bias_shape(self):
  436. # Assume format is NCTHW
  437. return (1, self.out_channels, 1, 1, 1)
  438. def calc_conv(self, inp, weight, bias):
  439. return conv3d(
  440. inp,
  441. weight,
  442. bias,
  443. self.stride,
  444. self.padding,
  445. self.dilation,
  446. self.groups,
  447. self.conv_mode,
  448. )
  449. def forward(self, inp):
  450. return self.calc_conv(inp, self.weight, self.bias)
  451. class ConvTranspose2d(_ConvNd):
  452. r"""Applies a 2D transposed convolution over an input tensor.
  453. This module is also known as a deconvolution or a fractionally-strided convolution.
  454. :class:`ConvTranspose2d` can be seen as the gradient of :class:`Conv2d` operation
  455. with respect to its input.
  456. Convolution usually reduces the size of input, while transposed convolution works
  457. the opposite way, transforming a smaller input to a larger output while preserving the
  458. connectivity pattern.
  459. Args:
  460. in_channels: number of input channels.
  461. out_channels: number of output channels.
  462. kernel_size: size of weight on spatial dimensions. If ``kernel_size`` is
  463. an :class:`int`, the actual kernel size would be
  464. ``(kernel_size, kernel_size)``.
  465. stride: stride of the 2D convolution operation. Default: 1
  466. padding: size of the paddings added to the input on both sides of its
  467. spatial dimensions. Only zero-padding is supported. Default: 0
  468. dilation: dilation of the 2D convolution operation. Default: 1
  469. groups: number of groups into which the input and output channels are divided,
  470. so as to perform a ``grouped convolution``. When ``groups`` is not 1,
  471. ``in_channels`` and ``out_channels`` must be divisible by groups,
  472. and the shape of weight should be ``(groups, in_channels // groups,
  473. out_channels // groups, height, width)``. Default: 1
  474. bias: wether to add a bias onto the result of convolution. Default: True
  475. conv_mode: Supports `cross_correlation`. Default: `cross_correlation`
  476. compute_mode: When set to "default", no special requirements will be
  477. placed on the precision of intermediate results. When set to "float32",
  478. "float32" would be used for accumulator and intermediate result, but only
  479. effective when input and output are of float16 dtype.
  480. Note:
  481. * ``weight`` usually has shape ``(in_channels, out_channels, height, width)`` ,
  482. if groups is not 1, shape will be ``(groups, in_channels // groups, out_channels // groups, height, width)``
  483. * ``bias`` usually has shape ``(1, out_channels, *1)``
  484. """
  485. def __init__(
  486. self,
  487. in_channels: int,
  488. out_channels: int,
  489. kernel_size: Union[int, Tuple[int, int]],
  490. stride: Union[int, Tuple[int, int]] = 1,
  491. padding: Union[int, Tuple[int, int]] = 0,
  492. dilation: Union[int, Tuple[int, int]] = 1,
  493. groups: int = 1,
  494. bias: bool = True,
  495. conv_mode: str = "cross_correlation",
  496. compute_mode: str = "default",
  497. **kwargs
  498. ):
  499. kernel_size = _pair_nonzero(kernel_size)
  500. stride = _pair_nonzero(stride)
  501. padding = _pair(padding)
  502. dilation = _pair_nonzero(dilation)
  503. self.conv_mode = conv_mode
  504. self.compute_mode = compute_mode
  505. super().__init__(
  506. in_channels,
  507. out_channels,
  508. kernel_size,
  509. stride,
  510. padding,
  511. dilation,
  512. groups,
  513. bias,
  514. **kwargs,
  515. )
  516. def _get_fanin(self):
  517. kh, kw = self.kernel_size
  518. oc = self.out_channels
  519. return kh * kw * oc
  520. def _infer_weight_shape(self):
  521. group = self.groups
  522. ichl = self.in_channels
  523. ochl = self.out_channels
  524. kh, kw = self.kernel_size
  525. if group == 1:
  526. # Assume format is NCHW
  527. return (ichl, ochl, kh, kw)
  528. assert (
  529. ichl % group == 0 and ochl % group == 0
  530. ), "invalid config: in_channels={} out_channels={} group={}".format(
  531. ichl, ochl, group
  532. )
  533. # Assume format is NCHW
  534. return (group, ichl // group, ochl // group, kh, kw)
  535. def _infer_bias_shape(self):
  536. # Assume format is NCHW
  537. return (1, self.out_channels, 1, 1)
  538. def calc_conv_transpose2d(self, inp, weight, bias):
  539. return conv_transpose2d(
  540. inp,
  541. weight,
  542. bias,
  543. self.stride,
  544. self.padding,
  545. self.dilation,
  546. self.groups,
  547. self.conv_mode,
  548. self.compute_mode,
  549. )
  550. def forward(self, inp):
  551. return self.calc_conv_transpose2d(inp, self.weight, self.bias)
  552. class LocalConv2d(Conv2d):
  553. r"""Applies a spatial convolution with untied kernels over an groupped channeled input 4D tensor.
  554. It is also known as the locally connected layer.
  555. Args:
  556. in_channels: number of input channels.
  557. out_channels: number of output channels.
  558. input_height: the height of the input images.
  559. input_width: the width of the input images.
  560. kernel_size: size of weight on spatial dimensions. If kernel_size is
  561. an :class:`int`, the actual kernel size would be
  562. ``(kernel_size, kernel_size)``.
  563. stride: stride of the 2D convolution operation. Default: 1
  564. padding: size of the paddings added to the input on both sides of its
  565. spatial dimensions. Only zero-padding is supported. Default: 0
  566. dilation: dilation of the 2D convolution operation. Default: 1
  567. groups: number of groups into which the input and output channels are divided,
  568. so as to perform a "grouped convolution". When ``groups`` is not 1,
  569. ``in_channels`` and ``out_channels`` must be divisible by ``groups``. Default: 1
  570. Note:
  571. * ``weight`` usually has shape ``(out_height, out_width, in_channels, height, width, in_channels)`` ,
  572. if groups is not 1, shape will be ``(groups, out_height, out_width, in_channels // groups, height, width, out_channels // groups)``
  573. * ``bias`` usually has shape ``(1, out_channels, *1)``
  574. """
  575. def __init__(
  576. self,
  577. in_channels: int,
  578. out_channels: int,
  579. input_height: int,
  580. input_width: int,
  581. kernel_size: Union[int, Tuple[int, int]],
  582. stride: Union[int, Tuple[int, int]] = 1,
  583. padding: Union[int, Tuple[int, int]] = 0,
  584. dilation: Union[int, Tuple[int, int]] = 1,
  585. groups: int = 1,
  586. conv_mode: str = "cross_correlation",
  587. **kwargs
  588. ):
  589. self.input_height = input_height
  590. self.input_width = input_width
  591. super().__init__(
  592. in_channels,
  593. out_channels,
  594. kernel_size,
  595. stride,
  596. padding,
  597. dilation,
  598. groups,
  599. bias=False,
  600. **kwargs,
  601. )
  602. def _infer_weight_shape(self):
  603. group = self.groups
  604. out_height = (
  605. self.input_height + self.padding[0] * 2 - self.kernel_size[0]
  606. ) // self.stride[0] + 1
  607. out_width = (
  608. self.input_width + self.padding[1] * 2 - self.kernel_size[1]
  609. ) // self.stride[1] + 1
  610. # Assume format is NCHW
  611. return (
  612. group,
  613. out_height,
  614. out_width,
  615. self.in_channels // group,
  616. self.kernel_size[0],
  617. self.kernel_size[1],
  618. self.out_channels // group,
  619. )
  620. def forward(self, inp):
  621. return local_conv2d(
  622. inp,
  623. self.weight,
  624. None,
  625. self.stride,
  626. self.padding,
  627. self.dilation,
  628. self.conv_mode,
  629. )
  630. class ConvRelu2d(Conv2d):
  631. r"""A fused :class:`~.Module` including :class:`~.module.Conv2d` and :func:`~.relu`.
  632. Could be replaced with :class:`~.QATModule` version :class:`~.qat.ConvRelu2d` using :func:`~.quantize.quantize_qat`.
  633. """
  634. def forward(self, inp):
  635. return relu(self.calc_conv(inp, self.weight, self.bias))
  636. class DeformableConv2d(_ConvNd):
  637. r"""Deformable Convolution.
  638. Args:
  639. in_channels: number of input channels.
  640. out_channels: number of output channels.
  641. kernel_size: size of weight on spatial dimensions. If kernel_size is
  642. an :class:`int`, the actual kernel size would be
  643. ``(kernel_size, kernel_size)``.
  644. stride: stride of the 2D convolution operation. Default: 1
  645. padding: size of the paddings added to the input on both sides of its
  646. spatial dimensions. Only zero-padding is supported. Default: 0
  647. dilation: dilation of the 2D convolution operation. Default: 1
  648. groups: number of groups into which the input and output channels are divided,
  649. so as to perform a ``grouped convolution``. When ``groups`` is not 1,
  650. ``in_channels`` and ``out_channels`` must be divisible by groups,
  651. and the shape of weight should be ``(groups, out_channel // groups,
  652. in_channels // groups, height, width)``. Default: 1
  653. bias: whether to add a bias onto the result of convolution. Default: True
  654. conv_mode: Supports `cross_correlation`. Default: `cross_correlation`
  655. compute_mode: When set to "default", no special requirements will be
  656. placed on the precision of intermediate results. When set to "float32",
  657. "float32" would be used for accumulator and intermediate result, but only
  658. effective when input and output are of float16 dtype.
  659. Note:
  660. * ``weight`` usually has shape ``(out_channels, in_channels, height, width)`` ,
  661. if groups is not 1, shape will be ``(groups, out_channels // groups, in_channels // groups, height, width)``
  662. * ``bias`` usually has shape ``(1, out_channels, *1)``
  663. """
  664. def __init__(
  665. self,
  666. in_channels: int,
  667. out_channels: int,
  668. kernel_size: Union[int, Tuple[int, int]],
  669. stride: Union[int, Tuple[int, int]] = 1,
  670. padding: Union[int, Tuple[int, int]] = 0,
  671. dilation: Union[int, Tuple[int, int]] = 1,
  672. groups: int = 1,
  673. bias: bool = True,
  674. conv_mode: str = "cross_correlation",
  675. compute_mode: str = "default",
  676. **kwargs
  677. ):
  678. kernel_size = _pair_nonzero(kernel_size)
  679. stride = _pair_nonzero(stride)
  680. padding = _pair(padding)
  681. dilation = _pair_nonzero(dilation)
  682. self.conv_mode = conv_mode
  683. self.compute_mode = compute_mode
  684. super().__init__(
  685. in_channels,
  686. out_channels,
  687. kernel_size,
  688. stride,
  689. padding,
  690. dilation,
  691. groups,
  692. bias,
  693. **kwargs,
  694. )
  695. def _get_fanin(self):
  696. kh, kw = self.kernel_size
  697. ic = self.in_channels
  698. return kh * kw * ic
  699. def _infer_weight_shape(self):
  700. group = self.groups
  701. ichl = self.in_channels
  702. ochl = self.out_channels
  703. kh, kw = self.kernel_size
  704. if group == 1:
  705. # Assume format is NCHW
  706. return (ochl, ichl, kh, kw)
  707. assert (
  708. ichl % group == 0 and ochl % group == 0
  709. ), "invalid config: in_channels={} out_channels={} group={}".format(
  710. ichl, ochl, group
  711. )
  712. # Assume format is NCHW
  713. return (group, ochl // group, ichl // group, kh, kw)
  714. def _infer_bias_shape(self):
  715. # Assume format is NCHW
  716. return (1, self.out_channels, 1, 1)
  717. def calc_conv(self, inp, weight, offset, mask, bias):
  718. return deformable_conv2d(
  719. inp,
  720. weight,
  721. offset,
  722. mask,
  723. bias,
  724. self.stride,
  725. self.padding,
  726. self.dilation,
  727. self.groups,
  728. self.conv_mode,
  729. self.compute_mode,
  730. )
  731. def forward(self, inp, offset, mask):
  732. return self.calc_conv(inp, self.weight, offset, mask, self.bias)
  733. class ConvTranspose3d(_ConvNd):
  734. r"""Applies a 3D transposed convolution over an input tensor.
  735. Only support the case that groups = 1 and conv_mode = "cross_correlation".
  736. :class:`ConvTranspose3d` can be seen as the gradient of :class:`Conv3d` operation
  737. with respect to its input.
  738. Convolution3D usually reduces the size of input, while transposed convolution3d
  739. works the opposite way, transforming a smaller input to a larger output while
  740. preserving the connectivity pattern.
  741. Args:
  742. in_channels: number of input channels.
  743. out_channels: number of output channels.
  744. kernel_size: size of weight on spatial dimensions. If ``kernel_size`` is
  745. an :class:`int`, the actual kernel size would be
  746. ``(kernel_size, kernel_size, kernel_size)``.
  747. stride: stride of the 3D convolution operation. Default: 1
  748. padding: size of the paddings added to the input on all sides of its
  749. spatial dimensions. Only zero-padding is supported. Default: 0
  750. dilation: dilation of the 3D convolution operation. Default: 1
  751. groups: number of groups into which the input and output channels are divided,
  752. so as to perform a ``grouped convolution``. When ``groups`` is not 1,
  753. ``in_channels`` and ``out_channels`` must be divisible by groups,
  754. and the shape of weight should be ``(groups, in_channels // groups,
  755. out_channels // groups, depth, height, width)``. Default: 1
  756. bias: wether to add a bias onto the result of convolution. Default: True
  757. Note:
  758. * ``weight`` usually has shape ``(in_channels, out_channels, depth, height, width)`` .
  759. * ``bias`` usually has shape ``(1, out_channels, *1)``
  760. """
  761. def __init__(
  762. self,
  763. in_channels: int,
  764. out_channels: int,
  765. kernel_size: Union[int, Tuple[int, int, int]],
  766. stride: Union[int, Tuple[int, int, int]] = 1,
  767. padding: Union[int, Tuple[int, int, int]] = 0,
  768. dilation: Union[int, Tuple[int, int, int]] = 1,
  769. groups: int = 1,
  770. bias: bool = True,
  771. ):
  772. kernel_size = _triple_nonzero(kernel_size)
  773. stride = _triple_nonzero(stride)
  774. padding = _triple(padding)
  775. dilation = _triple_nonzero(dilation)
  776. super().__init__(
  777. in_channels=in_channels,
  778. out_channels=out_channels,
  779. kernel_size=kernel_size,
  780. stride=stride,
  781. padding=padding,
  782. dilation=dilation,
  783. groups=groups,
  784. bias=bias,
  785. )
  786. def _get_fanin(self):
  787. kt, kh, kw = self.kernel_size
  788. ic = self.in_channels
  789. return kt * kh * kw * ic
  790. def _infer_weight_shape(self):
  791. group = self.groups
  792. ichl = self.in_channels
  793. ochl = self.out_channels
  794. kt, kh, kw = self.kernel_size
  795. if group == 1:
  796. # Assume format is NCHW
  797. return (ichl, ochl, kt, kh, kw)
  798. assert (
  799. ichl % group == 0 and ochl % group == 0
  800. ), "invalid config: in_channels={} out_channels={} group={}".format(
  801. ichl, ochl, group
  802. )
  803. # Assume format is NCHW
  804. return (group, ichl // group, ochl // group, kt, kh, kw)
  805. def _infer_bias_shape(self):
  806. # Assume format is NCTHW
  807. return (1, self.out_channels, 1, 1, 1)
  808. def forward(self, inp):
  809. return conv_transpose3d(
  810. inp, self.weight, self.bias, self.stride, self.padding, self.dilation,
  811. )