1122cdce33e3e0a01a7f82645617317530aa571fbA. Unique TensorFlower/* Copyright 2015 The TensorFlow Authors. All Rights Reserved. 2ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden 3ca4e053aa52ab9a42467d4df814ca9272487dbdfPete WardenLicensed under the Apache License, Version 2.0 (the "License"); 4ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Wardenyou may not use this file except in compliance with the License. 5ca4e053aa52ab9a42467d4df814ca9272487dbdfPete WardenYou may obtain a copy of the License at 6ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden 7ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden http://www.apache.org/licenses/LICENSE-2.0 8ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden 9ca4e053aa52ab9a42467d4df814ca9272487dbdfPete WardenUnless required by applicable law or agreed to in writing, software 10ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Wardendistributed under the License is distributed on an "AS IS" BASIS, 11ca4e053aa52ab9a42467d4df814ca9272487dbdfPete WardenWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12ca4e053aa52ab9a42467d4df814ca9272487dbdfPete WardenSee the License for the specific language governing permissions and 13ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Wardenlimitations under the License. 14ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden==============================================================================*/ 15ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden 1641997756c73532666d8531ba760b313c9f3e076fA. Unique TensorFlower#define EIGEN_USE_THREADS 1741997756c73532666d8531ba760b313c9f3e076fA. Unique TensorFlower 18ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden#include <functional> 19ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden 20ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden#include "tensorflow/core/framework/allocator.h" 21ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden#include "tensorflow/core/framework/fake_input.h" 22ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden#include "tensorflow/core/framework/node_def_builder.h" 23ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden#include "tensorflow/core/framework/op_kernel.h" 24ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden#include "tensorflow/core/framework/tensor.h" 25ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden#include "tensorflow/core/framework/tensor_testutil.h" 26ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden#include "tensorflow/core/framework/types.h" 27ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden#include "tensorflow/core/framework/types.pb.h" 28ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden#include "tensorflow/core/kernels/ops_testutil.h" 29ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden#include "tensorflow/core/kernels/ops_util.h" 3041997756c73532666d8531ba760b313c9f3e076fA. Unique TensorFlower#include "tensorflow/core/kernels/quantization_utils.h" 31ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden#include "tensorflow/core/lib/core/status_test_util.h" 32ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden#include "tensorflow/core/platform/test.h" 33ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden 34ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Wardennamespace tensorflow { 35ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden 36ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Wardenclass QuantizedBiasAddTest : public OpsTestBase { 37ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden protected: 38ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden}; 39ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden 40ca4e053aa52ab9a42467d4df814ca9272487dbdfPete WardenTEST_F(QuantizedBiasAddTest, Small) { 41ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden TF_ASSERT_OK(NodeDefBuilder("quantized_bias_add_op", "QuantizedBiasAdd") 42ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden .Input(FakeInput(DT_QUINT8)) 43ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden .Input(FakeInput(DT_QUINT8)) 44ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden .Input(FakeInput(DT_FLOAT)) 45ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden .Input(FakeInput(DT_FLOAT)) 46ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden .Input(FakeInput(DT_FLOAT)) 47ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden .Input(FakeInput(DT_FLOAT)) 48ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden .Attr("out_type", DataTypeToEnum<qint32>::v()) 49ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden .Finalize(node_def())); 50ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden TF_ASSERT_OK(InitOp()); 51ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden const float input_min = 0.0f; 52ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden const float input_max = 60.0f; 53ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden const int input_height = 2; 54ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden const int input_width = 3; 55ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden Tensor input_float(DT_FLOAT, {input_height, input_width}); 56ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden test::FillValues<float>(&input_float, 57ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden {10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f}); 58ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden Tensor input_quantized = 59ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden FloatTensorToQuantized<quint8>(input_float, input_min, input_max); 60ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden 61ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden const float bias_min = 0.0f; 62ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden const float bias_max = 3.0f; 63ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden const int bias_width = 3; 64ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden Tensor bias_float(DT_FLOAT, {bias_width}); 65ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden test::FillValues<float>(&bias_float, {1.0f, 2.0f, 3.0f}); 66ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden Tensor bias_quantized = 67ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden FloatTensorToQuantized<quint8>(bias_float, bias_min, bias_max); 68ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden 69ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden Tensor expected_float(DT_FLOAT, {input_height, input_width}); 70ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden test::FillValues<float>(&expected_float, 71ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden {11.0f, 22.0f, 33.0f, 41.0f, 52.0f, 63.0f}); 72ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden 73ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden AddInputFromArray<quint8>(input_quantized.shape(), 74ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden input_quantized.flat<quint8>()); 75ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden AddInputFromArray<quint8>(bias_quantized.shape(), 76ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden bias_quantized.flat<quint8>()); 77ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden AddInputFromArray<float>(TensorShape({1}), {input_min}); 78ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden AddInputFromArray<float>(TensorShape({1}), {input_max}); 79ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden AddInputFromArray<float>(TensorShape({1}), {bias_min}); 80ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden AddInputFromArray<float>(TensorShape({1}), {bias_max}); 81ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden TF_ASSERT_OK(RunOpKernel()); 82ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden const Tensor& output_quantized = *GetOutput(0); 83ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden const float output_min = GetOutput(1)->flat<float>()(0); 84ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden const float output_max = GetOutput(2)->flat<float>()(0); 85ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden Tensor output_float = 86ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden QuantizedTensorToFloat<qint32>(output_quantized, output_min, output_max); 87ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden test::ExpectTensorNear<float>(expected_float, output_float, 0.2); 88ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden} 89ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden 90ca4e053aa52ab9a42467d4df814ca9272487dbdfPete WardenTEST_F(QuantizedBiasAddTest, RealData) { 91ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden TF_ASSERT_OK(NodeDefBuilder("quantized_bias_add_op", "QuantizedBiasAdd") 92ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden .Input(FakeInput(DT_QUINT8)) 93ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden .Input(FakeInput(DT_QUINT8)) 94ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden .Input(FakeInput(DT_FLOAT)) 95ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden .Input(FakeInput(DT_FLOAT)) 96ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden .Input(FakeInput(DT_FLOAT)) 97ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden .Input(FakeInput(DT_FLOAT)) 98ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden .Attr("out_type", DataTypeToEnum<qint32>::v()) 99ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden .Finalize(node_def())); 100ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden TF_ASSERT_OK(InitOp()); 101ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden const float input_min = -2164.25f; 102ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden const float input_max = 2006.27f; 103ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden const int input_height = 1; 104ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden const int input_width = 64; 105ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden Tensor input_float(DT_FLOAT, {input_height, input_width}); 106ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden test::FillValues<float>( 107ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden &input_float, 108ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden {-1014.12, -157.382, -810.17, 1435.28, 1016.37, 219.684, -316.054, 109ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden -2164.25, 2006.27, -547.444, 857.376, 404.376, 9.72115, 332.588, 110ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden 194.385, -286.57, 26.062, 23.1125, 110.436, 247.055, -127.683, 111ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden -376.275, -124.81, -846.826, -77.1507, 305.581, -202.747, 12.9528, 112ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden 9.64886, 872.686, 40.9069, 197.816, 44.16, -306.768, -1457.52, 113ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden -368.939, -1049.42, -486.353, 1745.87, 95.7695, 395.773, -254.333, 114ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden -404.27, 787.16, -2.44114, 199.37, -1024.08, 784.901, 235.055, 115ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden -42.7295, 241.498, -245.365, 470.763, 186.159, 186.579, -220.163, 116ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden 1304.58, 386.272, -358.853, -755.996, 360.109, -866.007, 55.2828, 117ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden -508.801}); 118ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden Tensor input_quantized = 119ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden FloatTensorToQuantized<quint8>(input_float, input_min, input_max); 120ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden 121ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden const float bias_min = -0.739539f; 122ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden const float bias_max = 0.641057f; 123ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden const int bias_width = 64; 124ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden Tensor bias_float(DT_FLOAT, {bias_width}); 125ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden test::FillValues<float>( 126ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden &bias_float, 127ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden {-0.294619, -0.0670519, 0.261507, -0.126274, 0.127229, -0.176945, 128ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden -0.251223, 0.231086, 0.453694, 0.415666, -0.288733, 0.508717, 129ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden 0.211551, 0.0435907, -0.582383, -0.308779, 0.0696883, -0.438122, 130ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden 0.114, 0.433964, 0.109883, 0.284931, -0.149661, 0.108657, 131ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden 0.458333, -0.130231, -0.35805, -0.123206, -0.437968, 0.0282411, 132ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden 0.628818, -0.0522173, -0.0233403, 0.124863, 0.217165, 0.262294, 133ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden -0.171005, -0.254693, -0.200433, -0.287354, 0.488166, -0.0354688, 134ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden -0.118091, -0.590444, 0.491537, -0.739539, 0.083117, 0.282482, 135ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden 0.275269, -0.36574, 0.107476, 0.0511428, -0.136887, -0.0149852, 136ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden -0.259694, 0.641057, 0.264054, -0.295126, -0.0218791, 0.361211, 137ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden 0.012448, 0.0709718, -0.392394, -0.434215}); 138ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden Tensor bias_quantized = 139ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden FloatTensorToQuantized<quint8>(bias_float, bias_min, bias_max); 140ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden 141ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden Tensor expected_float(DT_FLOAT, {input_height, input_width}); 142ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden test::FillValues<float>( 143ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden &expected_float, 144ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden {-1014.42, -157.449, -809.908, 1435.16, 1016.5, 219.507, -316.305, 145ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden -2164.02, 2006.73, -547.028, 857.088, 404.885, 9.9327, 332.632, 146ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden 193.803, -286.878, 26.1317, 22.6744, 110.55, 247.489, -127.573, 147ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden -375.99, -124.959, -846.717, -76.6923, 305.451, -203.105, 12.8296, 148ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden 9.21089, 872.714, 41.5357, 197.764, 44.1367, -306.643, -1457.3, 149ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden -368.677, -1049.6, -486.608, 1745.67, 95.4821, 396.261, -254.368, 150ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden -404.388, 786.57, -1.94961, 198.63, -1024.0, 785.183, 235.33, 151ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden -43.0953, 241.605, -245.314, 470.627, 186.144, 186.319, -219.522, 152ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden 1304.84, 385.977, -358.874, -755.635, 360.122, -865.936, 54.8904, 153ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden -509.235}); 154ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden 155ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden AddInputFromArray<quint8>(input_quantized.shape(), 156ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden input_quantized.flat<quint8>()); 157ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden AddInputFromArray<quint8>(bias_quantized.shape(), 158ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden bias_quantized.flat<quint8>()); 159ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden AddInputFromArray<float>(TensorShape({1}), {input_min}); 160ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden AddInputFromArray<float>(TensorShape({1}), {input_max}); 161ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden AddInputFromArray<float>(TensorShape({1}), {bias_min}); 162ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden AddInputFromArray<float>(TensorShape({1}), {bias_max}); 163ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden TF_ASSERT_OK(RunOpKernel()); 164ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden const Tensor& output_quantized = *GetOutput(0); 165ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden const float output_min = GetOutput(1)->flat<float>()(0); 166ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden const float output_max = GetOutput(2)->flat<float>()(0); 167ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden Tensor output_float = 168ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden QuantizedTensorToFloat<qint32>(output_quantized, output_min, output_max); 169ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden test::ExpectTensorNear<float>(expected_float, output_float, 20.0); 170ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden} 171ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden 172ca4e053aa52ab9a42467d4df814ca9272487dbdfPete Warden} // namespace tensorflow 173