From 51cec9092e73f22cabaca3c7e0ba7154b1a4b27d Mon Sep 17 00:00:00 2001 From: Mohamed Nour Abouelseoud Date: Tue, 27 Aug 2019 16:29:28 +0100 Subject: [PATCH] [Lite] Support Int8 Unpack Operator Added support for Unpack Operator Added relevant tests. --- tensorflow/lite/tools/optimize/BUILD | 1 + .../lite/tools/optimize/operator_property.cc | 8 ++- .../tools/optimize/quantize_model_test.cc | 50 ++++++++++++++++++ tensorflow/lite/tools/optimize/test_util.cc | 2 + tensorflow/lite/tools/optimize/test_util.h | 3 ++ .../lite/tools/optimize/testdata/unpack.bin | Bin 0 -> 616 bytes 6 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 tensorflow/lite/tools/optimize/testdata/unpack.bin diff --git a/tensorflow/lite/tools/optimize/BUILD b/tensorflow/lite/tools/optimize/BUILD index 5548567c2c7..ea554b08522 100644 --- a/tensorflow/lite/tools/optimize/BUILD +++ b/tensorflow/lite/tools/optimize/BUILD @@ -242,6 +242,7 @@ tf_cc_test( "//tensorflow/lite/tools/optimize:testdata/single_conv_weights_min_minus_127_max_plus_127.bin", "//tensorflow/lite/tools/optimize:testdata/single_softmax_min_minus_5_max_plus_5.bin", "//tensorflow/lite/tools/optimize:testdata/split.bin", + "//tensorflow/lite/tools/optimize:testdata/unpack.bin", ], tags = [ "tflite_not_portable_android", diff --git a/tensorflow/lite/tools/optimize/operator_property.cc b/tensorflow/lite/tools/optimize/operator_property.cc index b284e025159..aeb653f6a38 100644 --- a/tensorflow/lite/tools/optimize/operator_property.cc +++ b/tensorflow/lite/tools/optimize/operator_property.cc @@ -70,9 +70,9 @@ OperatorProperty GetOperatorProperty(const ModelT* model, int subgraph_index, property.version = 2; break; case BuiltinOperator_SPLIT: - property.arbitrary_outputs = true; // We skip input 0 since it is the split dim which is not real valued. property.inputs = {{1, {}}}; + property.arbitrary_outputs = true; property.restrict_same_input_output_scale = true; property.version = 2; break; @@ -383,6 +383,12 @@ OperatorProperty GetOperatorProperty(const ModelT* model, int subgraph_index, property.restrict_same_input_output_scale = true; property.version = 2; break; + case BuiltinOperator_UNPACK: + property.inputs = {{0, {}}}; + property.arbitrary_outputs = true; + property.restrict_same_input_output_scale = true; + property.version = 1; + break; default: // No quantized implementation exists for this operation. property.quantizable = false; diff --git a/tensorflow/lite/tools/optimize/quantize_model_test.cc b/tensorflow/lite/tools/optimize/quantize_model_test.cc index 5e736d96e5b..3e708144d8c 100644 --- a/tensorflow/lite/tools/optimize/quantize_model_test.cc +++ b/tensorflow/lite/tools/optimize/quantize_model_test.cc @@ -1124,6 +1124,56 @@ TEST_F(QuantizeCustomOpTest, VerifyMixedQuantization) { } } +class QuantizeUnpackTest : public QuantizeModelTest { +protected: + QuantizeUnpackTest() { + input_model_ = ReadModel(internal::kModelWithUnpack); + readonly_model_ = input_model_->GetModel(); + readonly_model_->UnPackTo(&model_); + } +}; + +TEST_F(QuantizeUnpackTest, VerifyUnpack) { + auto status = QuantizeModel(&builder_, &model_, &error_reporter_); + + ASSERT_EQ(kTfLiteOk, status); + + const auto subgraph = model_.subgraphs[0].get(); + auto op = subgraph->operators[1].get(); + + auto float_graph = readonly_model_->subgraphs()->Get(0); + + ASSERT_EQ(model_.operator_codes[op->opcode_index].get()->builtin_code, + BuiltinOperator_UNPACK); + + // Get unpack input and output tensors + auto unpack_input = subgraph->tensors[op->inputs[0]].get(); + auto unpack_output_0 = subgraph->tensors[op->outputs[0]].get(); + auto unpack_output_1 = subgraph->tensors[op->outputs[1]].get(); + + // Verify Unpack input is quantized. + ASSERT_EQ(float_graph->tensors()->Get(op->inputs[0])->type(), + TensorType_FLOAT32); + EXPECT_EQ(unpack_input->type, TensorType_INT8); + + // The model should only have one input and 2 outputs. + EXPECT_EQ(subgraph->inputs.size(), 1); + EXPECT_EQ(subgraph->outputs.size(), 2); + + // Ensure quantization parameters before and after unpack + // are preserved after quantization for all outputs of + // unpack. + EXPECT_FLOAT_EQ(unpack_input->quantization->scale[0], + unpack_output_0->quantization->scale[0]); + EXPECT_FLOAT_EQ(unpack_input->quantization->scale[0], + unpack_output_1->quantization->scale[0]); + EXPECT_FLOAT_EQ(unpack_input->quantization->zero_point[0], + unpack_output_0->quantization->zero_point[0]); + EXPECT_FLOAT_EQ(unpack_input->quantization->zero_point[0], + unpack_output_1->quantization->zero_point[0]); + +} + } // namespace } // namespace optimize } // namespace tflite diff --git a/tensorflow/lite/tools/optimize/test_util.cc b/tensorflow/lite/tools/optimize/test_util.cc index 74524a18081..ecceacb278c 100644 --- a/tensorflow/lite/tools/optimize/test_util.cc +++ b/tensorflow/lite/tools/optimize/test_util.cc @@ -52,6 +52,8 @@ const char* kModelSplit = "split.bin"; const char* kLstmCalibrated = "lstm_calibrated.bin"; const char* kLstmQuantized = "lstm_quantized.bin"; +const char* kModelWithUnpack = "unpack.bin"; + int FailOnErrorReporter::Report(const char* format, va_list args) { char buf[1024]; vsnprintf(buf, sizeof(buf), format, args); diff --git a/tensorflow/lite/tools/optimize/test_util.h b/tensorflow/lite/tools/optimize/test_util.h index 12c46aa882b..7690ab212cf 100644 --- a/tensorflow/lite/tools/optimize/test_util.h +++ b/tensorflow/lite/tools/optimize/test_util.h @@ -80,6 +80,9 @@ extern const char* kModelSplit; extern const char* kLstmCalibrated; extern const char* kLstmQuantized; +// Test model with an unpack op. +extern const char* kModelWithUnpack; + // An error reporter that fails on testing. class FailOnErrorReporter : public ErrorReporter { public: diff --git a/tensorflow/lite/tools/optimize/testdata/unpack.bin b/tensorflow/lite/tools/optimize/testdata/unpack.bin new file mode 100644 index 0000000000000000000000000000000000000000..72e58bfa1eabe61cb31fc3bbcf9dab9211610a3a GIT binary patch literal 616 zcmaJ;F;Buk7=3D`s0|YBz|et#ku)?q7~?>KaWa8{!HpnoVk4BK6yxYm@FzGj_zRr; zQ4S8q`rgqJ7ro@&_uad@cklbo12DY0J^_y4!9o=d>Tt<6$N)P;dmDIWd?Zc@i`Xh+ z=R41-gKM4E|@ImgA_%eHz zId{nYVZYaJ_T~vSvnce<`*rdTy_T*WuAhjE2nlJ+XM=FftmYqBKe(F#E@_4|#!E`){ Y?&i}lO3i&~$fx{DXWc*B^pA_1AImUHkN^Mx literal 0 HcmV?d00001