test_linear_interp_op.py 10.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
#   Copyright (c) 2018 PaddlePaddle 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 platform
import unittest
import numpy as np
from op_test import OpTest
import paddle
import paddle.fluid.core as core
import paddle.fluid as fluid
from paddle.fluid import Program, program_guard


25 26 27 28 29 30 31 32 33
def linear_interp_np(
    input,
    out_w,
    out_size=None,
    actual_shape=None,
    align_corners=True,
    align_mode=0,
    data_layout='NCHW',
):
34 35 36 37 38 39 40 41 42 43
    if data_layout == "NHWC":
        input = np.transpose(input, (0, 2, 1))  # NHWC => NCHW
    if out_size is not None:
        out_w = out_size[0]
    if actual_shape is not None:
        out_w = actual_shape[0]
    batch_size, channel, in_w = input.shape

    ratio_w = 0.0
    if out_w > 1:
44
        if align_corners:
45 46 47 48 49 50 51
            ratio_w = (in_w - 1.0) / (out_w - 1.0)
        else:
            ratio_w = 1.0 * in_w / out_w

    out = np.zeros((batch_size, channel, out_w))

    for j in range(out_w):
52
        if align_mode == 0 and not align_corners:
53 54 55 56 57 58
            w = int(ratio_w * (j + 0.5) - 0.5)
        else:
            w = int(ratio_w * j)
        w = max(0, w)
        wid = 1 if w < in_w - 1 else 0

59
        if align_mode == 0 and not align_corners:
60 61 62 63 64 65
            idx_src_w = max(ratio_w * (j + 0.5) - 0.5, 0)
            w1lambda = idx_src_w - w
        else:
            w1lambda = ratio_w * j - w
        w2lambda = 1.0 - w1lambda

66 67 68
        out[:, :, j] = (
            w2lambda * input[:, :, w] + w1lambda * input[:, :, w + wid]
        )
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94

    if data_layout == "NHWC":
        out = np.transpose(out, (0, 2, 1))  # NCHW => NHWC

    return out.astype(input.dtype)


class TestLinearInterpOp(OpTest):
    def setUp(self):
        self.out_size = None
        self.actual_shape = None
        self.data_layout = 'NCHW'
        self.init_test_case()
        self.op_type = "linear_interp"
        input_np = np.random.random(self.input_shape).astype("float64")

        if self.data_layout == "NCHW":
            in_w = self.input_shape[2]
        else:
            in_w = self.input_shape[1]

        if self.scale > 0:
            out_w = int(in_w * self.scale)
        else:
            out_w = self.out_w

95 96 97 98 99 100 101 102 103
        output_np = linear_interp_np(
            input_np,
            out_w,
            self.out_size,
            self.actual_shape,
            self.align_corners,
            self.align_mode,
            self.data_layout,
        )
104 105 106 107 108 109 110 111 112 113 114 115
        self.inputs = {'X': input_np}
        if self.out_size is not None:
            self.inputs['OutSize'] = self.out_size
        if self.actual_shape is not None:
            self.inputs['OutSize'] = self.actual_shape

        self.attrs = {
            'out_w': self.out_w,
            'scale': self.scale,
            'interp_method': self.interp_method,
            'align_corners': self.align_corners,
            'align_mode': self.align_mode,
116
            'data_layout': self.data_layout,
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
        }
        self.outputs = {'Out': output_np}

    def test_check_output(self):
        if platform.system() == "Linux":
            self.check_output(atol=1e-7)
        else:
            self.check_output(atol=1e-5)

    def test_check_grad(self):
        self.check_grad(['X'], 'Out', in_place=True)

    def init_test_case(self):
        self.interp_method = 'linear'
        self.input_shape = [1, 3, 100]
        self.out_w = 50
133 134 135 136 137 138
        self.scale = 0.0
        self.out_size = np.array(
            [
                50,
            ]
        ).astype("int32")
139 140 141 142 143 144 145 146 147
        self.align_corners = False
        self.align_mode = 1


class TestLinearInterpOpDataLayout(TestLinearInterpOp):
    def init_test_case(self):
        self.interp_method = 'linear'
        self.input_shape = [1, 3, 100]
        self.out_w = 50
148 149 150 151 152 153
        self.scale = 0.0
        self.out_size = np.array(
            [
                50,
            ]
        ).astype("int32")
154 155 156 157 158 159 160 161 162 163
        self.align_corners = False
        self.align_mode = 1
        self.data_layout = 'NHWC'


class TestLinearInterpOpAlignMode(TestLinearInterpOp):
    def init_test_case(self):
        self.interp_method = 'linear'
        self.input_shape = [1, 3, 100]
        self.out_w = 50
164 165 166 167 168 169
        self.scale = 0.0
        self.out_size = np.array(
            [
                50,
            ]
        ).astype("int32")
170 171 172 173 174 175 176 177 178 179
        self.align_corners = False
        self.align_mode = 0


class TestLinearInterpOpScale(TestLinearInterpOp):
    def init_test_case(self):
        self.interp_method = 'linear'
        self.input_shape = [1, 3, 100]
        self.out_w = 50
        self.scale = 0.5
180 181 182 183 184
        self.out_size = np.array(
            [
                50,
            ]
        ).astype("int32")
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
        self.align_corners = False
        self.align_mode = 0


