Commit 1ce31a49 authored by Tomasz Socha's avatar Tomasz Socha Committed by Michał Karzyński

[SPEC] Add v1:Convolution operator (#3636)

parent ac4676ff
......@@ -25,16 +25,475 @@
using namespace std;
using namespace ngraph;
constexpr NodeTypeInfo op::Convolution::type_info;
op::Convolution::Convolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& window_movement_strides,
const Strides& window_dilation_strides,
const CoordinateDiff& padding_below,
const CoordinateDiff& padding_above,
const Strides& data_dilation_strides,
const PadType& pad_type)
// *** Convolution OP SET 1 ***
constexpr NodeTypeInfo op::v1::Convolution::type_info;
op::v1::Convolution::Convolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& strides,
const CoordinateDiff& pads_begin,
const CoordinateDiff& pads_end,
const Strides& dilations,
const PadType& auto_pad)
: Op({data_batch, filters})
, m_strides(strides)
, m_dilations(dilations)
, m_pads_begin(pads_begin)
, m_pads_end(pads_end)
, m_auto_pad(auto_pad)
{
constructor_validate_and_infer_types();
}
void op::v1::Convolution::validate_and_infer_types()
{
const PartialShape& data_batch_shape = get_input_partial_shape(0);
element::Type data_batch_et = get_input_element_type(0);
const PartialShape& filters_shape = get_input_partial_shape(1);
element::Type filters_et = get_input_element_type(1);
if (m_strides.size() == 0)
{
m_strides = conv_default_strides(this, data_batch_shape, filters_shape);
}
if (m_dilations.size() == 0)
{
m_dilations = conv_default_strides(this, data_batch_shape, filters_shape);
}
if (m_pads_begin.size() == 0)
{
m_pads_begin = conv_default_padding(this, data_batch_shape, filters_shape);
}
if (m_pads_end.size() == 0)
{
m_pads_end = conv_default_padding(this, data_batch_shape, filters_shape);
}
if (m_auto_pad == PadType::SAME_UPPER || m_auto_pad == PadType::SAME_LOWER)
{
if (data_batch_shape.is_static() && filters_shape.is_static())
{
m_pads_begin.clear();
m_pads_end.clear();
auto filter_shape = filters_shape.to_shape();
filter_shape.erase(filter_shape.begin(), filter_shape.begin() + 2); // Remove {O,I}
infer_auto_padding(data_batch_shape.to_shape(),
filter_shape,
m_strides,
m_dilations,
m_auto_pad,
m_pads_end,
m_pads_begin);
}
}
element::Type result_et;
PartialShape result_shape;
NODE_VALIDATION_CHECK(
this,
element::Type::merge(result_et, data_batch_et, filters_et),
"Element types for data batch and filters do not match (data batch element type: ",
data_batch_et,
", filters element type: ",
filters_et,
").");
result_shape =
infer_convolution_forward(this,
data_batch_shape,
Strides(static_cast<size_t>(data_batch_shape.rank()) - 2, 1),
m_pads_begin,
m_pads_end,
filters_shape,
m_strides,
m_dilations);
set_output_type(0, result_et, result_shape);
}
shared_ptr<Node> op::v1::Convolution::copy_with_new_args(const NodeVector& new_args) const
{
check_new_args_count(this, new_args);
return make_shared<v1::Convolution>(new_args.at(0),
new_args.at(1),
m_strides,
m_pads_begin,
m_pads_end,
m_dilations,
m_auto_pad);
}
void op::v1::Convolution::generate_adjoints(autodiff::Adjoints& adjoints, const NodeVector& deltas)
{
auto delta = deltas.at(0);
auto x = input_value(0);
const auto x_shape = x.get_shape();
auto f = input_value(1);
const auto f_shape = f.get_shape();
adjoints.add_delta(x,
make_shared<op::v1::ConvolutionBackpropData>(
x_shape, f, delta, m_strides, m_dilations, m_pads_begin, m_pads_end));
adjoints.add_delta(f,
make_shared<op::v1::ConvolutionBackpropFilters>(
x, f_shape, delta, m_strides, m_dilations, m_pads_begin, m_pads_end));
}
constexpr NodeTypeInfo op::v1::ConvolutionBackpropData::type_info;
shared_ptr<Node> op::v1::Convolution::get_default_value() const
{
return ngraph::make_constant_from_string("0", get_element_type(), get_shape());
}
op::v1::ConvolutionBackpropData::ConvolutionBackpropData(const Shape& data_batch_shape,
const Output<Node>& filters,
const Output<Node>& output_delta,
const Strides& strides,
const Strides& dilations,
const CoordinateDiff& pads_begin,
const CoordinateDiff& pads_end)
: Op({filters, output_delta})
, m_data_batch_shape(data_batch_shape)
, m_strides(strides)
, m_dilations(dilations)
, m_pads_begin(pads_begin)
, m_pads_end(pads_end)
{
constructor_validate_and_infer_types();
}
void op::v1::ConvolutionBackpropData::validate_and_infer_types()
{
// Backprop to data is itself convolution, with inputs/outputs/attributes transmogrified as
// follows.
//
// Forward Backward
// "N" axis for data batch 0 0
// "C" axis for data batch 1 1
// "Co" axis for filters 0 0
// "Ci" axis for filters 1 1
// "N" axis for output 0 0
// "C" axis for output 1 1
// Data batch x delta
// Data batch shape S_x S_o
// Filters f reverse(f) [on spatial axes]
// Filters shape S_f S_f
// Window movement strides q_x p_x
// Window dilation strides p_f p_f
// Padding below a_x (S_f - 1)p_f - a_x
// Padding above b_x (S_f - 1)p_f +
// + ((a_x + (S_x - 1)p_x + b_x - (S_f - 1)p_f)
// % q_x)
// - b_x
// Output shape S_o S_x
//
// To _validate_, we simply need to check/infer the output shape of the forward convolution,
// then check to make sure that the incoming delta has the same shape as the forward output.
const PartialShape& filters_shape = get_input_partial_shape(0);
element::Type filters_et = get_input_element_type(0);
const PartialShape& delta_shape = get_input_partial_shape(1);
element::Type delta_et = get_input_element_type(1);
element::Type forward_result_et;
PartialShape forward_result_shape;
NODE_VALIDATION_CHECK(
this,
element::Type::merge(forward_result_et, delta_et, filters_et),
"Element types for data batch and filters do not match (data batch element type: ",
delta_et,
", filters element type: ",
filters_et,
").");
forward_result_shape = infer_convolution_forward(this,
m_data_batch_shape,
Strides(m_data_batch_shape.size() - 2, 0),
m_pads_begin,
m_pads_end,
filters_shape,
m_strides,
m_dilations);
NODE_VALIDATION_CHECK(this,
forward_result_shape.compatible(delta_shape),
"Inferred forward output shape (",
forward_result_shape,
") does not match shape of ",
"delta (",
delta_shape,
").");
set_output_type(0, forward_result_et, m_data_batch_shape);
}
void op::v1::ConvolutionBackpropData::generate_adjoints(autodiff::Adjoints& adjoints,
const NodeVector& deltas)
{
auto delta = deltas.at(0);
auto x = input_value(1);
const auto x_shape = x.get_shape();
auto f = input_value(0);
const auto f_shape = f.get_shape();
auto data_conv = make_shared<op::v1::Convolution>(
delta, f, m_strides, m_pads_begin, m_pads_end, m_dilations);
adjoints.add_delta(x, data_conv);
Strides strides = m_dilations;
CoordinateDiff pads_begin;
CoordinateDiff pads_end;
const Shape& filters_shape = get_input_shape(0);
for (size_t i = 0; i < f_shape.size() - 2; i++)
{
ptrdiff_t pads_begin_backward =
(static_cast<ptrdiff_t>(filters_shape[i + 2]) - 1) - m_pads_begin[i];
pads_begin.push_back(pads_begin_backward);
ptrdiff_t pads_end_backward =
(static_cast<ptrdiff_t>(filters_shape[i + 2]) - 1) * m_dilations[i] +
((m_pads_begin[i] + ((m_data_batch_shape[i + 2]) - 1) * m_strides[i] + m_pads_end[i] -
(static_cast<ptrdiff_t>(filters_shape[i + 2]) - 1) * m_dilations[i]) %
m_strides[i]) -
m_pads_end[i];
pads_end.push_back(pads_end_backward -
(pads_begin_backward + (x_shape[i + 2] - 1) * m_strides[i] +
pads_end_backward - (f_shape[i + 2] - 1) * m_dilations[i]) %
m_strides[i]);
}
auto swap_NC = [](const Output<Node>& n) {
AxisVector ax_order = ngraph::get_default_order(n.get_shape());
ax_order[0] = 1;
ax_order[1] = 0;
auto new_shape = n.get_shape();
new_shape[0] = n.get_shape()[1];
new_shape[1] = n.get_shape()[0];
return make_shared<op::Reshape>(n, ax_order, new_shape);
};
delta = swap_NC(delta);
x = swap_NC(x);
shared_ptr<Node> filter_deconv_bprop = make_shared<op::v1::Convolution>(
x, delta, strides, pads_begin, pads_end, Strides(x.get_shape().size() - 2, 1));
AxisSet axes;
for (size_t i = 2; i < filter_deconv_bprop->get_shape().size(); ++i)
{
axes.insert(i);
}
filter_deconv_bprop = make_shared<ngraph::op::Reverse>(filter_deconv_bprop, axes);
adjoints.add_delta(f, filter_deconv_bprop);
}
shared_ptr<Node>
op::v1::ConvolutionBackpropData::copy_with_new_args(const NodeVector& new_args) const
{
check_new_args_count(this, new_args);
return make_shared<v1::ConvolutionBackpropData>(m_data_batch_shape,
new_args.at(0),
new_args.at(1),
m_strides,
m_dilations,
m_pads_begin,
m_pads_end);
}
CoordinateDiff op::v1::ConvolutionBackpropData::compute_backward_delta_out_pad_below() const
{
auto& in_shape = get_data_batch_shape();
auto& filter_dilation = get_dilations();
auto& filter_shape = get_input_shape(0);
auto& in_pad_below = get_pads_begin();
size_t spatial_dim_count = static_cast<size_t>(in_shape.size()) - 2;
CoordinateDiff backward_delta_out_pad_below;
backward_delta_out_pad_below.resize(spatial_dim_count);
for (size_t i = 0; i < spatial_dim_count; i++)
{
backward_delta_out_pad_below[i] =
(static_cast<ptrdiff_t>(filter_shape[i + 2]) - 1) * filter_dilation[i] -
in_pad_below[i];
}
return backward_delta_out_pad_below;
}
CoordinateDiff op::v1::ConvolutionBackpropData::compute_backward_delta_out_pad_above() const
{
auto& in_shape = get_data_batch_shape();
auto& filter_dilation = get_dilations();
auto& filter_shape = get_input_shape(0);
auto& in_pad_below = get_pads_begin();
auto& in_pad_above = get_pads_end();
auto& stride = get_strides();
size_t spatial_dim_count = static_cast<size_t>(in_shape.size()) - 2;
CoordinateDiff backward_delta_out_pad_above;
backward_delta_out_pad_above.resize(spatial_dim_count);
for (size_t i = 0; i < spatial_dim_count; i++)
{
backward_delta_out_pad_above[i] =
(static_cast<ptrdiff_t>(filter_shape[i + 2]) - 1) * filter_dilation[i] +
((in_pad_below[i] + ((in_shape[i + 2]) - 1) + in_pad_above[i] -
(static_cast<ptrdiff_t>(filter_shape[i + 2]) - 1) * filter_dilation[i]) %
stride[i]) -
in_pad_above[i];
}
return backward_delta_out_pad_above;
}
constexpr NodeTypeInfo op::v1::ConvolutionBackpropFilters::type_info;
op::v1::ConvolutionBackpropFilters::ConvolutionBackpropFilters(const Output<Node>& data_batch,
const Shape& filters_shape,
const Output<Node>& output_delta,
const Strides& strides,
const Strides& dilations,
const CoordinateDiff& pads_begin,
const CoordinateDiff& pads_end)
: Op({data_batch, output_delta})
, m_filters_shape(filters_shape)
, m_strides(strides)
, m_dilations(dilations)
, m_pads_begin(pads_begin)
, m_pads_end(pads_end)
{
constructor_validate_and_infer_types();
}
void op::v1::ConvolutionBackpropFilters::validate_and_infer_types()
{
// Backprop to filters is itself convolution, with inputs/outputs/attributes transmogrified as
// follows.
//
// Forward Backward
// "N" axis for data batch 0 1
// "C" axis for data batch 1 0
// "Co" axis for filters 0 0
// "Ci" axis for filters 1 1
// "N" axis for output 0 1
// "C" axis for output 1 0
// Data batch x x
// Data batch shape S_x S_x
// Filters f delta
// Filters shape S_f S_f
// Window movement strides q_x p_f
// Window dilation strides p_f q_x
// Padding below a_x a_x
// Padding above b_x b_x - (a_x + (S_x - 1)p_x + b_x - (S_f - 1)p_f) % q_x
// Output shape S_o S_f
//
// To _validate_, we simply need to check/infer the output shape of the forward convolution,
// then check to make sure that the incoming delta has the same shape as the forward output.
//
// We will also compute and store the various parameters in the "backward" column above, since
// some backends need them. (TODO(amprocte): Is it just because of the way the reference works
// that this stuff is needed? If so, we can probably get rid of it and have conv_backprop
// reference kernels that do the calculations of the backward parameters internally, or supply
// utility functions to do it.)
const PartialShape& data_batch_shape = get_input_partial_shape(0);
element::Type data_batch_et = get_input_element_type(0);
const PartialShape& delta_shape = get_input_partial_shape(1);
element::Type delta_et = get_input_element_type(1);
element::Type forward_result_et;
PartialShape forward_result_shape;
NODE_VALIDATION_CHECK(
this,
element::Type::merge(forward_result_et, data_batch_et, delta_et),
"Element types for data batch and filters do not match (data batch element type: ",
data_batch_et,
", filters element type: ",
delta_et,
").");
forward_result_shape =
infer_convolution_forward(this,
data_batch_shape,
Strides(static_cast<size_t>(data_batch_shape.rank()) - 2, 1),
m_pads_begin,
m_pads_end,
m_filters_shape,
m_strides,
m_dilations);
NODE_VALIDATION_CHECK(this,
forward_result_shape.compatible(delta_shape),
"Inferred forward output shape (",
forward_result_shape,
") does not match shape of ",
"delta (",
delta_shape,
").");
set_output_type(0, forward_result_et, m_filters_shape);
}
shared_ptr<Node>
op::v1::ConvolutionBackpropFilters::copy_with_new_args(const NodeVector& new_args) const
{
check_new_args_count(this, new_args);
return make_shared<v1::ConvolutionBackpropFilters>(new_args.at(0),
m_filters_shape,
new_args.at(1),
m_strides,
m_dilations,
m_pads_begin,
m_pads_end);
}
CoordinateDiff op::v1::ConvolutionBackpropFilters::compute_backward_in_pad_above() const
{
const auto& in_shape = get_input_shape(0);
const auto& out_shape = get_input_shape(1);
const auto& filter_shape = get_filters_shape();
const auto& in_pad_above = get_pads_end();
const auto& in_pad_below = get_pads_begin();
const auto& filter_dilation = get_dilations();
const auto& stride = get_strides();
size_t spatial_dim_count = static_cast<size_t>(out_shape.size()) - 2;
CoordinateDiff backward_in_pad_above;
backward_in_pad_above.resize(spatial_dim_count);
for (size_t i = 0; i < spatial_dim_count; i++)
{
backward_in_pad_above[i] =
in_pad_above[i] -
(in_pad_below[i] + (static_cast<ptrdiff_t>(in_shape[i + 2]) - 1) + in_pad_above[i] -
(filter_shape[i + 2] - 1) * filter_dilation[i]) %
stride[i];
}
return backward_in_pad_above;
}
// *** Convolution OP SET 0 ***
constexpr NodeTypeInfo op::v0::Convolution::type_info;
op::v0::Convolution::Convolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& window_movement_strides,
const Strides& window_dilation_strides,
const CoordinateDiff& padding_below,
const CoordinateDiff& padding_above,
const Strides& data_dilation_strides,
const PadType& pad_type)
: Op({data_batch, filters})
, m_window_movement_strides(window_movement_strides)
, m_window_dilation_strides(window_dilation_strides)
......@@ -46,7 +505,7 @@ op::Convolution::Convolution(const Output<Node>& data_batch,
constructor_validate_and_infer_types();
}
void op::Convolution::validate_and_infer_types()
void op::v0::Convolution::validate_and_infer_types()
{
const PartialShape& data_batch_shape = get_input_partial_shape(0);
element::Type data_batch_et = get_input_element_type(0);
......@@ -121,12 +580,12 @@ void op::Convolution::validate_and_infer_types()
set_output_type(0, result_et, result_shape);
}
op::Convolution::Convolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& window_movement_strides,
const Strides& window_dilation_strides,
const CoordinateDiff& padding_below,
const CoordinateDiff& padding_above)
op::v0::Convolution::Convolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& window_movement_strides,
const Strides& window_dilation_strides,
const CoordinateDiff& padding_below,
const CoordinateDiff& padding_above)
: Convolution(data_batch,
filters,
window_movement_strides,
......@@ -137,10 +596,10 @@ op::Convolution::Convolution(const Output<Node>& data_batch,
{
}
op::Convolution::Convolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& window_movement_strides,
const Strides& window_dilation_strides)
op::v0::Convolution::Convolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& window_movement_strides,
const Strides& window_dilation_strides)
: Convolution(data_batch,
filters,
window_movement_strides,
......@@ -150,9 +609,9 @@ op::Convolution::Convolution(const Output<Node>& data_batch,
{
}
op::Convolution::Convolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& window_movement_strides)
op::v0::Convolution::Convolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& window_movement_strides)
: Convolution(data_batch,
filters,
window_movement_strides,
......@@ -162,25 +621,25 @@ op::Convolution::Convolution(const Output<Node>& data_batch,
{
}
op::Convolution::Convolution(const Output<Node>& data_batch, const Output<Node>& filters)
op::v0::Convolution::Convolution(const Output<Node>& data_batch, const Output<Node>& filters)
: Convolution(data_batch, filters, Strides(), Strides(), CoordinateDiff(), CoordinateDiff())
{
}
shared_ptr<Node> op::Convolution::copy_with_new_args(const NodeVector& new_args) const
shared_ptr<Node> op::v0::Convolution::copy_with_new_args(const NodeVector& new_args) const
{
check_new_args_count(this, new_args);
return make_shared<Convolution>(new_args.at(0),
new_args.at(1),
m_window_movement_strides,
m_window_dilation_strides,
m_padding_below,
m_padding_above,
m_data_dilation_strides,
m_pad_type);
return make_shared<v0::Convolution>(new_args.at(0),
new_args.at(1),
m_window_movement_strides,
m_window_dilation_strides,
m_padding_below,
m_padding_above,
m_data_dilation_strides,
m_pad_type);
}
void op::Convolution::generate_adjoints(autodiff::Adjoints& adjoints, const NodeVector& deltas)
void op::v0::Convolution::generate_adjoints(autodiff::Adjoints& adjoints, const NodeVector& deltas)
{
auto delta = deltas.at(0);
......@@ -191,40 +650,41 @@ void op::Convolution::generate_adjoints(autodiff::Adjoints& adjoints, const Node
const auto f_shape = f.get_shape();
adjoints.add_delta(x,
make_shared<op::ConvolutionBackpropData>(x_shape,
f,
delta,
m_window_movement_strides,
m_window_dilation_strides,
m_padding_below,
m_padding_above,
m_data_dilation_strides));
make_shared<op::v0::ConvolutionBackpropData>(x_shape,
f,
delta,
m_window_movement_strides,
m_window_dilation_strides,
m_padding_below,
m_padding_above,
m_data_dilation_strides));
adjoints.add_delta(f,
make_shared<op::ConvolutionBackpropFilters>(x,
f_shape,
delta,
m_window_movement_strides,
m_window_dilation_strides,
m_padding_below,
m_padding_above,
m_data_dilation_strides));
make_shared<op::v0::ConvolutionBackpropFilters>(x,
f_shape,
delta,
m_window_movement_strides,
m_window_dilation_strides,
m_padding_below,
m_padding_above,
m_data_dilation_strides));
}
constexpr NodeTypeInfo op::ConvolutionBackpropData::type_info;
shared_ptr<Node> op::Convolution::get_default_value() const
constexpr NodeTypeInfo op::v0::ConvolutionBackpropData::type_info;
shared_ptr<Node> op::v0::Convolution::get_default_value() const
{
return ngraph::make_constant_from_string("0", get_element_type(), get_shape());
}
op::ConvolutionBackpropData::ConvolutionBackpropData(const Shape& data_batch_shape,
const Output<Node>& filters,
const Output<Node>& output_delta,
const Strides& window_movement_strides_forward,
const Strides& window_dilation_strides_forward,
const CoordinateDiff& padding_below_forward,
const CoordinateDiff& padding_above_forward,
const Strides& data_dilation_strides_forward)
op::v0::ConvolutionBackpropData::ConvolutionBackpropData(
const Shape& data_batch_shape,
const Output<Node>& filters,
const Output<Node>& output_delta,
const Strides& window_movement_strides_forward,
const Strides& window_dilation_strides_forward,
const CoordinateDiff& padding_below_forward,
const CoordinateDiff& padding_above_forward,
const Strides& data_dilation_strides_forward)
: Op({filters, output_delta})
, m_data_batch_shape(data_batch_shape)
, m_window_movement_strides_forward(window_movement_strides_forward)
......@@ -236,7 +696,7 @@ op::ConvolutionBackpropData::ConvolutionBackpropData(const Shape& data_batch_sha
constructor_validate_and_infer_types();
}
void op::ConvolutionBackpropData::validate_and_infer_types()
void op::v0::ConvolutionBackpropData::validate_and_infer_types()
{
// Backprop to data is itself convolution, with inputs/outputs/attributes transmogrified as
// follows.
......@@ -302,8 +762,8 @@ void op::ConvolutionBackpropData::validate_and_infer_types()
set_output_type(0, forward_result_et, m_data_batch_shape);
}
void op::ConvolutionBackpropData::generate_adjoints(autodiff::Adjoints& adjoints,
const NodeVector& deltas)
void op::v0::ConvolutionBackpropData::generate_adjoints(autodiff::Adjoints& adjoints,
const NodeVector& deltas)
{
auto delta = deltas.at(0);
......@@ -313,13 +773,13 @@ void op::ConvolutionBackpropData::generate_adjoints(autodiff::Adjoints& adjoints
auto f = input_value(0);
const auto f_shape = f.get_shape();
auto data_conv = make_shared<op::Convolution>(delta,
f,
m_window_movement_strides_forward,
m_window_dilation_strides_forward,
m_padding_below_forward,
m_padding_above_forward,
m_data_dilation_strides_forward);
auto data_conv = make_shared<op::v0::Convolution>(delta,
f,
m_window_movement_strides_forward,
m_window_dilation_strides_forward,
m_padding_below_forward,
m_padding_above_forward,
m_data_dilation_strides_forward);
adjoints.add_delta(x, data_conv);
......@@ -369,13 +829,13 @@ void op::ConvolutionBackpropData::generate_adjoints(autodiff::Adjoints& adjoints
delta = swap_NC(delta);
x = swap_NC(x);
shared_ptr<Node> filter_deconv_bprop = make_shared<op::Convolution>(x,
delta,
window_movement_strides,
window_dilation_strides,
padding_below,
padding_above,
data_dilation_strides);
shared_ptr<Node> filter_deconv_bprop = make_shared<op::v0::Convolution>(x,
delta,
window_movement_strides,
window_dilation_strides,
padding_below,
padding_above,
data_dilation_strides);
AxisSet axes;
for (size_t i = 2; i < filter_deconv_bprop->get_shape().size(); ++i)
{
......@@ -385,20 +845,21 @@ void op::ConvolutionBackpropData::generate_adjoints(autodiff::Adjoints& adjoints
adjoints.add_delta(f, filter_deconv_bprop);
}
shared_ptr<Node> op::ConvolutionBackpropData::copy_with_new_args(const NodeVector& new_args) const
shared_ptr<Node>
op::v0::ConvolutionBackpropData::copy_with_new_args(const NodeVector& new_args) const
{
check_new_args_count(this, new_args);
return make_shared<ConvolutionBackpropData>(m_data_batch_shape,
new_args.at(0),
new_args.at(1),
m_window_movement_strides_forward,
m_window_dilation_strides_forward,
m_padding_below_forward,
m_padding_above_forward,
m_data_dilation_strides_forward);
return make_shared<v0::ConvolutionBackpropData>(m_data_batch_shape,
new_args.at(0),
new_args.at(1),
m_window_movement_strides_forward,
m_window_dilation_strides_forward,
m_padding_below_forward,
m_padding_above_forward,
m_data_dilation_strides_forward);
}
CoordinateDiff op::ConvolutionBackpropData::compute_backward_delta_out_pad_below() const
CoordinateDiff op::v0::ConvolutionBackpropData::compute_backward_delta_out_pad_below() const
{
auto& in_shape = get_data_batch_shape();
auto& filter_dilation = get_window_dilation_strides_forward();
......@@ -418,7 +879,7 @@ CoordinateDiff op::ConvolutionBackpropData::compute_backward_delta_out_pad_below
return backward_delta_out_pad_below;
}
CoordinateDiff op::ConvolutionBackpropData::compute_backward_delta_out_pad_above() const
CoordinateDiff op::v0::ConvolutionBackpropData::compute_backward_delta_out_pad_above() const
{
auto& in_shape = get_data_batch_shape();
auto& filter_dilation = get_window_dilation_strides_forward();
......@@ -444,9 +905,9 @@ CoordinateDiff op::ConvolutionBackpropData::compute_backward_delta_out_pad_above
return backward_delta_out_pad_above;
}
constexpr NodeTypeInfo op::ConvolutionBackpropFilters::type_info;
constexpr NodeTypeInfo op::v0::ConvolutionBackpropFilters::type_info;
op::ConvolutionBackpropFilters::ConvolutionBackpropFilters(
op::v0::ConvolutionBackpropFilters::ConvolutionBackpropFilters(
const Output<Node>& data_batch,
const Shape& filters_shape,
const Output<Node>& output_delta,
......@@ -466,7 +927,7 @@ op::ConvolutionBackpropFilters::ConvolutionBackpropFilters(
constructor_validate_and_infer_types();
}
void op::ConvolutionBackpropFilters::validate_and_infer_types()
void op::v0::ConvolutionBackpropFilters::validate_and_infer_types()
{
// Backprop to filters is itself convolution, with inputs/outputs/attributes transmogrified as
// follows.
......@@ -537,20 +998,20 @@ void op::ConvolutionBackpropFilters::validate_and_infer_types()
}
shared_ptr<Node>
op::ConvolutionBackpropFilters::copy_with_new_args(const NodeVector& new_args) const
op::v0::ConvolutionBackpropFilters::copy_with_new_args(const NodeVector& new_args) const
{
check_new_args_count(this, new_args);
return make_shared<ConvolutionBackpropFilters>(new_args.at(0),
m_filters_shape,
new_args.at(1),
m_window_movement_strides_forward,
m_window_dilation_strides_forward,
m_padding_below_forward,
m_padding_above_forward,
m_data_dilation_strides_forward);
return make_shared<v0::ConvolutionBackpropFilters>(new_args.at(0),
m_filters_shape,
new_args.at(1),
m_window_movement_strides_forward,
m_window_dilation_strides_forward,
m_padding_below_forward,
m_padding_above_forward,
m_data_dilation_strides_forward);
}
CoordinateDiff op::ConvolutionBackpropFilters::compute_backward_in_pad_above() const
CoordinateDiff op::v0::ConvolutionBackpropFilters::compute_backward_in_pad_above() const
{
const auto& in_shape = get_input_shape(0);
const auto& out_shape = get_input_shape(1);
......
......@@ -24,373 +24,588 @@ namespace ngraph
{
namespace op
{
/// \brief Batched convolution operation, with optional window dilation and stride.
///
class Convolution : public Op
namespace v1
{
public:
NGRAPH_API
static constexpr NodeTypeInfo type_info{"Convolution", 0};
const NodeTypeInfo& get_type_info() const override { return type_info; }
/// \brief Constructs a batched convolution operation.
Convolution() = default;
/// \brief Constructs a batched convolution operation.
/// \brief Batched convolution operation, with optional window dilation and stride.
///
/// \param data_batch The node producing the input data batch tensor.<br>
/// `[N, C_IN, D1, ... Df]`
/// \param filters The node producing the filters tensor.<br>
/// `[C_OUT, C_IN, F1, ... Ff]`
/// \param window_movement_strides The window movement strides.<br>
/// `[f]`
/// \param window_dilation_strides The window dilation strides.<br>
/// `[f]`
/// \param padding_below The padding-below sizes.<br>
/// `[f]`
/// \param padding_above The padding-above sizes.<br>
/// `[f]`
/// \param data_dilation_strides The data dilation strides.<br>
/// `[f]`
/// \param pad_type The pad type for automatically computing padding sizes.<br>
/// `[f]`
///
/// Output `[N, C_OUT, R1, ... Rf]`
///
Convolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& window_movement_strides,
const Strides& window_dilation_strides,
const CoordinateDiff& padding_below,
const CoordinateDiff& padding_above,
const Strides& data_dilation_strides,
const PadType& pad_type = PadType::EXPLICIT);
/// \brief Constructs a batched convolution operation with no data dilation (i.e., all
/// data dilation strides are 1).
///
/// \param data_batch The node producing the input data batch tensor.<br>
/// `[N, C_IN, D1, ... Df]`
/// \param filters The node producing the filters tensor.<br>
/// `[C_OUT, C_IN, F1, ... Ff]`
/// \param window_movement_strides The window movement strides.<br>
/// `[f]`
/// \param window_dilation_strides The window dilation strides.<br>
/// `[f]`
/// \param padding_below The padding-below sizes.<br>
/// `[f]`
/// \param padding_above The padding-above sizes.<br>
/// `[f]`
///
/// Output `[N, C_OUT, R1, ... Rf]`
///
Convolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& window_movement_strides,
const Strides& window_dilation_strides,
const CoordinateDiff& padding_below,
const CoordinateDiff& padding_above);
/// \brief Constructs a batched convolution operation with no padding or data dilation
/// (i.e., padding above and below are 0 everywhere, and all data dilation
/// strides are 1).
///
/// \param data_batch The node producing the input data batch tensor.<br>
/// `[N, C_IN, D1, ... Df]`
/// \param filters The node producing the filters tensor.<br>
/// `[C_OUT, C_IN, F1, ... Ff]`
/// \param window_movement_strides The window movement strides.<br>
/// `[f]`
/// \param window_dilation_strides The window dilation strides.<br>
/// `[f]`
///
/// Output `[N, C_OUT, R1, ... Rf]`
///
Convolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& window_movement_strides,
const Strides& window_dilation_strides);
/// \brief Constructs a batched convolution operation with no window dilation, padding,
/// or data dilation (i.e., padding above and below are 0 everywhere, and all
/// window/data dilation strides are 1).
///
/// \param data_batch The node producing the input data batch tensor.<br>
/// `[N, C_IN, D1, ... Df]`
/// \param filters The node producing the filters tensor.<br>
/// `[C_OUT, C_IN, F1, ... Ff]`
/// \param window_movement_strides The window movement strides.<br>
/// `[f]`
///
/// Output `[N, C_OUT, R1, ... Rf]`
///
Convolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& window_movement_strides);
class Convolution : public Op
{
public:
NGRAPH_API
static constexpr NodeTypeInfo type_info{"Convolution", 1};
const NodeTypeInfo& get_type_info() const override { return type_info; }
/// \brief Constructs a batched convolution operation.
Convolution() = default;
/// \brief Constructs a batched convolution operation.
///
/// \param data_batch The node producing the input data batch tensor.<br>
/// `[N, C_IN, D1, ... Df]`
/// \param filters The node producing the filters tensor.<br>
/// `[C_OUT, C_IN, F1, ... Ff]`
/// \param strides The strides.<br>
/// `[f]`
/// \param dilations The dilations.<br>
/// `[f]`
/// \param pads_begin The beginning of padding shape.<br>
/// `[f]`
/// \param pads_end The end of padding shape.<br>
/// `[f]`
/// \param auto_pad The pad type for automatically computing padding sizes.<br>
/// `[f]`
///
/// Output `[N, C_OUT, R1, ... Rf]`
///
Convolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& strides,
const CoordinateDiff& pads_begin,
const CoordinateDiff& pads_end,
const Strides& dilations,
const PadType& auto_pad = PadType::EXPLICIT);
/// \brief Constructs a batched convolution operation with no window dilation or
/// movement stride (i.e., padding above and below are 0 everywhere, and all
/// window/data dilation strides and window movement strides are 1).
///
/// \param data_batch The node producing the input data batch tensor.<br>
/// `[N, C_IN, D1, ... Df]`
/// \param filters The node producing the filters tensor.<br>
/// `[C_OUT, C_IN, F1, ... Ff]`
///
/// Output `[N, C_OUT, R1, ... Rf]`
///
Convolution(const Output<Node>& data_batch, const Output<Node>& filters);
size_t get_version() const override { return 1; }
void validate_and_infer_types() override;
void validate_and_infer_types() override;
virtual std::shared_ptr<Node>
copy_with_new_args(const NodeVector& new_args) const override;
void generate_adjoints(autodiff::Adjoints& adjoints,
const NodeVector& deltas) override;
virtual std::shared_ptr<Node>
copy_with_new_args(const NodeVector& new_args) const override;
void generate_adjoints(autodiff::Adjoints& adjoints, const NodeVector& deltas) override;
/// \return The strides.
const Strides& get_strides() const { return m_strides; }
void set_strides(const Strides& strides) { m_strides = strides; }
/// \return The dilations.
const Strides& get_dilations() const { return m_dilations; }
void set_dilations(const Strides& dilations) { m_dilations = dilations; }
/// \return The padding-below sizes (possibly negative).
const CoordinateDiff& get_pads_begin() const { return m_pads_begin; }
void set_pads_begin(const CoordinateDiff& pads_begin) { m_pads_begin = pads_begin; }
/// \return The padding-above sizes (possibly negative).
const CoordinateDiff& get_pads_end() const { return m_pads_end; }
void set_adding_above(const CoordinateDiff& pads_end) { m_pads_end = pads_end; }
/// \return The pad type for convolution.
const PadType& get_auto_pad() const { return m_auto_pad; }
void set_auto_pad(const PadType& auto_pad) { m_auto_pad = auto_pad; }
/// \return The default value for Convolution.
virtual std::shared_ptr<Node> get_default_value() const override;
/// \return The window movement strides.
const Strides& get_window_movement_strides() const { return m_window_movement_strides; }
void set_window_movement_strides(const Strides& window_movement_strides)
{
m_window_movement_strides = window_movement_strides;
}
/// \return The window dilation strides.
const Strides& get_window_dilation_strides() const { return m_window_dilation_strides; }
void set_window_dilation_strides(const Strides& window_dilation_strides)
{
m_window_dilation_strides = window_dilation_strides;
}
/// \return The padding-below sizes (possibly negative).
const CoordinateDiff& get_padding_below() const { return m_padding_below; }
void set_padding_below(const CoordinateDiff& padding_below)
{
m_padding_below = padding_below;
}
/// \return The padding-above sizes (possibly negative).
const CoordinateDiff& get_padding_above() const { return m_padding_above; }
void set_adding_above(const CoordinateDiff& padding_above)
{
m_padding_above = padding_above;
}
/// \return The input data dilation strides.
const Strides& get_data_dilation_strides() const { return m_data_dilation_strides; }
void set_data_dilation_strides(const Strides& data_dilation_strides)
{
m_data_dilation_strides = data_dilation_strides;
}
/// \return The pad type for convolution.
const PadType& get_pad_type() const { return m_pad_type; }
void set_pad_type(const PadType& pad_type) { m_pad_type = pad_type; }
/// \return The default value for Convolution.
virtual std::shared_ptr<Node> get_default_value() const override;
protected:
Strides m_window_movement_strides;
Strides m_window_dilation_strides;
CoordinateDiff m_padding_below;
CoordinateDiff m_padding_above;
Strides m_data_dilation_strides;
PadType m_pad_type;
};
/// \brief Data batch backprop for batched convolution operation.
class ConvolutionBackpropData : public Op
{
public:
NGRAPH_API
static constexpr NodeTypeInfo type_info{"ConvolutionBackpropData", 0};
const NodeTypeInfo& get_type_info() const override { return type_info; }
/// \brief Constructs a batched-convolution data batch-backprop operation.
ConvolutionBackpropData() = default;
/// \brief Constructs a batched-convolution data batch-backprop operation.
///
/// \param data_batch_shape The shape of the data batch from forward-prop.
/// \param filters The node producing the filters from forward-prop.
/// \param output_delta The node producing output delta.
/// \param window_movement_strides_forward The window movement strides from
/// forward-prop.
/// \param window_dilation_strides_forward The window dilation strides from
/// forward-prop.
/// \param padding_below_forward The padding-below sizes from forward-prop.
/// \param padding_above_forward The padding-above sizes from forward-prop.
/// \param data_dilation_strides_forward The data dilation strides from forward-prop.
ConvolutionBackpropData(const Shape& data_batch_shape,
const Output<Node>& filters,
const Output<Node>& output_delta,
const Strides& window_movement_strides_forward,
const Strides& window_dilation_strides_forward,
const CoordinateDiff& padding_below_forward,
const CoordinateDiff& padding_above_forward,
const Strides& data_dilation_strides_forward);
void validate_and_infer_types() override;
void generate_adjoints(autodiff::Adjoints& adjoints, const NodeVector& deltas) override;
virtual std::shared_ptr<Node>
copy_with_new_args(const NodeVector& new_args) const override;
/// \return The data batch shape.
const Shape& get_data_batch_shape() const { return m_data_batch_shape; }
void set_data_batch_shape(const Shape& data_batch_shape)
{
m_data_batch_shape = data_batch_shape;
}
/// \return The window movement strides from the forward prop.
const Strides& get_window_movement_strides_forward() const
{
return m_window_movement_strides_forward;
}
void set_window_movement_strides_forward(const Strides& window_movement_strides_forward)
{
m_window_movement_strides_forward = window_movement_strides_forward;
}
/// \return The window dilation strides from the forward prop.
const Strides& get_window_dilation_strides_forward() const
{
return m_window_dilation_strides_forward;
}
void set_window_dilation_strides_forward(const Strides& window_dilation_strides_forward)
{
m_window_dilation_strides_forward = window_dilation_strides_forward;
}
/// \return The padding-below sizes (possibly negative) from the forward prop.
const CoordinateDiff& get_padding_below_forward() const
{
return m_padding_below_forward;
}
void set_padding_below_forward(const CoordinateDiff& padding_below_forward)
{
m_padding_below_forward = padding_below_forward;
}
/// \return The padding-above sizes (possibly negative) from the forward prop.
const CoordinateDiff& get_padding_above_forward() const
{
return m_padding_above_forward;
}
void set_padding_above_forward(const CoordinateDiff& padding_above_forward)
{
m_padding_above_forward = padding_above_forward;
}
/// \return The input data dilation strides from the forward prop.
const Strides& get_data_dilation_strides_forward() const
protected:
Strides m_strides;
Strides m_dilations;
CoordinateDiff m_pads_begin;
CoordinateDiff m_pads_end;
PadType m_auto_pad;
};
/// \brief Data batch backprop for batched convolution operation.
class ConvolutionBackpropData : public Op
{
return m_data_dilation_strides_forward;
}
void set_data_dilation_strides_forward(const Strides& data_dilation_strides_forward)
public:
NGRAPH_API
static constexpr NodeTypeInfo type_info{"ConvolutionBackpropData", 1};
const NodeTypeInfo& get_type_info() const override { return type_info; }
/// \brief Constructs a batched-convolution data batch-backprop operation.
ConvolutionBackpropData() = default;
/// \brief Constructs a batched-convolution data batch-backprop operation.
///
/// \param data_batch_shape The shape of the data batch from forward-prop.
/// \param filters The node producing the filters from forward-prop.
/// \param output_delta The node producing output delta.
/// \param strides The strides from forward-prop.
/// \param dilations The dilations from forward-prop.
/// \param pads_begin The padding-below sizes from forward-prop.
/// \param pads_end The padding-above sizes from forward-prop.
ConvolutionBackpropData(const Shape& data_batch_shape,
const Output<Node>& filters,
const Output<Node>& output_delta,
const Strides& strides,
const Strides& dilations,
const CoordinateDiff& pads_begin,
const CoordinateDiff& pads_end);
size_t get_version() const override { return 1; }
void validate_and_infer_types() override;
void generate_adjoints(autodiff::Adjoints& adjoints,
const NodeVector& deltas) override;
virtual std::shared_ptr<Node>
copy_with_new_args(const NodeVector& new_args) const override;
/// \return The data batch shape.
const Shape& get_data_batch_shape() const { return m_data_batch_shape; }
void set_data_batch_shape(const Shape& data_batch_shape)
{
m_data_batch_shape = data_batch_shape;
}
/// \return The strides from the forward prop.
const Strides& get_strides() const { return m_strides; }
void set_strides(const Strides& strides) { m_strides = strides; }
/// \return The dilations from the forward prop.
const Strides& get_dilations() const { return m_dilations; }
void set_dilations(const Strides& dilations) { m_dilations = dilations; }
/// \return The padding-below sizes (possibly negative) from the forward prop.
const CoordinateDiff& get_pads_begin() const { return m_pads_begin; }
void set_pads_begin(const CoordinateDiff& pads_begin) { m_pads_begin = pads_begin; }
/// \return The padding-above sizes (possibly negative) from the forward prop.
const CoordinateDiff& get_pads_end() const { return m_pads_end; }
void set_pads_end(const CoordinateDiff& pads_end) { m_pads_end = pads_end; }
// Compute the pad_above values to be used if in a convolution
CoordinateDiff compute_backward_delta_out_pad_above() const;
CoordinateDiff compute_backward_delta_out_pad_below() const;
protected:
Shape m_data_batch_shape;
Strides m_strides;
Strides m_dilations;
CoordinateDiff m_pads_begin;
CoordinateDiff m_pads_end;
};
/// \brief Filters backprop for batched convolution operation.
class ConvolutionBackpropFilters : public Op
{
m_data_dilation_strides_forward = data_dilation_strides_forward;
}
// Compute the pad_above values to be used if in a convolution
CoordinateDiff compute_backward_delta_out_pad_above() const;
CoordinateDiff compute_backward_delta_out_pad_below() const;
protected:
Shape m_data_batch_shape;
Strides m_window_movement_strides_forward;
Strides m_window_dilation_strides_forward;
CoordinateDiff m_padding_below_forward;
CoordinateDiff m_padding_above_forward;
Strides m_data_dilation_strides_forward;
};
/// \brief Filters backprop for batched convolution operation.
class ConvolutionBackpropFilters : public Op
public:
NGRAPH_API
static constexpr NodeTypeInfo type_info{"ConvolutionBackpropFilters", 1};
const NodeTypeInfo& get_type_info() const override { return type_info; }
/// \brief Constructs a batched-convolution filter-backprop operation.
ConvolutionBackpropFilters() = default;
/// \brief Constructs a batched-convolution filter-backprop operation.
///
/// \param data_batch The tensor producing the data batch from forward-prop.
/// \param filters_shape The shape of the filters from forward-prop.
/// \param output_delta The node producing output delta.
/// \param strides The strides from forward-prop.
/// \param dilations The dilations from forward-prop.
/// \param pads_begin The padding-below sizes from forward-prop.
/// \param pads_end The padding-above sizes from forward-prop.
ConvolutionBackpropFilters(const Output<Node>& data_batch,
const Shape& filters_shape,
const Output<Node>& output_delta,
const Strides& strides,
const Strides& dilations,
const CoordinateDiff& pads_begin,
const CoordinateDiff& pads_end);
size_t get_version() const override { return 1; }
void validate_and_infer_types() override;
virtual std::shared_ptr<Node>
copy_with_new_args(const NodeVector& new_args) const override;
/// \return The filters tensor shape.
const Shape& get_filters_shape() const { return m_filters_shape; }
/// \return The strides from the forward prop.
const Strides& get_strides() const { return m_strides; }
void set_strides(const Strides& strides) { m_strides = strides; }
/// \return The dilations from the forward prop.
const Strides& get_dilations() const { return m_dilations; }
void set_dilations(const Strides& dilations) { m_dilations = dilations; }
/// \return The padding-below sizes (possibly negative) from the forward prop.
const CoordinateDiff& get_pads_begin() const { return m_pads_begin; }
void set_pads_begin(const CoordinateDiff& pads_begin) { m_pads_begin = pads_begin; }
/// \return The padding-above sizes (possibly negative) from the forward prop.
const CoordinateDiff& get_pads_end() const { return m_pads_end; }
void set_pads_end(const CoordinateDiff& pads_end) { m_pads_end = pads_end; }
// Compute the pad_above value to be used if in a convolution
CoordinateDiff compute_backward_in_pad_above() const;
protected:
Shape m_filters_shape;
Strides m_strides;
Strides m_dilations;
CoordinateDiff m_pads_begin;
CoordinateDiff m_pads_end;
};
} // namespace v1
namespace v0
{
public:
NGRAPH_API
static constexpr NodeTypeInfo type_info{"ConvolutionBackpropFilters", 0};
const NodeTypeInfo& get_type_info() const override { return type_info; }
/// \brief Constructs a batched-convolution filter-backprop operation.
ConvolutionBackpropFilters() = default;
/// \brief Constructs a batched-convolution filter-backprop operation.
/// \brief Batched convolution operation, with optional window dilation and stride.
///
/// \param data_batch The tensor producing the data batch from forward-prop.
/// \param filters_shape The shape of the filters from forward-prop.
/// \param output_delta The node producing output delta.
/// \param window_movement_strides_forward The window movement strides from
/// forward-prop.
/// \param window_dilation_strides_forward The window dilation strides from
/// forward-prop.
/// \param padding_below_forward The padding-below sizes from forward-prop.
/// \param padding_above_forward The padding-above sizes from forward-prop.
/// \param data_dilation_strides_forward The data dilation strides from forward-prop.
ConvolutionBackpropFilters(const Output<Node>& data_batch,
const Shape& filters_shape,
const Output<Node>& output_delta,
const Strides& window_movement_strides_forward,
const Strides& window_dilation_strides_forward,
const CoordinateDiff& padding_below_forward,
const CoordinateDiff& padding_above_forward,
const Strides& data_dilation_strides_forward);
void validate_and_infer_types() override;
virtual std::shared_ptr<Node>
copy_with_new_args(const NodeVector& new_args) const override;
/// \return The filters tensor shape.
const Shape& get_filters_shape() const { return m_filters_shape; }
/// \return The window movement strides from the forward prop.
const Strides& get_window_movement_strides_forward() const
{
return m_window_movement_strides_forward;
}
void set_window_movement_strides_forward(const Strides& window_movement_strides_forward)
class Convolution : public Op
{
m_window_movement_strides_forward = window_movement_strides_forward;
}
/// \return The window dilation strides from the forward prop.
const Strides& get_window_dilation_strides_forward() const
{
return m_window_dilation_strides_forward;
}
void set_window_dilation_strides_forward(const Strides& window_dilation_strides_forward)
{
m_window_dilation_strides_forward = window_dilation_strides_forward;
}
/// \return The padding-below sizes (possibly negative) from the forward prop.
const CoordinateDiff& get_padding_below_forward() const
{
return m_padding_below_forward;
}
void set_padding_below_forward(const CoordinateDiff& padding_below_forward)
{
m_padding_below_forward = padding_below_forward;
}
/// \return The padding-above sizes (possibly negative) from the forward prop.
const CoordinateDiff& get_padding_above_forward() const
{
return m_padding_above_forward;
}
void set_padding_above_forward(const CoordinateDiff& padding_above_forward)
{
m_padding_above_forward = padding_above_forward;
}
/// \return The data dilation strides from the forward prop.
const Strides& get_data_dilation_strides_forward() const
public:
NGRAPH_API
static constexpr NodeTypeInfo type_info{"Convolution", 0};
const NodeTypeInfo& get_type_info() const override { return type_info; }
/// \brief Constructs a batched convolution operation.
Convolution() = default;
/// \brief Constructs a batched convolution operation.
///
/// \param data_batch The node producing the input data batch tensor.<br>
/// `[N, C_IN, D1, ... Df]`
/// \param filters The node producing the filters tensor.<br>
/// `[C_OUT, C_IN, F1, ... Ff]`
/// \param window_movement_strides The window movement strides.<br>
/// `[f]`
/// \param window_dilation_strides The window dilation strides.<br>
/// `[f]`
/// \param padding_below The padding-below sizes.<br>
/// `[f]`
/// \param padding_above The padding-above sizes.<br>
/// `[f]`
/// \param data_dilation_strides The data dilation strides.<br>
/// `[f]`
/// \param pad_type The pad type for automatically computing padding sizes.<br>
/// `[f]`
///
/// Output `[N, C_OUT, R1, ... Rf]`
///
Convolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& window_movement_strides,
const Strides& window_dilation_strides,
const CoordinateDiff& padding_below,
const CoordinateDiff& padding_above,
const Strides& data_dilation_strides,
const PadType& pad_type = PadType::EXPLICIT);
/// \brief Constructs a batched convolution operation with no data dilation (i.e.,
/// all
/// data dilation strides are 1).
///
/// \param data_batch The node producing the input data batch tensor.<br>
/// `[N, C_IN, D1, ... Df]`
/// \param filters The node producing the filters tensor.<br>
/// `[C_OUT, C_IN, F1, ... Ff]`
/// \param window_movement_strides The window movement strides.<br>
/// `[f]`
/// \param window_dilation_strides The window dilation strides.<br>
/// `[f]`
/// \param padding_below The padding-below sizes.<br>
/// `[f]`
/// \param padding_above The padding-above sizes.<br>
/// `[f]`
///
/// Output `[N, C_OUT, R1, ... Rf]`
///
Convolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& window_movement_strides,
const Strides& window_dilation_strides,
const CoordinateDiff& padding_below,
const CoordinateDiff& padding_above);
/// \brief Constructs a batched convolution operation with no padding or data
/// dilation
/// (i.e., padding above and below are 0 everywhere, and all data dilation
/// strides are 1).
///
/// \param data_batch The node producing the input data batch tensor.<br>
/// `[N, C_IN, D1, ... Df]`
/// \param filters The node producing the filters tensor.<br>
/// `[C_OUT, C_IN, F1, ... Ff]`
/// \param window_movement_strides The window movement strides.<br>
/// `[f]`
/// \param window_dilation_strides The window dilation strides.<br>
/// `[f]`
///
/// Output `[N, C_OUT, R1, ... Rf]`
///
Convolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& window_movement_strides,
const Strides& window_dilation_strides);
/// \brief Constructs a batched convolution operation with no window dilation,
/// padding,
/// or data dilation (i.e., padding above and below are 0 everywhere, and all
/// window/data dilation strides are 1).
///
/// \param data_batch The node producing the input data batch tensor.<br>
/// `[N, C_IN, D1, ... Df]`
/// \param filters The node producing the filters tensor.<br>
/// `[C_OUT, C_IN, F1, ... Ff]`
/// \param window_movement_strides The window movement strides.<br>
/// `[f]`
///
/// Output `[N, C_OUT, R1, ... Rf]`
///
Convolution(const Output<Node>& data_batch,
const Output<Node>& filters,
const Strides& window_movement_strides);
/// \brief Constructs a batched convolution operation with no window dilation or
/// movement stride (i.e., padding above and below are 0 everywhere, and all
/// window/data dilation strides and window movement strides are 1).
///
/// \param data_batch The node producing the input data batch tensor.<br>
/// `[N, C_IN, D1, ... Df]`
/// \param filters The node producing the filters tensor.<br>
/// `[C_OUT, C_IN, F1, ... Ff]`
///
/// Output `[N, C_OUT, R1, ... Rf]`
///
Convolution(const Output<Node>& data_batch, const Output<Node>& filters);
void validate_and_infer_types() override;
virtual std::shared_ptr<Node>
copy_with_new_args(const NodeVector& new_args) const override;
void generate_adjoints(autodiff::Adjoints& adjoints,
const NodeVector& deltas) override;
/// \return The window movement strides.
const Strides& get_window_movement_strides() const
{
return m_window_movement_strides;
}
void set_window_movement_strides(const Strides& window_movement_strides)
{
m_window_movement_strides = window_movement_strides;
}
/// \return The window dilation strides.
const Strides& get_window_dilation_strides() const
{
return m_window_dilation_strides;
}
void set_window_dilation_strides(const Strides& window_dilation_strides)
{
m_window_dilation_strides = window_dilation_strides;
}
/// \return The padding-below sizes (possibly negative).
const CoordinateDiff& get_padding_below() const { return m_padding_below; }
void set_padding_below(const CoordinateDiff& padding_below)
{
m_padding_below = padding_below;
}
/// \return The padding-above sizes (possibly negative).
const CoordinateDiff& get_padding_above() const { return m_padding_above; }
void set_adding_above(const CoordinateDiff& padding_above)
{
m_padding_above = padding_above;
}
/// \return The input data dilation strides.
const Strides& get_data_dilation_strides() const { return m_data_dilation_strides; }
void set_data_dilation_strides(const Strides& data_dilation_strides)
{
m_data_dilation_strides = data_dilation_strides;
}
/// \return The pad type for convolution.
const PadType& get_pad_type() const { return m_pad_type; }
void set_pad_type(const PadType& pad_type) { m_pad_type = pad_type; }
/// \return The default value for Convolution.
virtual std::shared_ptr<Node> get_default_value() const override;
protected:
Strides m_window_movement_strides;
Strides m_window_dilation_strides;
CoordinateDiff m_padding_below;
CoordinateDiff m_padding_above;
Strides m_data_dilation_strides;
PadType m_pad_type;
};
/// \brief Data batch backprop for batched convolution operation.
class ConvolutionBackpropData : public Op
{
return m_data_dilation_strides_forward;
}
void set_data_dilation_strides_forward(const Strides& data_dilation_strides_forward)
public:
NGRAPH_API
static constexpr NodeTypeInfo type_info{"ConvolutionBackpropData", 0};
const NodeTypeInfo& get_type_info() const override { return type_info; }
/// \brief Constructs a batched-convolution data batch-backprop operation.
ConvolutionBackpropData() = default;
/// \brief Constructs a batched-convolution data batch-backprop operation.
///
/// \param data_batch_shape The shape of the data batch from forward-prop.
/// \param filters The node producing the filters from forward-prop.
/// \param output_delta The node producing output delta.
/// \param window_movement_strides_forward The window movement strides from
/// forward-prop.
/// \param window_dilation_strides_forward The window dilation strides from
/// forward-prop.
/// \param padding_below_forward The padding-below sizes from forward-prop.
/// \param padding_above_forward The padding-above sizes from forward-prop.
/// \param data_dilation_strides_forward The data dilation strides from
/// forward-prop.
ConvolutionBackpropData(const Shape& data_batch_shape,
const Output<Node>& filters,
const Output<Node>& output_delta,
const Strides& window_movement_strides_forward,
const Strides& window_dilation_strides_forward,
const CoordinateDiff& padding_below_forward,
const CoordinateDiff& padding_above_forward,
const Strides& data_dilation_strides_forward);
void validate_and_infer_types() override;
void generate_adjoints(autodiff::Adjoints& adjoints,
const NodeVector& deltas) override;
virtual std::shared_ptr<Node>
copy_with_new_args(const NodeVector& new_args) const override;
/// \return The data batch shape.
const Shape& get_data_batch_shape() const { return m_data_batch_shape; }
void set_data_batch_shape(const Shape& data_batch_shape)
{
m_data_batch_shape = data_batch_shape;
}
/// \return The window movement strides from the forward prop.
const Strides& get_window_movement_strides_forward() const
{
return m_window_movement_strides_forward;
}
void set_window_movement_strides_forward(
const Strides& window_movement_strides_forward)
{
m_window_movement_strides_forward = window_movement_strides_forward;
}
/// \return The window dilation strides from the forward prop.
const Strides& get_window_dilation_strides_forward() const
{
return m_window_dilation_strides_forward;
}
void set_window_dilation_strides_forward(
const Strides& window_dilation_strides_forward)
{
m_window_dilation_strides_forward = window_dilation_strides_forward;
}
/// \return The padding-below sizes (possibly negative) from the forward prop.
const CoordinateDiff& get_padding_below_forward() const
{
return m_padding_below_forward;
}
void set_padding_below_forward(const CoordinateDiff& padding_below_forward)
{
m_padding_below_forward = padding_below_forward;
}
/// \return The padding-above sizes (possibly negative) from the forward prop.
const CoordinateDiff& get_padding_above_forward() const
{
return m_padding_above_forward;
}
void set_padding_above_forward(const CoordinateDiff& padding_above_forward)
{
m_padding_above_forward = padding_above_forward;
}
/// \return The input data dilation strides from the forward prop.
const Strides& get_data_dilation_strides_forward() const
{
return m_data_dilation_strides_forward;
}
void set_data_dilation_strides_forward(const Strides& data_dilation_strides_forward)
{
m_data_dilation_strides_forward = data_dilation_strides_forward;
}
// Compute the pad_above values to be used if in a convolution
CoordinateDiff compute_backward_delta_out_pad_above() const;
CoordinateDiff compute_backward_delta_out_pad_below() const;
protected:
Shape m_data_batch_shape;
Strides m_window_movement_strides_forward;
Strides m_window_dilation_strides_forward;
CoordinateDiff m_padding_below_forward;
CoordinateDiff m_padding_above_forward;
Strides m_data_dilation_strides_forward;
};
/// \brief Filters backprop for batched convolution operation.
class ConvolutionBackpropFilters : public Op
{
m_data_dilation_strides_forward = data_dilation_strides_forward;
}
public:
NGRAPH_API
static constexpr NodeTypeInfo type_info{"ConvolutionBackpropFilters", 0};
const NodeTypeInfo& get_type_info() const override { return type_info; }
/// \brief Constructs a batched-convolution filter-backprop operation.
ConvolutionBackpropFilters() = default;
/// \brief Constructs a batched-convolution filter-backprop operation.
///
/// \param data_batch The tensor producing the data batch from forward-prop.
/// \param filters_shape The shape of the filters from forward-prop.
/// \param output_delta The node producing output delta.
/// \param window_movement_strides_forward The window movement strides from
/// forward-prop. \param window_dilation_strides_forward The window dilation strides
/// from forward-prop. \param padding_below_forward The padding-below sizes from
/// forward-prop. \param padding_above_forward The padding-above sizes from
/// forward-prop. \param data_dilation_strides_forward The data dilation strides
/// from forward-prop.
ConvolutionBackpropFilters(const Output<Node>& data_batch,
const Shape& filters_shape,
const Output<Node>& output_delta,
const Strides& window_movement_strides_forward,
const Strides& window_dilation_strides_forward,
const CoordinateDiff& padding_below_forward,
const CoordinateDiff& padding_above_forward,
const Strides& data_dilation_strides_forward);
void validate_and_infer_types() override;
// Compute the pad_above value to be used if in a convolution
CoordinateDiff compute_backward_in_pad_above() const;
virtual std::shared_ptr<Node>
copy_with_new_args(const NodeVector& new_args) const override;
protected:
Shape m_filters_shape;
Strides m_window_movement_strides_forward;
Strides m_window_dilation_strides_forward;
CoordinateDiff m_padding_below_forward;
CoordinateDiff m_padding_above_forward;
Strides m_data_dilation_strides_forward;
};
/// \return The filters tensor shape.
const Shape& get_filters_shape() const { return m_filters_shape; }
/// \return The window movement strides from the forward prop.
const Strides& get_window_movement_strides_forward() const
{
return m_window_movement_strides_forward;
}
void set_window_movement_strides_forward(
const Strides& window_movement_strides_forward)
{
m_window_movement_strides_forward = window_movement_strides_forward;
}
/// \return The window dilation strides from the forward prop.
const Strides& get_window_dilation_strides_forward() const
{
return m_window_dilation_strides_forward;
}
void set_window_dilation_strides_forward(
const Strides& window_dilation_strides_forward)
{
m_window_dilation_strides_forward = window_dilation_strides_forward;
}
/// \return The padding-below sizes (possibly negative) from the forward prop.
const CoordinateDiff& get_padding_below_forward() const
{
return m_padding_below_forward;
}
void set_padding_below_forward(const CoordinateDiff& padding_below_forward)
{
m_padding_below_forward = padding_below_forward;
}
/// \return The padding-above sizes (possibly negative) from the forward prop.
const CoordinateDiff& get_padding_above_forward() const
{
return m_padding_above_forward;
}
void set_padding_above_forward(const CoordinateDiff& padding_above_forward)
{
m_padding_above_forward = padding_above_forward;
}
/// \return The data dilation strides from the forward prop.
const Strides& get_data_dilation_strides_forward() const
{
return m_data_dilation_strides_forward;
}
void set_data_dilation_strides_forward(const Strides& data_dilation_strides_forward)
{
m_data_dilation_strides_forward = data_dilation_strides_forward;
}
// Compute the pad_above value to be used if in a convolution
CoordinateDiff compute_backward_in_pad_above() const;
protected:
Shape m_filters_shape;
Strides m_window_movement_strides_forward;
Strides m_window_dilation_strides_forward;
CoordinateDiff m_padding_below_forward;
CoordinateDiff m_padding_above_forward;
Strides m_data_dilation_strides_forward;
};
} // namespace v0
namespace util
{
// This is a legacy function, retained because the CPU backend uses it for now.
// TODO: Update CPU backend to use the new stuff in validation_util.hpp, and remove
// this function.
// TODO: Update CPU backend to use the new stuff in validation_util.hpp, and remove this
// function.
Shape infer_convolution_output_shape(const Node* node,
const Shape& data_batch_shape,
const Shape& filters_shape,
......@@ -405,6 +620,10 @@ namespace ngraph
size_t output_channel_axis_filters,
size_t batch_axis_result,
size_t output_channel_axis_result);
}
}
}
} // namespace util
using v0::Convolution;
using v0::ConvolutionBackpropData;
using v0::ConvolutionBackpropFilters;
} // namespace op
} // namespace ngraph
......@@ -17,6 +17,7 @@
#include "ngraph/graph_util.hpp"
#include "ngraph/op/avg_pool.hpp"
#include "ngraph/op/constant.hpp"
#include "ngraph/op/convolution.hpp"
#include "ngraph/op/gather.hpp"
#include "ngraph/op/get_output_element.hpp"
#include "ngraph/op/max_pool.hpp"
......@@ -131,6 +132,107 @@ bool pass::Opset1Upgrade::run_on_node(shared_ptr<Node> node)
modified = true;
break;
}
case OP_TYPEID::Convolution:
{
auto tmp = dynamic_cast<const op::v0::Convolution*>(node.get());
auto strides = tmp->get_window_movement_strides();
auto dilations = tmp->get_window_dilation_strides();
auto pads_begin = tmp->get_padding_below();
auto pads_end = tmp->get_padding_above();
auto data_dilation_strides = tmp->get_data_dilation_strides();
auto auto_pad = tmp->get_pad_type();
bool is_dds_valid = true;
for (auto value : data_dilation_strides)
{
is_dds_valid = is_dds_valid && (value == 1);
}
NGRAPH_CHECK(is_dds_valid,
"Unable to convert Convolution:0 to Convolution:1 with data dilation strides "
"other than `1`. Node: ",
*node);
auto replacement_node = make_shared<op::v1::Convolution>(node->input(0).get_source_output(),
node->input(1).get_source_output(),
strides,
pads_begin,
pads_end,
dilations,
auto_pad);
replace_node(node, replacement_node);
modified = true;
break;
}
case OP_TYPEID::ConvolutionBackpropData:
{
auto tmp = dynamic_cast<const op::v0::ConvolutionBackpropData*>(node.get());
auto data_batch_shape = tmp->get_data_batch_shape();
auto strides = tmp->get_window_movement_strides_forward();
auto dilations = tmp->get_window_dilation_strides_forward();
auto pads_begin = tmp->get_padding_below_forward();
auto pads_end = tmp->get_padding_above_forward();
auto data_dilation_strides = tmp->get_data_dilation_strides_forward();
bool is_dds_valid = true;
for (auto value : data_dilation_strides)
{
is_dds_valid = is_dds_valid && (value == 1);
}
NGRAPH_CHECK(is_dds_valid,
"Unable to convert ConvolutionBackpropData:0 to ConvolutionBackpropData:1 "
"with data dilation strides "
"other than `1`. Node: ",
*node);
auto replacement_node =
make_shared<op::v1::ConvolutionBackpropData>(data_batch_shape,
node->input(0).get_source_output(),
node->input(1).get_source_output(),
strides,
dilations,
pads_begin,
pads_end);
replace_node(node, replacement_node);
modified = true;
break;
}
case OP_TYPEID::ConvolutionBackpropFilters:
{
auto tmp = dynamic_cast<const op::v0::ConvolutionBackpropFilters*>(node.get());
auto filters_shape = tmp->get_filters_shape();
auto strides = tmp->get_window_movement_strides_forward();
auto dilations = tmp->get_window_dilation_strides_forward();
auto pads_begin = tmp->get_padding_below_forward();
auto pads_end = tmp->get_padding_above_forward();
auto data_dilation_strides = tmp->get_data_dilation_strides_forward();
bool is_dds_valid = true;
for (auto value : data_dilation_strides)
{
is_dds_valid = is_dds_valid && (value == 1);
}
NGRAPH_CHECK(
is_dds_valid,
"Unable to convert ConvolutionBackpropFilters:0 to ConvolutionBackpropFilters:1 "
"with data dilation strides "
"other than `1`. Node: ",
*node);
auto replacement_node =
make_shared<op::v1::ConvolutionBackpropFilters>(node->input(0).get_source_output(),
filters_shape,
node->input(1).get_source_output(),
strides,
dilations,
pads_begin,
pads_end);
replace_node(node, replacement_node);
modified = true;
break;
}
case OP_TYPEID::Gather:
{
auto tmp = dynamic_cast<const op::v0::Gather*>(node.get());
......@@ -143,6 +245,60 @@ bool pass::Opset1Upgrade::run_on_node(shared_ptr<Node> node)
modified = true;
break;
}
case OP_TYPEID::Product:
{
bool keep_dims = false;
auto replacement_node = make_shared<op::v1::ReduceProd>(
node->input(0).get_source_output(), node->input(1).get_source_output(), keep_dims);
replace_node(node, replacement_node);
modified = true;
break;
}
case OP_TYPEID::Sum:
{
bool keep_dims = false;
auto replacement_node = make_shared<op::v1::ReduceSum>(
node->input(0).get_source_output(), node->input(1).get_source_output(), keep_dims);
replace_node(node, replacement_node);
modified = true;
break;
}
case OP_TYPEID::Pad:
{
auto tmp = dynamic_cast<const op::v0::Pad*>(node.get());
auto padding_below = tmp->get_padding_below();
auto pads_begin_node =
make_shared<op::Constant>(element::i64, Shape{padding_below.size()}, padding_below);
auto padding_above = tmp->get_padding_above();
auto pads_end_node =
make_shared<op::Constant>(element::i64, Shape{padding_above.size()}, padding_above);
auto replacement_node = make_shared<op::v1::Pad>(node->input(0).get_source_output(),
pads_begin_node,
pads_end_node,
node->input(1).get_source_output(),
tmp->get_pad_mode());
replace_node(node, replacement_node);
modified = true;
break;
}
case OP_TYPEID::Softmax:
{
auto tmp = dynamic_cast<const op::v0::Softmax*>(node.get());
AxisSet axes = tmp->get_axes();
NGRAPH_CHECK(
axes.size() == 1,
"Unable to convert Softmax:0 to Softmax:1 with zero or more than one axis. Node: ",
*node);
auto replacement_node =
make_shared<op::v1::Softmax>(node->input(0).get_source_output(), axes.to_vector()[0]);
replace_node(node, replacement_node);
modified = true;
break;
}
case OP_TYPEID::MaxPool:
{
auto tmp = dynamic_cast<const op::v0::MaxPool*>(node.get());
......@@ -200,44 +356,6 @@ bool pass::Opset1Upgrade::run_on_node(shared_ptr<Node> node)
modified = true;
break;
}
case OP_TYPEID::Product:
{
bool keep_dims = false;
auto replacement_node = make_shared<op::v1::ReduceProd>(
node->input(0).get_source_output(), node->input(1).get_source_output(), keep_dims);
replace_node(node, replacement_node);
modified = true;
break;
}
case OP_TYPEID::Sum:
{
bool keep_dims = false;
auto replacement_node = make_shared<op::v1::ReduceSum>(
node->input(0).get_source_output(), node->input(1).get_source_output(), keep_dims);
replace_node(node, replacement_node);
modified = true;
break;
}
case OP_TYPEID::Pad:
{
auto tmp = dynamic_cast<const op::v0::Pad*>(node.get());
auto padding_below = tmp->get_padding_below();
auto pads_begin_node =
make_shared<op::Constant>(element::i64, Shape{padding_below.size()}, padding_below);
auto padding_above = tmp->get_padding_above();
auto pads_end_node =
make_shared<op::Constant>(element::i64, Shape{padding_above.size()}, padding_above);
auto replacement_node = make_shared<op::v1::Pad>(node->input(0).get_source_output(),
pads_begin_node,
pads_end_node,
node->input(1).get_source_output(),
tmp->get_pad_mode());
replace_node(node, replacement_node);
modified = true;
break;
}
case OP_TYPEID::Reverse:
{
// creates a Constant node from the v0::Reverse reversed_axes attribute
......@@ -257,24 +375,9 @@ bool pass::Opset1Upgrade::run_on_node(shared_ptr<Node> node)
break;
}
case OP_TYPEID::Softmax:
{
auto tmp = dynamic_cast<const op::v0::Softmax*>(node.get());
AxisSet axes = tmp->get_axes();
NGRAPH_CHECK(
axes.size() == 1,
"Unable to convert Softmax:0 to Softmax:1 with zero or more than one axis. Node: ",
*node);
auto replacement_node =
make_shared<op::v1::Softmax>(node->input(0).get_source_output(), axes.to_vector()[0]);
replace_node(node, replacement_node);
modified = true;
break;
}
default: break;
}
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
......
......@@ -22,6 +22,7 @@
#include "ngraph/code_writer.hpp"
#include "ngraph/node.hpp"
#include "ngraph/op/avg_pool.hpp"
#include "ngraph/op/convolution.hpp"
#include "ngraph/op/gather.hpp"
#include "ngraph/op/max_pool.hpp"
#include "ngraph/op/pad.hpp"
......@@ -109,10 +110,7 @@ namespace ngraph
class QuantizedConvolution;
class GroupConvolution;
class GroupConvolutionBias;
class Convolution;
class ConvolutionBackpropFilters;
class DeconvolutionBias;
class ConvolutionBackpropData;
class QuantizedConvolutionBias;
class QuantizedConvolutionBiasAdd;
class QuantizedConvolutionBiasSignedAdd;
......
......@@ -965,94 +965,136 @@ shared_ptr<Node> JSONDeserializer::deserialize_node(json node_js)
}
case OP_TYPEID::Convolution:
{
auto window_movement_strides =
node_js.at("window_movement_strides").get<vector<size_t>>();
auto window_dilation_strides =
node_js.at("window_dilation_strides").get<vector<size_t>>();
auto padding_below = node_js.at("padding_below").get<vector<std::ptrdiff_t>>();
auto padding_above = node_js.at("padding_above").get<vector<std::ptrdiff_t>>();
// For backwards compatibility, we accept "image_dilation_strides" in place of
// "data_dilation_strides", and we also allow it to be omitted altogether.
json data_dilation_strides;
if (has_key(node_js, "data_dilation_strides"))
{
data_dilation_strides = node_js["data_dilation_strides"];
}
else if (has_key(node_js, "image_dilation_strides"))
if (op_version == 0)
{
data_dilation_strides = node_js["image_dilation_strides"];
}
auto window_movement_strides =
node_js.at("window_movement_strides").get<vector<size_t>>();
auto window_dilation_strides =
node_js.at("window_dilation_strides").get<vector<size_t>>();
auto padding_below = node_js.at("padding_below").get<vector<std::ptrdiff_t>>();
auto padding_above = node_js.at("padding_above").get<vector<std::ptrdiff_t>>();
// For backwards compatibility, we accept "image_dilation_strides" in place of
// "data_dilation_strides", and we also allow it to be omitted altogether.
json data_dilation_strides;
if (has_key(node_js, "data_dilation_strides"))
{
data_dilation_strides = node_js["data_dilation_strides"];
}
else if (has_key(node_js, "image_dilation_strides"))
{
data_dilation_strides = node_js["image_dilation_strides"];
}
op::PadType pad_type = read_pad_type(node_js);
op::PadType pad_type = read_pad_type(node_js);
if (data_dilation_strides.empty())
{
node = make_shared<op::Convolution>(args[0],
args[1],
window_movement_strides,
window_dilation_strides,
padding_below,
padding_above);
if (data_dilation_strides.empty())
{
node = make_shared<op::v0::Convolution>(args[0],
args[1],
window_movement_strides,
window_dilation_strides,
padding_below,
padding_above);
}
else
{
node = make_shared<op::v0::Convolution>(
args[0],
args[1],
window_movement_strides,
window_dilation_strides,
padding_below,
padding_above,
data_dilation_strides.get<std::vector<size_t>>(),
pad_type);
}
}
else
if (op_version == 1)
{
node =
make_shared<op::Convolution>(args[0],
args[1],
window_movement_strides,
window_dilation_strides,
padding_below,
padding_above,
data_dilation_strides.get<std::vector<size_t>>(),
pad_type);
auto strides = node_js.at("strides").get<vector<size_t>>();
auto dilations = node_js.at("dilations").get<vector<size_t>>();
auto pads_begin = node_js.at("pads_begin").get<vector<std::ptrdiff_t>>();
auto pads_end = node_js.at("pads_end").get<vector<std::ptrdiff_t>>();
op::PadType auto_pad = read_pad_type(node_js);
node = make_shared<op::v1::Convolution>(
args[0], args[1], strides, pads_begin, pads_end, dilations, auto_pad);
}
break;
}
case OP_TYPEID::ConvolutionBackpropData:
{
auto data_batch_shape = node_js.at("data_batch_shape").get<vector<size_t>>();
auto window_movement_strides_forward =
node_js.at("window_movement_strides_forward").get<vector<size_t>>();
auto window_dilation_strides_forward =
node_js.at("window_dilation_strides_forward").get<vector<size_t>>();
auto padding_below_forward =
node_js.at("padding_below_forward").get<vector<std::ptrdiff_t>>();
auto padding_above_forward =
node_js.at("padding_above_forward").get<vector<std::ptrdiff_t>>();
auto data_dilation_strides_forward =
node_js.at("data_dilation_strides_forward").get<vector<size_t>>();
node = make_shared<op::ConvolutionBackpropData>(data_batch_shape,
args[0],
args[1],
window_movement_strides_forward,
window_dilation_strides_forward,
padding_below_forward,
padding_above_forward,
data_dilation_strides_forward);
if (op_version == 0)
{
auto data_batch_shape = node_js.at("data_batch_shape").get<vector<size_t>>();
auto window_movement_strides_forward =
node_js.at("window_movement_strides_forward").get<vector<size_t>>();
auto window_dilation_strides_forward =
node_js.at("window_dilation_strides_forward").get<vector<size_t>>();
auto padding_below_forward =
node_js.at("padding_below_forward").get<vector<std::ptrdiff_t>>();
auto padding_above_forward =
node_js.at("padding_above_forward").get<vector<std::ptrdiff_t>>();
auto data_dilation_strides_forward =
node_js.at("data_dilation_strides_forward").get<vector<size_t>>();
node = make_shared<op::v0::ConvolutionBackpropData>(data_batch_shape,
args[0],
args[1],
window_movement_strides_forward,
window_dilation_strides_forward,
padding_below_forward,
padding_above_forward,
data_dilation_strides_forward);
}
if (op_version == 1)
{
auto data_batch_shape = node_js.at("data_batch_shape").get<vector<size_t>>();
auto strides = node_js.at("strides").get<vector<size_t>>();
auto dilations = node_js.at("dilations").get<vector<size_t>>();
auto pads_begin = node_js.at("pads_begin").get<vector<std::ptrdiff_t>>();
auto pads_end = node_js.at("pads_end").get<vector<std::ptrdiff_t>>();
node = make_shared<op::v1::ConvolutionBackpropData>(
data_batch_shape, args[0], args[1], strides, dilations, pads_begin, pads_end);
}
break;
}
case OP_TYPEID::ConvolutionBackpropFilters:
{
auto filters_shape = node_js.at("filters_shape").get<vector<size_t>>();
auto window_movement_strides_forward =
node_js.at("window_movement_strides_forward").get<vector<size_t>>();
auto window_dilation_strides_forward =
node_js.at("window_dilation_strides_forward").get<vector<size_t>>();
auto padding_below_forward =
node_js.at("padding_below_forward").get<vector<std::ptrdiff_t>>();
auto padding_above_forward =
node_js.at("padding_above_forward").get<vector<std::ptrdiff_t>>();
auto data_dilation_strides_forward =
node_js.at("data_dilation_strides_forward").get<vector<size_t>>();
node = make_shared<op::ConvolutionBackpropFilters>(args[0],
filters_shape,
args[1],
window_movement_strides_forward,
window_dilation_strides_forward,
padding_below_forward,
padding_above_forward,
data_dilation_strides_forward);
if (op_version == 0)
{
auto filters_shape = node_js.at("filters_shape").get<vector<size_t>>();
auto window_movement_strides_forward =
node_js.at("window_movement_strides_forward").get<vector<size_t>>();
auto window_dilation_strides_forward =
node_js.at("window_dilation_strides_forward").get<vector<size_t>>();
auto padding_below_forward =
node_js.at("padding_below_forward").get<vector<std::ptrdiff_t>>();
auto padding_above_forward =
node_js.at("padding_above_forward").get<vector<std::ptrdiff_t>>();
auto data_dilation_strides_forward =
node_js.at("data_dilation_strides_forward").get<vector<size_t>>();
node =
make_shared<op::v0::ConvolutionBackpropFilters>(args[0],
filters_shape,
args[1],
window_movement_strides_forward,
window_dilation_strides_forward,
padding_below_forward,
padding_above_forward,
data_dilation_strides_forward);
}
if (op_version == 1)
{
auto filters_shape = node_js.at("filters_shape").get<vector<size_t>>();
auto strides = node_js.at("strides").get<vector<size_t>>();
auto dilations = node_js.at("dilations").get<vector<size_t>>();
auto pads_begin = node_js.at("pads_begin").get<vector<std::ptrdiff_t>>();
auto pads_end = node_js.at("pads_end").get<vector<std::ptrdiff_t>>();
node = make_shared<op::v1::ConvolutionBackpropFilters>(
args[0], filters_shape, args[1], strides, dilations, pads_begin, pads_end);
}
break;
}
case OP_TYPEID::ConvolutionBias:
......@@ -2483,35 +2525,71 @@ json JSONSerializer::serialize_node(const Node& n)
}
case OP_TYPEID::Convolution:
{
auto tmp = dynamic_cast<const op::Convolution*>(&n);
node["window_movement_strides"] = tmp->get_window_movement_strides();
node["window_dilation_strides"] = tmp->get_window_dilation_strides();
node["padding_below"] = tmp->get_padding_below();
node["padding_above"] = tmp->get_padding_above();
node["data_dilation_strides"] = tmp->get_data_dilation_strides();
node["pad_type"] = tmp->get_pad_type();
if (op_version == 0)
{
auto tmp = dynamic_cast<const op::v0::Convolution*>(&n);
node["window_movement_strides"] = tmp->get_window_movement_strides();
node["window_dilation_strides"] = tmp->get_window_dilation_strides();
node["padding_below"] = tmp->get_padding_below();
node["padding_above"] = tmp->get_padding_above();
node["data_dilation_strides"] = tmp->get_data_dilation_strides();
node["pad_type"] = tmp->get_pad_type();
}
if (op_version == 1)
{
auto tmp = dynamic_cast<const op::v1::Convolution*>(&n);
node["strides"] = tmp->get_strides();
node["dilations"] = tmp->get_dilations();
node["pads_begin"] = tmp->get_pads_begin();
node["pads_end"] = tmp->get_pads_end();
node["auto_pad"] = tmp->get_auto_pad();
}
break;
}
case OP_TYPEID::ConvolutionBackpropData:
{
auto tmp = dynamic_cast<const op::ConvolutionBackpropData*>(&n);
node["data_batch_shape"] = tmp->get_data_batch_shape();
node["window_movement_strides_forward"] = tmp->get_window_movement_strides_forward();
node["window_dilation_strides_forward"] = tmp->get_window_dilation_strides_forward();
node["padding_below_forward"] = tmp->get_padding_below_forward();
node["padding_above_forward"] = tmp->get_padding_above_forward();
node["data_dilation_strides_forward"] = tmp->get_data_dilation_strides_forward();
if (op_version == 0)
{
auto tmp = dynamic_cast<const op::v0::ConvolutionBackpropData*>(&n);
node["data_batch_shape"] = tmp->get_data_batch_shape();
node["window_movement_strides_forward"] = tmp->get_window_movement_strides_forward();
node["window_dilation_strides_forward"] = tmp->get_window_dilation_strides_forward();
node["padding_below_forward"] = tmp->get_padding_below_forward();
node["padding_above_forward"] = tmp->get_padding_above_forward();
node["data_dilation_strides_forward"] = tmp->get_data_dilation_strides_forward();
}
if (op_version == 1)
{
auto tmp = dynamic_cast<const op::v1::ConvolutionBackpropData*>(&n);
node["data_batch_shape"] = tmp->get_data_batch_shape();
node["strides"] = tmp->get_strides();
node["dilations"] = tmp->get_dilations();
node["pads_begin"] = tmp->get_pads_begin();
node["pads_end"] = tmp->get_pads_end();
}
break;
}
case OP_TYPEID::ConvolutionBackpropFilters:
{
auto tmp = dynamic_cast<const op::ConvolutionBackpropFilters*>(&n);
node["filters_shape"] = tmp->get_filters_shape();
node["window_movement_strides_forward"] = tmp->get_window_movement_strides_forward();
node["window_dilation_strides_forward"] = tmp->get_window_dilation_strides_forward();
node["padding_below_forward"] = tmp->get_padding_below_forward();
node["padding_above_forward"] = tmp->get_padding_above_forward();
node["data_dilation_strides_forward"] = tmp->get_data_dilation_strides_forward();
if (op_version == 0)
{
auto tmp = dynamic_cast<const op::v0::ConvolutionBackpropFilters*>(&n);
node["filters_shape"] = tmp->get_filters_shape();
node["window_movement_strides_forward"] = tmp->get_window_movement_strides_forward();
node["window_dilation_strides_forward"] = tmp->get_window_dilation_strides_forward();
node["padding_below_forward"] = tmp->get_padding_below_forward();
node["padding_above_forward"] = tmp->get_padding_above_forward();
node["data_dilation_strides_forward"] = tmp->get_data_dilation_strides_forward();
}
if (op_version == 1)
{
auto tmp = dynamic_cast<const op::v1::ConvolutionBackpropFilters*>(&n);
node["filters_shape"] = tmp->get_filters_shape();
node["strides"] = tmp->get_strides();
node["dilations"] = tmp->get_dilations();
node["pads_begin"] = tmp->get_pads_begin();
node["pads_end"] = tmp->get_pads_end();
}
break;
}
case OP_TYPEID::ConvolutionBias:
......
......@@ -69,13 +69,14 @@ set(SRC
node_input_output.cpp
nop_elimination.cpp
op.cpp
opset_pass/convolution_opset_pass.cpp
opset_pass/gather_opset_pass.cpp
opset_pass/pad_opset_pass.cpp
opset_pass/poolings_opset_pass.cpp
opset_pass/product_opset_pass.cpp
opset_pass/reverse_opset_pass.cpp
opset_pass/softmax_opset_pass.cpp
opset_pass/sum_opset_pass.cpp
opset_pass/poolings_opset_pass.cpp
partial_shape.cpp
pass.cpp
pass_liveness.cpp
......
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "ngraph/ngraph.hpp"
#include "ngraph/pass/manager.hpp"
#include "ngraph/pass/opset1_upgrade.hpp"
#include "util/test_control.hpp"
#include "util/type_prop.hpp"
using namespace std;
using namespace ngraph;
TEST(upgrade_pass, opset1_convolution_pass)
{
auto data = make_shared<op::Parameter>(element::f32, Shape{1, 3, 6, 9});
auto filters = make_shared<op::Parameter>(element::f32, Shape{1, 3, 3, 3});
CoordinateDiff pads_begin{0, 0};
CoordinateDiff pads_end{0, 0};
Strides strides{1, 1};
Strides dilations{1, 1};
Strides data_dilations_strides{1, 1};
op::PadType pad_type = op::PadType::EXPLICIT;
auto convolution_v0 = make_shared<op::v0::Convolution>(
data, filters, strides, dilations, pads_begin, pads_end, data_dilations_strides, pad_type);
auto result = make_shared<op::Result>(convolution_v0);
auto f = make_shared<Function>(ResultVector{result}, ParameterVector{data, filters});
ngraph::pass::Manager pass_manager;
pass_manager.register_pass<pass::Opset1Upgrade>();
pass_manager.run_passes(f);
auto convolution_s1_result = f->get_results().at(0);
auto node = convolution_s1_result->input(0).get_source_output().get_node_shared_ptr();
auto convolution_v1_node = static_pointer_cast<op::v1::Convolution>(node);
EXPECT_EQ(convolution_v1_node->description(), "Convolution");
EXPECT_EQ(convolution_v1_node->get_version(), 1);
EXPECT_EQ(convolution_v1_node->get_pads_begin(), pads_begin);
EXPECT_EQ(convolution_v1_node->get_pads_end(), pads_end);
EXPECT_EQ(convolution_v1_node->get_strides(), strides);
EXPECT_EQ(convolution_v1_node->get_auto_pad(), pad_type);
EXPECT_EQ(convolution_v1_node->get_dilations(), dilations);
}
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