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:
@@ -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>
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
89
ngraph/core/reference/src/runtime/reference/reorg_yolo.cpp
Normal file
89
ngraph/core/reference/src/runtime/reference/reorg_yolo.cpp
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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]);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
|
|||||||
101
ngraph/test/backend/reorg_yolo.in.cpp
Normal file
101
ngraph/test/backend/reorg_yolo.in.cpp
Normal 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();
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
97
ngraph/test/type_prop/reorg_yolo.cpp
Normal file
97
ngraph/test/type_prop/reorg_yolo.cpp
Normal 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.";
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user