diff --git a/inference-engine/src/gna_plugin/gna_plugin.cpp b/inference-engine/src/gna_plugin/gna_plugin.cpp index fde061f91b7..83c2c0dbaea 100644 --- a/inference-engine/src/gna_plugin/gna_plugin.cpp +++ b/inference-engine/src/gna_plugin/gna_plugin.cpp @@ -70,6 +70,7 @@ #include "transformations/op_conversions/lstm_cell_decomposition.hpp" #include "transformations/remove_single_input_concat.hpp" #include "transformations/broadcast_const.hpp" +#include "transformations/substitute_softsign.hpp" #include @@ -713,6 +714,7 @@ void GNAPlugin::LoadNetwork(CNNNetwork & _network) { manager.register_pass(); manager.register_pass(); manager.register_pass(); + manager.register_pass(); manager.register_pass(); manager.register_pass(); manager.register_pass(); @@ -781,6 +783,9 @@ void GNAPlugin::LoadNetwork(CNNNetwork & _network) { passes->registerPass(); } + if (fake_quantized) + passes->registerPass(); + // fake quantisation aware passes passes->registerPass(); passes->registerPass(); @@ -788,7 +793,6 @@ void GNAPlugin::LoadNetwork(CNNNetwork & _network) { passes->registerPass(); passes->registerPass(); - passes->registerPass(); passes->registerPass(); passes->registerPass(); diff --git a/inference-engine/src/gna_plugin/ops/softsign.cpp b/inference-engine/src/gna_plugin/ops/softsign.cpp new file mode 100644 index 00000000000..eb10bffea27 --- /dev/null +++ b/inference-engine/src/gna_plugin/ops/softsign.cpp @@ -0,0 +1,79 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "softsign.hpp" + +#include + +#include "ngraph/attribute_visitor.hpp" +#include "ngraph/runtime/host_tensor.hpp" + +#include +#include + +NGRAPH_RTTI_DEFINITION(GNAPluginNS::SoftSign, "SoftSign", 0); + +namespace GNAPluginNS { + +template +void softsign(const T* arg, T* out, size_t count) { + for (size_t i = 0; i < count; i++) { + out[i] = 1 / (1 + std::abs(arg[i])); + } +} + +SoftSign::SoftSign(const ngraph::Output& arg) : ov::op::util::UnaryElementwiseArithmetic(arg) { + constructor_validate_and_infer_types(); +} + +std::shared_ptr SoftSign::clone_with_new_inputs(const ngraph::OutputVector& new_args) const { + check_new_args_count(this, new_args); + return std::make_shared(new_args.at(0)); +} + +template +inline bool evaluate(const ov::runtime::Tensor& arg, ov::runtime::Tensor& out, const size_t count) { + using T = typename ngraph::element_type_traits::value_type; + softsign(arg.data(), out.data(), count); + return true; +} + +namespace { +bool evaluate_softsign(const ov::runtime::Tensor& arg, ov::runtime::Tensor& out) { + bool rc = true; + size_t count = shape_size(arg.get_shape()); + + switch (arg.get_element_type()) { + case ov::element::Type_t::f16: + rc = evaluate(arg, out, count); + break; + case ov::element::Type_t::f32: + rc = evaluate(arg, out, count); + break; + default: + rc = false; + break; + } + return rc; +} +} // namespace + +bool SoftSign::evaluate(ov::runtime::TensorVector& outputs, + const ov::runtime::TensorVector& inputs, + const ov::EvaluationContext& evaluation_context) const { + return evaluate_softsign(inputs[0], outputs[0]); +} + +bool SoftSign::has_evaluate() const { + switch (get_input_element_type(0)) { + case ngraph::element::f16: + case ngraph::element::f32: + return true; + default: + break; + } + return false; +} + +} // namespace GNAPluginNS diff --git a/inference-engine/src/gna_plugin/ops/softsign.hpp b/inference-engine/src/gna_plugin/ops/softsign.hpp new file mode 100644 index 00000000000..ffbcbc9dbb9 --- /dev/null +++ b/inference-engine/src/gna_plugin/ops/softsign.hpp @@ -0,0 +1,30 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "openvino/op/op.hpp" +#include "ngraph/node.hpp" +#include "openvino/op/util/unary_elementwise_arithmetic.hpp" + +namespace GNAPluginNS { +/// \brief Neural Activation Function +/// f(x) = x/(1.0 + |x|) +/// +class SoftSign : public ov::op::util::UnaryElementwiseArithmetic { +public: + NGRAPH_RTTI_DECLARATION; + + SoftSign() = default; + /// \brief Constructs an SoftSign operation. + /// + /// \param data Input tensor + SoftSign(const ngraph::Output& arg); + std::shared_ptr clone_with_new_inputs(const ngraph::OutputVector& new_args) const override; + bool evaluate(ov::runtime::TensorVector& output_values, + const ov::runtime::TensorVector& input_values, + const ov::EvaluationContext & evaluation_context) const override; + bool has_evaluate() const override; +}; +} // namespace GNAPluginNS diff --git a/inference-engine/src/gna_plugin/transformations/substitute_softsign.cpp b/inference-engine/src/gna_plugin/transformations/substitute_softsign.cpp new file mode 100644 index 00000000000..36329ed7c34 --- /dev/null +++ b/inference-engine/src/gna_plugin/transformations/substitute_softsign.cpp @@ -0,0 +1,89 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "transformations/substitute_softsign.hpp" + +#include "transformations/utils/transformation_helper.hpp" +#include "transformations/utils/utils.hpp" + +#include +#include +#include +#include +#include + +using namespace GNAPluginNS; + +NGRAPH_RTTI_DEFINITION(SubstituteSoftsign, "SubstituteSoftsign", 0); + +using Node = std::shared_ptr; + +namespace { + +void DoTransformation(Node start_node, Node last_node) { + auto activation = std::make_shared(start_node); + activation->set_friendly_name(last_node->get_friendly_name()); + ngraph::copy_runtime_info(last_node, activation); + ngraph::replace_node(last_node, activation); +} + +class IsConstValueAcceptable { +public: + IsConstValueAcceptable(double expected_value) : + m_expected_value(expected_value) {} + + bool operator()(const ngraph::Output& output) const { + auto node = std::dynamic_pointer_cast(output.get_node_shared_ptr()); + if (!node) + return false; + + float value; + if (!ngraph::op::util::get_single_value(node, value)) { + return false; + } + + return (value == m_expected_value); + } + +private: + const double m_expected_value; +}; + +} // namespace + +SubstituteSoftsign::SubstituteSoftsign() { + MATCHER_SCOPE(SubstituteSoftsign); + + auto root = ngraph::pattern::any_input(); + auto abs = ngraph::pattern::wrap_type({root}); + + auto add_const = ngraph::pattern::wrap_type(IsConstValueAcceptable(1.0)); + auto add = ngraph::pattern::wrap_type({abs, add_const}); + + auto power_const = ngraph::pattern::wrap_type(IsConstValueAcceptable(-1.0)); + auto power = ngraph::pattern::wrap_type({add, power_const}); + + auto multiply = ngraph::pattern::wrap_type({root, power}); + auto divide = ngraph::pattern::wrap_type({root, add}); + auto last = std::make_shared(ngraph::OutputVector{multiply, divide}); + + ngraph::matcher_pass_callback callback = [=](ngraph::pattern::Matcher& m) { + const auto& pattern_map = m.get_pattern_value_map(); + auto root_node = pattern_map.at(root).get_node_shared_ptr(); + + auto last_node_it = pattern_map.find(multiply); + if (last_node_it == pattern_map.end()) + last_node_it = pattern_map.find(divide); + auto last_node = last_node_it->second.get_node_shared_ptr(); + + DoTransformation(root_node, last_node); + + return true; + }; + + auto m = std::make_shared(last, matcher_name); + this->register_matcher(m, callback); +} diff --git a/inference-engine/src/gna_plugin/transformations/substitute_softsign.hpp b/inference-engine/src/gna_plugin/transformations/substitute_softsign.hpp new file mode 100644 index 00000000000..fe11241c04f --- /dev/null +++ b/inference-engine/src/gna_plugin/transformations/substitute_softsign.hpp @@ -0,0 +1,45 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include + +namespace GNAPluginNS { + +/** + * @brief Current version of ModelOptimizer substitutes SoftSign activation + * function with next subgraph + * a layer + * | \ + * abs \ + * | | + * add | + * | | + * power | + * \ / + * Divide + * + * See model-optimizer/extensions/front/softsign_replacer.py + * + * The ConvertDivide transformation from CommonOptimizations + * substitutes Divide with {-1} and add constant {1} + * - GNA supports Power [0, 2.8] + * - Add, Power, Divide layers are more perfomance expensive in GNA + * than SoftSign PWL + * + * Legacy SubstituteSoftSignPass supports irv7 model where SoftSign subgraph + * could have been without add layer. Current ModelOptimezer always generates + * SoftSign subgraph with that layer. + * + * SubstituteSoftsign transformation does backward substitution to SoftSign. + * TODO: remove that pass as soon as ModelOptimizer will not substitute SoftSign activation + */ +class SubstituteSoftsign : public ngraph::pass::MatcherPass { +public: + NGRAPH_RTTI_DECLARATION; + SubstituteSoftsign(); +}; + +} // namespace GNAPluginNS diff --git a/inference-engine/tests/unit/gna/CMakeLists.txt b/inference-engine/tests/unit/gna/CMakeLists.txt index 76a2a1ac94f..64af7e40ecd 100644 --- a/inference-engine/tests/unit/gna/CMakeLists.txt +++ b/inference-engine/tests/unit/gna/CMakeLists.txt @@ -13,6 +13,7 @@ addIeTargetTest( gmock commonTestUtils_s GNAPlugin_test_static + engines_test_util ADD_CPPLINT LABELS GNA diff --git a/inference-engine/tests/unit/gna/ngraph/op_eval/softsign.cpp b/inference-engine/tests/unit/gna/ngraph/op_eval/softsign.cpp new file mode 100644 index 00000000000..4df575cbb34 --- /dev/null +++ b/inference-engine/tests/unit/gna/ngraph/op_eval/softsign.cpp @@ -0,0 +1,40 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "ops/softsign.hpp" + +#include +#include + +#include "execute_tools.hpp" +#include "gtest/gtest.h" +#include "ngraph/runtime/host_tensor.hpp" +#include "ngraph/validation_util.hpp" +#include "ngraph/opsets/opset8.hpp" + +using namespace GNAPluginNS; + +TEST(op_eval, softsign) { + auto p = std::make_shared(ngraph::element::f32, ngraph::Shape{4}); + auto softsign = std::make_shared(p); + auto fun = std::make_shared(ngraph::OutputVector{softsign}, ngraph::ParameterVector{p}); + + float inputs[] = {-1.0, 0.0, 1.0, 20.0}; + std::vector expected_result{0.5, 1.0, 0.5, 0.047619}; + + ov::runtime::TensorVector result(1); + ov::runtime::Tensor input{ov::element::f32, ov::Shape{4}, inputs}; + + ASSERT_TRUE(fun->evaluate(result, ov::runtime::TensorVector{input})); + + EXPECT_EQ(result.size(), 1); + EXPECT_EQ(result[0].get_element_type(), ngraph::element::f32); + EXPECT_EQ(result[0].get_shape(), ngraph::Shape{4}); + EXPECT_EQ(result[0].get_size(), 4); + + const float * result_data = result[0].data(); + for (size_t i = 0; i < result[0].get_size(); ++i) + EXPECT_NEAR(result_data[i], expected_result[i], 0.000001); +} + diff --git a/inference-engine/tests/unit/gna/ngraph/transformations/gna_substitute_softsign.cpp b/inference-engine/tests/unit/gna/ngraph/transformations/gna_substitute_softsign.cpp new file mode 100644 index 00000000000..8df3db75000 --- /dev/null +++ b/inference-engine/tests/unit/gna/ngraph/transformations/gna_substitute_softsign.cpp @@ -0,0 +1,167 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "transformations/substitute_softsign.hpp" + +#include "common_test_utils/ngraph_test_utils.hpp" +#include +#include +#include +#include +#include + +namespace testing { + +namespace { + +std::shared_ptr createSoftSignFunction() { + auto input_params = std::make_shared(ngraph::element::f32, + ngraph::Shape{ 1, 1, 1, 64 }); + + auto softsign = std::make_shared(input_params); + + ngraph::ResultVector results{ std::make_shared(softsign) }; + + return std::make_shared(ngraph::ResultVector{results}, + ngraph::ParameterVector{input_params}); +} + +} // namespace + +TEST(TransformationTests, SubstituteSoftSignMulPower) { + std::shared_ptr func(nullptr), reference_func(nullptr); + + { + auto input_params = std::make_shared(ngraph::element::f32, + ngraph::Shape{ 1, 1, 1, 64 }); + + auto abs = std::make_shared(input_params); + + auto const_1 = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {1}); + auto const_neg_1 = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {-1}); + + auto add = std::make_shared(abs, const_1); + auto power = std::make_shared(add, const_neg_1); + + auto mul = std::make_shared(power, input_params); + ngraph::ResultVector results{ std::make_shared(mul) }; + + func = std::make_shared(ngraph::ResultVector{results}, + ngraph::ParameterVector{input_params}); + ngraph::pass::Manager m; + m.register_pass(); + m.register_pass(); + m.run_passes(func); + ASSERT_NO_THROW(check_rt_info(func)); + } + + reference_func = createSoftSignFunction(); + + const FunctionsComparator func_comparator = FunctionsComparator::with_default().enable(FunctionsComparator::ATTRIBUTES); + const FunctionsComparator::Result result = func_comparator(func, reference_func); + ASSERT_TRUE(result.valid); +} + +TEST(TransformationTests, SubstituteSoftSignDivide) { + std::shared_ptr func(nullptr), reference_func(nullptr); + + { + auto input_params = std::make_shared(ngraph::element::f32, + ngraph::Shape{ 1, 1, 1, 64 }); + + auto abs = std::make_shared(input_params); + + auto const_1 = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {1}); + auto add = std::make_shared(abs, const_1); + + auto divide = std::make_shared(input_params, add); + ngraph::ResultVector results{ std::make_shared(divide) }; + + func = std::make_shared(ngraph::ResultVector{results}, + ngraph::ParameterVector{input_params}); + ngraph::pass::Manager m; + m.register_pass(); + m.register_pass(); + m.run_passes(func); + ASSERT_NO_THROW(check_rt_info(func)); + } + + reference_func = createSoftSignFunction(); + + const FunctionsComparator func_comparator = FunctionsComparator::with_default().enable(FunctionsComparator::ATTRIBUTES); + const FunctionsComparator::Result result = func_comparator(func, reference_func); + ASSERT_TRUE(result.valid); +} + +TEST(TransformationTests, SubstituteSoftSignMulPowerInvalidAddConst) { + std::shared_ptr func(nullptr), reference_func(nullptr); + + { + auto input_params = std::make_shared(ngraph::element::f32, + ngraph::Shape{ 1, 1, 1, 64 }); + + auto abs = std::make_shared(input_params); + + auto const_1 = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {1.1}); + auto const_neg_1 = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {-1}); + + auto add = std::make_shared(abs, const_1); + auto power = std::make_shared(add, const_neg_1); + + auto mul = std::make_shared(power, input_params); + ngraph::ResultVector results{ std::make_shared(mul) }; + + func = std::make_shared(ngraph::ResultVector{results}, + ngraph::ParameterVector{input_params}); + ngraph::pass::Manager m; + m.register_pass(); + m.register_pass(); + m.run_passes(func); + ASSERT_NO_THROW(check_rt_info(func)); + } + + reference_func = ngraph::clone_function(*func); + + const FunctionsComparator func_comparator = FunctionsComparator::with_default().enable(FunctionsComparator::ATTRIBUTES); + const FunctionsComparator::Result result = func_comparator(func, reference_func); + ASSERT_TRUE(result.valid); +} + +TEST(TransformationTests, SubstituteSoftSignMulPowerInvalidPowerConst) { + std::shared_ptr func(nullptr), reference_func(nullptr); + + { + auto input_params = std::make_shared(ngraph::element::f32, + ngraph::Shape{ 1, 1, 1, 64 }); + + auto abs = std::make_shared(input_params); + + auto const_1 = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {1}); + auto const_neg_1 = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {-1.1}); + + auto add = std::make_shared(abs, const_1); + auto power = std::make_shared(add, const_neg_1); + + auto mul = std::make_shared(power, input_params); + ngraph::ResultVector results{ std::make_shared(mul) }; + + func = std::make_shared(ngraph::ResultVector{results}, + ngraph::ParameterVector{input_params}); + ngraph::pass::Manager m; + m.register_pass(); + m.register_pass(); + m.run_passes(func); + ASSERT_NO_THROW(check_rt_info(func)); + } + + reference_func = ngraph::clone_function(*func); + + const FunctionsComparator func_comparator = FunctionsComparator::with_default().enable(FunctionsComparator::ATTRIBUTES); + const FunctionsComparator::Result result = func_comparator(func, reference_func); + ASSERT_TRUE(result.valid); +} + +} // namespace testing diff --git a/inference-engine/tests_deprecated/unit/engines/gna/i16_quantisation_test.cpp b/inference-engine/tests_deprecated/unit/engines/gna/i16_quantisation_test.cpp index 36c201d60f9..b8f32671fe9 100644 --- a/inference-engine/tests_deprecated/unit/engines/gna/i16_quantisation_test.cpp +++ b/inference-engine/tests_deprecated/unit/engines/gna/i16_quantisation_test.cpp @@ -218,12 +218,6 @@ TEST_F(I16QuantisationTest, canDetectLeakyRelu) { .gna().propagate_forward().called_with().pwl_inserted_into_nnet(); } -TEST_F(I16QuantisationTest, canDetectSoftWSignSubgraph) { - assert_that().onInferModel(TFSoftsignUnfoldedModel()) - .inNotCompactMode().withGNAConfig(GNA_CONFIG_KEY(SCALE_FACTOR), 1.0f) - .gna().propagate_forward().called_with().pwls_inserted_into_nnet({kActSigmoid}); -} - TEST_F(I16QuantisationTest, MaxPool_followedAfterActivation) { assert_that().onInferModel(maxpoolAfterRelu()) .inNotCompactMode().withGNAConfig(GNA_CONFIG_KEY(SCALE_FACTOR), 1.0f) diff --git a/inference-engine/tests_deprecated/unit/engines/gna/layers/activation_test.cpp b/inference-engine/tests_deprecated/unit/engines/gna/layers/activation_test.cpp deleted file mode 100644 index 0d768f823a1..00000000000 --- a/inference-engine/tests_deprecated/unit/engines/gna/layers/activation_test.cpp +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include -#include -#include -#include -#include -#include -#include -#include "../gna_matcher.hpp" - -typedef struct { - std::string activationType; - size_t input_shape; - std::pair range; -} ActivationCaseParam; - -using ActivationCaseParam2 = std::tuple; - -class GNAActivationTest : public GNATest<>, - public testing::WithParamInterface { - public: - - static std::string getTestName(const testing::TestParamInfo& params) { - std::string test_name = std::string(std::get<0>(params.param).name()) + "_"; - test_name += std::get<1>(params.param).activationType + "_"; - test_name += std::to_string(std::get<1>(params.param).input_shape) + "_"; - test_name += std::to_string(std::get<1>(params.param).range.first) + "_"; - test_name += std::to_string(std::get<1>(params.param).range.second); - return test_name; - } - - std::shared_ptr buildNgraphFunction(const ActivationCaseParam& param) { - - auto shape = ngraph::Shape{1, param.input_shape}; - auto inputN = std::make_shared(ngraph::element::f32, shape); - - auto absN = std::make_shared(inputN); - - auto powerN = std::make_shared(absN, -1, 1, 1.0); - - auto eltwiseN = std::make_shared(powerN, inputN); - - auto function = std::make_shared(ngraph::NodeVector{eltwiseN}, ngraph::ParameterVector{inputN}); - return function; - } -}; - -TEST_P(GNAActivationTest, ActivationTest) { - const auto precision = std::get<0>(GetParam()); - const auto param = std::get<1>(GetParam()); - - if (precision == InferenceEngine::Precision::FP32) { - auto input_data = generate_random_1d(param.input_shape, param.range.first, param.range.second); - std::vector expected_result(param.input_shape); - - - for (std::size_t i = 0; i < expected_result.size(); i++) { - auto & x = input_data[i]; - if (param.activationType == "softsign") { - expected_result[i] = x / (1 + fabs(x)); - } else { - FAIL() << "Unsupported activation type: " << param.activationType; - } - } - - assert_that().onInferNgraphModel(buildNgraphFunction(param)) - .inNotCompactMode() - .gna() - .propagate_forward() - .onCPU() - .called_with_input(input_data) - .equals_to(expected_result); - } else { - assert_that().onInferNgraphModel(buildNgraphFunction(param)) - .inNotCompactMode() - .gna() - .withGNAConfig(GNA_CONFIG_KEY(SCALE_FACTOR), 1.0f) - .withGNAConfig(GNA_CONFIG_KEY(PRECISION), precision.name()) - .propagate_forward() - .called_with().pwls_inserted_into_nnet({kActSigmoid}); - } -} - -static const ActivationCaseParam gna_activation_test_params[] = { - {"softsign", 200, {-10, 10}}, -}; - -INSTANTIATE_TEST_SUITE_P( - GNALayerTests, GNAActivationTest, - ::testing::Combine( - ::testing::Values(InferenceEngine::Precision::FP32, InferenceEngine::Precision::I16, InferenceEngine::Precision::I8), - ::testing::ValuesIn(gna_activation_test_params)), - GNAActivationTest::getTestName); diff --git a/inference-engine/tests_deprecated/unit/engines/gna/test_irs.cpp b/inference-engine/tests_deprecated/unit/engines/gna/test_irs.cpp index bd41ec0118b..8d20b04311f 100644 --- a/inference-engine/tests_deprecated/unit/engines/gna/test_irs.cpp +++ b/inference-engine/tests_deprecated/unit/engines/gna/test_irs.cpp @@ -2164,146 +2164,6 @@ std::string TFLeakyReluModel() { )V0G0N"; } -std::string TFSoftsignUnfoldedModel() { - return R"V0G0N( - - - - - - - 1 - 64 - - - - - - - 1 - - - - - - - - - - 1 - 64 - - - 1 - - - - - 1 - 1 - 64 - - - - - - - 1 - 1 - 64 - - - - - 1 - 1 - 64 - - - - - - - - 1 - 1 - 64 - - - - - 1 - 1 - 64 - - - - - - - - 1 - 1 - 64 - - - 1 - 1 - 64 - - - - - 1 - 1 - 64 - - - - - - - 1 - - - - - - - - - - 1 - 1 - 64 - - - 1 - - - - - 1 - 64 - - - - - - - - - - - - - - - - - )V0G0N"; -} - std::string maxpoolAfterRelu() { return R"V0G0N( diff --git a/inference-engine/tests_deprecated/unit/engines/gna/test_irs.hpp b/inference-engine/tests_deprecated/unit/engines/gna/test_irs.hpp index 929cc644fc4..745c4dd4262 100644 --- a/inference-engine/tests_deprecated/unit/engines/gna/test_irs.hpp +++ b/inference-engine/tests_deprecated/unit/engines/gna/test_irs.hpp @@ -39,7 +39,6 @@ std::string ClampActivationModel(); std::string IdentityActivationModel(); std::string maxpoolAfterRelu(); std::string TFLeakyReluModel(); -std::string TFSoftsignUnfoldedModel(); std::string cropWithoutOffsetModel(); std::string cropWithAlignedOffsetModel(); std::string cropWithOffsetModel();