• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2020 Huawei Technologies Co., Ltd
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14# ============================================================================
15
16import pytest
17import numpy as np
18
19import mindspore
20import mindspore.nn as nn
21import mindspore.context as context
22
23from mindspore import Tensor
24from mindspore.ops.composite import GradOperation
25
26
27@pytest.mark.level0
28@pytest.mark.platform_x86_cpu
29@pytest.mark.env_onecard
30def test_pad_basic():
31    """
32    Test array is being padded with 0's
33    """
34    context.set_context(mode=context.GRAPH_MODE, device_target="CPU")
35
36    # float32
37    test_arr = np.array([[1, 2], [3, 4]]).astype(np.float32)
38    test_arr_expected = np.array(
39        [[0, 0, 0, 0], [0, 1, 2, 0], [0, 3, 4, 0], [0, 0, 0, 0]]).astype(np.float32)
40    x_test = Tensor(test_arr, dtype=mindspore.float32)
41    pad_op = nn.Pad(mode='CONSTANT', paddings=((1, 1), (1, 1)))
42    y_test = pad_op(x_test).asnumpy()
43    np.testing.assert_array_equal(y_test, test_arr_expected)
44
45    # float16
46    test_arr = np.array([[1, 2], [3, 4]]).astype(np.float16)
47    test_arr_expected = np.array(
48        [[0, 0, 0, 0], [0, 1, 2, 0], [0, 3, 4, 0], [0, 0, 0, 0]]).astype(np.float16)
49    x_test = Tensor(test_arr, dtype=mindspore.float16)
50    pad_op = nn.Pad(mode='CONSTANT', paddings=((1, 1), (1, 1)))
51    y_test = pad_op(x_test).asnumpy()
52    np.testing.assert_array_equal(y_test, test_arr_expected)
53
54
55@pytest.mark.level0
56@pytest.mark.platform_x86_cpu
57@pytest.mark.env_onecard
58def test_pad_row():
59    """
60    Test correct row padding
61    """
62    context.set_context(mode=context.PYNATIVE_MODE, device_target="CPU")
63
64    test_arr_1 = np.random.rand(40, 40).astype(np.float32)
65    test_paddings_1 = ((2, 3), (0, 0))
66    test_arr_2 = np.random.randn(3, 10, 30, 30).astype(np.float32)
67    test_paddings_2 = ((0, 0), (0, 0), (3, 0), (0, 0))
68
69    pad_op_row_1 = nn.Pad(mode='CONSTANT', paddings=test_paddings_1)
70    pad_op_row_2 = nn.Pad(mode='CONSTANT', paddings=test_paddings_2)
71
72    x_test_1 = Tensor(np.array(test_arr_1), dtype=mindspore.float32)
73    x_test_2 = Tensor(np.array(test_arr_2), dtype=mindspore.float32)
74    y_test_1 = pad_op_row_1(x_test_1).asnumpy()
75    y_test_2 = pad_op_row_2(x_test_2).asnumpy()
76
77    # check size
78    assert y_test_1.shape == (45, 40)
79    assert y_test_2.shape == (3, 10, 33, 30)
80
81    # check values - select correct sections
82    np.testing.assert_equal(y_test_1[2:-3, :], test_arr_1)
83    np.testing.assert_equal(y_test_2[:, :, 3:, :], test_arr_2)
84
85
86@pytest.mark.level0
87@pytest.mark.platform_x86_cpu
88@pytest.mark.env_onecard
89def test_pad_column():
90    """
91    Test correct column padding
92    """
93    context.set_context(mode=context.GRAPH_MODE, device_target="CPU")
94
95    test_arr_1 = np.random.randn(40, 40).astype(np.float32)
96    test_paddings_1 = ((0, 0), (3, 3))
97    test_arr_2 = np.random.randn(3, 10, 30, 30).astype(np.float32)
98    test_paddings_2 = ((0, 0), (0, 0), (0, 0), (6, 1))
99
100    pad_op_col_1 = nn.Pad(mode='CONSTANT', paddings=test_paddings_1)
101    pad_op_col_2 = nn.Pad(mode='CONSTANT', paddings=test_paddings_2)
102
103    x_test_1 = Tensor(np.array(test_arr_1), dtype=mindspore.float32)
104    x_test_2 = Tensor(np.array(test_arr_2), dtype=mindspore.float32)
105    y_test_1 = pad_op_col_1(x_test_1).asnumpy()
106    y_test_2 = pad_op_col_2(x_test_2).asnumpy()
107
108    # check size
109    assert y_test_1.shape == (40, 46)
110    assert y_test_2.shape == (3, 10, 30, 37)
111
112    # check values - select correct sections - should match
113    np.testing.assert_equal(y_test_1[:, 3:-3], test_arr_1)
114    np.testing.assert_equal(y_test_2[:, :, :, 6:-1], test_arr_2)
115
116
117@pytest.mark.level0
118@pytest.mark.platform_x86_cpu
119@pytest.mark.env_onecard
120def test_pad_3d_pad():
121    """
122    Test full 3d padding, with all 3 input types
123    """
124    context.set_context(mode=context.GRAPH_MODE, device_target="CPU")
125
126    # float32
127    test_arr = np.random.randn(5, 3, 30, 30).astype(np.float32)
128    test_paddings = ((0, 0), (2, 1), (0, 1), (0, 2))  # padding 3 dims now
129    pad_op_3d = nn.Pad(mode='CONSTANT', paddings=test_paddings)
130    x_test = Tensor(np.array(test_arr), dtype=mindspore.float32)
131    y_test = pad_op_3d(x_test).asnumpy()
132    assert y_test.shape == (5, 6, 31, 32)
133    np.testing.assert_equal(test_arr, y_test[:, 2:-1, :-1, :-2])
134
135    # float16
136    test_arr = np.random.randn(5, 3, 30, 30).astype(np.float16)
137    test_paddings = ((0, 0), (2, 1), (0, 1), (0, 2))
138    pad_op_3d = nn.Pad(mode='CONSTANT', paddings=test_paddings)
139    x_test = Tensor(np.array(test_arr), dtype=mindspore.float16)
140    y_test = pad_op_3d(x_test).asnumpy()
141    assert y_test.shape == (5, 6, 31, 32)
142    np.testing.assert_equal(test_arr, y_test[:, 2:-1, :-1, :-2])
143
144    # int32
145    test_arr = np.random.randint(1, 3000, (5, 3, 30, 30)).astype(np.int32)
146    test_paddings = ((0, 0), (2, 1), (0, 1), (0, 2))
147    pad_op_3d = nn.Pad(mode='CONSTANT', paddings=test_paddings)
148    x_test = Tensor(np.array(test_arr), dtype=mindspore.int32)
149    y_test = pad_op_3d(x_test).asnumpy()
150    assert y_test.shape == (5, 6, 31, 32)
151    np.testing.assert_equal(test_arr, y_test[:, 2:-1, :-1, :-2])
152
153
154# For testing backprop
155class Grad(nn.Cell):
156    def __init__(self, network):
157        super(Grad, self).__init__()
158        self.grad = GradOperation(get_all=True, sens_param=True)
159        self.network = network
160
161    def construct(self, input_, output_grad):
162        return self.grad(self.network)(input_, output_grad)
163
164
165class Net(nn.Cell):
166    def __init__(self):
167        super(Net, self).__init__()
168        self.pad = nn.Pad(mode="CONSTANT", paddings=(
169            (0, 0), (4, 3), (1, 1), (0, 2)))
170
171    def construct(self, x):
172        return self.pad(x)
173
174
175@pytest.mark.level0
176@pytest.mark.platform_x86_cpu
177@pytest.mark.env_onecard
178def test_pad_3d_backprop():
179    """
180    Confirm correct 3d padding backprop
181    """
182    context.set_context(mode=context.GRAPH_MODE, device_target="CPU")
183    net = Grad(Net())
184    padded_shape = (5, 10, 32, 32)
185
186    # float32
187    test_arr = np.random.randn(5, 3, 30, 30).astype(np.float32)
188    x_test = Tensor(test_arr, dtype=mindspore.float32)
189    dy = np.random.randn(*padded_shape).astype(np.float32)
190    expected_dx = dy[:, 4:-3, 1:-1, :-2]
191    dx = net(x_test, Tensor(dy))
192    dx = dx[0].asnumpy()
193    np.testing.assert_array_equal(dx, expected_dx)
194
195    # float16
196    test_arr = np.random.randn(5, 3, 30, 30).astype(np.float16)
197    x_test = Tensor(test_arr, dtype=mindspore.float16)
198    dy = np.random.randn(*padded_shape).astype(np.float16)
199    expected_dx = dy[:, 4:-3, 1:-1, :-2]
200    dx = net(x_test, Tensor(dy))
201    dx = dx[0].asnumpy()
202    np.testing.assert_array_equal(dx, expected_dx)
203
204    # int32
205    test_arr = np.random.randint(1, 3000, (5, 3, 30, 30)).astype(np.int32)
206    x_test = Tensor(test_arr, dtype=mindspore.int32)
207    dy = np.random.randn(*padded_shape).astype(np.int32)
208    expected_dx = dy[:, 4:-3, 1:-1, :-2]
209    dx = net(x_test, Tensor(dy))
210    dx = dx[0].asnumpy()
211    np.testing.assert_array_equal(dx, expected_dx)
212
213
214@pytest.mark.level0
215@pytest.mark.platform_x86_cpu
216@pytest.mark.env_onecard
217def test_pad_error_cases():
218    context.set_context(mode=context.GRAPH_MODE, device_target="CPU")
219
220    # TEST 1 - Neg padding values
221    test_op = nn.Pad(paddings=((0, 0), (-1, -1)), mode="CONSTANT")
222    test_arr = np.random.randn(3, 3)
223    test_arr_ms = Tensor(test_arr, dtype=mindspore.float32)
224
225    with pytest.raises(ValueError):
226        test_op(test_arr_ms)
227
228    # TEST 2 - Mismatched input size and paddings - 1D tensor
229    test_op = nn.Pad(paddings=((0, 0), (1, 0)), mode="CONSTANT")
230    test_arr = np.random.randn(3)  # 1D Tensor
231    test_arr_ms = Tensor(test_arr, dtype=mindspore.float32)
232
233    with pytest.raises(ValueError):
234        test_op(test_arr_ms)
235
236    # TEST 3 - Mismatched input size and paddings - 2D tensor, 3D padding
237    test_op = nn.Pad(paddings=((0, 0), (1, 0)), mode="CONSTANT")  # 2D Padding
238    test_arr = np.random.randn(1, 3, 3)  # 3D Tensor
239    test_arr_ms = Tensor(test_arr, dtype=mindspore.float32)
240
241    with pytest.raises(ValueError):
242        test_op(test_arr_ms)
243
244    # TEST 4 - 1D Paddings should not work
245    with pytest.raises(TypeError):
246        test_op = nn.Pad(paddings=((0, 2)), mode="CONSTANT")
247
248    # TEST 5 - Padding beyond 4d - (added check in nn file in PR)
249    with pytest.raises(ValueError):
250        _ = nn.Pad(paddings=((0, 0), (0, 0,), (0, 0), (0, 0),
251                             (1, 0)), mode="CONSTANT")  # 2D Padding
252