Review ROIPooling class for shape inference aspects (#16403)

* Review ROIPooling class
- check interval shape and label propagation
- add template shape_infer
- add shape infer into cpu plugin
- add test with StaticShape

* Use get_output_roi instead of get_output_size

* Add missing includes
This commit is contained in:
Pawel Raasz authored and GitHub committed 2023-03-21 09:02:37 +00:00
1 parent 82a992b95d
commit 63797db257
8 files changed
+384 -156

No files matched your search

+19 -1
View File
@@ -34,12 +34,30 @@ public:
std::shared_ptr<Node> clone_with_new_inputs(const OutputVector& new_args) const override;
/// \brief Set the output ROI feature map (pooled_h, pooled_w).
/// \param output_size Shape with pooling attributes pooled_h and pooled_w sizes.
void set_output_roi(Shape output_size);
/// \brief Get the output ROI feature map shape (H x W)
/// \return Shape with pooled_h and pooled_w attributes.
const Shape& get_output_roi() const;
OPENVINO_DEPRECATED("Use 'get_output_roi' instead. Use of this member can be ambiguous with Node base "
"'get_output_size' which return number of outputs.")
const Shape& get_output_size() const {
return m_output_size;
}
/// \brief Set the spatial scale value.
/// \param scale Scale value to set.
void set_spatial_scale(float scale);
float get_spatial_scale() const {
return m_spatial_scale;
}
/// \brief Set the method of pooling
/// \param method_name Pooling method name.
void set_method(std::string method_name);
const std::string& get_method() const {
return m_method;
}
@@ -47,7 +65,7 @@ public:
private:
Shape m_output_size{0, 0};
float m_spatial_scale{0};
float m_spatial_scale{0.0f};
std::string m_method = "max";
};
} // namespace v0
@@ -0,0 +1,107 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <cmath>
#include "compare.hpp"
#include "dimension_util.hpp"
#include "openvino/op/roi_pooling.hpp"
namespace ov {
namespace op {
namespace pooling {
namespace validate {
template <class TROIPooling, class TShape>
void rois_input_shape(const TROIPooling* op, const TShape rois_shape) {
if (rois_shape.rank().is_static()) {
NODE_VALIDATION_CHECK(op,
rois_shape.size() == 2,
"Expected a 2D tensor for the ROIs input with box coordinates. Got: ",
rois_shape);
NODE_VALIDATION_CHECK(op,
rois_shape[1].compatible(5),
"The second dimension of ROIs input should contain batch id and box coordinates. ",
"This dimension is expected to be equal to 5. Got: ",
rois_shape[1]);
}
}
template <class TROIPooling>
void output_roi_attr(const TROIPooling* op) {
const auto& out_roi = op->get_output_roi();
NODE_VALIDATION_CHECK(op,
out_roi.size() == 2,
"The dimension of pooled size is expected to be equal to 2. Got: ",
out_roi.size());
NODE_VALIDATION_CHECK(op,
std::none_of(out_roi.cbegin(), out_roi.cend(), cmp::Less<size_t>(1)),
"Pooled size attributes pooled_h and pooled_w should should be positive integers. Got: ",
out_roi[0],
" and: ",
out_roi[1],
"respectively");
}
template <class TROIPooling>
void scale_attr(const TROIPooling* op) {
const auto scale = op->get_spatial_scale();
NODE_VALIDATION_CHECK(op,
std::isnormal(scale) && !std::signbit(scale),
"The spatial scale attribute should be a positive floating point number. Got: ",
scale);
}
template <class TROIPooling>
void method_attr(const TROIPooling* op) {
const auto& method = op->get_method();
NODE_VALIDATION_CHECK(op,
method == "max" || method == "bilinear",
"Pooling method attribute should be either \'max\' or \'bilinear\'. Got: ",
method);
}
} // namespace validate
} // namespace pooling
namespace v0 {
template <class TShape>
std::vector<TShape> shape_infer(const ROIPooling* op, const std::vector<TShape>& input_shapes) {
NODE_VALIDATION_CHECK(op, input_shapes.size() == 2);
using namespace ov::util;
const auto& feat_shape = input_shapes[0];
const auto& rois_shape = input_shapes[1];
const auto& feat_rank = feat_shape.rank();
NODE_VALIDATION_CHECK(op,
feat_rank.compatible(4),
"Expected a 4D tensor for the feature maps input. Got: ",
feat_shape);
pooling::validate::rois_input_shape(op, rois_shape);
pooling::validate::output_roi_attr(op);
pooling::validate::scale_attr(op);
pooling::validate::method_attr(op);
TShape out_shape;
out_shape.reserve(4);
out_shape.emplace_back(rois_shape.rank().is_static() ? rois_shape[0] : dim::inf_bound);
out_shape.emplace_back(feat_rank.is_static() ? feat_shape[1] : dim::inf_bound);
std::copy(op->get_output_roi().cbegin(), op->get_output_roi().cend(), std::back_inserter(out_shape));
return {out_shape};
}
template <class TShape>
void shape_infer(const ROIPooling* op, const std::vector<TShape>& input_shapes, std::vector<TShape>& output_shapes) {
output_shapes = shape_infer(op, input_shapes);
}
} // namespace v0
} // namespace op
} // namespace ov
+37 -71
View File
@@ -2,18 +2,22 @@
// SPDX-License-Identifier: Apache-2.0
//
#include "ngraph/op/roi_pooling.hpp"
#include "openvino/op/roi_pooling.hpp"
#include "itt.hpp"
#include "openvino/core/validation_util.hpp"
#include "roi_pooling_shape_inference.hpp"
using namespace std;
using namespace ngraph;
op::ROIPooling::ROIPooling(const Output<Node>& input,
const Output<Node>& coords,
const ov::Shape& output_size,
const float spatial_scale,
const string& method)
namespace ov {
namespace op {
namespace v0 {
ROIPooling::ROIPooling(const Output<Node>& input,
const Output<Node>& coords,
const ov::Shape& output_size,
const float spatial_scale,
const string& method)
: Op({input, coords}),
m_output_size(output_size),
m_spatial_scale(spatial_scale),
@@ -21,10 +25,10 @@ op::ROIPooling::ROIPooling(const Output<Node>& input,
constructor_validate_and_infer_types();
}
void op::ROIPooling::validate_and_infer_types() {
void ROIPooling::validate_and_infer_types() {
OV_OP_SCOPE(v0_ROIPooling_validate_and_infer_types);
auto feat_maps_et = get_input_element_type(0);
auto coords_et = get_input_element_type(1);
const auto& feat_maps_et = get_input_element_type(0);
const auto& coords_et = get_input_element_type(1);
NODE_VALIDATION_CHECK(this,
feat_maps_et.is_real() && coords_et.is_real(),
"The data type for input and ROIs is expected to be a floating point type. Got: ",
@@ -34,72 +38,16 @@ void op::ROIPooling::validate_and_infer_types() {
NODE_VALIDATION_CHECK(this,
feat_maps_et == coords_et,
"Type of feature maps (inputs) and rois is expected to be the same. Got: ",
"Type of feature maps (inputs) and ROIs is expected to be the same. Got: ",
feat_maps_et,
" and: ",
coords_et);
NODE_VALIDATION_CHECK(this,
m_output_size.size() == 2,
"The dimension of pooled size is expected to be equal to 2. Got: ",
m_output_size.size());
NODE_VALIDATION_CHECK(this,
m_output_size[0] > 0 && m_output_size[1] > 0,
"Pooled size attributes pooled_h and pooled_w should should be "
"non-negative integers. Got: ",
m_output_size[0],
" and: ",
m_output_size[1],
"respectively");
NODE_VALIDATION_CHECK(this,
m_spatial_scale > 0,
"The spatial scale attribute should be a positive floating point number. Got: ",
m_spatial_scale);
NODE_VALIDATION_CHECK(this,
m_method == "max" || m_method == "bilinear",
"Pooling method attribute should be either \'max\' or \'bilinear\'. Got: ",
m_method);
const auto output_shapes = shape_infer(this, get_node_input_partial_shapes(*this));
set_output_type(0, feat_maps_et, output_shapes[0]);
const auto& feat_maps_ps = get_input_partial_shape(0);
NODE_VALIDATION_CHECK(this,
feat_maps_ps.rank().compatible(4),
"Expected a 4D tensor for the feature maps input. Got: ",
feat_maps_ps);
const auto& coords_ps = get_input_partial_shape(1);
NODE_VALIDATION_CHECK(this,
coords_ps.rank().compatible(2),
"Expected a 2D tensor for the ROIs input with box coordinates. Got: ",
coords_ps);
if (coords_ps.rank().is_static()) {
const auto coords_second_dim = coords_ps[1];
NODE_VALIDATION_CHECK(this,
coords_second_dim.compatible(5),
"The second dimension of ROIs input should contain batch id and box coordinates. ",
"This dimension is expected to be equal to 5. Got: ",
coords_second_dim);
}
// output shape should be {NUM_ROIS, C, pooled_h, pooled_w}
auto output_shape = ov::PartialShape{{Dimension::dynamic(),
Dimension::dynamic(),
Dimension{static_cast<int64_t>(m_output_size[0])},
Dimension{static_cast<int64_t>(m_output_size[1])}}};
if (coords_ps.rank().is_static()) {
output_shape[0] = coords_ps[0];
}
if (feat_maps_ps.rank().is_static()) {
output_shape[1] = feat_maps_ps[1];
}
set_output_size(1);
set_output_type(0, feat_maps_et, output_shape);
// if channel dimension, C, not known
// feature maps input is used by shape specialization pass
@@ -114,13 +62,13 @@ void op::ROIPooling::validate_and_infer_types() {
}
}
shared_ptr<Node> op::ROIPooling::clone_with_new_inputs(const OutputVector& new_args) const {
shared_ptr<Node> ROIPooling::clone_with_new_inputs(const OutputVector& new_args) const {
OV_OP_SCOPE(v0_ROIPooling_clone_with_new_inputs);
check_new_args_count(this, new_args);
return make_shared<ROIPooling>(new_args.at(0), new_args.at(1), m_output_size, m_spatial_scale, m_method);
}
bool op::ROIPooling::visit_attributes(AttributeVisitor& visitor) {
bool ROIPooling::visit_attributes(AttributeVisitor& visitor) {
OV_OP_SCOPE(v0_ROIPooling_visit_attributes);
visitor.on_attribute("output_size", m_output_size);
visitor.on_attribute("pooled_h", m_output_size[0]);
@@ -129,3 +77,21 @@ bool op::ROIPooling::visit_attributes(AttributeVisitor& visitor) {
visitor.on_attribute("method", m_method);
return true;
}
void ROIPooling::set_output_roi(Shape output_size) {
m_output_size = std::move(output_size);
}
const Shape& ROIPooling::get_output_roi() const {
return m_output_size;
}
void ROIPooling::set_spatial_scale(float scale) {
m_spatial_scale = scale;
}
void ROIPooling::set_method(std::string method_name) {
m_method = std::move(method_name);
}
} // namespace v0
} // namespace op
} // namespace ov
+139 -77
View File
@@ -2,109 +2,171 @@
// SPDX-License-Identifier: Apache-2.0
//
#include "common_test_utils/test_assertions.hpp"
#include "gtest/gtest.h"
#include "ngraph/ngraph.hpp"
#include "openvino/opsets/opset11.hpp"
#include "type_prop.hpp"
using namespace std;
using namespace ngraph;
using namespace ov;
using namespace ov::opset11;
using namespace testing;
TEST(type_prop, roi_pooling_basic_shape_inference) {
const auto feat_maps = make_shared<op::Parameter>(element::f32, Shape{1, 3, 6, 6});
const auto rois = make_shared<op::Parameter>(element::f32, Shape{4, 5});
const auto op = make_shared<op::v0::ROIPooling>(feat_maps, rois, Shape{2, 2}, 0.625f);
ASSERT_EQ(op->get_method(), "max");
ASSERT_EQ(op->get_shape(), (Shape{4, 3, 2, 2}));
class TypePropROIPoolingV0 : public TypePropOpTest<op::v0::ROIPooling> {
protected:
float spatial_scale = 0.625f;
Shape pooling_roi_2x2{2, 2};
};
TEST_F(TypePropROIPoolingV0, default_ctor) {
const auto feat_maps = make_shared<Parameter>(element::f32, PartialShape{{0, 3}, {1, 3}, {1, 6}, {1, 6}});
const auto rois = make_shared<Parameter>(element::f32, PartialShape{{2, 4}, {1, 5}});
const auto op = make_op();
op->set_arguments(OutputVector{feat_maps, rois});
op->set_spatial_scale(spatial_scale);
op->set_method("max");
op->set_output_roi({3, 4});
op->validate_and_infer_types();
EXPECT_FLOAT_EQ(op->get_spatial_scale(), spatial_scale);
EXPECT_EQ(op->get_output_roi(), Shape({3, 4}));
EXPECT_EQ(op->get_method(), "max");
EXPECT_EQ(op->get_input_size(), 2);
EXPECT_EQ(op->get_element_type(), element::f32);
EXPECT_EQ(static_cast<Node*>(op.get())->get_output_size(), 1);
EXPECT_EQ(op->get_output_partial_shape(0), (PartialShape{{2, 4}, {1, 3}, 3, 4}));
}
TEST(type_prop, roi_pooling_dynamic_channels_dim) {
const auto feat_maps = make_shared<op::Parameter>(element::f32, PartialShape{1, Dimension(), 6, 6});
const auto rois = make_shared<op::Parameter>(element::f32, Shape{4, 5});
const auto op = make_shared<op::v0::ROIPooling>(feat_maps, rois, Shape{2, 2}, 0.625f, "max");
ASSERT_TRUE(op->get_output_partial_shape(0).same_scheme(PartialShape{4, Dimension(), 2, 2}));
TEST_F(TypePropROIPoolingV0, basic_shape_inference) {
const auto feat_maps = make_shared<Parameter>(element::f32, Shape{1, 3, 6, 6});
const auto rois = make_shared<Parameter>(element::f32, Shape{4, 5});
const auto op = make_op(feat_maps, rois, pooling_roi_2x2, 0.625f);
EXPECT_EQ(op->get_element_type(), element::f32);
EXPECT_EQ(op->get_method(), "max");
EXPECT_EQ(op->get_shape(), (Shape{4, 3, 2, 2}));
}
TEST(type_prop, roi_pooling_dynamic_num_rois_dim) {
const auto feat_maps = make_shared<op::Parameter>(element::f32, Shape{1, 3, 6, 6});
const auto rois = make_shared<op::Parameter>(element::f32, PartialShape{Dimension(), 5});
const auto op = make_shared<op::v0::ROIPooling>(feat_maps, rois, Shape{2, 2}, 0.625f);
ASSERT_TRUE(op->get_output_partial_shape(0).same_scheme(PartialShape{Dimension(), 3, 2, 2}));
TEST_F(TypePropROIPoolingV0, dynamic_channels_dim) {
auto feat_shape = PartialShape{1, -1, 6, 6};
auto rois_shape = PartialShape{4, 5};
set_shape_labels(feat_shape, 10);
set_shape_labels(rois_shape, 20);
const auto feat_maps = make_shared<Parameter>(element::f32, feat_shape);
const auto rois = make_shared<Parameter>(element::f32, rois_shape);
const auto op = make_op(feat_maps, rois, pooling_roi_2x2, spatial_scale, "max");
EXPECT_EQ(op->get_element_type(), element::f32);
EXPECT_EQ(op->get_output_partial_shape(0), (PartialShape{4, -1, 2, 2}));
EXPECT_THAT(get_shape_labels(op->get_output_partial_shape(0)), ElementsAre(20, 11, ov::no_label, ov::no_label));
}
TEST(type_prop, roi_pooling_dynamic_rank_feat_maps) {
const auto feat_maps = make_shared<op::Parameter>(element::f32, PartialShape::dynamic());
const auto rois = make_shared<op::Parameter>(element::f32, Shape{4, 5});
const auto op = make_shared<op::v0::ROIPooling>(feat_maps, rois, Shape{2, 2}, 0.625f);
ASSERT_TRUE(op->get_output_partial_shape(0).same_scheme(PartialShape{4, Dimension(), 2, 2}));
TEST_F(TypePropROIPoolingV0, dynamic_num_rois_dim) {
auto feat_shape = PartialShape{1, 3, 6, 6};
auto rois_shape = PartialShape{-1, 5};
set_shape_labels(feat_shape, 10);
set_shape_labels(rois_shape, 20);
const auto feat_maps = make_shared<Parameter>(element::f64, feat_shape);
const auto rois = make_shared<Parameter>(element::f64, rois_shape);
const auto op = make_op(feat_maps, rois, pooling_roi_2x2, spatial_scale, "bilinear");
EXPECT_EQ(op->get_element_type(), element::f64);
EXPECT_EQ(op->get_output_partial_shape(0), (PartialShape{-1, 3, 2, 2}));
EXPECT_THAT(get_shape_labels(op->get_output_partial_shape(0)), ElementsAre(20, 11, ov::no_label, ov::no_label));
}
TEST(type_prop, roi_pooling_dynamic_rank_rois) {
const auto feat_maps = make_shared<op::Parameter>(element::f32, Shape{1, 3, 6, 6});
const auto rois = make_shared<op::Parameter>(element::f32, PartialShape::dynamic());
const auto op = make_shared<op::v0::ROIPooling>(feat_maps, rois, Shape{2, 2}, 0.625f);
ASSERT_TRUE(op->get_output_partial_shape(0).same_scheme(PartialShape{Dimension(), 3, 2, 2}));
TEST_F(TypePropROIPoolingV0, dynamic_rank_feat_maps) {
const auto feat_maps = make_shared<Parameter>(element::f16, PartialShape::dynamic());
const auto rois = make_shared<Parameter>(element::f16, Shape{4, 5});
const auto op = make_op(feat_maps, rois, pooling_roi_2x2, spatial_scale);
EXPECT_EQ(op->get_element_type(), element::f16);
EXPECT_EQ(op->get_output_partial_shape(0), (PartialShape{4, -1, 2, 2}));
EXPECT_THAT(get_shape_labels(op->get_output_partial_shape(0)), Each(ov::no_label));
}
TEST(type_prop, roi_pooling_incompatible_input_rank) {
const auto feat_maps = make_shared<op::Parameter>(element::f32, Shape{1, 3, 2, 6, 6});
const auto rois = make_shared<op::Parameter>(element::f32, Shape{3, 5});
// feat_maps must be of rank 4
ASSERT_THROW(const auto unused = make_shared<op::v0::ROIPooling>(feat_maps, rois, Shape{2, 2}, 0.625f, "max"),
ngraph::NodeValidationFailure);
TEST_F(TypePropROIPoolingV0, dynamic_rank_feat_rois) {
const auto feat_maps = make_shared<Parameter>(element::f32, Shape{1, 3, 6, 6});
const auto rois = make_shared<Parameter>(element::f32, PartialShape::dynamic());
const auto op = make_op(feat_maps, rois, pooling_roi_2x2, spatial_scale);
EXPECT_EQ(op->get_element_type(), element::f32);
EXPECT_EQ(op->get_output_partial_shape(0), (PartialShape{-1, 3, 2, 2}));
EXPECT_THAT(get_shape_labels(op->get_output_partial_shape(0)), Each(ov::no_label));
}
TEST(type_prop, roi_pooling_incompatible_pooling_shape) {
Shape pool_shape{2, 2, 2};
const auto feat_maps = make_shared<op::Parameter>(element::f32, Shape{3, 2, 6, 6});
const auto rois = make_shared<op::Parameter>(element::f32, Shape{3, 5});
// pool_shape must be of rank 2 {pooled_h, pooled_w}
ASSERT_THROW(const auto unused = make_shared<op::v0::ROIPooling>(feat_maps, rois, pool_shape, 0.625f, "max"),
ngraph::NodeValidationFailure);
TEST_F(TypePropROIPoolingV0, incompatible_input_rank) {
const auto feat_maps = make_shared<Parameter>(element::f32, Shape{1, 3, 6, 6, 6});
const auto rois = make_shared<Parameter>(element::f32, PartialShape{3, 5});
OV_EXPECT_THROW(const auto op = make_op(feat_maps, rois, pooling_roi_2x2, spatial_scale, "max"),
NodeValidationFailure,
HasSubstr("Expected a 4D tensor for the feature maps input"));
}
TEST(type_prop, roi_pooling_incompatible_rois_second_dim) {
const auto feat_maps = make_shared<op::Parameter>(element::f32, Shape{3, 2, 6, 6});
const auto rois = make_shared<op::Parameter>(element::f32, Shape{3, 4});
// the second dim of rois must be 5. [batch_id, x_1, y_1, x_2, y_2]
ASSERT_THROW(const auto unused = make_shared<op::v0::ROIPooling>(feat_maps, rois, Shape{2, 2}, 0.625f, "max"),
ngraph::NodeValidationFailure);
TEST_F(TypePropROIPoolingV0, incompatible_pooling_shape) {
const auto feat_maps = make_shared<Parameter>(element::f32, Shape{3, 2, 6, 6});
const auto rois = make_shared<Parameter>(element::f32, PartialShape{3, 5});
OV_EXPECT_THROW(const auto op = make_op(feat_maps, rois, Shape{2, 2, 2}, spatial_scale, "max"),
NodeValidationFailure,
HasSubstr("The dimension of pooled size is expected to be equal to 2"));
}
TEST(type_prop, roi_pooling_incompatible_feature_maps_element_type) {
const auto feat_maps = make_shared<op::Parameter>(element::i32, Shape{3, 2, 6, 6});
const auto rois = make_shared<op::Parameter>(element::f32, Shape{3, 5});
// feat_maps element type must be floating point type
ASSERT_THROW(const auto unused = make_shared<op::v0::ROIPooling>(feat_maps, rois, Shape{2, 2}, 0.625f, "max"),
ngraph::NodeValidationFailure);
TEST_F(TypePropROIPoolingV0, incompatible_rois_second_dim) {
const auto feat_maps = make_shared<Parameter>(element::f32, Shape{3, 2, 6, 6});
const auto rois = make_shared<Parameter>(element::f32, PartialShape{3, 4});
OV_EXPECT_THROW(const auto op = make_op(feat_maps, rois, pooling_roi_2x2, spatial_scale, "max"),
NodeValidationFailure,
HasSubstr("The second dimension of ROIs input should contain batch id and box coordinates. This "
"dimension is expected to be equal to 5"));
}
TEST(type_prop, roi_pooling_incompatible_rois_element_type) {
const auto feat_maps = make_shared<op::Parameter>(element::f32, Shape{3, 2, 6, 6});
const auto rois = make_shared<op::Parameter>(element::f16, Shape{3, 5});
// rois element type must be equal to feat_maps element type (floating point type)
ASSERT_THROW(const auto unused = make_shared<op::v0::ROIPooling>(feat_maps, rois, Shape{2, 2}, 0.625f, "bilinear"),
ngraph::NodeValidationFailure);
TEST_F(TypePropROIPoolingV0, incompatible_feature_maps_element_type) {
const auto feat_maps = make_shared<Parameter>(element::i32, Shape{3, 2, 6, 6});
const auto rois = make_shared<Parameter>(element::f32, PartialShape{3, 5});
OV_EXPECT_THROW(const auto op = make_op(feat_maps, rois, pooling_roi_2x2, spatial_scale, "max"),
NodeValidationFailure,
HasSubstr("The data type for input and ROIs is expected to be a floating point type"));
}
TEST(type_prop, roi_pooling_invalid_pooling_method) {
const auto feat_maps = make_shared<op::Parameter>(element::f32, Shape{3, 2, 6, 6});
const auto rois = make_shared<op::Parameter>(element::f16, Shape{3, 5});
// ROIPooling method is invalid: not max nor bilinear
ASSERT_THROW(const auto unused = make_shared<op::v0::ROIPooling>(feat_maps, rois, Shape{2, 2}, 0.625f, "invalid"),
ngraph::NodeValidationFailure);
TEST_F(TypePropROIPoolingV0, incompatible_rois_element_type) {
const auto feat_maps = make_shared<Parameter>(element::f32, Shape{3, 2, 6, 6});
const auto rois = make_shared<Parameter>(element::i16, PartialShape{3, 5});
OV_EXPECT_THROW(const auto op = make_op(feat_maps, rois, pooling_roi_2x2, spatial_scale, "bilinear"),
NodeValidationFailure,
HasSubstr("The data type for input and ROIs is expected to be a floating point type"));
}
TEST(type_prop, roi_pooling_invalid_spatial_scale) {
const auto feat_maps = make_shared<op::Parameter>(element::f32, Shape{3, 2, 6, 6});
const auto rois = make_shared<op::Parameter>(element::f16, Shape{3, 5});
// ROIPooling spatial scale attribute must be a positive floating point number
ASSERT_THROW(const auto unused = make_shared<op::v0::ROIPooling>(feat_maps, rois, Shape{2, 2}, -0.625f, "max"),
ngraph::NodeValidationFailure);
TEST_F(TypePropROIPoolingV0, invalid_pooling_method) {
const auto feat_maps = make_shared<Parameter>(element::f32, Shape{3, 2, 6, 6});
const auto rois = make_shared<Parameter>(element::f32, PartialShape{3, 5});
OV_EXPECT_THROW(const auto op = make_op(feat_maps, rois, pooling_roi_2x2, spatial_scale, "invalid"),
NodeValidationFailure,
HasSubstr("Pooling method attribute should be either \'max\' or \'bilinear\'"));
}
TEST(type_prop, roi_pooling_invalid_pooled_size) {
const auto feat_maps = make_shared<op::Parameter>(element::f32, Shape{3, 2, 6, 6});
const auto rois = make_shared<op::Parameter>(element::f16, Shape{3, 5});
// ROIPooling pooled_h and pooled_w must be non-negative integers
ASSERT_THROW(const auto unused = make_shared<op::v0::ROIPooling>(feat_maps, rois, Shape{1, 0}, 0.625f, "max"),
ngraph::NodeValidationFailure);
TEST_F(TypePropROIPoolingV0, invalid_spatial_scale) {
const auto feat_maps = make_shared<Parameter>(element::f32, Shape{3, 2, 6, 6});
const auto rois = make_shared<Parameter>(element::f32, PartialShape{3, 5});
OV_EXPECT_THROW(const auto op = make_op(feat_maps, rois, pooling_roi_2x2, -1.0f),
NodeValidationFailure,
HasSubstr("The spatial scale attribute should be a positive floating point number"));
}
TEST_F(TypePropROIPoolingV0, invalid_pooled_size) {
const auto feat_maps = make_shared<Parameter>(element::f32, Shape{3, 2, 6, 6});
const auto rois = make_shared<Parameter>(element::f32, PartialShape{3, 5});
OV_EXPECT_THROW(const auto op = make_op(feat_maps, rois, Shape{1, 0}, spatial_scale),
NodeValidationFailure,
HasSubstr("Pooled size attributes pooled_h and pooled_w should should be positive integers"));
}
+1 -1
View File
@@ -25,7 +25,7 @@ TEST(attributes, roi_pooling_op) {
NodeBuilder builder(op, {data, coords});
const auto g_op = ov::as_type_ptr<opset3::ROIPooling>(builder.create());
EXPECT_EQ(g_op->get_output_size(), op->get_output_size());
EXPECT_EQ(g_op->get_output_roi(), op->get_output_roi());
EXPECT_EQ(g_op->get_spatial_scale(), op->get_spatial_scale());
EXPECT_EQ(g_op->get_method(), op->get_method());
}
@@ -393,10 +393,10 @@ ROIPooling::ROIPooling(const std::shared_ptr<ngraph::Node>& op, const GraphConte
std::string errorPrefix = "ROIPooling layer with name '" + getName() + "' ";
auto roiPooling = ngraph::as_type_ptr<const ngraph::opset2::ROIPooling>(op);
refParams.pooled_h = roiPooling->get_output_size()[0];
refParams.pooled_w = roiPooling->get_output_size()[1];
refParams.pooled_h = roiPooling->get_output_roi()[0];
refParams.pooled_w = roiPooling->get_output_roi()[1];
refParams.spatial_scale = roiPooling->get_spatial_scale();
std::string m = roiPooling->get_method();
const auto& m = roiPooling->get_method();
if (m == "max") {
algorithm = Algorithm::ROIPoolingMax;
} else if (m == "bilinear") {
@@ -62,6 +62,7 @@
#include "reverse_sequence_shape_inference.hpp"
#include "reverse_shape_inference.hpp"
#include "roi_align_shape_inference.hpp"
#include "roi_pooling_shape_inference.hpp"
#include "roll_shape_inference.hpp"
#include "scatter_elements_update_shape_inference.hpp"
#include "scatter_nd_base_shape_inference.hpp"
@@ -125,9 +126,8 @@ public:
IShapeInferCommon::Result
infer(const std::vector<StaticShape>& input_shapes, const std::map<size_t, HostTensorPtr>& constant_data) override {
auto op = static_cast<OP*>(node.get());
std::vector<StaticShape> output_shapes(op->get_output_size());
shape_infer(op, input_shapes, output_shapes);
std::vector<StaticShape> output_shapes(node->get_output_size());
shape_infer(static_cast<OP*>(node.get()), input_shapes, output_shapes);
return {std::move(output_shapes), ShapeInferStatus::success};
}
};
@@ -597,6 +597,7 @@ const IShapeInferCommonFactory::TRegistry IShapeInferCommonFactory::registry{
_OV_OP_SHAPE_INFER_REG(Reshape, entryIOC),
_OV_OP_SHAPE_INFER_REG(ReverseSequence, entryIO),
_OV_OP_SHAPE_INFER_REG(ROIAlign, entryIO),
_OV_OP_SHAPE_INFER_REG(ROIPooling, entryIO),
_OV_OP_SHAPE_INFER_REG(Roll, entryIOC),
_OV_OP_SHAPE_INFER_REG(ScatterElementsUpdate, entryIOC),
_OV_OP_SHAPE_INFER_REG(ScatterNDUpdate, entryIO),
@@ -0,0 +1,74 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <gmock/gmock.h>
#include "common_test_utils/test_assertions.hpp"
#include "openvino/opsets/opset11.hpp"
#include "utils.hpp"
using namespace ov;
using namespace ov::intel_cpu;
using namespace testing;
class ROIPoolingV0StaticShapeInferenceTest : public OpStaticShapeInferenceTest<op::v0::ROIPooling> {
protected:
void SetUp() override {
output_shapes.resize(1);
}
};
TEST_F(ROIPoolingV0StaticShapeInferenceTest, default_ctor) {
op = make_op();
op->set_output_roi({3, 3});
op->set_method("max");
op->set_spatial_scale(0.34f);
input_shapes = ShapeVector{{1, 5, 10, 10}, {2, 5}};
auto shape_infer = make_shape_inference(op);
shape_inference(op.get(), input_shapes, output_shapes);
EXPECT_EQ(output_shapes.size(), 1);
EXPECT_EQ(output_shapes.front(), StaticShape({2, 5, 3, 3}));
}
TEST_F(ROIPoolingV0StaticShapeInferenceTest, inputs_dynamic_rank) {
const auto feat = std::make_shared<op::v0::Parameter>(element::f64, PartialShape::dynamic());
const auto rois = std::make_shared<op::v0::Parameter>(element::f64, PartialShape::dynamic());
op = make_op(feat, rois, ov::Shape{5, 5}, 0.9f);
input_shapes = ShapeVector{{2, 3, 100, 100}, {10, 5}};
shape_inference(op.get(), input_shapes, output_shapes);
EXPECT_EQ(output_shapes.size(), 1);
EXPECT_EQ(output_shapes.front(), StaticShape({10, 3, 5, 5}));
}
TEST_F(ROIPoolingV0StaticShapeInferenceTest, inputs_static_rank) {
const auto feat = std::make_shared<op::v0::Parameter>(element::f64, PartialShape::dynamic(4));
const auto rois = std::make_shared<op::v0::Parameter>(element::f64, PartialShape::dynamic(2));
op = make_op(feat, rois, ov::Shape{7, 5}, 1.9f, "max");
input_shapes = ShapeVector{{2, 3, 20, 100}, {10, 5}};
shape_inference(op.get(), input_shapes, output_shapes);
EXPECT_EQ(output_shapes.size(), 1);
EXPECT_EQ(output_shapes.front(), StaticShape({10, 3, 7, 5}));
}
TEST_F(ROIPoolingV0StaticShapeInferenceTest, invalid_rois_batch_size) {
const auto feat = std::make_shared<op::v0::Parameter>(element::f64, PartialShape::dynamic(4));
const auto rois = std::make_shared<op::v0::Parameter>(element::f64, PartialShape::dynamic());
op = make_op(feat, rois, ov::Shape{7, 5}, 1.9f, "max");
input_shapes = ShapeVector{{2, 3, 20, 100}, {10, 6}};
OV_EXPECT_THROW(shape_inference(op.get(), input_shapes, output_shapes),
NodeValidationFailure,
HasSubstr("The second dimension of ROIs input should contain batch id and box coordinates. This "
"dimension is expected to be equal to 5"));
}