diff options
author | A. Unique TensorFlower <gardener@tensorflow.org> | 2018-05-04 18:49:08 -0700 |
---|---|---|
committer | TensorFlower Gardener <gardener@tensorflow.org> | 2018-05-05 08:45:32 -0700 |
commit | 5fb53fe69afe7f9106a8bcb5632cea23cf227d78 (patch) | |
tree | 2658e05fa2481666efbea50c56909abfec3f938f /tensorflow/contrib/lite/kernels/pad_test.cc | |
parent | dd5ef1b9fc22b37e5eec87d659a3af064ca54b8b (diff) |
add support for PadV2
PiperOrigin-RevId: 195503894
Diffstat (limited to 'tensorflow/contrib/lite/kernels/pad_test.cc')
-rw-r--r-- | tensorflow/contrib/lite/kernels/pad_test.cc | 368 |
1 files changed, 363 insertions, 5 deletions
diff --git a/tensorflow/contrib/lite/kernels/pad_test.cc b/tensorflow/contrib/lite/kernels/pad_test.cc index c06237e572..f8b9064fbb 100644 --- a/tensorflow/contrib/lite/kernels/pad_test.cc +++ b/tensorflow/contrib/lite/kernels/pad_test.cc @@ -24,21 +24,26 @@ namespace { using ::testing::ElementsAreArray; using ::testing::Matcher; +template <typename T> class PadOpModel : public SingleOpModel { public: - void SetInput(std::initializer_list<float> data) { - PopulateTensor<float>(input_, data); + void SetInput(std::initializer_list<T> data) { + PopulateTensor<T>(input_, data); } void SetQuantizedInput(std::initializer_list<float> data) { QuantizeAndPopulate<uint8_t>(input_, data); } + void SetQuantizedPadValue(float data) { + QuantizeAndPopulate<uint8_t>(constant_values_, {data}); + } + void SetPaddings(std::initializer_list<int> paddings) { PopulateTensor<int>(paddings_, paddings); } - std::vector<float> GetOutput() { return ExtractVector<float>(output_); } + std::vector<T> GetOutput() { return ExtractVector<T>(output_); } std::vector<int> GetOutputShape() { return GetTensorShape(output_); } std::vector<float> GetDequantizedOutput() { @@ -50,6 +55,59 @@ class PadOpModel : public SingleOpModel { int input_; int output_; int paddings_; + int constant_values_; +}; + +namespace { + +// Returns the corresponding TensorType given the type T. +template <typename T> +TensorType GetTensorType() { + if (std::is_same<T, float>::value) return TensorType_FLOAT32; + if (std::is_same<T, int32_t>::value) return TensorType_INT32; + if (std::is_same<T, uint8_t>::value) return TensorType_UINT8; + return TensorType_MIN; // default value +} + +} // namespace + +// Tests case where paddings is a const tensor. Type T is the dtype. +template <typename T> +class PadV2OpConstModel : public PadOpModel<T> { + public: + PadV2OpConstModel(const TensorData& input, + std::initializer_list<int> paddings_shape, + std::initializer_list<int> paddings, T constant_values, + const TensorData& output) { + this->input_ = this->AddInput(input); + this->paddings_ = + this->AddConstInput(TensorType_INT32, paddings, paddings_shape); + this->constant_values_ = + this->AddConstInput(GetTensorType<T>(), {constant_values}, {1}); + + this->output_ = this->AddOutput(output); + + this->SetBuiltinOp(BuiltinOperator_PADV2, BuiltinOptions_PadV2Options, + CreatePadV2Options(this->builder_).Union()); + this->BuildInterpreter({input.shape}); + } + + PadV2OpConstModel(const TensorData& input, + std::initializer_list<int> paddings_shape, + std::initializer_list<int> paddings, + const TensorData& constant_values, + const TensorData& output) { + this->input_ = this->AddInput(input); + this->paddings_ = + this->AddConstInput(TensorType_INT32, paddings, paddings_shape); + this->constant_values_ = this->AddInput(constant_values); + + this->output_ = this->AddOutput(output); + + this->SetBuiltinOp(BuiltinOperator_PADV2, BuiltinOptions_PadV2Options, + CreatePadV2Options(this->builder_).Union()); + this->BuildInterpreter({input.shape}); + } }; // Tests case where paddings is a const tensor. @@ -58,7 +116,7 @@ class PadOpModel : public SingleOpModel { // PadOpDynamicModel m(input_shape, paddings_shape, paddings_data); // m.SetInput(input_data); // m.Invoke(); -class PadOpConstModel : public PadOpModel { +class PadOpConstModel : public PadOpModel<float> { public: PadOpConstModel(const TensorData& input, std::initializer_list<int> paddings_shape, @@ -66,6 +124,7 @@ class PadOpConstModel : public PadOpModel { const TensorData& output) { input_ = AddInput(input); paddings_ = AddConstInput(TensorType_INT32, paddings, paddings_shape); + constant_values_ = AddNullInput(); output_ = AddOutput(output); SetBuiltinOp(BuiltinOperator_PAD, BuiltinOptions_PadOptions, @@ -75,19 +134,52 @@ class PadOpConstModel : public PadOpModel { }; // Test case where paddings is a non-const tensor. +template <typename T> +class PadV2OpDynamicModel : public PadOpModel<T> { + public: + PadV2OpDynamicModel(const TensorData& input, + std::initializer_list<int> paddings_shape, + T constant_values, const TensorData& output) { + this->input_ = this->AddInput(input); + this->paddings_ = this->AddInput(TensorType_INT32); + this->constant_values_ = + this->AddConstInput(GetTensorType<T>(), {constant_values}, {1}); + this->output_ = this->AddOutput(output); + + this->SetBuiltinOp(BuiltinOperator_PADV2, BuiltinOptions_PadV2Options, + CreatePadV2Options(this->builder_).Union()); + this->BuildInterpreter({input.shape, paddings_shape}); + } + PadV2OpDynamicModel(const TensorData& input, + std::initializer_list<int> paddings_shape, + const TensorData& constant_values, + const TensorData& output) { + this->input_ = this->AddInput(input); + this->paddings_ = this->AddInput(TensorType_INT32); + this->constant_values_ = this->AddInput(constant_values); + this->output_ = this->AddOutput(output); + + this->SetBuiltinOp(BuiltinOperator_PADV2, BuiltinOptions_PadV2Options, + CreatePadV2Options(this->builder_).Union()); + this->BuildInterpreter({input.shape, paddings_shape}); + } +}; + +// Test case where paddings is a non-const tensor. // // Example usage is as follows: // PadOpDynamicModel m(input_shape, paddings_shape); // m.SetInput(input_data); // m.SetPaddings(paddings_data); // m.Invoke(); -class PadOpDynamicModel : public PadOpModel { +class PadOpDynamicModel : public PadOpModel<float> { public: PadOpDynamicModel(const TensorData& input, std::initializer_list<int> paddings_shape, const TensorData& output) { input_ = AddInput(input); paddings_ = AddInput(TensorType_INT32); + constant_values_ = AddNullInput(); output_ = AddOutput(output); SetBuiltinOp(BuiltinOperator_PAD, BuiltinOptions_PadOptions, @@ -237,6 +329,272 @@ TEST_F(QuantizedPadOpTest, AdvancedDynamicTest) { EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 7, 1})); } +TEST(PadV2OpTest, TooManyDimensions) { + EXPECT_DEATH(PadV2OpConstModel<float>( + {TensorType_FLOAT32, {1, 2, 3, 4, 5, 6, 7, 8, 9}}, {9, 2}, + {1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9}, 0.0, + {TensorType_FLOAT32}), + "dims != 4"); +} + +TEST(PadV2OpTest, UnequalDimensions) { + EXPECT_DEATH( + PadV2OpConstModel<float>({TensorType_FLOAT32, {1, 1, 2, 1}}, {3, 2}, + {1, 1, 2, 2, 3, 3}, 0.0, {TensorType_FLOAT32}), + "3 != 4"); +} + +TEST(PadV2OpTest, InvalidPadValue) { + EXPECT_DEATH(PadV2OpConstModel<float>({TensorType_FLOAT32, {1, 1, 2, 1}}, + {4, 2}, {0, 0, 1, -1, 2, -1, 0, 0}, 0.0, + {TensorType_FLOAT32}), + "Pad value has to be greater than equal to 0."); +} + +TEST(PadV2OpTest, SimpleConstTest) { + // Padding is represented as four 2-D lists representing above padding and + // below padding (i.e. {{0, 0}, {1, 1}, {1, 1}, {0, 0}}). + PadV2OpConstModel<float> m({TensorType_FLOAT32, {1, 2, 2, 1}}, {4, 2}, + {0, 0, 1, 1, 1, 1, 0, 0}, 0.0, + {TensorType_FLOAT32}); + m.SetInput({1, 2, 3, 4}); + m.Invoke(); + EXPECT_THAT(m.GetOutput(), ElementsAreArray({0, 0, 0, 0, 0, 1, 2, 0, 0, 3, 4, + 0, 0, 0, 0, 0})); + EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1})); +} + +TEST(PadV2OpTest, SimpleConstFloat32ValuedTest) { + // Padding is represented as four 2-D lists representing above padding and + // below padding (i.e. {{0, 0}, {1, 1}, {1, 1}, {0, 0}}). + PadV2OpConstModel<float> m({TensorType_FLOAT32, {1, 2, 2, 1}}, {4, 2}, + {0, 0, 1, 1, 1, 1, 0, 0}, 5, {TensorType_FLOAT32}); + m.SetInput({1, 2, 3, 4}); + m.Invoke(); + EXPECT_THAT(m.GetOutput(), ElementsAreArray({5, 5, 5, 5, 5, 1, 2, 5, 5, 3, 4, + 5, 5, 5, 5, 5})); + EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1})); +} + +TEST(PadV2OpTest, Simple4DConstFloat32ValuedTest) { + // Padding is represented as four 2-D lists representing above padding and + // below padding (i.e. {{0, 0}, {1, 1}, {1, 1}, {0, 0}}). + PadV2OpConstModel<float> m({TensorType_FLOAT32, {1, 1, 2, 1}}, {4, 2}, + {0, 1, 0, 0, 0, 0, 0, 1}, 5, {TensorType_FLOAT32}); + m.SetInput({3, 3}); + m.Invoke(); + EXPECT_THAT(m.GetOutput(), ElementsAreArray({3, 5, 3, 5, 5, 5, 5, 5})); + EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({2, 1, 2, 2})); +} + +TEST(PadV2OpTest, SimpleConstInt32ValuedTest) { + // Padding is represented as four 2-D lists representing above padding and + // below padding (i.e. {{0, 0}, {1, 1}, {1, 1}, {0, 0}}). + PadV2OpConstModel<int32_t> m({TensorType_INT32, {1, 2, 2, 1}}, {4, 2}, + {0, 0, 1, 1, 1, 1, 0, 0}, 5, {TensorType_INT32}); + m.SetInput({1, 2, 3, 4}); + m.Invoke(); + EXPECT_THAT(m.GetOutput(), ElementsAreArray({5, 5, 5, 5, 5, 1, 2, 5, 5, 3, 4, + 5, 5, 5, 5, 5})); + EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1})); +} + +TEST(PadV2OpTest, SimpleDynamicTest) { + PadV2OpDynamicModel<float> m({TensorType_FLOAT32, {1, 2, 2, 1}}, {4, 2}, 0.0, + {TensorType_FLOAT32}); + m.SetInput({1, 2, 3, 4}); + m.SetPaddings({0, 0, 1, 1, 1, 1, 0, 0}); + m.Invoke(); + EXPECT_THAT(m.GetOutput(), ElementsAreArray({0, 0, 0, 0, 0, 1, 2, 0, 0, 3, 4, + 0, 0, 0, 0, 0})); + EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1})); +} + +TEST(PadV2OpTest, SimpleDynamicValuedTest) { + PadV2OpDynamicModel<float> m({TensorType_FLOAT32, {1, 2, 2, 1}}, {4, 2}, 5, + {TensorType_FLOAT32}); + m.SetInput({1, 2, 3, 4}); + m.SetPaddings({0, 0, 1, 1, 1, 1, 0, 0}); + m.Invoke(); + EXPECT_THAT(m.GetOutput(), ElementsAreArray({5, 5, 5, 5, 5, 1, 2, 5, 5, 3, 4, + 5, 5, 5, 5, 5})); + EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1})); +} + +TEST(PadV2OpTest, AdvancedConstTest) { + PadV2OpConstModel<float> m({TensorType_FLOAT32, {1, 2, 3, 1}}, {4, 2}, + {0, 0, 0, 2, 1, 3, 0, 0}, 0, {TensorType_FLOAT32}); + m.SetInput({1, 2, 3, 4, 5, 6}); + m.Invoke(); + EXPECT_THAT(m.GetOutput(), + ElementsAreArray({0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); + EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 7, 1})); +} + +TEST(PadV2OpTest, AdvancedDynamicTest) { + PadV2OpDynamicModel<float> m({TensorType_FLOAT32, {1, 2, 3, 1}}, {4, 2}, 0, + {TensorType_FLOAT32}); + m.SetInput({1, 2, 3, 4, 5, 6}); + m.SetPaddings({0, 0, 0, 2, 1, 3, 0, 0}); + m.Invoke(); + EXPECT_THAT(m.GetOutput(), + ElementsAreArray({0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); + EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 7, 1})); +} + +class QuantizedPadV2OpTest : public ::testing::Test { + protected: + std::vector<Matcher<float>> DequantizedArrayNear( + const std::vector<float>& values, const float min, const float max) { + const float quantization_tolerance = (max - min) / 255.0; + return ArrayFloatNear(values, quantization_tolerance); + } +}; + +TEST_F(QuantizedPadV2OpTest, ZeroNotInQuantizationRange) { + // The test_util and actual quantization code currently ensure that the range + // must include zero, but if that ever changes, this test will catch it. + EXPECT_DEATH( + PadV2OpConstModel<float> m({TensorType_UINT8, {1, 2, 2, 1}, 1.0, 2.0}, + {4, 2}, {0, 0, 1, 1, 1, 1, 0, 0}, 0, + {TensorType_UINT8, {}, 1.0, 2.0}), + ".*Check failed: f_min <= 0.*"); +} + +TEST_F(QuantizedPadV2OpTest, SimpleConstTest) { + // Padding is represented as four 2-D lists representing above padding and + // below padding (i.e. {{0, 0}, {1, 1}, {1, 1}, {0, 0}}). + PadV2OpConstModel<uint8_t> m({TensorType_UINT8, {1, 2, 2, 1}, -1.0, 1.0}, + {4, 2}, {0, 0, 1, 1, 1, 1, 0, 0}, + {TensorType_UINT8, {1}, -1.0, 1.0}, + {TensorType_UINT8, {}, -1.0, 1.0}); + m.SetQuantizedInput({-0.8, 0.2, 0.9, 0.7}); + m.SetQuantizedPadValue(0); + m.Invoke(); + EXPECT_THAT(m.GetDequantizedOutput(), + ElementsAreArray(DequantizedArrayNear( + {0, 0, 0, 0, 0, -0.8, 0.2, 0, 0, 0.9, 0.7, 0, 0, 0, 0, 0}, + -1.0, 1.0))); + EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1})); +} + +TEST_F(QuantizedPadV2OpTest, SimpleDynamicTest) { + PadV2OpDynamicModel<uint8_t> m({TensorType_UINT8, {1, 2, 2, 1}, -1.0, 1.0}, + {4, 2}, {TensorType_UINT8, {1}, -1.0, 1.0}, + {TensorType_UINT8, {}, -1.0, 1.0}); + m.SetQuantizedInput({-0.8, 0.2, 0.9, 0.7}); + m.SetQuantizedPadValue(0); + m.SetPaddings({0, 0, 1, 1, 1, 1, 0, 0}); + m.Invoke(); + EXPECT_THAT(m.GetDequantizedOutput(), + ElementsAreArray(DequantizedArrayNear( + {0, 0, 0, 0, 0, -0.8, 0.2, 0, 0, 0.9, 0.7, 0, 0, 0, 0, 0}, + -1.0, 1.0))); + EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1})); +} + +TEST_F(QuantizedPadV2OpTest, AdvancedConstTest) { + PadV2OpConstModel<uint8_t> m({TensorType_UINT8, {1, 2, 3, 1}, -1.0, 1.0}, + {4, 2}, {0, 0, 0, 2, 1, 3, 0, 0}, + {TensorType_UINT8, {1}, -1.0, 1.0}, + {TensorType_UINT8, {}, -1.0, 1.0}); + m.SetQuantizedInput({-0.8, 0.2, 0.9, 0.7, 0.1, -0.3}); + m.SetQuantizedPadValue(0); + m.Invoke(); + EXPECT_THAT(m.GetDequantizedOutput(), + ElementsAreArray(DequantizedArrayNear( + {0, -0.8, 0.2, 0.9, 0, 0, 0, 0, 0.7, 0.1, -0.3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + -1.0, 1.0))); + EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 7, 1})); +} + +TEST_F(QuantizedPadV2OpTest, AdvancedDynamicTest) { + PadV2OpDynamicModel<uint8_t> m({TensorType_UINT8, {1, 2, 3, 1}, -1.0, 1.0}, + {4, 2}, {TensorType_UINT8, {1}, -1.0, 1.0}, + {TensorType_UINT8, {}, -1.0, 1.0}); + m.SetQuantizedInput({-0.8, 0.2, 0.9, 0.7, 0.1, -0.3}); + m.SetQuantizedPadValue(0); + m.SetPaddings({0, 0, 0, 2, 1, 3, 0, 0}); + m.Invoke(); + EXPECT_THAT(m.GetDequantizedOutput(), + ElementsAreArray(DequantizedArrayNear( + {0, -0.8, 0.2, 0.9, 0, 0, 0, 0, 0.7, 0.1, -0.3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + -1.0, 1.0))); + EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 7, 1})); +} + +TEST_F(QuantizedPadV2OpTest, SimpleConstValuedTest) { + // Padding is represented as four 2-D lists representing above padding and + // below padding (i.e. {{0, 0}, {1, 1}, {1, 1}, {0, 0}}). + PadV2OpConstModel<uint8_t> m({TensorType_UINT8, {1, 2, 2, 1}, -1.0, 1.0}, + {4, 2}, {0, 0, 1, 1, 1, 1, 0, 0}, + {TensorType_UINT8, {1}, -1.0, 1.0}, + {TensorType_UINT8, {}, -1.0, 1.0}); + m.SetQuantizedInput({-0.8, 0.2, 0.9, 0.7}); + m.SetQuantizedPadValue(-0.5); + m.Invoke(); + EXPECT_THAT(m.GetDequantizedOutput(), + ElementsAreArray(DequantizedArrayNear( + {-0.5, -0.5, -0.5, -0.5, -0.5, -0.8, 0.2, -0.5, -0.5, 0.9, + 0.7, -0.5, -0.5, -0.5, -0.5, -0.5}, + -1.0, 1.0))); + EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1})); +} + +TEST_F(QuantizedPadV2OpTest, SimpleDynamicValuedTest) { + PadV2OpDynamicModel<uint8_t> m({TensorType_UINT8, {1, 2, 2, 1}, -1.0, 1.0}, + {4, 2}, {TensorType_UINT8, {1}, -1.0, 1.0}, + {TensorType_UINT8, {}, -1.0, 1.0}); + m.SetQuantizedInput({-0.8, 0.2, 0.9, 0.7}); + m.SetQuantizedPadValue(-0.5); + m.SetPaddings({0, 0, 1, 1, 1, 1, 0, 0}); + m.Invoke(); + EXPECT_THAT(m.GetDequantizedOutput(), + ElementsAreArray(DequantizedArrayNear( + {-0.5, -0.5, -0.5, -0.5, -0.5, -0.8, 0.2, -0.5, -0.5, 0.9, + 0.7, -0.5, -0.5, -0.5, -0.5, -0.5}, + -1.0, 1.0))); + EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1})); +} + +TEST_F(QuantizedPadV2OpTest, AdvancedConstValuedTest) { + PadV2OpConstModel<uint8_t> m({TensorType_UINT8, {1, 2, 3, 1}, -1.0, 1.0}, + {4, 2}, {0, 0, 0, 2, 1, 3, 0, 0}, + {TensorType_UINT8, {1}, -1.0, 1.0}, + {TensorType_UINT8, {}, -1.0, 1.0}); + m.SetQuantizedInput({-0.8, 0.2, 0.9, 0.7, 0.1, -0.3}); + m.SetQuantizedPadValue(-0.5); + m.Invoke(); + EXPECT_THAT(m.GetDequantizedOutput(), + ElementsAreArray(DequantizedArrayNear( + {-0.5, -0.8, 0.2, 0.9, -0.5, -0.5, -0.5, -0.5, 0.7, 0.1, + -0.3, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, + -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5}, + -1.0, 1.0))); + EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 7, 1})); +} + +TEST_F(QuantizedPadV2OpTest, AdvancedDynamicValuedTest) { + PadV2OpDynamicModel<uint8_t> m({TensorType_UINT8, {1, 2, 3, 1}, -1.0, 1.0}, + {4, 2}, {TensorType_UINT8, {1}, -1.0, 1.0}, + {TensorType_UINT8, {}, -1.0, 1.0}); + m.SetQuantizedInput({-0.8, 0.2, 0.9, 0.7, 0.1, -0.3}); + m.SetQuantizedPadValue(-0.5); + m.SetPaddings({0, 0, 0, 2, 1, 3, 0, 0}); + m.Invoke(); + EXPECT_THAT(m.GetDequantizedOutput(), + ElementsAreArray(DequantizedArrayNear( + {-0.5, -0.8, 0.2, 0.9, -0.5, -0.5, -0.5, -0.5, 0.7, 0.1, + -0.3, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, + -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5}, + -1.0, 1.0))); + EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 7, 1})); +} + } // namespace } // namespace tflite |