From 7e5fa3ade34c76007913ee642276b6417c8c0c1f Mon Sep 17 00:00:00 2001 From: Amir Ramezani Date: Wed, 20 Sep 2023 09:38:31 +0330 Subject: [PATCH] shrink operator (#5022) --- docs/developer-guide/operators.md | 16 +++++++ src/CMakeLists.txt | 1 + src/layer/shrink.cpp | 54 ++++++++++++++++++++++ src/layer/shrink.h | 37 +++++++++++++++ tests/CMakeLists.txt | 1 + tests/test_shrink.cpp | 76 +++++++++++++++++++++++++++++++ tools/onnx/onnx2ncnn.cpp | 11 +++++ 7 files changed, 196 insertions(+) create mode 100644 src/layer/shrink.cpp create mode 100644 src/layer/shrink.h create mode 100644 tests/test_shrink.cpp diff --git a/docs/developer-guide/operators.md b/docs/developer-guide/operators.md index 56e7516a36a0..b0975ee46877 100644 --- a/docs/developer-guide/operators.md +++ b/docs/developer-guide/operators.md @@ -72,6 +72,7 @@ * [RNN](#rnn) * [Scale](#scale) * [SELU](#selu) +* [Shrink](#shrink) * [ShuffleChannel](#shufflechannel) * [Sigmoid](#sigmoid) * [Slice](#slice) @@ -1675,6 +1676,21 @@ else y = x * lambda | 0 | alpha | float | 1.67326324f| | | 1 | lambda | float | 1.050700987f| | +# Shrink +``` +if x < -lambd y = x + bias +if x > lambd y = x - bias +else y = x +``` + +* one_blob_only +* support_inplace + +| param id | name | type | default | description | +| --------- | ------------- | ----- | --------- | ----------------- | +| 0 | bias | float | 0.0f | | +| 1 | lambd | float | 0.5f | | + # ShuffleChannel ``` if reverse == 0 y = shufflechannel(x) by group diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4a4ea24e6365..09f1b8ff48d5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -165,6 +165,7 @@ ncnn_add_layer(CopyTo) ncnn_add_layer(Erf) ncnn_add_layer(Diag) ncnn_add_layer(CELU) +ncnn_add_layer(Shrink) if(NCNN_VULKAN) ncnn_add_shader(${CMAKE_CURRENT_SOURCE_DIR}/convert_ycbcr.comp) diff --git a/src/layer/shrink.cpp b/src/layer/shrink.cpp new file mode 100644 index 000000000000..4410ac767539 --- /dev/null +++ b/src/layer/shrink.cpp @@ -0,0 +1,54 @@ +// Tencent is pleased to support the open source community by making ncnn available. +// +// Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// https://opensource.org/licenses/BSD-3-Clause +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "shrink.h" + +namespace ncnn { + +Shrink::Shrink() +{ + one_blob_only = true; + support_inplace = true; +} + +int Shrink::load_param(const ParamDict& pd) +{ + bias = pd.get(0, 0.0f); + lambd = pd.get(1, 0.5f); + + return 0; +} + +int Shrink::forward_inplace(Mat& bottom_top_blob, const Option& opt) const +{ + int w = bottom_top_blob.w; + int h = bottom_top_blob.h; + int channels = bottom_top_blob.c; + int size = w * h; + + #pragma omp parallel for num_threads(opt.num_threads) + for (int q = 0; q < channels; q++) + { + float* ptr = bottom_top_blob.channel(q); + + for (int i = 0; i < size; i++) + { + ptr[i] = ptr[i] < -lambd ? ptr[i] + bias : ptr[i] > lambd ? ptr[i] - bias : ptr[i]; + } + } + + return 0; +} + +} // namespace ncnn diff --git a/src/layer/shrink.h b/src/layer/shrink.h new file mode 100644 index 000000000000..26ef688398d5 --- /dev/null +++ b/src/layer/shrink.h @@ -0,0 +1,37 @@ +// Tencent is pleased to support the open source community by making ncnn available. +// +// Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// https://opensource.org/licenses/BSD-3-Clause +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef LAYER_SHRINK_H +#define LAYER_SHRINK_H + +#include "layer.h" + +namespace ncnn { + +class Shrink : public Layer +{ +public: + Shrink(); + + virtual int load_param(const ParamDict& pd); + virtual int forward_inplace(Mat& bottom_top_blob, const Option& opt) const; + +public: + float bias; + float lambd; +}; + +} // namespace ncnn + +#endif // LAYER_SHRINK_H diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 21de08c6ff35..bef56d44a585 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -143,6 +143,7 @@ ncnn_add_layer_test(ROIPooling) ncnn_add_layer_test(ROIAlign) ncnn_add_layer_test(Scale) ncnn_add_layer_test(SELU) +ncnn_add_layer_test(Shrink) ncnn_add_layer_test(ShuffleChannel) ncnn_add_layer_test(Sigmoid) ncnn_add_layer_test(Slice) diff --git a/tests/test_shrink.cpp b/tests/test_shrink.cpp new file mode 100644 index 000000000000..2eef8dd0976c --- /dev/null +++ b/tests/test_shrink.cpp @@ -0,0 +1,76 @@ +// Tencent is pleased to support the open source community by making ncnn available. +// +// Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// https://opensource.org/licenses/BSD-3-Clause +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "layer/shrink.h" +#include "testutil.h" + +static int test_shrink(const ncnn::Mat& a, float lambd, float bias) +{ + ncnn::ParamDict pd; + pd.set(0, bias); + pd.set(1, lambd); + + std::vector weights(0); + + int ret = test_layer("Shrink", pd, weights, a); + if (ret != 0) + { + fprintf(stderr, "test_shrink failed a.dims=%d a=(%d %d %d %d)\n", a.dims, a.w, a.h, a.d, a.c); + } + + return ret; +} + +static int test_shrink_0() +{ + return 0 + || test_shrink(RandomMat(12, 24, 8, 3), 0.5f, 5.0f) + || test_shrink(RandomMat(9, 7, 16, 4), 1.0f, 0.3f) + || test_shrink(RandomMat(6, 9, 4, 3), 4.5, 6.1); +} + +static int test_shrink_1() +{ + return 0 + || test_shrink(RandomMat(12, 6, 24), 0.5f, 5.0f) + || test_shrink(RandomMat(7, 8, 24), 1.0f, 0.3f) + || test_shrink(RandomMat(3, 4, 5), 4.5, 6.1); +} + +static int test_shrink_2() +{ + return 0 + || test_shrink(RandomMat(5, 7), 3.4f, 0.3f) + || test_shrink(RandomMat(7, 9), 3.1f, 4.0f) + || test_shrink(RandomMat(3, 5), 2.0f, 4.0f); +} + +static int test_shrink_3() +{ + return 0 + || test_shrink(RandomMat(25), 3.4f, 0.3f) + || test_shrink(RandomMat(63), 3.1f, 4.0f) + || test_shrink(RandomMat(1024), 2.0f, 4.0f); +} + +int main() +{ + SRAND(7767517); + + return 0 + || test_shrink_0() + || test_shrink_1() + || test_shrink_2() + || test_shrink_3(); +} diff --git a/tools/onnx/onnx2ncnn.cpp b/tools/onnx/onnx2ncnn.cpp index 137ecf7bf95a..e443a28edf14 100644 --- a/tools/onnx/onnx2ncnn.cpp +++ b/tools/onnx/onnx2ncnn.cpp @@ -3894,6 +3894,10 @@ int main(int argc, char** argv) { fprintf(pp, "%-16s", "BinaryOp"); } + else if (op == "Shrink") + { + fprintf(pp, "%-16s", "Shrink"); + } else if (op == "ShuffleChannel") { fprintf(pp, "%-16s", "ShuffleChannel"); @@ -5746,6 +5750,13 @@ int main(int argc, char** argv) fprintf(pp, " 2=%e", b); } } + else if (op == "Shrink") + { + float bias = get_node_attr_f(node, "bias", 0.0f); + float lambd = get_node_attr_f(node, "lambd", 0.5f); + fprintf(pp, " 0=%e", bias); + fprintf(pp, " 1=%e", lambd); + } else if (op == "ShuffleChannel") { int group = get_node_attr_i(node, "group", 1);