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
{
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>>(
"kernel_shape", std::vector<std::size_t>(input_spacial_dims, 1UL));
"kernel_shape", std::vector<std::size_t>(input_spatial_dims, 1UL));
}
namespace detail
......@@ -64,38 +64,67 @@ namespace ngraph
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.
auto pad_value = [](size_t dim) {
return (static_cast<float>(dim) - 1.f) / 2.f;
};
Shape get_pad_shape(const Shape& input,
const Shape& kernel,
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")
{
for (size_t dim : kernel_shape)
{
pads.emplace_back(std::floor(pad_value(dim)));
}
for (size_t dim : kernel_shape)
for (size_t pad : pad_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")
{
for (size_t dim : kernel_shape)
for (size_t pad : pad_shape)
{
pads.emplace_back(std::ceil(pad_value(dim)));
}
for (size_t dim : kernel_shape)
{
pads.emplace_back(std::floor(pad_value(dim)));
// Integer division
pads_end.emplace_back(pad / 2);
pads_begin.emplace_back(pad - pads_end.back());
}
}
CoordinateDiff pads{pads_begin};
pads.insert(std::end(pads), std::begin(pads_end), std::end(pads_end));
return pads;
}
......@@ -115,7 +144,10 @@ namespace ngraph
std::string auto_pad{node.get_attribute_value<std::string>("auto_pad", "")};
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())
......@@ -130,8 +162,8 @@ namespace ngraph
}
else
{
return {{std::begin(pads) + pads.size() / 2, std::end(pads)},
{std::begin(pads), std::begin(pads) + pads.size() / 2}};
return {{std::begin(pads), std::begin(pads) + pads.size() / 2},
{std::begin(pads) + pads.size() / 2, std::end(pads)}};
}
}
......
......@@ -118,8 +118,8 @@ namespace ngraph
bool count_include_pad = node.get_attribute_value<int64_t>("count_include_pad", 0);
// Convert padding from CoordinateDiff to Shape objects
const CoordinateDiff& padding_above{paddings.first};
const CoordinateDiff& padding_below{paddings.second};
const CoordinateDiff& padding_above{paddings.second};
const CoordinateDiff& padding_below{paddings.first};
Shape padding_below_shape{std::begin(padding_below), std::end(padding_below)};
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