class TestLinearInterpOpSizeTensor(TestLinearInterpOp):
    def setUp(self):
        self.out_size = None
        self.actual_shape = None
        self.data_layout = 'NCHW'
        self.init_test_case()
        self.op_type = "linear_interp"
        input_np = np.random.random(self.input_shape).astype("float64")
        self.shape_by_1Dtensor = False
        self.scale_by_1Dtensor = False

        if self.data_layout == "NCHW":
            in_w = self.input_shape[2]
        else:
            in_w = self.input_shape[1]

        if self.scale > 0:
            out_w = int(in_w * self.scale)
        else:
            out_w = self.out_w

210 211 212 213 214 215 216 217 218
        output_np = linear_interp_np(
            input_np,
            out_w,
            self.out_size,
            self.actual_shape,
            self.align_corners,
            self.align_mode,
            self.data_layout,
        )
219 220 221 222 223 224 225 226 227

        self.inputs = {'X': input_np}
        if self.out_size is not None and self.shape_by_1Dtensor:
            self.inputs['OutSize'] = self.out_size
        elif self.actual_shape is not None and self.shape_by_1Dtensor:
            self.inputs['OutSize'] = self.actual_shape
        else:
            size_tensor = []
            for index, ele in enumerate(self.out_size):
228 229 230
                size_tensor.append(
                    ("x" + str(index), np.ones((1)).astype('int32') * ele)
                )
231 232 233 234 235 236 237 238
            self.inputs['SizeTensor'] = size_tensor

        self.attrs = {
            'out_w': self.out_w,
            'scale': self.scale,
            'interp_method': self.interp_method,
            'align_corners': self.align_corners,
            'align_mode': self.align_mode,
239
            'data_layout': self.data_layout,
240 241 242 243 244 245 246
        }
        self.outputs = {'Out': output_np}


class TestLinearInterpOpAPI2_0(unittest.TestCase):
    def test_case(self):

247
        # dygraph
248
        x_data = np.random.random((1, 3, 128)).astype("float32")
249 250 251 252 253 254 255 256 257
        us_1 = paddle.nn.Upsample(
            size=[
                64,
            ],
            mode='linear',
            align_mode=1,
            align_corners=False,
            data_format='NCW',
        )
258 259 260 261
        with fluid.dygraph.guard():
            x = fluid.dygraph.to_variable(x_data)
            interp = us_1(x)

262 263 264
            expect = linear_interp_np(
                x_data, out_w=64, align_mode=1, align_corners=False
            )
265

266
            np.testing.assert_allclose(interp.numpy(), expect, rtol=1e-05)
267 268


269
class TestResizeLinearOpUint8(OpTest):
270 271 272 273 274 275 276 277 278 279 280 281
    def setUp(self):
        self.out_size = None
        self.actual_shape = None
        self.init_test_case()
        self.op_type = "linear_interp"
        input_np = np.random.random(self.input_shape).astype("uint8")

        if self.scale > 0:
            out_w = int(self.input_shape[3] * self.scale)
        else:
            out_w = self.out_w

282 283 284 285 286 287 288 289
        output_np = linear_interp_np(
            input_np,
            out_w,
            self.out_size,
            self.actual_shape,
            self.align_corners,
            self.align_mode,
        )
290 291 292 293 294 295 296 297 298
        self.inputs = {'X': input_np}
        if self.out_size is not None:
            self.inputs['OutSize'] = self.out_size

        self.attrs = {
            'out_w': self.out_w,
            'scale': self.scale,
            'interp_method': self.interp_method,
            'align_corners': self.align_corners,
299
            'align_mode': self.align_mode,
300 301 302 303 304 305 306 307 308 309 310 311 312
        }
        self.outputs = {'Out': output_np}

    def test_check_output(self):
        if platform.system() == "Linux":
            self.check_output_with_place(place=core.CPUPlace(), atol=1e-7)
        else:
            self.check_output_with_place(place=core.CPUPlace(), atol=1e-5)

    def init_test_case(self):
        self.interp_method = 'linear'
        self.input_shape = [2, 3, 100]
        self.out_w = 50
313 314 315 316 317 318
        self.scale = 0.0
        self.out_size = np.array(
            [
                50,
            ]
        ).astype("int32")
319 320 321 322 323 324 325 326 327 328
        self.align_corners = True
        self.align_mode = 1


class TestLinearInterpOpError(unittest.TestCase):
    def test_error(self):
        with program_guard(Program(), Program()):

            def input_shape_error():
                x1 = fluid.data(name="x1", shape=[1], dtype="float32")
329 330 331 332 333 334 335
                out1 = paddle.nn.Upsample(
                    size=[
                        256,
                    ],
                    data_format='NCW',
                    mode='linear',
                )
336 337 338 339
                out1_res = out1(x1)

            def data_format_error():
                x2 = fluid.data(name="x2", shape=[1, 3, 128], dtype="float32")
340 341 342 343 344 345 346
                out2 = paddle.nn.Upsample(
                    size=[
                        256,
                    ],
                    data_format='NHWCD',
                    mode='linear',
                )
347 348 349 350
                out2_res = out2(x2)

            def out_shape_error():
                x3 = fluid.data(name="x3", shape=[1, 3, 128], dtype="float32")
351 352 353 354 355 356 357 358
                out3 = paddle.nn.Upsample(
                    size=[
                        256,
                        256,
                    ],
                    data_format='NHWC',
                    mode='linear',
                )
359 360 361 362 363 364 365 366 367
                out3_res = out3(x3)

            self.assertRaises(ValueError, input_shape_error)
            self.assertRaises(ValueError, data_format_error)
            self.assertRaises(ValueError, out_shape_error)


if __name__ == "__main__":
    unittest.main()