Deformable Convolution v8: transformations (#6533)

* add DeformableConv8to1 transformation

* update deformable conv v8 to v1 transformation

* Update inference-engine/src/transformations/src/transformations/op_conversions/convert_deformable_conv_v8_to_v1.cpp

Co-authored-by: Gleb Kazantaev <gleb.nnstu@gmail.com>

Co-authored-by: Gleb Kazantaev <gleb.nnstu@gmail.com>
This commit is contained in:
Ivan Tikhonov
2021-07-07 08:52:38 +03:00
committed by GitHub
co-authored by Gleb Kazantaev
parent 79f26cea7a
commit 85a5e9beb0
4 changed files with 241 additions and 0 deletions
@@ -61,6 +61,7 @@
#include <transformations/op_conversions/convert_nms_to_nms_ie_internal.hpp>
#include <transformations/op_conversions/convert_interpolate1_to_interpolate4.hpp>
#include <transformations/op_conversions/convert_gather_0d.hpp>
#include <transformations/op_conversions/convert_deformable_conv_v8_to_v1.hpp>
#include <transformations/op_conversions/simplify_ctc_greedy_decoder_seq_len.hpp>
#include <transformations/convert_precision.hpp>
#include <transformations/init_node_info.hpp>
@@ -191,6 +192,7 @@ InferenceEngine::CNNNetwork clDNNEngine::CloneAndTransformNetwork(const Inferenc
manager.register_pass<ngraph::pass::ConvertNMS4ToNMS5>();
manager.register_pass<ngraph::pass::ConvertNMSToNMSIEInternal>();
manager.register_pass<ngraph::pass::ConvertGather0D>();
manager.register_pass<ngraph::pass::ConvertDeformableConv8To1>();
static const precisions_array convert_precision_list {
{ngraph::element::i64, ngraph::element::i32},
@@ -0,0 +1,27 @@
// Copyright (C) 2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <transformations_visibility.hpp>
#include <ngraph/pass/graph_rewrite.hpp>
namespace ngraph {
namespace pass {
class TRANSFORMATIONS_API ConvertDeformableConv8To1;
} // namespace pass
} // namespace ngraph
/**
* @ingroup ie_transformation_common_api
* @brief ConvertDeformableConv8To1 converts v8::DeformableConvolution into v1::DeformableConvolution.
*/
class ngraph::pass::ConvertDeformableConv8To1 : public ngraph::pass::MatcherPass {
public:
NGRAPH_RTTI_DECLARATION;
ConvertDeformableConv8To1();
};
@@ -0,0 +1,52 @@
// Copyright (C) 2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "transformations/op_conversions/convert_deformable_conv_v8_to_v1.hpp"
#include <ngraph/opsets/opset1.hpp>
#include <ngraph/opsets/opset8.hpp>
#include <ngraph/rt_info.hpp>
#include <ngraph/pattern/op/wrap_type.hpp>
#include "itt.hpp"
NGRAPH_RTTI_DEFINITION(ngraph::pass::ConvertDeformableConv8To1, "ConvertDeformableConv8To1", 0);
ngraph::pass::ConvertDeformableConv8To1::ConvertDeformableConv8To1() {
MATCHER_SCOPE(ConvertDeformableConv8To1);
auto deformable_conv_v8 = pattern::wrap_type<ngraph::opset8::DeformableConvolution>();
ngraph::matcher_pass_callback callback = [=](pattern::Matcher& m) {
auto deformable_conv_v8_node = std::dynamic_pointer_cast<ngraph::opset8::DeformableConvolution>(m.get_match_root());
if (!deformable_conv_v8_node)
return false;
if (deformable_conv_v8_node->get_input_size() != 3
|| deformable_conv_v8_node->get_bilinear_interpolation_pad())
return false;
auto arg = deformable_conv_v8_node->input_value(0);
auto offsets = deformable_conv_v8_node->input_value(1);
auto filters = deformable_conv_v8_node->input_value(2);
auto deformable_conv_v1 =
std::make_shared<ngraph::opset1::DeformableConvolution>(arg,
offsets,
filters,
deformable_conv_v8_node->get_strides(),
deformable_conv_v8_node->get_pads_begin(),
deformable_conv_v8_node->get_pads_end(),
deformable_conv_v8_node->get_dilations(),
deformable_conv_v8_node->get_auto_pad(),
deformable_conv_v8_node->get_group(),
deformable_conv_v8_node->get_deformable_group());
deformable_conv_v1->set_friendly_name(deformable_conv_v8_node->get_friendly_name());
ngraph::copy_runtime_info(deformable_conv_v8_node, deformable_conv_v1);
ngraph::replace_node(deformable_conv_v8_node, deformable_conv_v1);
return true;
};
auto m = std::make_shared<pattern::Matcher>(deformable_conv_v8, matcher_name);
register_matcher(m, callback);
}
@@ -0,0 +1,160 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <gtest/gtest.h>
#include <string>
#include <memory>
#include <ngraph/function.hpp>
#include <ngraph/opsets/opset1.hpp>
#include <ngraph/opsets/opset8.hpp>
#include <ngraph/pass/manager.hpp>
#include <transformations/op_conversions/convert_deformable_conv_v8_to_v1.hpp>
#include <transformations/init_node_info.hpp>
#include "common_test_utils/ngraph_test_utils.hpp"
using namespace testing;
using namespace ngraph;
TEST(TransformationTests, ConvertDeformableConv8to1) {
std::shared_ptr<Function> f(nullptr), f_ref(nullptr);
{
const Strides strides{1, 1};
const CoordinateDiff padding{0, 0};
const Strides dilations{1, 1};
const Shape input_shape{1, 1, 4, 4};
const Shape filter_shape{1, 1, 2, 2};
const Shape offsets_shape{1, 8, 3, 3};
auto data = std::make_shared<opset8::Parameter>(element::f32, input_shape);
auto filter = std::make_shared<opset8::Parameter>(element::f32, filter_shape);
auto offsets = std::make_shared<opset8::Parameter>(element::f32, offsets_shape);
auto deformable_conv = std::make_shared<opset8::DeformableConvolution>(data,
offsets,
filter,
strides,
padding,
padding,
dilations);
f = std::make_shared<Function>(NodeVector{deformable_conv}, ParameterVector{data, filter, offsets});
pass::Manager manager;
manager.register_pass<pass::InitNodeInfo>();
manager.register_pass<pass::ConvertDeformableConv8To1>();
manager.run_passes(f);
ASSERT_NO_THROW(check_rt_info(f));
}
{
const Strides strides{1, 1};
const CoordinateDiff padding{0, 0};
const Strides dilations{1, 1};
const Shape input_shape{1, 1, 4, 4};
const Shape filter_shape{1, 1, 2, 2};
const Shape offsets_shape{1, 8, 3, 3};
auto data = std::make_shared<opset1::Parameter>(element::f32, input_shape);
auto filter = std::make_shared<opset1::Parameter>(element::f32, filter_shape);
auto offsets = std::make_shared<opset1::Parameter>(element::f32, offsets_shape);
auto deformable_conv = std::make_shared<opset1::DeformableConvolution>(data,
offsets,
filter,
strides,
padding,
padding,
dilations);
f_ref = std::make_shared<Function>(NodeVector{deformable_conv}, ParameterVector{data, filter, offsets});
}
auto res = compare_functions(f, f_ref);
ASSERT_TRUE(res.first) << res.second;
}
TEST(TransformationTests, ConvertDeformableConv8to1_mask) {
std::shared_ptr<Function> f(nullptr), f_ref(nullptr);
{
const Strides strides{1, 1};
const CoordinateDiff padding{0, 0};
const Strides dilations{1, 1};
const Shape input_shape{1, 1, 4, 4};
const Shape filter_shape{1, 1, 2, 2};
const Shape offsets_shape{1, 8, 3, 3};
const Shape mask_shape{1, 4, 3, 3};
auto data = std::make_shared<opset8::Parameter>(element::f32, input_shape);
auto filter = std::make_shared<opset8::Parameter>(element::f32, filter_shape);
auto offsets = std::make_shared<opset8::Parameter>(element::f32, offsets_shape);
auto mask = std::make_shared<opset8::Parameter>(element::f32, mask_shape);
auto deformable_conv = std::make_shared<opset8::DeformableConvolution>(data,
offsets,
filter,
mask,
strides,
padding,
padding,
dilations);
f = std::make_shared<Function>(NodeVector{deformable_conv}, ParameterVector{data, filter,
mask, offsets});
pass::Manager manager;
manager.register_pass<pass::InitNodeInfo>();
manager.register_pass<pass::ConvertDeformableConv8To1>();
manager.run_passes(f);
ASSERT_NO_THROW(check_rt_info(f));
}
// mask input is provided, DeformableConvolution-8 must remain
ASSERT_EQ(count_ops_of_type<opset1::DeformableConvolution>(f), 0);
ASSERT_EQ(count_ops_of_type<opset8::DeformableConvolution>(f), 1);
}
TEST(TransformationTests, ConvertDeformableConv8to1_bilinear_interpolation_padding) {
std::shared_ptr<Function> f(nullptr), f_ref(nullptr);
{
const Strides strides{1, 1};
const CoordinateDiff padding{0, 0};
const Strides dilations{1, 1};
const Shape input_shape{1, 1, 4, 4};
const Shape filter_shape{1, 1, 2, 2};
const Shape offsets_shape{1, 8, 3, 3};
auto data = std::make_shared<opset8::Parameter>(element::f32, input_shape);
auto filter = std::make_shared<opset8::Parameter>(element::f32, filter_shape);
auto offsets = std::make_shared<opset8::Parameter>(element::f32, offsets_shape);
auto deformable_conv = std::make_shared<opset8::DeformableConvolution>(data,
offsets,
filter,
strides,
padding,
padding,
dilations,
op::PadType::EXPLICIT,
1,
1,
true);
f = std::make_shared<Function>(NodeVector{deformable_conv}, ParameterVector{data, filter, offsets});
pass::Manager manager;
manager.register_pass<pass::InitNodeInfo>();
manager.register_pass<pass::ConvertDeformableConv8To1>();
manager.run_passes(f);
ASSERT_NO_THROW(check_rt_info(f));
}
// use_bilinear_interpolation_padding is true, DeformableConvolution-8 must remain
ASSERT_EQ(count_ops_of_type<opset1::DeformableConvolution>(f), 0);
ASSERT_EQ(count_ops_of_type<opset8::DeformableConvolution>(f), 1);
}