From b3695af15ecf4fa3dc76c274787536aa7bbf9376 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Mon, 19 Oct 2020 08:56:58 -0700 Subject: [PATCH] Add quantizer test for UnidirectionalSequenceLSTM. PiperOrigin-RevId: 337864606 Change-Id: I32d315126edc886fff78b123f29dd60a09a2f3b5 --- tensorflow/lite/tools/optimize/BUILD | 2 + .../lite/tools/optimize/quantize_model.cc | 13 +- .../tools/optimize/quantize_model_test.cc | 137 +++++++++--------- tensorflow/lite/tools/optimize/test_util.cc | 5 + tensorflow/lite/tools/optimize/test_util.h | 13 +- ...nidirectional_sequence_lstm_calibrated.bin | Bin 0 -> 3088 bytes ...unidirectional_sequence_lstm_quantized.bin | Bin 0 -> 4448 bytes 7 files changed, 88 insertions(+), 82 deletions(-) create mode 100644 tensorflow/lite/tools/optimize/testdata/unidirectional_sequence_lstm_calibrated.bin create mode 100644 tensorflow/lite/tools/optimize/testdata/unidirectional_sequence_lstm_quantized.bin diff --git a/tensorflow/lite/tools/optimize/BUILD b/tensorflow/lite/tools/optimize/BUILD index 9beb7a239e8..7157a7c1002 100644 --- a/tensorflow/lite/tools/optimize/BUILD +++ b/tensorflow/lite/tools/optimize/BUILD @@ -312,6 +312,8 @@ tf_cc_test( "//tensorflow/lite/tools/optimize:testdata/svdf_calibrated.bin", "//tensorflow/lite/tools/optimize:testdata/svdf_quantized.bin", "//tensorflow/lite/tools/optimize:testdata/transpose.bin", + "//tensorflow/lite/tools/optimize:testdata/unidirectional_sequence_lstm_calibrated.bin", + "//tensorflow/lite/tools/optimize:testdata/unidirectional_sequence_lstm_quantized.bin", "//tensorflow/lite/tools/optimize:testdata/unpack.bin", ], tags = [ diff --git a/tensorflow/lite/tools/optimize/quantize_model.cc b/tensorflow/lite/tools/optimize/quantize_model.cc index e7f1c7a8bdf..54ed2e50fe7 100644 --- a/tensorflow/lite/tools/optimize/quantize_model.cc +++ b/tensorflow/lite/tools/optimize/quantize_model.cc @@ -829,12 +829,13 @@ TfLiteStatus QuantizeIntemediateTensors(ModelT* model, utils::QuantizeActivation(tensor, activations_type, error_reporter); } else { - TF_LITE_REPORT_ERROR( - error_reporter, - "Unable to find min/max value for output %d in %s in " - "subgraph %d, node: %d", - tensor, EnumNameBuiltinOperator(op_code), subgraph_idx, - op_idx); + TF_LITE_REPORT_ERROR(error_reporter, + "Unable to find min/max value for " + "intermediate tensor %d in %s in " + "subgraph %d, node: %d", + index_local, + EnumNameBuiltinOperator(op_code), + subgraph_idx, op_idx); return kTfLiteError; } } else if (input.second.number_of_bits == 16 && diff --git a/tensorflow/lite/tools/optimize/quantize_model_test.cc b/tensorflow/lite/tools/optimize/quantize_model_test.cc index 32a23033019..9afd163efd2 100644 --- a/tensorflow/lite/tools/optimize/quantize_model_test.cc +++ b/tensorflow/lite/tools/optimize/quantize_model_test.cc @@ -81,6 +81,44 @@ class QuantizeModelTest : public testing::Test { internal::FailOnErrorReporter error_reporter_; }; +void ExpectSameModels(const ModelT& model, const ModelT& expected_model) { + ASSERT_EQ(model.subgraphs.size(), expected_model.subgraphs.size()); + for (size_t subgraph_idx = 0; subgraph_idx < model.subgraphs.size(); + subgraph_idx++) { + const auto graph = model.subgraphs[subgraph_idx].get(); + const auto expected_graph = expected_model.subgraphs[subgraph_idx].get(); + ASSERT_EQ(graph->tensors.size(), expected_graph->tensors.size()); + for (size_t i = 0; i < graph->tensors.size(); i++) { + const auto tensor = graph->tensors[i].get(); + const auto expected_tensor = expected_graph->tensors[i].get(); + EXPECT_EQ(tensor->buffer, expected_tensor->buffer); + EXPECT_EQ(tensor->is_variable, expected_tensor->is_variable); + EXPECT_EQ(tensor->shape, expected_tensor->shape); + EXPECT_EQ(tensor->name, expected_tensor->name); + EXPECT_EQ(tensor->type, expected_tensor->type); + const auto quantization_params = tensor->quantization.get(); + const auto expected_quantization_params = + expected_tensor->quantization.get(); + if (quantization_params != nullptr || + expected_quantization_params != nullptr) { + EXPECT_NE(quantization_params, nullptr); + EXPECT_NE(expected_quantization_params, nullptr); + EXPECT_EQ(quantization_params->scale, + expected_quantization_params->scale); + EXPECT_EQ(quantization_params->zero_point, + expected_quantization_params->zero_point); + } + } + } + ASSERT_EQ(model.buffers.size(), expected_model.buffers.size()); + for (size_t buffer_idx = 0; buffer_idx < model.buffers.size(); ++buffer_idx) { + const auto buffer = model.buffers[buffer_idx].get()->data; + const auto expected_buffer = expected_model.buffers[buffer_idx].get()->data; + EXPECT_EQ(buffer, expected_buffer); + } + // TODO(jianlijianli): Compare operators as well. +} + class QuantizeConvModelTest : public QuantizeModelTest, public testing::WithParamInterface { protected: @@ -1121,42 +1159,7 @@ TEST_F(QuantizeLSTMTest, VerifyLSTM) { ModelT expected_model; expected_read_only_model->UnPackTo(&expected_model); - // Comparison. - ASSERT_EQ(model_.subgraphs.size(), expected_model.subgraphs.size()); - for (size_t subgraph_idx = 0; subgraph_idx < model_.subgraphs.size(); - subgraph_idx++) { - const auto graph = model_.subgraphs[subgraph_idx].get(); - const auto expected_graph = expected_model.subgraphs[subgraph_idx].get(); - ASSERT_EQ(graph->tensors.size(), expected_graph->tensors.size()); - for (size_t i = 0; i < graph->tensors.size(); i++) { - const auto tensor = graph->tensors[i].get(); - const auto expected_tensor = expected_graph->tensors[i].get(); - EXPECT_EQ(tensor->buffer, expected_tensor->buffer); - EXPECT_EQ(tensor->is_variable, expected_tensor->is_variable); - EXPECT_EQ(tensor->shape, expected_tensor->shape); - EXPECT_EQ(tensor->name, expected_tensor->name); - EXPECT_EQ(tensor->type, expected_tensor->type); - const auto quantization_params = tensor->quantization.get(); - const auto expected_quantization_params = - expected_tensor->quantization.get(); - if (quantization_params != nullptr || - expected_quantization_params != nullptr) { - EXPECT_NE(quantization_params, nullptr); - EXPECT_NE(expected_quantization_params, nullptr); - EXPECT_EQ(quantization_params->scale, - expected_quantization_params->scale); - EXPECT_EQ(quantization_params->zero_point, - expected_quantization_params->zero_point); - } - } - } - ASSERT_EQ(model_.buffers.size(), expected_model.buffers.size()); - for (size_t buffer_idx = 0; buffer_idx < model_.buffers.size(); - ++buffer_idx) { - const auto buffer = model_.buffers[buffer_idx].get()->data; - const auto expected_buffer = expected_model.buffers[buffer_idx].get()->data; - EXPECT_EQ(buffer, expected_buffer); - } + ExpectSameModels(model_, expected_model); } class QuantizeLSTM2Test : public QuantizeModelTest { @@ -1181,42 +1184,34 @@ TEST_F(QuantizeLSTM2Test, VerifyLSTM) { ModelT expected_model; expected_read_only_model->UnPackTo(&expected_model); - // Comparison. - ASSERT_EQ(model_.subgraphs.size(), expected_model.subgraphs.size()); - for (size_t subgraph_idx = 0; subgraph_idx < model_.subgraphs.size(); - subgraph_idx++) { - const auto graph = model_.subgraphs[subgraph_idx].get(); - const auto expected_graph = expected_model.subgraphs[subgraph_idx].get(); - ASSERT_EQ(graph->tensors.size(), expected_graph->tensors.size()); - for (size_t i = 0; i < graph->tensors.size(); i++) { - const auto tensor = graph->tensors[i].get(); - const auto expected_tensor = expected_graph->tensors[i].get(); - EXPECT_EQ(tensor->buffer, expected_tensor->buffer); - EXPECT_EQ(tensor->is_variable, expected_tensor->is_variable); - EXPECT_EQ(tensor->shape, expected_tensor->shape); - EXPECT_EQ(tensor->name, expected_tensor->name); - EXPECT_EQ(tensor->type, expected_tensor->type); - const auto quantization_params = tensor->quantization.get(); - const auto expected_quantization_params = - expected_tensor->quantization.get(); - if (quantization_params != nullptr || - expected_quantization_params != nullptr) { - EXPECT_NE(quantization_params, nullptr); - EXPECT_NE(expected_quantization_params, nullptr); - EXPECT_EQ(quantization_params->scale, - expected_quantization_params->scale); - EXPECT_EQ(quantization_params->zero_point, - expected_quantization_params->zero_point); - } - } - } - ASSERT_EQ(model_.buffers.size(), expected_model.buffers.size()); - for (size_t buffer_idx = 0; buffer_idx < model_.buffers.size(); - ++buffer_idx) { - const auto buffer = model_.buffers[buffer_idx].get()->data; - const auto expected_buffer = expected_model.buffers[buffer_idx].get()->data; - EXPECT_EQ(buffer, expected_buffer); + ExpectSameModels(model_, expected_model); +} + +class QuantizeUnidirectionalSequenceLSTMTest : public QuantizeModelTest { + protected: + QuantizeUnidirectionalSequenceLSTMTest() { + input_model_ = ReadModel(internal::kUnidirectionalSequenceLstmCalibrated); + readonly_model_ = input_model_->GetModel(); + readonly_model_->UnPackTo(&model_); } +}; + +TEST_F(QuantizeUnidirectionalSequenceLSTMTest, + VerifyUnidirectionalSequenceLSTM) { + // Quantize model. + auto status = QuantizeModelAllOperators( + &builder_, &model_, TensorType_FLOAT32, TensorType_FLOAT32, false, + TensorType_INT8, &error_reporter_); + ASSERT_EQ(kTfLiteOk, status); + + // Read expected model. + auto expected_fb_model = + ReadModel(internal::kUnidirectionalSequenceLstmQuantized); + auto expected_read_only_model = expected_fb_model->GetModel(); + ModelT expected_model; + expected_read_only_model->UnPackTo(&expected_model); + + ExpectSameModels(model_, expected_model); } class QuantizeSVDFTest : public QuantizeModelTest { diff --git a/tensorflow/lite/tools/optimize/test_util.cc b/tensorflow/lite/tools/optimize/test_util.cc index b22902a3e4b..5565fc4d657 100644 --- a/tensorflow/lite/tools/optimize/test_util.cc +++ b/tensorflow/lite/tools/optimize/test_util.cc @@ -57,6 +57,11 @@ const char* kModelPack = "pack.bin"; const char* kLstmCalibrated = "lstm_calibrated.bin"; const char* kLstmQuantized = "lstm_quantized.bin"; +const char* kUnidirectionalSequenceLstmCalibrated = + "unidirectional_sequence_lstm_calibrated.bin"; +const char* kUnidirectionalSequenceLstmQuantized = + "unidirectional_sequence_lstm_quantized.bin"; + const char* kModelWithMinimumOp = "minimum.bin"; const char* kModelWithMaximumOp = "maximum.bin"; const char* kLstmCalibrated2 = "lstm_calibrated2.bin"; diff --git a/tensorflow/lite/tools/optimize/test_util.h b/tensorflow/lite/tools/optimize/test_util.h index 99e8f0aedd3..4341a67d1ae 100644 --- a/tensorflow/lite/tools/optimize/test_util.h +++ b/tensorflow/lite/tools/optimize/test_util.h @@ -92,17 +92,20 @@ extern const char* kModelPack; extern const char* kLstmCalibrated; extern const char* kLstmQuantized; +// Test model with LSTM op that has peephole, without layer norm, without +// projection, without cifg. +extern const char* kLstmCalibrated2; +extern const char* kLstmQuantized2; + +extern const char* kUnidirectionalSequenceLstmCalibrated; +extern const char* kUnidirectionalSequenceLstmQuantized; + // Test model with a minimum op. extern const char* kModelWithMinimumOp; // Test model with a maximum op. extern const char* kModelWithMaximumOp; -// Test model with LSTM op that has peephole, without layer norm, without -// projection, without cifg. -extern const char* kLstmCalibrated2; -extern const char* kLstmQuantized2; - // Test model with a transpose op. extern const char* kModelWithTranspose; diff --git a/tensorflow/lite/tools/optimize/testdata/unidirectional_sequence_lstm_calibrated.bin b/tensorflow/lite/tools/optimize/testdata/unidirectional_sequence_lstm_calibrated.bin new file mode 100644 index 0000000000000000000000000000000000000000..5712f85329dd2bb3110b130ab9390c411be22bb7 GIT binary patch literal 3088 zcmb7GJ4_T&6n*F_sHmuj_`$3R1qCL%3$7RqXtF8=g)xR0V=}Jnh-21WvW%$FSQA5u-@Wh6#Dx&2 zj`g%*(qn_D7co&IYH?pDHsF6HFu6{Mi4_78A+`WdaD5HP0C8ZZN{G+E7%&Xvfo`A~ z5Wp8qB);Ks|>oxRT(-HE9*`@8%5%S&$`H+^^AtDps z$yn9fPvwR#200pG|0+UWj*w4B$QwMB|6=i_Bjmji@}UU%XoUP#guEOf_Zva1Mvuhs zuli=Oe5oIkzd1`@u@z}k>vwpa>T(ETz%R(yht%5z2+<&C?uBY;DPY-%r*a(6VLA45vFawfzz#ZTO&pp28YHZFaXr>8o`eM=YVEl3S`%SMqnH+P6IF#)4x0~gSlDXPvM^NQ^xq* zms`6y-~V1tGIpon+NH~O&dIvAm9W~ai%u?Q7o;x4;@EG`JAv8w>%e``U;R@@`Ww63 z^k&a|e{EJid)+Qsg<|QlX#$Kwj$Bg^xhTFUoqh3_BB^PODE_nAN8HR-|q zGS(!qly7z&`;UWf5%!>2`>_h1rrWBP<6rta*~7&vE*3b|PTS01&uhiZo@MR150u>M zXQ}fA>#FVaUvvjk^4-OnpsmDB*pZL@PCL$hc0M08Na2~$f1!Cy{^Yq(EcM&&Jf0*( zzTG$2wcwuni#)0q5&k^0gm3c#JCrUC$^E{b!23E58P6c`V6CP5 zeRFY~)B5D6KG#pKkn9YpEqlnsJ*@TDYJK_-)>vAgi;Vt+)?cIb*+XiL<_Lm4^ayoj z{EUU?Dq~6M1a!)K**x^mF}aYw4rn3$TC5Cxt2f15U3rd6E)`tR)aSZ~ZwJQ49-$AO z|0TPxBD@Y+2UCv;ZNqm9ZJ0l8q4GT zI;eY)=PYcv@2F33y`_FdMr?qf-H7JGtH_T}*#)y|3)#HaT=Wy>3TMS$2y$^JQlH-q z>}kf!+VdG}rg%eH%CjZtgS$p~QGU3G4gow9>65;BzOt^t^W)UfTk8BsTL)PS$&ygt V4W_@z!)y8x@|&t!epBJ5^*^77TRQ*% literal 0 HcmV?d00001 diff --git a/tensorflow/lite/tools/optimize/testdata/unidirectional_sequence_lstm_quantized.bin b/tensorflow/lite/tools/optimize/testdata/unidirectional_sequence_lstm_quantized.bin new file mode 100644 index 0000000000000000000000000000000000000000..3b547b4f4ec69267fc8dbcac0752d635fed11595 GIT binary patch literal 4448 zcmbuDO>C4!9LA@$_5)X}S}H1HHNh?z?YSmMlY_o%zqq zJJ0;TW~K}nW5zabT|*U>#iq}6m~N9o?lp_~y$5{TYs`%{!-z2tgDbSpgJa+@D1x0} z6r{m2Ft2&w6L1u~4aPtKR)M8J>mC0$3{?x^^t#EJggl#&FD2xwk=)JquYO?6b0r$F zax*snl}*>CJ445(`Q}#G_W2K|*ln#m(`0;elkwe6#@~;|rLXpLJR#2{*|?pWFtIX2 z=1HJhem17xEaO*k)n#WH;%q6sw!D<1+6lIR0iZSS1&@Nqz~eyQKLOl&H0ny5sG{|| zscm7IflYo7{yWLqt90-@vPl=vcbKnQlm+(#<-r3$`aK990?LCvumnhtM}RSlnB($i z5t6v#Hqi|AEstt%Bgq3`9>OB{?mlC3;3pO-f*U=?RKPqNya?U{+rT$$ItOl`z(LRr zPGY!~;5^C&;3A4{16NS`2dKOjPpObap5^S;*z`C2LR3**<6ay1YK(yZm<;%I|9XwP@NR`NuOq z4?jhnSbI&jIPp%toGne2_hzkr%< z31q8|e`-GVded!f@IN+7-;P5Wr1)|tC-t^l^w& zDkI2W-gGvaq^+C`fY#eUf1@~K$QJ1|cW%S5>UYn6wo&ztGbc7`4~`?dM`2bhW#7sd z_DojxXY3uRd5Z1L->ROw zr^o@M9v=)< zi)>`f;Su@Y=4#eja(@K}4z6?l@^ zTx#6$PVA}_-khiurb=1It|e`}c>Y6wT6?zdq+fSR0A$Z!uyZp%emtF75U*SjW?y;g zjqK}%iT#7aRU2M+JU!A&c@qHfjM3kW=UV4S_Wb?&YQH^yw|BH%&|WQ1lnsMxonGzq z3p@UDdX3YT^#UNii+8|B9%f{pcpl1^@jSHZJztBR$fcw8b@ zi`HnQqs|x?r!^(xXUr*bOzVnAZyMPn6FDJr`?ES6w7$w$jpj#6HJYCyGPJgPr8ylW z>m6XZ+~(q+R=H-m_n6j`vtQTjv4Z|Pu}7nr*88oT-<42t#KyB?T3F4!L}ht(cZ~w= zS@&?Oyz+y1ZM;R=4%6p3RnNqD^~UnNee}1=>-DX7(b_uR<-Fsev-;}&?Rk&h1+QXV z`qsIZT#oB|JjN^g20(QO{mt^Zk#7~hmM`I5C3T#4vAt`YzWRH>>w6I1yRoz5j(d1b z9k2cdgwEPo`w4*box5v&>%FV|j_a#iXDRnu7rCgrQ0F?u?n8MU0PW)-`)kGS%4Mf} zowx0qBDoLU#L6k{B)*Sr^!3_)|34AE_D*T!kK}!PVszTxU1KjEs{ZYu`@!xe?Ou)Y wvp;9GC&^oZ)_1&m8Msp_MNR3{JmsNYt{U@a7>#n-%8M9tU+I3JtkO6C0diLY+5i9m literal 0 HcmV?d00001