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_gpu_training 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="GPU") 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_gpu_training 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="GPU") 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_gpu_training 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="GPU") 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_gpu_training 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="GPU") 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_gpu_training 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="GPU") 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_gpu_training 216@pytest.mark.env_onecard 217def test_pad_error_cases(): 218 """ 219 Test against common errorneous inputs to trigger correct errors 220 """ 221 context.set_context(mode=context.GRAPH_MODE, device_target="GPU") 222 223 # TEST 1 - Neg padding values 224 test_op = nn.Pad(paddings=((0, 0), (-1, -1)), mode="CONSTANT") 225 test_arr = np.random.randn(3, 3) 226 test_arr_ms = Tensor(test_arr, dtype=mindspore.float32) 227 228 with pytest.raises(ValueError): 229 test_op(test_arr_ms) 230 231 # TEST 2 - Mismatched input size and paddings - 1D tensor 232 test_op = nn.Pad(paddings=((0, 0), (1, 0)), mode="CONSTANT") 233 test_arr = np.random.randn(3) # 1D Tensor 234 test_arr_ms = Tensor(test_arr, dtype=mindspore.float32) 235 236 with pytest.raises(ValueError): 237 test_op(test_arr_ms) 238 239 # TEST 3 - Mismatched input size and paddings - 2D tensor, 3D padding 240 test_op = nn.Pad(paddings=((0, 0), (1, 0)), mode="CONSTANT") # 2D Padding 241 test_arr = np.random.randn(1, 3, 3) # 3D Tensor 242 test_arr_ms = Tensor(test_arr, dtype=mindspore.float32) 243 244 with pytest.raises(ValueError): 245 test_op(test_arr_ms) 246 247 # TEST 4 - 1D Paddings should not work 248 with pytest.raises(TypeError): 249 test_op = nn.Pad(paddings=((0, 2)), mode="CONSTANT") 250 251 # TEST 5 - Padding beyond 4d - (added check in nn file in PR) 252 with pytest.raises(ValueError): 253 _ = nn.Pad(paddings=((0, 0), (0, 0,), (0, 0), (0, 0), 254 (1, 0)), mode="CONSTANT") # 2D Padding 255