ReorgYolo reference implementation (#2384)

* Align ReorgYolo to the spec (vector strides -> int stride)

* ReorgYolo ref impl

* ReorgYolo evaluate method

* ReorgYolo tests

* Tests update

* Style apply

* Add some coments

* Code refactor

* Comment update

* Style apply

* Build fix, mark evaluate as override

* Revert "Align ReorgYolo to the spec (vector strides -> int stride)"

* Use int_executable instead of evaluate

* Use char* instead of templates

* Code refactor

* Comment update

* Code review comment

* Add constructor aligned with spec

* Update shape validation

* Update attributes tests

* Add type_prop tests

* Update backend tests

* Add single layer tests

* Update the spec

* Remove wrong transformation test
This commit is contained in:
Katarzyna Mitrus
2020-10-15 12:42:21 +02:00
committed by GitHub
parent 49e760381e
commit fadd16ce89
15 changed files with 540 additions and 41 deletions

View File

@@ -22,7 +22,7 @@
**Inputs**: **Inputs**:
* **1**: 4D input tensor of any type and shape `[N, C, H, W]`. `H` and `W` should be divisible by `stride`. Required. * **1**: 4D input tensor of any type and shape `[N, C, H, W]`. `H` and `W` should be divisible by `stride` and `C >= (stride*stride)`. **Required.**
**Outputs**: **Outputs**:
@@ -31,7 +31,7 @@
**Example** **Example**
```xml ```xml
<layer id="89" name="ExtractImagePatches" type="ReorgYolo"> <layer id="89" name="reorg" type="ReorgYolo">
<data stride="2"/> <data stride="2"/>
<input> <input>
<port id="0"> <port id="0">
@@ -50,4 +50,4 @@
</port> </port>
</output> </output>
</layer> </layer>
``` ```

View File

@@ -19,38 +19,7 @@
using namespace testing; using namespace testing;
TEST(TransformationTests, ConvertExtractImagePatchesToReorgYoloTests1) { // TODO: bug 39971, remove ConvertExtractImagePatchesToReorgYolo transformation
std::shared_ptr<ngraph::Function> f(nullptr), f_ref(nullptr);
{
auto input = std::make_shared<ngraph::opset1::Parameter>(ngraph::element::f32, ngraph::Shape{1, 3, 10, 10});
auto sizes = ngraph::Shape{5, 5};
auto strides = ngraph::Strides{5, 5};
auto rates = ngraph::Shape{1, 1};
ngraph::op::PadType auto_pad = ngraph::op::PadType::VALID;
auto eip = std::make_shared<ngraph::opset3::ExtractImagePatches>(input, sizes, strides, rates, auto_pad);
f = std::make_shared<ngraph::Function>(ngraph::NodeVector{eip}, ngraph::ParameterVector{input});
ngraph::pass::Manager manager;
manager.register_pass<ngraph::pass::InitNodeInfo>();
manager.register_pass<ngraph::pass::ConvertExtractImagePatchesToReorgYolo>();
manager.run_passes(f);
ASSERT_NO_THROW(check_rt_info(f));
}
{
auto input = std::make_shared<ngraph::opset1::Parameter>(ngraph::element::f32, ngraph::Shape{1, 3, 10, 10});
auto strides = ngraph::Strides{5, 5};
auto reorg_yolo = std::make_shared<ngraph::opset3::ReorgYolo>(input, strides);
f_ref = std::make_shared<ngraph::Function>(ngraph::NodeVector{reorg_yolo}, ngraph::ParameterVector{input});
}
auto res = compare_functions(f, f_ref);
ASSERT_TRUE(res.first) << res.second;
}
TEST(TransformationTests, ConvertExtractImagePatchesToReorgYoloTestsNegative1) { TEST(TransformationTests, ConvertExtractImagePatchesToReorgYoloTestsNegative1) {
std::shared_ptr<ngraph::Function> f(nullptr), f_ref(nullptr); std::shared_ptr<ngraph::Function> f(nullptr), f_ref(nullptr);

View File

@@ -0,0 +1,75 @@
// Copyright (C) 2020 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <vector>
#include "single_layer_tests/reorg_yolo.hpp"
#include "common_test_utils/test_constants.hpp"
using namespace LayerTestsDefinitions;
const std::vector<ngraph::Shape> inShapes_caffe_yolov2 = {
{1, 64, 26, 26},
};
const std::vector<ngraph::Shape> inShapes = {
{1, 4, 4, 4},
{1, 8, 4, 4},
{1, 9, 3, 3},
{1, 24, 34, 62},
{2, 8, 4, 4},
};
const std::vector<size_t> strides = {
2, 3
};
const auto testCase_caffe_yolov2 = ::testing::Combine(
::testing::ValuesIn(inShapes_caffe_yolov2),
::testing::Values(strides[0]),
::testing::Values(InferenceEngine::Precision::FP32),
::testing::Values(CommonTestUtils::DEVICE_CPU)
);
const auto testCase_smallest = ::testing::Combine(
::testing::Values(inShapes[0]),
::testing::Values(strides[0]),
::testing::Values(InferenceEngine::Precision::FP32),
::testing::Values(CommonTestUtils::DEVICE_CPU)
);
const auto testCase_stride_2 = ::testing::Combine(
::testing::Values(inShapes[1]),
::testing::Values(strides[0]),
::testing::Values(InferenceEngine::Precision::FP32),
::testing::Values(CommonTestUtils::DEVICE_CPU)
);
const auto testCase_stride_3 = ::testing::Combine(
::testing::Values(inShapes[2]),
::testing::Values(strides[1]),
::testing::Values(InferenceEngine::Precision::FP32),
::testing::Values(CommonTestUtils::DEVICE_CPU)
);
const auto testCase_smaller_h = ::testing::Combine(
::testing::Values(inShapes[4]),
::testing::Values(strides[0]),
::testing::Values(InferenceEngine::Precision::FP32),
::testing::Values(CommonTestUtils::DEVICE_CPU)
);
const auto testCase_batch_2 = ::testing::Combine(
::testing::Values(inShapes[3]),
::testing::Values(strides[0]),
::testing::Values(InferenceEngine::Precision::FP32),
::testing::Values(CommonTestUtils::DEVICE_CPU)
);
INSTANTIATE_TEST_CASE_P(smoke_TestsReorgYolo_caffe_YoloV2, ReorgYoloLayerTest, testCase_caffe_yolov2, ReorgYoloLayerTest::getTestCaseName);
INSTANTIATE_TEST_CASE_P(smoke_TestsReorgYolo_stride_2_smallest, ReorgYoloLayerTest, testCase_smallest, ReorgYoloLayerTest::getTestCaseName);
INSTANTIATE_TEST_CASE_P(smoke_TestsReorgYolo_stride_2, ReorgYoloLayerTest, testCase_stride_2, ReorgYoloLayerTest::getTestCaseName);
INSTANTIATE_TEST_CASE_P(smoke_TestsReorgYolo_stride_3, ReorgYoloLayerTest, testCase_stride_3, ReorgYoloLayerTest::getTestCaseName);
INSTANTIATE_TEST_CASE_P(smoke_TestsReorgYolo_smaller_h, ReorgYoloLayerTest, testCase_smaller_h, ReorgYoloLayerTest::getTestCaseName);
INSTANTIATE_TEST_CASE_P(smoke_TestsReorgYolo_batch_2, ReorgYoloLayerTest, testCase_batch_2, ReorgYoloLayerTest::getTestCaseName);

View File

@@ -0,0 +1,32 @@
// Copyright (C) 2019 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <tuple>
#include <string>
#include <vector>
#include "functional_test_utils/layer_test_utils.hpp"
#include "ngraph_functions/builders.hpp"
#include "ngraph_functions/utils/ngraph_helpers.hpp"
namespace LayerTestsDefinitions {
using ReorgYoloParamsTuple = typename std::tuple<
ngraph::Shape, // Input Shape
size_t, // stride
InferenceEngine::Precision, // Network precision
std::string>; // Device name
class ReorgYoloLayerTest : public testing::WithParamInterface<ReorgYoloParamsTuple>,
virtual public LayerTestsUtils::LayerTestsCommon {
public:
static std::string getTestCaseName(const testing::TestParamInfo<ReorgYoloParamsTuple> &obj);
protected:
void SetUp() override;
};
} // namespace LayerTestsDefinitions

View File

@@ -0,0 +1,46 @@
// Copyright (C) 2020 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "ie_core.hpp"
#include "common_test_utils/common_utils.hpp"
#include "functional_test_utils/blob_utils.hpp"
#include "functional_test_utils/precision_utils.hpp"
#include "functional_test_utils/plugin_cache.hpp"
#include "functional_test_utils/skip_tests_config.hpp"
#include "single_layer_tests/reorg_yolo.hpp"
namespace LayerTestsDefinitions {
std::string ReorgYoloLayerTest::getTestCaseName(const testing::TestParamInfo<ReorgYoloParamsTuple> &obj) {
ngraph::Shape inputShape;
size_t stride;
InferenceEngine::Precision netPrecision;
std::string targetName;
std::tie(inputShape, stride, netPrecision, targetName) = obj.param;
std::ostringstream result;
result << "IS=" << inputShape << "_";
result << "stride=" << stride << "_";
result << "netPRC=" << netPrecision.name() << "_";
result << "targetDevice=" << targetName << "_";
return result.str();
}
void ReorgYoloLayerTest::SetUp() {
ngraph::Shape inputShape;
size_t stride;
InferenceEngine::Precision netPrecision;
std::tie(inputShape, stride, netPrecision, targetDevice) = this->GetParam();
auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision);
auto param = std::make_shared<ngraph::op::Parameter>(ngraph::element::f32, inputShape);
auto reorg_yolo = std::make_shared<ngraph::op::v0::ReorgYolo>(param, stride);
function = std::make_shared<ngraph::Function>(std::make_shared<ngraph::opset1::Result>(reorg_yolo), ngraph::ParameterVector{param}, "ReorgYolo");
}
TEST_P(ReorgYoloLayerTest, CompareWithRefs) {
Run();
};
} // namespace LayerTestsDefinitions

View File

@@ -33,7 +33,10 @@ namespace ngraph
/// \brief Constructs a ReorgYolo operation /// \brief Constructs a ReorgYolo operation
/// ///
/// \param input Input /// \param input Input
/// \param strides Stride to reorganize input by /// \param stride Stride to reorganize input by
ReorgYolo(const Output<Node>& input, const size_t stride);
// Constructor with `strides` for backward compatibility
ReorgYolo(const Output<Node>& input, const Strides& strides); ReorgYolo(const Output<Node>& input, const Strides& strides);
void validate_and_infer_types() override; void validate_and_infer_types() override;

View File

@@ -0,0 +1,37 @@
//*****************************************************************************
// Copyright 2017-2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// 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.
//*****************************************************************************
#pragma once
#include <cmath>
#include <cstddef>
#include "ngraph/shape.hpp"
namespace ngraph
{
namespace runtime
{
namespace reference
{
void reorg_yolo(const char* arg,
char* out,
const Shape& in_shape,
int64_t stride,
const size_t elem_size);
}
}
}

View File

@@ -0,0 +1,89 @@
//*****************************************************************************
// Copyright 2017-2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// 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 <cmath>
#include <stdio.h>
#include "ngraph/runtime/reference/reorg_yolo.hpp"
#include "ngraph/shape.hpp"
using namespace ngraph;
namespace ngraph
{
namespace runtime
{
namespace reference
{
void reorg_yolo(const char* arg,
char* out,
const Shape& in_shape,
int64_t stride,
const size_t elem_size)
{
// [N, C, H, W]
size_t in_N = in_shape[0];
size_t in_C = in_shape[1];
size_t in_H = in_shape[2];
size_t in_W = in_shape[3];
// Inference output shape logic:
// in_shape [N,C,H,W] -> out_shape [N, C*(stride*stride), H/stride, W/stride]
// ReorgYolo implementation calculates new indices like for backprop:
// in_shape [N,C,H,W] -> out_shape [N, C/(stride*stride), H*stride, W*stride]
size_t impl_out_C = in_C / (stride * stride);
if (impl_out_C == 0)
{
throw ngraph_error(
"ReorgYolo. For [N, C, H, W] input shape, C >= (stride*stride) is "
"required.");
}
size_t impl_out_H = in_H * stride;
size_t impl_out_W = in_W * stride;
for (size_t n = 0; n < in_N; ++n)
{
for (size_t c = 0; c < in_C; ++c)
{
for (size_t h = 0; h < in_H; ++h)
{
for (size_t w = 0; w < in_W; ++w)
{
size_t offset = c / impl_out_C;
size_t impl_c = c % impl_out_C;
size_t impl_h = h * stride + offset / stride;
size_t impl_w = w * stride + offset % stride;
size_t arg_index =
((n * impl_out_C + impl_c) * impl_out_H + impl_h) * impl_out_W +
impl_w;
size_t dest_index = ((n * in_C + c) * in_H + h) * in_W + w;
arg_index *= elem_size;
dest_index *= elem_size;
std::copy(arg + arg_index,
arg + (arg_index + elem_size),
out + dest_index);
}
}
}
}
}
}
}
}

View File

@@ -15,6 +15,7 @@
//***************************************************************************** //*****************************************************************************
#include "ngraph/op/reorg_yolo.hpp" #include "ngraph/op/reorg_yolo.hpp"
#include "ngraph/runtime/reference/reorg_yolo.hpp"
using namespace std; using namespace std;
using namespace ngraph; using namespace ngraph;
@@ -28,14 +29,37 @@ op::ReorgYolo::ReorgYolo(const Output<Node>& input, const Strides& strides)
constructor_validate_and_infer_types(); constructor_validate_and_infer_types();
} }
op::ReorgYolo::ReorgYolo(const Output<Node>& input, const size_t stride)
: Op({input})
, m_strides(std::vector<size_t>{stride, stride})
{
constructor_validate_and_infer_types();
}
void op::ReorgYolo::validate_and_infer_types() void op::ReorgYolo::validate_and_infer_types()
{ {
NODE_VALIDATION_CHECK(this, !m_strides.empty(), "Stride attribute is required.");
auto input_et = get_input_element_type(0); auto input_et = get_input_element_type(0);
if (get_input_partial_shape(0).is_static()) if (get_input_partial_shape(0).is_static())
{ {
auto input_shape = get_input_partial_shape(0).to_shape(); auto input_shape = get_input_partial_shape(0).to_shape();
Shape output_shape{input_shape[0], input_shape[1]}; NODE_VALIDATION_CHECK(
this, input_shape.size() == 4, "[N, C, H, W] input shape is required.");
NODE_VALIDATION_CHECK(this,
(input_shape[2] % m_strides[0]) == 0,
"For [N, C, H, W] input shape, H should be divisible by stride.");
NODE_VALIDATION_CHECK(this,
(input_shape[3] % m_strides[0]) == 0,
"For [N, C, H, W] input shape, W should be divisible by stride.");
NODE_VALIDATION_CHECK(this,
input_shape[1] >= (m_strides[0] * m_strides[0]),
"For [N, C, H, W] input shape, C >= (stride*stride) is required.");
Shape output_shape{input_shape[0], input_shape[1]};
for (size_t i = 2; i < input_shape.size(); i++) for (size_t i = 2; i < input_shape.size(); i++)
{ {
output_shape.push_back(input_shape[i] / m_strides[0]); output_shape.push_back(input_shape[i] / m_strides[0]);

View File

@@ -157,6 +157,7 @@ set(SRC
type_prop/read_value.cpp type_prop/read_value.cpp
type_prop/reduce_l1.cpp type_prop/reduce_l1.cpp
type_prop/reduce_l2.cpp type_prop/reduce_l2.cpp
type_prop/reorg_yolo.cpp
type_prop/replace_slice.cpp type_prop/replace_slice.cpp
type_prop/reshape.cpp type_prop/reshape.cpp
type_prop/reverse.cpp type_prop/reverse.cpp
@@ -325,6 +326,7 @@ set(MULTI_TEST_SRC
backend/reduce_prod.in.cpp backend/reduce_prod.in.cpp
backend/reduce_sum.in.cpp backend/reduce_sum.in.cpp
backend/relu.in.cpp backend/relu.in.cpp
backend/reorg_yolo.in.cpp
backend/replace_slice.in.cpp backend/replace_slice.in.cpp
backend/reshape.in.cpp backend/reshape.in.cpp
backend/reverse_sequence.in.cpp backend/reverse_sequence.in.cpp

View File

@@ -1323,14 +1323,26 @@ TEST(attributes, mvn_op)
EXPECT_EQ(g_op->get_eps(), op->get_eps()); EXPECT_EQ(g_op->get_eps(), op->get_eps());
} }
TEST(attributes, reorg_yolo_op) TEST(attributes, reorg_yolo_op_stride)
{ {
FactoryRegistry<Node>::get().register_factory<opset3::ReorgYolo>(); FactoryRegistry<Node>::get().register_factory<opset3::ReorgYolo>();
const auto data = make_shared<op::Parameter>(element::i32, Shape{2, 3, 4, 5}); const auto data = make_shared<op::Parameter>(element::i32, Shape{1, 64, 26, 26});
const auto op = make_shared<opset3::ReorgYolo>(data, Strides{2}); const auto op = make_shared<op::v0::ReorgYolo>(data, 2);
NodeBuilder builder(op); NodeBuilder builder(op);
const auto g_op = as_type_ptr<opset3::ReorgYolo>(builder.create()); const auto g_op = as_type_ptr<op::v0::ReorgYolo>(builder.create());
EXPECT_EQ(g_op->get_strides(), op->get_strides());
}
TEST(attributes, reorg_yolo_op_strides)
{
FactoryRegistry<Node>::get().register_factory<opset3::ReorgYolo>();
const auto data = make_shared<op::Parameter>(element::i32, Shape{1, 64, 26, 26});
const auto op = make_shared<op::v0::ReorgYolo>(data, Strides{2});
NodeBuilder builder(op);
const auto g_op = as_type_ptr<op::v0::ReorgYolo>(builder.create());
EXPECT_EQ(g_op->get_strides(), op->get_strides()); EXPECT_EQ(g_op->get_strides(), op->get_strides());
} }

View File

@@ -0,0 +1,101 @@
//*****************************************************************************
// Copyright 2017-2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// 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 <algorithm>
#include <cinttypes>
#include <cmath>
#include <cstdlib>
#include <random>
#include <string>
// clang-format off
#ifdef ${BACKEND_NAME}_FLOAT_TOLERANCE_BITS
#define DEFAULT_FLOAT_TOLERANCE_BITS ${BACKEND_NAME}_FLOAT_TOLERANCE_BITS
#endif
#ifdef ${BACKEND_NAME}_DOUBLE_TOLERANCE_BITS
#define DEFAULT_DOUBLE_TOLERANCE_BITS ${BACKEND_NAME}_DOUBLE_TOLERANCE_BITS
#endif
// clang-format on
#include "gtest/gtest.h"
#include "ngraph/ngraph.hpp"
#include "util/engine/test_engines.hpp"
#include "util/test_case.hpp"
#include "util/test_control.hpp"
#include "util/type_prop.hpp"
using namespace std;
using namespace ngraph;
static string s_manifest = "${MANIFEST}";
using TestEngine = test::ENGINE_CLASS_NAME(${BACKEND_NAME});
NGRAPH_TEST(${BACKEND_NAME}, reorg_yolo_stride_2)
{
// in_shape [N,C,H,W]
const auto in_shape = Shape{1, 8, 4, 4};
auto p = make_shared<op::Parameter>(element::f32, in_shape);
size_t stride = 2;
auto reorg_yolo = make_shared<op::v0::ReorgYolo>(p, Strides{stride});
auto fun = make_shared<Function>(OutputVector{reorg_yolo}, ParameterVector{p});
std::vector<float> inputs(128);
std::iota(inputs.begin(), inputs.end(), 0);
std::vector<float> expected_result{
0, 2, 4, 6, 16, 18, 20, 22, 32, 34, 36, 38, 48, 50, 52, 54,
64, 66, 68, 70, 80, 82, 84, 86, 96, 98, 100, 102, 112, 114, 116, 118,
1, 3, 5, 7, 17, 19, 21, 23, 33, 35, 37, 39, 49, 51, 53, 55,
65, 67, 69, 71, 81, 83, 85, 87, 97, 99, 101, 103, 113, 115, 117, 119,
8, 10, 12, 14, 24, 26, 28, 30, 40, 42, 44, 46, 56, 58, 60, 62,
72, 74, 76, 78, 88, 90, 92, 94, 104, 106, 108, 110, 120, 122, 124, 126,
9, 11, 13, 15, 25, 27, 29, 31, 41, 43, 45, 47, 57, 59, 61, 63,
73, 75, 77, 79, 89, 91, 93, 95, 105, 107, 109, 111, 121, 123, 125, 127};
// in_shape [N,C,H,W] -> out_shape [N, C*stride*stride, H/stride, W/stride]
Shape expected_shape = Shape{
in_shape[0], in_shape[1] * stride * stride, in_shape[2] / stride, in_shape[3] / stride};
auto test_case = test::TestCase<TestEngine>(fun);
test_case.add_input<float>(inputs);
test_case.add_expected_output<float>(expected_shape, expected_result);
test_case.run();
}
NGRAPH_TEST(${BACKEND_NAME}, reorg_yolo_stride_3)
{
// in_shape [N,C,H,W]
const auto in_shape = Shape{1, 9, 3, 3};
auto p = make_shared<op::Parameter>(element::f32, in_shape);
size_t stride = 3;
auto reorg_yolo = make_shared<op::v0::ReorgYolo>(p, Strides{stride});
auto fun = make_shared<Function>(OutputVector{reorg_yolo}, ParameterVector{p});
std::vector<float> inputs(81);
std::iota(inputs.begin(), inputs.end(), 0);
std::vector<float> expected_result{
0, 3, 6, 27, 30, 33, 54, 57, 60, 1, 4, 7, 28, 31, 34, 55, 58, 61, 2, 5, 8,
29, 32, 35, 56, 59, 62, 9, 12, 15, 36, 39, 42, 63, 66, 69, 10, 13, 16, 37, 40, 43,
64, 67, 70, 11, 14, 17, 38, 41, 44, 65, 68, 71, 18, 21, 24, 45, 48, 51, 72, 75, 78,
19, 22, 25, 46, 49, 52, 73, 76, 79, 20, 23, 26, 47, 50, 53, 74, 77, 80};
// in_shape [N,C,H,W] -> out_shape [N, C*stride*stride, H/stride, W/stride]
Shape expected_shape = Shape{
in_shape[0], in_shape[1] * stride * stride, in_shape[2] / stride, in_shape[3] / stride};
auto test_case = test::TestCase<TestEngine>(fun);
test_case.add_input<float>(inputs);
test_case.add_expected_output<float>(expected_shape, expected_result);
test_case.run();
}

View File

@@ -78,6 +78,7 @@
#include "ngraph/runtime/reference/product.hpp" #include "ngraph/runtime/reference/product.hpp"
#include "ngraph/runtime/reference/quantize.hpp" #include "ngraph/runtime/reference/quantize.hpp"
#include "ngraph/runtime/reference/relu.hpp" #include "ngraph/runtime/reference/relu.hpp"
#include "ngraph/runtime/reference/reorg_yolo.hpp"
#include "ngraph/runtime/reference/replace_slice.hpp" #include "ngraph/runtime/reference/replace_slice.hpp"
#include "ngraph/runtime/reference/reshape.hpp" #include "ngraph/runtime/reference/reshape.hpp"
#include "ngraph/runtime/reference/result.hpp" #include "ngraph/runtime/reference/result.hpp"
@@ -932,6 +933,16 @@ protected:
pbox->get_attrs()); pbox->get_attrs());
break; break;
} }
case OP_TYPEID::ReorgYolo_v0:
{
const op::v0::ReorgYolo* reorg_yolo = static_cast<const op::v0::ReorgYolo*>(&node);
runtime::reference::reorg_yolo(args[0]->get_data_ptr<char>(),
out[0]->get_data_ptr<char>(),
args[0]->get_shape(),
reorg_yolo->get_strides().at(0),
args[0]->get_element_type().size());
break;
}
case OP_TYPEID::Quantize: case OP_TYPEID::Quantize:
{ {
const op::Quantize* quantize = static_cast<const op::Quantize*>(&node); const op::Quantize* quantize = static_cast<const op::Quantize*>(&node);

View File

@@ -21,6 +21,7 @@
#define ID_SUFFIX(NAME) NAME##_v0 #define ID_SUFFIX(NAME) NAME##_v0
NGRAPH_OP(CTCGreedyDecoder, ngraph::op::v0) NGRAPH_OP(CTCGreedyDecoder, ngraph::op::v0)
NGRAPH_OP(DetectionOutput, op::v0) NGRAPH_OP(DetectionOutput, op::v0)
NGRAPH_OP(ReorgYolo, op::v0)
NGRAPH_OP(RNNCell, op::v0) NGRAPH_OP(RNNCell, op::v0)
#undef ID_SUFFIX #undef ID_SUFFIX

View File

@@ -0,0 +1,97 @@
//*****************************************************************************
// Copyright 2017-2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// 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 "gtest/gtest.h"
#include "ngraph/ngraph.hpp"
#include "util/type_prop.hpp"
using namespace std;
using namespace ngraph;
TEST(type_prop, reorg_yolo_stride_2)
{
const auto in_shape = Shape{1, 64, 26, 26};
size_t stride = 2;
auto data_param = make_shared<op::Parameter>(element::f32, in_shape);
auto reorg_yolo = make_shared<op::v0::ReorgYolo>(data_param, stride);
// in_shape [N,C,H,W] -> out_shape [N, C*stride*stride, H/stride, W/stride]
Shape expected_shape = Shape{1, 256, 13, 13};
EXPECT_EQ(reorg_yolo->get_output_shape(0), expected_shape);
}
TEST(type_prop, reorg_yolo_stride_2_batch_2)
{
const auto in_shape = Shape{2, 64, 26, 26};
size_t stride = 2;
auto data_param = make_shared<op::Parameter>(element::f32, in_shape);
auto reorg_yolo = make_shared<op::v0::ReorgYolo>(data_param, stride);
// in_shape [N,C,H,W] -> out_shape [N, C*stride*stride, H/stride, W/stride]
Shape expected_shape = Shape{2, 256, 13, 13};
EXPECT_EQ(reorg_yolo->get_output_shape(0), expected_shape);
}
TEST(type_prop, reorg_yolo_stride_2_smaller_H)
{
const auto in_shape = Shape{1, 24, 34, 62};
size_t stride = 2;
auto data_param = make_shared<op::Parameter>(element::f32, in_shape);
auto reorg_yolo = make_shared<op::v0::ReorgYolo>(data_param, stride);
// in_shape [N,C,H,W] -> out_shape [N, C*stride*stride, H/stride, W/stride]
Shape expected_shape = Shape{1, 96, 17, 31};
EXPECT_EQ(reorg_yolo->get_output_shape(0), expected_shape);
}
TEST(type_prop, reorg_yolo_stride_3)
{
const auto in_shape = Shape{1, 9, 3, 3};
size_t stride = 3;
auto data_param = make_shared<op::Parameter>(element::f32, in_shape);
auto reorg_yolo = make_shared<op::v0::ReorgYolo>(data_param, stride);
// in_shape [N,C,H,W] -> out_shape [N, C*stride*stride, H/stride, W/stride]
Shape expected_shape = Shape{
in_shape[0], in_shape[1] * stride * stride, in_shape[2] / stride, in_shape[3] / stride};
EXPECT_EQ(reorg_yolo->get_output_shape(0), expected_shape);
}
TEST(type_prop, reorg_yolo_catch_small_shape_stride)
{
const auto in_shape = Shape{1, 1, 4, 4};
size_t stride = 2;
auto data_param = make_shared<op::Parameter>(element::f32, in_shape);
try
{
// Throw error test: For [N, C, H, W] input shape, C >= (stride*stride) is required.
auto reorg_yolo = make_shared<op::v0::ReorgYolo>(data_param, stride);
// Should have thrown, so fail if it didn't
FAIL() << "Incompatible stride was not detected.";
}
catch (const ngraph_error& error)
{
EXPECT_HAS_SUBSTRING(error.what(), std::string("stride"));
}
catch (...)
{
FAIL() << "Stride size check failed for unexpected reason.";
}
}