|
- # 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 unittest
-
- import numpy as np
- from mkldnn_op_test import format_reorder
- from op_test import OpTest
-
- import paddle
- from paddle import base
- from paddle.base import core
-
-
- class TestReQuantizeOp(OpTest):
- def set_input_size(self):
- self.input_size = [1, 1, 10, 10]
- self.format_reorder = format_reorder
-
- def setUp(self):
- self.op_type = 'requantize'
- self.scale_in = 127.0
- self.shift_in = 0.0
- self.scale_out = 100.0
- self.shift_out = 0.0
- self.input_data_type = 'int8'
- self.set_input_size()
- self.set_scales()
- self.set_shifts()
- self.set_input_data_type()
- self.prepare_input()
- self.prepare_output()
-
- def prepare_input(self):
- if self.input_data_type == 'int8':
- # input data values are integers from interval [-128, 128)
- self.input = (
- np.random.randint(0, 256, self.input_size) - 128
- ).astype(self.input_data_type)
- else:
- # input data values are integers from interval [0, 256)
- self.input = (np.random.randint(0, 256, self.input_size)).astype(
- self.input_data_type
- )
-
- self.inputs = {'Input': OpTest.np_dtype_to_base_dtype(self.input)}
- self.attrs = {
- 'Scale_in': self.scale_in,
- 'Scale_out': self.scale_out,
- 'Shift_in': self.shift_in,
- 'Shift_out': self.shift_out,
- }
-
- def prepare_output(self):
- scale_ratio = self.scale_out / self.scale_in
- with_shift = self.shift_in != 0.0 or self.shift_out != 0.0
-
- if with_shift or self.input_data_type == 'uint8':
- dst_type = 'uint8'
- type_min = 0
- type_max = 255
- new_shift = np.clip(
- np.rint(self.shift_out - scale_ratio * self.shift_in),
- type_min,
- type_max,
- )
- else:
- dst_type = 'int8'
- type_min = -128
- type_max = 127
- new_shift = 0
-
- output_tmp = np.clip(
- np.rint(self.input.astype('float32') * scale_ratio + new_shift),
- type_min,
- type_max,
- ).astype(dst_type)
-
- self.output = self.format_reorder(output_tmp, self.input_size)
- self.outputs = {'Output': self.output}
-
- def test_check_output(self):
- # TODO(wangzhongpu): support onednn op in dygraph mode
- self.assertTrue(
- self.input_data_type == 'uint8' or self.shift_in == 0.0,
- 'Input data must be unsigned if it has nonzero shift.',
- )
- self.check_output(check_dygraph=False, check_pir_onednn=True)
-
- def check_raise_error(self, msg):
- try:
- self.check_output()
- except Exception as e:
- if msg in str(e):
- raise AttributeError
- else:
- print(e)
-
- def set_scales(self):
- pass
-
- def set_shifts(self):
- pass
-
- def set_input_data_type(self):
- pass
-
-
- # ---------------test requantize with s8 input, no shift--------------------
-
-
- class TestReQuantizeOp_S8_SameScales(TestReQuantizeOp):
- def set_scales(self):
- self.scale_in = 127.0
- self.scale_out = 127.0
-
-
- class TestReQuantizeOp_S8_DifferentScales_1(TestReQuantizeOp):
- def set_scales(self):
- self.scale_in = 127.0
- self.scale_out = 100.0
-
-
- class TestReQuantizeOp_S8_DifferentScales_2(TestReQuantizeOp):
- def set_scales(self):
- self.scale_in = 100.0
- self.scale_out = 127.0
-
-
- class TestReQuantizeOp_S8_ZeroInputScale(TestReQuantizeOp):
- def set_scales(self):
- self.scale_in = 0.0
- self.scale_out = 127.0
-
- def prepare_output(self):
- self.output = np.zeros(self.input_size)
- self.outputs = {'Output': self.output}
-
- def test_check_output(self):
- self.assertRaises(
- AttributeError,
- self.check_raise_error,
- 'Scale of input cannot be 0.0',
- )
-
-
- class TestReQuantizeOp_S8_ZeroOutputScale(TestReQuantizeOp):
- def set_scales(self):
- self.scale_in = 127.0
- self.scale_out = 0.0
-
- def prepare_output(self):
- self.output = np.zeros(self.input_size)
- self.outputs = {'Output': self.output}
-
- def test_check_output(self):
- self.assertRaises(
- AttributeError,
- self.check_raise_error,
- 'Scale of output cannot be 0.0',
- )
-
-
- # ---------------test requantize with u8 input, no shift--------------------
-
-
- class TestReQuantizeOp_U8_SameScales(TestReQuantizeOp_S8_SameScales):
- def set_input_data_type(self):
- self.input_data_type = 'uint8'
-
-
- class TestReQuantizeOp_U8_DifferentScales_1(
- TestReQuantizeOp_S8_DifferentScales_1
- ):
- def set_input_data_type(self):
- self.input_data_type = 'uint8'
-
-
- class TestReQuantizeOp_U8_DifferentScales_2(
- TestReQuantizeOp_S8_DifferentScales_2
- ):
- def set_input_data_type(self):
- self.input_data_type = 'uint8'
-
-
- # ---------------test requantize with s8 input, with shift------------------
-
-
- class TestReQuantizeOp_S8_WithShift(TestReQuantizeOp):
- def set_scales(self):
- self.scale_in = 60.0
- self.scale_out = 127.0
-
- def set_shifts(self):
- self.shift_in = 128.0
- self.shift_out = 128.0
-
- def test_check_output(self):
- self.assertRaises(
- AttributeError,
- self.check_raise_error,
- 'Requantize does not support nonzero shift for signed input.',
- )
-
-
- class TestReQuantizeOp_S8_WithOutputShift(TestReQuantizeOp):
- def set_scales(self):
- self.scale_in = 127.0
- self.scale_out = 60.0
-
- def set_shifts(self):
- self.shift_in = 0.0
- self.shift_out = 120.0
-
-
- # ---------------test requantize with u8 input, with shift------------------
-
-
- class TestReQuantizeOp_U8_SameScales_SameShift(TestReQuantizeOp_U8_SameScales):
- def set_shifts(self):
- self.shift_in = 128.0
- self.shift_out = 128.0
-
-
- class TestReQuantizeOp_U8_SameScales_DifferentShift_1(
- TestReQuantizeOp_U8_SameScales
- ):
- def set_shifts(self):
- self.shift_in = 60.0
- self.shift_out = 128.0
-
-
- class TestReQuantizeOp_U8_SameScales_DifferentShift_2(
- TestReQuantizeOp_U8_SameScales
- ):
- def set_shifts(self):
- self.shift_in = 128.0
- self.shift_out = 60.0
-
-
- class TestReQuantizeOp_U8_DifferentScales_1_SameShift(
- TestReQuantizeOp_U8_DifferentScales_1
- ):
- def set_shifts(self):
- self.shift_in = 128.0
- self.shift_out = 128.0
-
-
- class TestReQuantizeOp_U8_DifferentScales_2_SameShift(
- TestReQuantizeOp_U8_DifferentScales_2
- ):
- def set_shifts(self):
- self.shift_in = 128.0
- self.shift_out = 128.0
-
-
- class TestReQuantizeOp_U8_DifferentScales_1_DifferentShift_1(
- TestReQuantizeOp_U8_DifferentScales_1
- ):
- def set_shifts(self):
- self.shift_in = 128.0
- self.shift_out = 60.0
-
-
- class TestReQuantizeOp_U8_DifferentScales_2_DifferentShift_1(
- TestReQuantizeOp_U8_DifferentScales_2
- ):
- def set_shifts(self):
- self.shift_in = 128.0
- self.shift_out = 60.0
-
-
- class TestReQuantizeOp_U8_DifferentScales_1_DifferentShift_2(
- TestReQuantizeOp_U8_DifferentScales_1
- ):
- def set_shifts(self):
- self.shift_in = 60.0
- self.shift_out = 128.0
-
-
- class TestReQuantizeOp_U8_DifferentScales_2_DifferentShift_2(
- TestReQuantizeOp_U8_DifferentScales_2
- ):
- def set_shifts(self):
- self.shift_in = 60.0
- self.shift_out = 128.0
-
-
- # ---------------test non-four dimensional formats--------------------------
-
-
- class TestReQuantizeOp_2DimFormat(TestReQuantizeOp):
- def format_reorder_2Dim(self, out, size):
- return out
-
- def set_input_size(self):
- self.input_size = [10, 20]
- self.format_reorder = self.format_reorder_2Dim
-
-
- # ---------------test reused requantize op, no shift------------------------
-
-
- class TestReQuantizeOpReused(TestReQuantizeOp):
- def setUp(self):
- # self.input_size = [1, 1, 10, 10]
- self.input_size = [1, 1, 2, 2]
- self.input_data_type = 'int8'
- self.format_reorder = format_reorder
- self.set_scales()
- self.set_shifts()
- self.set_input_data_type()
- self.prepare_input()
- self.prepare_output()
-
- def set_scales(self):
- self.scale_in = 100.0
- self.scale_out = 120.0
-
- def set_shifts(self):
- self.shift_in = 0.0
- self.shift_out = 0.0
-
- def set_input_data_type(self):
- pass
-
- def test_check_output(self):
- paddle.enable_static()
- variables = {
- "input": self.input,
- "output": self.output,
- }
- program = base.Program()
- with base.program_guard(program):
- block = program.global_block()
- for name in variables:
- block.create_var(
- name=name, dtype="int8", shape=variables[name].shape
- )
- block.append_op(
- type="requantize",
- inputs={
- 'Input': block.var('input'),
- },
- outputs={"Output": block.var('output')},
- attrs={
- 'Scale_in': self.scale_in,
- 'Scale_out': self.scale_out,
- 'Shift_in': self.shift_in,
- 'Shift_out': self.shift_out,
- },
- )
- place = core.CPUPlace()
- exe = base.Executor(place)
- for i in range(2):
- out = exe.run(
- program,
- feed={'input': variables['input']},
- fetch_list=['output'],
- )
-
- np.testing.assert_allclose(
- variables['output'], out[0], rtol=1e-05, atol=1e-4
- )
-
-
- # ---------------test reused requantize op, no shift------------------------
-
-
- class TestReQuantizeOpReused_WithShift(TestReQuantizeOpReused):
- def set_input_data_type(self):
- self.input_data_type = 'uint8'
-
- def set_shifts(self):
- self.shift_in = 128
- self.shift_out = 60
-
-
- if __name__ == '__main__':
- unittest.main()
|