-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Implement Shrink operator #485
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
fbade79
Initial commit
hariharans29 a546222
Merge branch 'master' into shrinkOp
hariharans29 71ceae0
Adding shrink tests
hariharans29 2e4996f
Fix formatting in shrink_test.cc
hariharans29 9b6efde
Fix broken build
hariharans29 ee71c12
More changes
hariharans29 17db480
PR feedback and formatting
hariharans29 9519a96
Place files in the right location corresponding to def file location …
hariharans29 e31c9fc
Exclude shrink model test in test_series.py
hariharans29 5538cb0
Merge master
hariharans29 f55cd8b
Remove shrink from exclusion list in main.cc
hariharans29 398c063
Adding test to exclusion list
hariharans29 98ccd3f
More tests
hariharans29 6edf474
Formatting
hariharans29 9195528
PR feedback
hariharans29 f0fdddf
PR feedback
hariharans29 bdbe1d4
More changes
hariharans29 626a8c3
PR feedback
hariharans29 c346014
More changes
hariharans29 a83a75e
Fix broken build
hariharans29 dfe07b1
Fix nit
hariharans29 25b413b
Fix nit
hariharans29 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
|
|
||
| #include "core/providers/cpu/nn/shrink.h" | ||
|
|
||
| #include "core/util/math.h" | ||
| #include "core/util/math_cpuonly.h" | ||
| #include "core/framework/utils.h" | ||
|
|
||
| namespace onnxruntime { | ||
| ONNX_CPU_OPERATOR_KERNEL( | ||
| Shrink, | ||
| 9, | ||
| KernelDefBuilder().TypeConstraint("T", DataTypeImpl::AllNumericTensorTypes()), | ||
| Shrink); | ||
|
|
||
| namespace shrink_internal { | ||
| template <class T> | ||
| inline T ShrinkCore(const T& val, float bias, float lambd) { | ||
| // The ONNX spec doesn't take numeric overflow and underflow into account | ||
| // Implementing the spec as is for now | ||
| if (val < -lambd) { | ||
| return T(val + bias); | ||
| } else if (val > lambd) { | ||
| return T(val - bias); | ||
| } else { | ||
| return T(0); | ||
| } | ||
| } | ||
|
|
||
| template <class T> | ||
| Status ShrinkImpl(const Tensor* input, Tensor* output, float bias, float lambd) { | ||
| EigenMap<T>(*output) = EigenMap<T>(*input).unaryExpr([bias, lambd](const T& val) { return ShrinkCore<T>(val, bias, lambd); }); | ||
| return Status::OK(); | ||
| } | ||
|
|
||
| template <> | ||
| Status ShrinkImpl<MLFloat16>(const Tensor* input, Tensor* output, float bias, float lambd) { | ||
| const auto& span = gsl::make_span(input->Data<MLFloat16>(), input->Shape().Size()); | ||
| auto* output_data = output->template MutableData<MLFloat16>(); | ||
| std::transform(span.cbegin(), span.cend(), output_data, [bias, lambd](const MLFloat16& val) { | ||
| float fl = math::halfToFloat(val.val); | ||
| return MLFloat16(math::floatToHalf(ShrinkCore<float>(fl, bias, lambd))); | ||
| }); | ||
| return Status::OK(); | ||
| } | ||
|
|
||
| template <> | ||
| Status ShrinkImpl<BFloat16>(const Tensor* input, Tensor* output, float bias, float lambd) { | ||
| const auto& span = gsl::make_span(input->Data<BFloat16>(), input->Shape().Size()); | ||
| auto* output_data = output->template MutableData<BFloat16>(); | ||
| std::transform(span.cbegin(), span.cend(), output_data, [bias, lambd](const BFloat16& val) { | ||
| float fl = val.ToFloat(); | ||
| return BFloat16(ShrinkCore<float>(fl, bias, lambd)); | ||
| }); | ||
| return Status::OK(); | ||
| } | ||
|
|
||
| template <> | ||
| Status ShrinkImpl<bool>(const Tensor* /*input*/, Tensor* /*output*/, float /*bias*/, float /*lambd*/) { | ||
| return ORT_MAKE_STATUS( | ||
| ONNXRUNTIME, INVALID_ARGUMENT, | ||
| "Input types for the Shrink operator are constrained " | ||
| "to all numeric types only. Got bool type here." | ||
| ); | ||
| } | ||
|
|
||
| } // namespace shrink_internal | ||
|
|
||
| Status Shrink::Compute(OpKernelContext* p_op_kernel_context) const { | ||
| using namespace shrink_internal; | ||
|
|
||
| const auto* input = p_op_kernel_context->Input<Tensor>(0); | ||
| auto* output = p_op_kernel_context->Output(0, input->Shape()); | ||
| const auto& dtype = input->DataType(); | ||
| Status status; | ||
| DispatchOnTensorTypeWithReturn(dtype, status, ShrinkImpl, input, output, bias_, lambd_); | ||
| return status; | ||
| } | ||
| } // namespace onnxruntime | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
|
|
||
| #pragma once | ||
|
|
||
| #include "core/framework/op_kernel.h" | ||
|
|
||
| namespace onnxruntime { | ||
| class Shrink final : public OpKernel { | ||
| public: | ||
| Shrink(const OpKernelInfo& op_kernel_info) : OpKernel(op_kernel_info) { | ||
| float bias_temp; | ||
| ORT_ENFORCE(op_kernel_info.GetAttr<float>("bias", &bias_temp).IsOK()); | ||
| bias_ = gsl::narrow_cast<float>(bias_temp); | ||
|
|
||
| float lambd_temp; | ||
| ORT_ENFORCE(op_kernel_info.GetAttr<float>("lambd", &lambd_temp).IsOK()); | ||
| lambd_ = gsl::narrow_cast<float>(lambd_temp); | ||
| } | ||
|
|
||
| Status Compute(OpKernelContext* p_op_kernel_context) const override; | ||
|
|
||
| private: | ||
| float bias_; | ||
| float lambd_; | ||
| }; | ||
| } // namespace onnxruntime |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -312,8 +312,6 @@ int real_main(int argc, char* argv[]) { | |
| {"scatter_without_axis", "opset 9 not supported yet"}, | ||
| {"scan_sum", "opset 9 not supported yet"}, | ||
| {"shrink", "opset 9 not supported yet"}, | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Keeping "shrink" test excluded because of bug in test input - onnx/onnx#1823
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| {"shrink_hard", "opset 9 not supported yet"}, | ||
| {"shrink_soft", "opset 9 not supported yet"}, | ||
| {"cast_DOUBLE_to_FLOAT16", "Cast opset 9 not supported yet"}, | ||
| {"cast_DOUBLE_to_FLOAT", "Cast opset 9 not supported yet"}, | ||
| {"cast_FLOAT_to_DOUBLE", "Cast opset 9 not supported yet"}, | ||
|
|
||
File renamed without changes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,174 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
|
|
||
| #include "gtest/gtest.h" | ||
| #include "test/providers/provider_test_utils.h" | ||
| #include "core/util/math.h" | ||
|
|
||
| namespace onnxruntime { | ||
| namespace test { | ||
|
|
||
| template <typename T> | ||
| struct ShrinkTestData { | ||
| std::string name; | ||
| float bias; | ||
| float lambd; | ||
| std::vector<T> input_vals; | ||
| std::vector<int64_t> input_dimensions; | ||
| std::vector<T> expected_vals; | ||
| std::vector<int64_t> expected_dimensions; | ||
| }; | ||
|
|
||
| template <typename T> | ||
| std::vector<ShrinkTestData<T>> GenerateSignedTestCases() { | ||
| std::vector<ShrinkTestData<T>> test_cases; | ||
| test_cases.push_back( | ||
| {"default attributes", | ||
| 0.0f, | ||
| 0.5f, | ||
| {-1, 0, 0, 1}, | ||
| {2, 2}, | ||
| {-1, 0, 0, 1}, | ||
| {2, 2}}); | ||
|
|
||
| test_cases.push_back( | ||
| {"non-default attributes", | ||
| 10.0f, | ||
| 2.0f, | ||
| {-3, -1, 1, 4}, | ||
| {2, 2}, | ||
| {7, 0, 0, -6}, | ||
| {2, 2}}); | ||
| return test_cases; | ||
| } | ||
|
|
||
| template <typename T> | ||
| std::vector<ShrinkTestData<T>> GenerateUnsignedTestCases() { | ||
| std::vector<ShrinkTestData<T>> test_cases; | ||
|
|
||
| test_cases.push_back( | ||
| {"default attributes", | ||
| 0.0f, | ||
| 0.5f, | ||
| {0, 0, 0, 1}, | ||
| {2, 2}, | ||
| {0, 0, 0, 1}, | ||
| {2, 2}}); | ||
|
|
||
| test_cases.push_back( | ||
| {"non-default attributes", | ||
| 10.0f, | ||
| 2.0f, | ||
| {37, 1, 1, 11}, | ||
| {2, 2}, | ||
| {27, 0, 0, 1}, | ||
| {2, 2}}); | ||
|
|
||
| return test_cases; | ||
| } | ||
|
|
||
| template <typename T> | ||
| void RunShrinkTest(const std::vector<ShrinkTestData<T>>& test_cases) { | ||
| for (const auto& test_data : test_cases) { | ||
| OpTester test("Shrink", 9); | ||
|
|
||
| if (test_data.bias != 0.0f) { | ||
| test.AddAttribute("bias", test_data.bias); | ||
| } | ||
|
|
||
| if (test_data.lambd != 0.5f) { | ||
| test.AddAttribute("lambd", test_data.lambd); | ||
| } | ||
|
|
||
| test.AddInput<T>("X", test_data.input_dimensions, test_data.input_vals); | ||
| test.AddOutput<T>("Y", test_data.expected_dimensions, test_data.expected_vals); | ||
| test.Run(); | ||
| } | ||
| } | ||
|
|
||
| const std::vector<MLFloat16> ConvertFloatToMLFloat16(const std::vector<float>& float_data) { | ||
| std::vector<MLFloat16> new_data; | ||
| for (const auto& f : float_data) { | ||
| new_data.push_back(MLFloat16(math::floatToHalf(f))); | ||
| } | ||
| return new_data; | ||
| } | ||
|
|
||
| TEST(MathOpTest, ShrinkInt8Type) { | ||
| const auto& test_cases = GenerateSignedTestCases<int8_t>(); | ||
| RunShrinkTest<int8_t>(test_cases); | ||
| } | ||
|
|
||
| TEST(MathOpTest, ShrinkUint8Type) { | ||
| const auto& test_cases = GenerateUnsignedTestCases<uint8_t>(); | ||
| RunShrinkTest<uint8_t>(test_cases); | ||
| } | ||
|
|
||
| TEST(MathOpTest, ShrinkInt16Type) { | ||
| const auto& test_cases = GenerateSignedTestCases<int16_t>(); | ||
| RunShrinkTest<int16_t>(test_cases); | ||
| } | ||
|
|
||
| TEST(MathOpTest, ShrinkUint16Type) { | ||
| const auto& test_cases = GenerateUnsignedTestCases<uint16_t>(); | ||
| RunShrinkTest<uint16_t>(test_cases); | ||
| } | ||
|
|
||
| TEST(MathOpTest, ShrinkInt32Type) { | ||
| const auto& test_cases = GenerateSignedTestCases<int32_t>(); | ||
| RunShrinkTest<int32_t>(test_cases); | ||
| } | ||
|
|
||
| TEST(MathOpTest, ShrinkUint32Type) { | ||
| const auto& test_cases = GenerateUnsignedTestCases<uint32_t>(); | ||
| RunShrinkTest<uint32_t>(test_cases); | ||
| } | ||
|
|
||
| TEST(MathOpTest, ShrinkInt64Type) { | ||
| const auto& test_cases = GenerateSignedTestCases<int64_t>(); | ||
| RunShrinkTest<int64_t>(test_cases); | ||
| } | ||
|
|
||
| TEST(MathOpTest, ShrinkUint64Type) { | ||
| const auto& test_cases = GenerateUnsignedTestCases<uint64_t>(); | ||
| RunShrinkTest<uint64_t>(test_cases); | ||
| } | ||
|
|
||
| TEST(MathOpTest, ShrinkFloatType) { | ||
| const auto& test_cases = GenerateSignedTestCases<float>(); | ||
| RunShrinkTest<float>(test_cases); | ||
| } | ||
|
|
||
| TEST(MathOpTest, ShrinkDoubleType) { | ||
| const auto& test_cases = GenerateSignedTestCases<double>(); | ||
| RunShrinkTest<double>(test_cases); | ||
| } | ||
|
|
||
| TEST(MathOpTest, ShrinkMLFloat16Type) { | ||
| const std::vector<MLFloat16> input_test_data_default = ConvertFloatToMLFloat16({-1, 0, 0, 1}); | ||
| const std::vector<MLFloat16> output_test_data_default = ConvertFloatToMLFloat16({-1, 0, 0, 1}); | ||
|
|
||
| const std::vector<MLFloat16> input_test_data_nondefault = ConvertFloatToMLFloat16({-3, -1, 1, 4}); | ||
| const std::vector<MLFloat16> output_test_data_nondefault = ConvertFloatToMLFloat16({7, 0, 0, -6}); | ||
| std::vector<ShrinkTestData<MLFloat16>> test_cases; | ||
| test_cases.push_back( | ||
| {"default attributes", | ||
| 0.0f, | ||
| 0.5f, | ||
| input_test_data_default, | ||
| {2, 2}, | ||
| output_test_data_default, | ||
| {2, 2}}); | ||
| test_cases.push_back( | ||
| {"non-default attributes", | ||
| 10.0f, | ||
| 2.0f, | ||
| input_test_data_nondefault, | ||
| {2, 2}, | ||
| output_test_data_nondefault, | ||
| {2, 2}}); | ||
| RunShrinkTest<MLFloat16>(test_cases); | ||
| } | ||
|
|
||
| } // namespace test | ||
| } // namespace onnxruntime |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: limit line length to 120
https://marketplace.visualstudio.com/items?itemName=PaulHarrington.EditorGuidelines is very helpful to show a vertical guideline at 120