未验证 提交 f7d738a0 编写于 作者: Z ZZK 提交者: GitHub

Fix backward bug in 3d (#5908)

* Fix backward bug in 3d

* add conv3d

* remove params in 1d

* fix format

* fix docs
Co-authored-by: Noneflow-ci-bot <69100618+oneflow-ci-bot@users.noreply.github.com>
Co-authored-by: NTianyu Zhao <guikarist@gmail.com>
上级 c82e6db1
......@@ -23,6 +23,7 @@ Operators for neural networks
ConstantPad3d,
Conv1d,
Conv2d,
Conv3d,
ConvTranspose2d,
CombinedMarginLoss,
CropMirrorNormalize,
......
......@@ -304,7 +304,7 @@ OF_DEVICE_FUNC void Avgpool3dForwardCompute(
int64_t n, c, t, h, w;
index_helper.OffsetToNdIndex(num, n, c, t, h, w);
const int64_t start_idx = (n * n_channel + c) * x_time * x_width * x_height;
const int64_t start_idx = (n * n_channel + c) * x_time * x_height * x_width;
int64_t tstart = t * stride_t - padding_t;
int64_t hstart = h * stride_h - padding_h;
int64_t wstart = w * stride_w - padding_w;
......@@ -322,13 +322,12 @@ OF_DEVICE_FUNC void Avgpool3dForwardCompute(
int64_t divide_factor;
if (divisor_override != 0) {
// std::cout << "divisor override != 0" << std::endl;
divide_factor = divisor_override;
} else {
if (count_include_pad) {
divide_factor = pool_size;
} else {
divide_factor = (hend - hstart) * (wend - wstart);
divide_factor = (tend - tstart) * (hend - hstart) * (wend - wstart);
}
}
T sum = 0;
......@@ -336,7 +335,7 @@ OF_DEVICE_FUNC void Avgpool3dForwardCompute(
for (int64_t i = tstart; i < tend; i += 1) {
for (int64_t j = hstart; j < hend; j += 1) {
for (int64_t k = wstart; k < wend; k += 1) {
const int64_t tcntr = i * x_width * x_height + j * x_height + k;
const int64_t tcntr = i * x_height * x_width + j * x_width + k;
const int64_t search_idx = start_idx + tcntr;
sum += src[search_idx];
}
......@@ -390,7 +389,7 @@ OF_DEVICE_FUNC void Avgpool3dBackwardCompute(
for (int64_t i = tstart; i < tend; i += 1) {
for (int64_t j = hstart; j < hend; j += 1) {
for (int64_t k = wstart; k < wend; k += 1) {
const int64_t tcntr = i * x_width * x_height + j * x_height + k;
const int64_t tcntr = i * x_height * x_width + j * x_width + k;
const int64_t search_idx = start_idx + tcntr;
XPUAdd<T>::Invoke(&grad_delta, &dest[search_idx]); // dest[search_idx] += grad_delta
}
......
......@@ -113,8 +113,7 @@ class Conv1d(Module):
stride (int or tuple, optional): Stride of the convolution. Default: 1
padding (int, tuple or str, optional): Padding added to both sides of
the input. Default: 0
padding_mode (string, optional): ``'zeros'``, ``'reflect'``,
``'replicate'`` or ``'circular'``. Default: ``'zeros'``
padding_mode (string, optional): ``'zeros'``. Default: ``'zeros'``
dilation (int or tuple, optional): Spacing between kernel
elements. Default: 1
groups (int, optional): Number of blocked connections from input
......@@ -327,8 +326,7 @@ class Conv2d(Module):
stride (int or tuple, optional): Stride of the convolution. Default: 1
padding (int or tuple, optional): Zero-padding added to both sides of
the input. Default: 0
padding_mode (string, optional): ``'zeros'``, ``'reflect'``,
``'replicate'`` or ``'circular'``. Default: ``'zeros'``
padding_mode (string, optional): ``'zeros'``. Default: ``'zeros'``
dilation (int or tuple, optional): Spacing between kernel elements. Default: 1
groups (int, optional): Number of blocked connections from input
channels to output channels. Default: 1
......@@ -492,74 +490,64 @@ class Conv3d(Module):
Applies a 3D convolution over an input signal composed of several input
planes.
In the simplest case, the output value of the layer with input size :math:`(N, C_{in}, D, H, W)`
and output :math:`(N, C_{out}, D_{out}, H_{out}, W_{out})` can be precisely described as:
.. math::
out(N_i, C_{out_j}) = bias(C_{out_j}) +
\sum_{k = 0}^{C_{in} - 1} weight(C_{out_j}, k) \star input(N_i, k)
where :math:`\star` is the valid 3D `cross-correlation`_ operator
This module supports :ref:`TensorFloat32<tf32_on_ampere>`.
* :attr:`stride` controls the stride for the cross-correlation.
* :attr:`padding` controls the amount of implicit zero-paddings on both
sides for :attr:`padding` number of points for each dimension.
* :attr:`padding` controls the amount of padding applied to the input. It
can be either a string {{'valid', 'same'}} or a tuple of ints giving the
amount of implicit padding applied on both sides.
* :attr:`dilation` controls the spacing between the kernel points; also known as the à trous algorithm.
It is harder to describe, but this `link`_ has a nice visualization of what :attr:`dilation` does.
* :attr:`groups` controls the connections between inputs and outputs.
:attr:`in_channels` and :attr:`out_channels` must both be divisible by
:attr:`groups`. For example,
* At groups=1, all inputs are convolved to all outputs.
* At groups=2, the operation becomes equivalent to having two conv
layers side by side, each seeing half the input channels,
and producing half the output channels, and both subsequently
concatenated.
* At groups= :attr:`in_channels`, each input channel is convolved with
its own set of filters, of size
:math:`\left\lfloor\frac{out\_channels}{in\_channels}\right\rfloor`.
The parameters :attr:`kernel_size`, :attr:`stride`, :attr:`padding`, :attr:`dilation` can either be:
- a single ``int`` -- in which case the same value is used for the depth, height and width dimension
- a ``tuple`` of three ints -- in which case, the first `int` is used for the depth dimension,
the second `int` for the height dimension and the third `int` for the width dimension
Note:
Depending of the size of your kernel, several (of the last)
columns of the input might be lost, because it is a valid `cross-correlation`_,
and not a full `cross-correlation`_.
It is up to the user to add proper padding.
Note:
When `groups == in_channels` and `out_channels == K * in_channels`,
where `K` is a positive integer, this operation is also termed in
literature as depthwise convolution.
In other words, for an input of size :math:`(N, C_{in}, D_{in}, H_{in}, W_{in})`,
a depthwise convolution with a depthwise multiplier `K`, can be constructed by arguments
:math:`(in\_channels=C_{in}, out\_channels=C_{in} \times K, ..., groups=C_{in})`.
Note:
In some circumstances when using the CUDA backend with CuDNN, this operator
may select a nondeterministic algorithm to increase performance. If this is
undesirable, you can try to make the operation deterministic (potentially at
a performance cost) by setting ``torch.backends.cudnn.deterministic =
True``.
Please see the notes on :doc:`/notes/randomness` for background.
``padding='valid'`` is the same as no padding. ``padding='same'`` pads
the input so the output has the shape as the input. However, this mode
doesn't support any stride values other than 1.
Args:
in_channels (int): Number of channels in the input image
out_channels (int): Number of channels produced by the convolution
kernel_size (int or tuple): Size of the convolving kernel
stride (int or tuple, optional): Stride of the convolution. Default: 1
padding (int or tuple, optional): Zero-padding added to all three sides of the input. Default: 0
padding_mode (string, optional): ``'zeros'``, ``'reflect'``, ``'replicate'`` or ``'circular'``. Default: ``'zeros'``
padding (int, tuple or str, optional): Padding added to all six sides of
the input. Default: 0
padding_mode (string, optional): ``'zeros'``. Default: ``'zeros'``
dilation (int or tuple, optional): Spacing between kernel elements. Default: 1
groups (int, optional): Number of blocked connections from input channels to output channels. Default: 1
bias (bool, optional): If ``True``, adds a learnable bias to the output. Default: ``True``
Shape:
- Input: :math:`(N, C_{in}, D_{in}, H_{in}, W_{in})`
- Output: :math:`(N, C_{out}, D_{out}, H_{out}, W_{out})` where
.. math::
D_{out} = \left\lfloor\frac{D_{in} + 2 \times \text{padding}[0] - \text{dilation}[0]
\times (\text{kernel\_size}[0] - 1) - 1}{\text{stride}[0]} + 1\right\rfloor
.. math::
H_{out} = \left\lfloor\frac{H_{in} + 2 \times \text{padding}[1] - \text{dilation}[1]
\times (\text{kernel\_size}[1] - 1) - 1}{\text{stride}[1]} + 1\right\rfloor
.. math::
W_{out} = \left\lfloor\frac{W_{in} + 2 \times \text{padding}[2] - \text{dilation}[2]
\times (\text{kernel\_size}[2] - 1) - 1}{\text{stride}[2]} + 1\right\rfloor
Attributes:
weight (Tensor): the learnable weights of the module of shape
:math:`(\text{out\_channels}, \frac{\text{in\_channels}}{\text{groups}},`
......@@ -571,8 +559,11 @@ class Conv3d(Module):
then the values of these weights are
sampled from :math:`\mathcal{U}(-\sqrt{k}, \sqrt{k})` where
:math:`k = \frac{groups}{C_\text{in} * \prod_{i=0}^{2}\text{kernel\_size}[i]}`
For example:
.. code-block:: python
>>> import numpy as np
>>> import oneflow as flow
>>> import oneflow.nn as nn
......
......@@ -384,7 +384,6 @@ class AvgPool1d(Module):
padding: _size_2_t = 0,
ceil_mode: bool = False,
count_include_pad: bool = True,
divisor_override: int = 0,
):
super().__init__()
self.kernel_size = _single(kernel_size)
......@@ -395,7 +394,6 @@ class AvgPool1d(Module):
self.stride = _single(stride) if (stride is not None) else _single(kernel_size)
self.ceil_mode = ceil_mode
self.count_include_pad = count_include_pad
self.divisor_override = int(divisor_override)
self.padding = _single(padding)
def forward(self, x):
......@@ -406,7 +404,7 @@ class AvgPool1d(Module):
padding=self.padding,
ceil_mode=self.ceil_mode,
count_include_pad=self.count_include_pad,
divisor_override=self.divisor_override,
divisor_override=0,
data_format=self.channel_pos,
)
......
"""
Copyright 2020 The OneFlow Authors. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import unittest
import numpy as np
import oneflow as flow
import oneflow.unittest
from oneflow.nn.modules.utils import _pair, _reverse_repeat_tuple, _single, _triple
g_samples = [
{
"kernel": (3, 2),
"padding": 0,
"stride": (2, 1),
"in": np.array(
[
[
[
[
-0.1953,
1.3992,
-0.7464,
0.691,
-1.5484,
0.497,
1.4963,
0.308,
-1.473,
-0.1238,
],
[
-0.3532,
1.2078,
-0.3796,
0.7326,
-1.5795,
0.2128,
0.6501,
-0.1266,
-1.3121,
0.1483,
],
[
-0.3412,
-1.6446,
-1.0039,
-0.5594,
0.745,
-0.5323,
-1.6887,
0.2399,
1.9422,
0.4214,
],
[
-1.6362,
-1.2234,
-1.2531,
0.6109,
0.2228,
-0.208,
0.6359,
0.2451,
0.3864,
0.4263,
],
[
0.7053,
0.3413,
0.909,
-0.4057,
-0.283,
1.0444,
-0.2884,
0.7638,
-1.4793,
0.2079,
],
[
-0.1207,
0.8458,
-0.9521,
0.363,
0.1772,
0.3945,
0.4056,
-0.7822,
0.6166,
1.3343,
],
[
-0.4115,
0.5802,
1.2909,
1.6508,
-0.0561,
-0.7964,
0.9786,
0.4265,
0.7262,
0.2819,
],
[
-0.2667,
-0.0792,
0.4771,
0.3248,
-0.1313,
-0.3325,
-0.9973,
0.3128,
-0.5151,
-0.1225,
],
[
-1.4983,
0.2604,
-0.9127,
0.0822,
0.3708,
-2.6024,
0.2249,
-0.75,
0.3152,
0.1931,
],
[
-0.2171,
-0.2602,
0.9051,
-0.0933,
-0.0902,
-1.3837,
-1.2519,
-1.3091,
0.7155,
2.3376,
],
]
]
]
),
"out": np.array(
[
[
[
[
0.0121,
-0.1946,
-0.211,
-0.2531,
-0.3675,
0.1059,
0.1465,
-0.0703,
-0.0662,
],
[
-0.6331,
-0.6458,
-0.2837,
0.0551,
0.1648,
-0.1729,
-0.0154,
0.3497,
0.3175,
],
[
0.3234,
0.5025,
0.476,
0.241,
0.0801,
0.2897,
0.2506,
0.0453,
0.2813,
],
[
-0.2359,
0.2694,
0.4855,
0.3735,
-0.5913,
-0.5875,
0.0326,
0.0859,
0.1465,
],
]
]
]
),
"ceil_mode": False,
},
{
"in": np.array(
[
[
[
[
-0.25874418,
-0.735277,
0.7187668,
0.4317905,
-0.15865013,
0.32455945,
0.91029733,
-0.42489085,
0.13257249,
-0.7680078,
],
[
-0.48924643,
0.41322532,
-0.24956563,
0.39011025,
1.1571697,
1.1312183,
1.3140937,
-0.88671404,
-0.73976123,
0.09273718,
],
[
-1.5684161,
0.94065344,
0.39506504,
-0.698693,
-0.9967914,
-2.0290415,
0.98462844,
0.7358801,
1.1113276,
0.6782418,
],
[
1.4970111,
-0.10413595,
1.4999448,
1.3459393,
-0.7604277,
1.2852267,
0.01842104,
-1.2325357,
0.44910756,
-0.66622615,
],
[
2.0804522,
-0.8352113,
-0.63586867,
0.16018416,
-0.08155673,
0.41048485,
-1.2774752,
-0.24625959,
0.06801426,
-0.36709896,
],
[
-2.2077172,
0.72850853,
0.48929325,
0.7826485,
1.3427622,
-1.1062458,
1.2447584,
1.87407,
1.0484176,
-1.321674,
],
[
1.0160061,
0.12091469,
-0.80043447,
1.3699176,
0.83278096,
-0.02582553,
-0.08430449,
-2.1967752,
-0.02168749,
-2.374834,
],
[
-0.6146652,
-1.5595887,
0.10382211,
-0.43930522,
0.11752917,
-0.03595898,
-1.216878,
2.0072885,
0.8048424,
2.2326653,
],
[
0.02489181,
0.01249131,
0.5591928,
0.20447306,
1.4736984,
0.76396596,
-0.90115523,
1.0401802,
0.22212219,
0.15565436,
],
[
-2.0538027,
-1.0389869,
-0.94865525,
-0.6091378,
-0.19524679,
-0.50839746,
0.4246262,
0.0206702,
0.62251437,
-1.7211599,
],
]
]
]
),
"out": np.array(
[
[
[
[
-0.28296748,
0.24714465,
0.164579,
0.02082263,
-0.09525593,
0.43929258,
0.43888247,
-0.01193098,
0.08451834,
],
[
0.3350589,
0.21007456,
0.34442863,
-0.1718909,
-0.36201763,
-0.10129262,
-0.16955681,
0.14758904,
0.2122277,
],
[
0.15049218,
-0.15546632,
0.2276234,
0.7344561,
0.22873335,
-0.13976796,
-0.11433101,
0.08762991,
-0.49481043,
],
[
-0.16665831,
-0.2606004,
0.16627766,
0.5931824,
0.5210317,
-0.25002605,
-0.22527404,
0.30932844,
0.16979378,
],
[
-0.76385164,
-0.35398954,
-0.19853179,
0.2184467,
0.38350502,
-0.05524013,
0.14608034,
0.47637174,
-0.18021727,
],
]
]
]
),
"kernel": (3, 2),
"stride": (2, 1),
"padding": 0,
"ceil_mode": True,
},
]
@flow.unittest.skip_unless_1n1d()
class TestModule(flow.unittest.TestCase):
def test_AvgPool2d(test_case):
global g_samples
for sample in g_samples:
of_avgpool2d = flow.nn.AvgPool2d(
kernel_size=sample["kernel"],
padding=sample["padding"],
stride=sample["stride"],
ceil_mode=sample["ceil_mode"],
)
x = flow.Tensor(sample["in"])
of_y = of_avgpool2d(x)
test_case.assertTrue(of_y.numpy().shape == sample["out"].shape)
test_case.assertTrue(np.allclose(of_y.numpy(), sample["out"], 0.001, 0.001))
if __name__ == "__main__":
unittest.main()
......@@ -32,6 +32,7 @@ TEST_TENSOR = 2
rng = np.random.default_rng()
annotation2default_generator = {}
annotation2torch_to_flow_converter = {}
NoneType = type(None)
def data_generator(annotation):
......@@ -245,6 +246,8 @@ class random(generator):
val = float(rng.random() * (high - low) + low)
elif annotation == bool:
val = random_util.choice([True, False])
elif annotation == NoneType:
val = None
else:
raise NotImplementedError(
f"Not implemented annotation {annotation} in random"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册