Commit 2cf9e4b2 authored by Adam Rogowiec's avatar Adam Rogowiec Committed by Robert Kimball

[ONNX] Fix convolution errors (#2025)

* Unit tests for conv2d causing errors.

* UT for conv3D_bias

* Fix padding order.

`padding below` in nGraph terminology means padding added at the beginning
of the axis. Whereas `padding above` means padding added at the end of
the axis.

* Rename test to sth more descriptive.

* Apply clang-format.

* Fix handling of `SAME_UPPER/LOWER` auto_pads mode for convolution/pooling ops.

* Fix order of padding_below/above.
Signed-off-by: 's avatarAdam Rogowiec <adam.rogowiec@intel.com>

* Fix error in calculating output data shape.
parent 1286fd44
...@@ -31,9 +31,9 @@ namespace ngraph ...@@ -31,9 +31,9 @@ namespace ngraph
{ {
Shape get_kernel_shape(const Node& node) Shape get_kernel_shape(const Node& node)
{ {
std::size_t input_spacial_dims = node.get_ng_inputs()[0]->get_shape().size() - 2; std::size_t input_spatial_dims = node.get_ng_inputs().at(0)->get_shape().size() - 2;
return node.get_attribute_value<std::vector<std::size_t>>( return node.get_attribute_value<std::vector<std::size_t>>(
"kernel_shape", std::vector<std::size_t>(input_spacial_dims, 1UL)); "kernel_shape", std::vector<std::size_t>(input_spatial_dims, 1UL));
} }
namespace detail namespace detail
...@@ -64,38 +64,67 @@ namespace ngraph ...@@ -64,38 +64,67 @@ namespace ngraph
namespace namespace
{ {
CoordinateDiff get_auto_pads(const Shape& kernel_shape, const std::string& auto_pad) Shape get_output_data_shape(const Shape& input, const Strides& strides)
{ {
CoordinateDiff pads; Shape output;
for (std::size_t idx = 0; idx < input.size(); ++idx)
{
output.emplace_back(std::ceil(static_cast<float>(input.at(idx)) /
static_cast<float>(strides.at(idx))));
}
return output;
}
// Add padding to the input to match the size of output size. Shape get_pad_shape(const Shape& input,
auto pad_value = [](size_t dim) { const Shape& kernel,
return (static_cast<float>(dim) - 1.f) / 2.f; const Shape& strides,
}; const Shape& output)
{
Shape pad_shape;
for (std::size_t idx = 0; idx < input.size(); ++idx)
{
pad_shape.emplace_back((output.at(idx) - 1) * strides.at(idx) +
kernel.at(idx) - input.at(idx));
}
return pad_shape;
}
CoordinateDiff get_auto_pads(const Shape& input_shape,
const Shape& kernel_shape,
const Strides& strides,
const std::string& auto_pad)
{
CoordinateDiff pads_begin;
CoordinateDiff pads_end;
// Omit {N,C} axes
Shape input_spatial_shape{std::next(std::begin(input_shape), 2),
std::end(input_shape)};
// Assume that all {input_spatial_shape,kernel_shape,strides}.size()
// is the same.
const Shape& output_spatial_shape =
get_output_data_shape(input_spatial_shape, strides);
const Shape& pad_shape = get_pad_shape(
input_spatial_shape, kernel_shape, strides, output_spatial_shape);
if (auto_pad == "SAME_UPPER") if (auto_pad == "SAME_UPPER")
{ {
for (size_t dim : kernel_shape) for (size_t pad : pad_shape)
{
pads.emplace_back(std::floor(pad_value(dim)));
}
for (size_t dim : kernel_shape)
{ {
pads.emplace_back(std::ceil(pad_value(dim))); // Integer division
pads_begin.emplace_back(pad / 2);
pads_end.emplace_back(pad - pads_begin.back());
} }
} }
else if (auto_pad == "SAME_LOWER") else if (auto_pad == "SAME_LOWER")
{ {
for (size_t dim : kernel_shape) for (size_t pad : pad_shape)
{ {
pads.emplace_back(std::ceil(pad_value(dim))); // Integer division
} pads_end.emplace_back(pad / 2);
for (size_t dim : kernel_shape) pads_begin.emplace_back(pad - pads_end.back());
{
pads.emplace_back(std::floor(pad_value(dim)));
} }
} }
CoordinateDiff pads{pads_begin};
pads.insert(std::end(pads), std::begin(pads_end), std::end(pads_end));
return pads; return pads;
} }
...@@ -115,7 +144,10 @@ namespace ngraph ...@@ -115,7 +144,10 @@ namespace ngraph
std::string auto_pad{node.get_attribute_value<std::string>("auto_pad", "")}; std::string auto_pad{node.get_attribute_value<std::string>("auto_pad", "")};
if (!auto_pad.empty()) if (!auto_pad.empty())
{ {
pads = get_auto_pads(kernel_shape, auto_pad); pads = get_auto_pads(node.get_ng_inputs().at(0)->get_shape(),
kernel_shape,
get_strides(node),
auto_pad);
} }
} }
if (pads.empty()) if (pads.empty())
...@@ -130,8 +162,8 @@ namespace ngraph ...@@ -130,8 +162,8 @@ namespace ngraph
} }
else else
{ {
return {{std::begin(pads) + pads.size() / 2, std::end(pads)}, return {{std::begin(pads), std::begin(pads) + pads.size() / 2},
{std::begin(pads), std::begin(pads) + pads.size() / 2}}; {std::begin(pads) + pads.size() / 2, std::end(pads)}};
} }
} }
......
...@@ -118,8 +118,8 @@ namespace ngraph ...@@ -118,8 +118,8 @@ namespace ngraph
bool count_include_pad = node.get_attribute_value<int64_t>("count_include_pad", 0); bool count_include_pad = node.get_attribute_value<int64_t>("count_include_pad", 0);
// Convert padding from CoordinateDiff to Shape objects // Convert padding from CoordinateDiff to Shape objects
const CoordinateDiff& padding_above{paddings.first}; const CoordinateDiff& padding_above{paddings.second};
const CoordinateDiff& padding_below{paddings.second}; const CoordinateDiff& padding_below{paddings.first};
Shape padding_below_shape{std::begin(padding_below), std::end(padding_below)}; Shape padding_below_shape{std::begin(padding_below), std::end(padding_below)};
Shape padding_above_shape{std::begin(padding_above), std::end(padding_above)}; Shape padding_above_shape{std::begin(padding_above), std::end(padding_above)};
......
ONNXNgraphImporter:
|
A
BC"Conv*
auto_pad*
dilations@@*
group*
kernel_shape@@*
pads@@@@*
strides@@ compute_graphZ
A




Z
B




b
C




B
\ No newline at end of file
ONNXNgraphImporter:

A
B
CD"Conv*
auto_pad*
dilations@@@*
group*
kernel_shape@@@*
pads@@@@@@*
strides@@@ compute_graphZ
A





Z
B





Z
C

b
D





B
\ No newline at end of file
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment