Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding conv2d operation #969

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
99 changes: 99 additions & 0 deletions phylanx/plugins/keras_support/conv2d_operation.hpp
@@ -0,0 +1,99 @@
// Copyright (c) 2019 Bita Hasheminezhad
// Copyright (c) 2019 Hartmut Kaiser
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#if !defined(PHYLANX_KERAS_SUPPORT_CONV2D_OPERATION)
#define PHYLANX_KERAS_SUPPORT_CONV2D_OPERATION

#include <phylanx/config.hpp>
#include <phylanx/execution_tree/primitives/base_primitive.hpp>
#include <phylanx/execution_tree/primitives/primitive_component_base.hpp>

#include <hpx/lcos/future.hpp>
#include <hpx/util/optional.hpp>

#include <cstddef>
#include <cstdint>
#include <memory>
#include <string>
#include <utility>
#include <vector>

namespace phylanx { namespace execution_tree { namespace primitives {
/// \brief returns 2D convoltion
/// \param x a matrix
/// \param kernel a matrix, the filter
/// \param padding Padding mode, either `valid` or `same`
/// \param strides The step to apply convolution on each dimension
/// \param dilation_rate The rate to sample x in each step

class conv2d_operation
: public primitive_component_base
, public std::enable_shared_from_this<conv2d_operation>
{
protected:
hpx::future<primitive_argument_type> eval(
primitive_arguments_type const& operands,
primitive_arguments_type const& args,
eval_context ctx) const override;

public:
static match_pattern_type const match_data;

conv2d_operation() = default;

conv2d_operation(primitive_arguments_type&& operands,
std::string const& name, std::string const& codename);

private:
template <typename Matrix1, typename Matrix2>
double convolve_step(const Matrix1& m1, const Matrix2& m2) const;
template <typename Matrix1, typename Matrix2>
double convolve_step(const Matrix1& m1, const Matrix2& m2,
std::size_t dilation_rate_r, std::size_t dilation_rate_c,
std::size_t kernel_rows, std::size_t kernel_columns) const;
template <typename Matrix1, typename Matrix2>
double convolve_step(const Matrix1& m1, const Matrix2& m2,
std::size_t dilation_height, std::size_t dilation_width,
std::size_t kernel_rows, std::size_t kernel_columns,
std::size_t r_remainder, std::size_t c_remainder) const;

primitive_argument_type conv2d_valid(ir::node_data<double>&& arg,
ir::node_data<double>&& kernel) const;
primitive_argument_type conv2d_valid(ir::node_data<double>&& arg,
ir::node_data<double>&& kernel, ir::range&& strides) const;
primitive_argument_type conv2d_valid_dilation(
ir::node_data<double>&& arg, ir::node_data<double>&& kernel,
ir::range&& dilation_rate) const;

primitive_argument_type conv2d_same(ir::node_data<double>&& arg,
ir::node_data<double>&& kernel) const;
primitive_argument_type conv2d_same(ir::node_data<double>&& arg,
ir::node_data<double>&& kernel, ir::range&& strides) const;
primitive_argument_type conv2d_same_dilation(
ir::node_data<double>&& arg, ir::node_data<double>&& kernel,
ir::range&& dilation_rate) const;


primitive_argument_type conv2d_any_pad(ir::node_data<double>&& arg,
ir::node_data<double>&& kernel, std::string&& padding) const;
primitive_argument_type conv2d_any_pad(ir::node_data<double>&& arg,
ir::node_data<double>&& kernel, std::string&& padding,
ir::range&& strides) const;
primitive_argument_type conv2d_any_pad_dilation(
ir::node_data<double>&& arg, ir::node_data<double>&& kernel,
std::string&& padding, ir::range&& dilation_rate) const;
};

inline primitive create_conv2d_operation(hpx::id_type const& locality,
primitive_arguments_type&& operands, std::string const& name = "",
std::string const& codename = "")
{
return create_primitive_component(
locality, "conv2d", std::move(operands), name, codename);
}
}}}

#endif
1 change: 1 addition & 0 deletions phylanx/plugins/keras_support/keras_support.hpp
Expand Up @@ -8,6 +8,7 @@

#include <phylanx/plugins/keras_support/batch_dot_operation.hpp>
#include <phylanx/plugins/keras_support/conv1d_operation.hpp>
#include <phylanx/plugins/keras_support/conv2d_operation.hpp>
#include <phylanx/plugins/keras_support/ctc_decode_operation.hpp>
#include <phylanx/plugins/keras_support/elu_operation.hpp>
#include <phylanx/plugins/keras_support/hard_sigmoid_operation.hpp>
Expand Down
185 changes: 89 additions & 96 deletions src/plugins/keras_support/conv1d_operation.cpp
Expand Up @@ -269,49 +269,48 @@ namespace phylanx { namespace execution_tree { namespace primitives
{
std::size_t kernel_size;
std::size_t remainder = -i_rel % dilation_rate;
if (dilated_k_size + i_rel > v_size)
if (v_size <= remainder)
{
kernel_size = 1;
}
else if (dilated_k_size + i_rel > v_size)
{
kernel_size =
blaze::ceil(static_cast<float>(v_size - remainder) /
static_cast<float>(dilation_rate));
if (remainder == 0)
result[i] = convolve_step(v,
blaze::subvector(k,
blaze::ceil(static_cast<float>(-i_rel) /
static_cast<float>(dilation_rate)),
kernel_size),
dilation_rate, kernel_size);
else
result[i] = convolve_step(v,
blaze::subvector(k,
blaze::ceil(static_cast<float>(-i_rel) /
static_cast<float>(dilation_rate)),
kernel_size),
dilation_rate, kernel_size,
dilation_rate - remainder);
}
else
{
kernel_size =
blaze::ceil(static_cast<float>(dilated_k_size + i_rel) /
static_cast<float>(dilation_rate));
if (remainder == 0)
result[i] = convolve_step(
blaze::subvector(v, 0, dilated_k_size + i_rel),
blaze::ceil(static_cast<float>(dilated_k_size + i_rel) /
static_cast<float>(dilation_rate));
}
std::size_t vector_size =
(blaze::min)(v_size, dilated_k_size + i_rel);

if (remainder == 0)
{
result[i] =
convolve_step(blaze::subvector(v, 0, vector_size),
blaze::subvector(k,
blaze::ceil(static_cast<float>(-i_rel) /
static_cast<float>(dilation_rate)),
kernel_size),
dilation_rate, kernel_size);
else
result[i] = convolve_step(
blaze::subvector(v, 0, dilated_k_size + i_rel),
blaze::subvector(k,
blaze::ceil(static_cast<float>(-i_rel) /
static_cast<float>(dilation_rate)),
kernel_size),
dilation_rate, kernel_size,
dilation_rate - remainder);
}
else if (dilation_rate - remainder >= v_size)
{
result[i] = 0;
}
else
{
result[i] = convolve_step(
blaze::subvector(v, 0, vector_size),
blaze::subvector(k,
blaze::ceil(static_cast<float>(-i_rel) /
static_cast<float>(dilation_rate)),
kernel_size),
dilation_rate, kernel_size, dilation_rate - remainder);
}
}
else if (i_rel > static_cast<std::int64_t>(v_size) -
Expand Down Expand Up @@ -542,96 +541,90 @@ namespace phylanx { namespace execution_tree { namespace primitives
"conv1d operation requires for x and kernel to be "
"vectors"));

std::string padding = "valid";
if (args.size() > 2)
{
padding = extract_string_value(
args[2], this_->name_, this_->codename_);
std::string padding;
padding = extract_string_value(
args[2], this_->name_, this_->codename_);

if (padding != "valid" && padding != "same" &&
padding != "causal")
HPX_THROW_EXCEPTION(hpx::bad_parameter,
"conv1d_operation::eval",
this_->generate_error_message(
"invalid padding. Padding can be either valid, "
"same or causal"));

if (padding != "valid" && padding != "same" &&
padding != "causal")
HPX_THROW_EXCEPTION(hpx::bad_parameter,
"conv1d_operation::eval",
this_->generate_error_message(
"invalid padding. Padding can be either valid, "
"same or causal"));
}

if (padding == "valid")
{
if (extract_numeric_value_dimension(
args[0], this_->name_, this_->codename_) <
extract_numeric_value_dimension(
args[1], this_->name_, this_->codename_))
if (extract_numeric_value_dimensions(
args[0], this_->name_, this_->codename_)[0] <
extract_numeric_value_dimensions(
args[1], this_->name_, this_->codename_)[0])
HPX_THROW_EXCEPTION(hpx::bad_parameter,
"conv1d_operation::eval",
this_->generate_error_message(
"the kernel size cannot be greater than the "
"array size in the valid padding mode"));
}

std::int64_t strides = 1;
if (args.size() > 3)
std::int64_t strides;
if (is_list_operand_strict(args[3]))
{
if (is_list_operand_strict(args[3]))
{
ir::range s = extract_list_value(
args[3], this_->name_, this_->codename_);
if (s.size() == 1)
strides =
extract_scalar_integer_value_strict(*s.begin());
else
HPX_THROW_EXCEPTION(hpx::bad_parameter,
"conv1d_operation::eval",
this_->generate_error_message(
"conv1d_operation requires the strides to "
"be of rank 1"));
}
ir::range s = extract_list_value(
args[3], this_->name_, this_->codename_);
if (s.size() == 1)
strides =
extract_scalar_integer_value_strict(*s.begin());
else
strides = extract_scalar_integer_value_strict(
args[3], this_->name_, this_->codename_);

if (strides <= 0)
HPX_THROW_EXCEPTION(hpx::bad_parameter,
"conv1d_operation::eval",
this_->generate_error_message(
"invalid strides. Strides must be positive"));
"conv1d_operation requires the strides to "
"be of rank 1"));
}
else
strides = extract_scalar_integer_value_strict(
args[3], this_->name_, this_->codename_);

std::int64_t dilation_rate = 1;
if (args.size() > 4)
{
if (is_list_operand_strict(args[4]))
{
ir::range d = extract_list_value(
args[4], this_->name_, this_->codename_);
if (d.size() == 1)
dilation_rate =
extract_scalar_integer_value_strict(*d.begin());
else
HPX_THROW_EXCEPTION(hpx::bad_parameter,
"conv1d_operation::eval",
this_->generate_error_message(
"conv1d_operation requires the "
"dilation_rate to be of rank 1"));
}
else
dilation_rate = extract_scalar_integer_value_strict(
args[4], this_->name_, this_->codename_);
if (strides <= 0)
HPX_THROW_EXCEPTION(hpx::bad_parameter,
"conv1d_operation::eval",
this_->generate_error_message(
"invalid strides. Strides must be positive"));

if (dilation_rate <= 0)
HPX_THROW_EXCEPTION(hpx::bad_parameter,
"conv1d_operation::eval",
this_->generate_error_message(
"dilation_rate must be positive"));

if (strides != 1 && dilation_rate != 1)
std::int64_t dilation_rate;
if (is_list_operand_strict(args[4]))
{
ir::range d = extract_list_value(
args[4], this_->name_, this_->codename_);
if (d.size() == 1)
dilation_rate =
extract_scalar_integer_value_strict(*d.begin());
else
HPX_THROW_EXCEPTION(hpx::bad_parameter,
"conv1d_operation::eval",
this_->generate_error_message(
"strides > 1 not supported in conjunction with "
"dilation_rate > 1"));
"conv1d_operation requires the "
"dilation_rate to be of rank 1"));
}
else
dilation_rate = extract_scalar_integer_value_strict(
args[4], this_->name_, this_->codename_);

if (dilation_rate <= 0)
HPX_THROW_EXCEPTION(hpx::bad_parameter,
"conv1d_operation::eval",
this_->generate_error_message(
"dilation_rate must be positive"));

if (strides != 1 && dilation_rate != 1)
HPX_THROW_EXCEPTION(hpx::bad_parameter,
"conv1d_operation::eval",
this_->generate_error_message(
"strides > 1 not supported in conjunction with "
"dilation_rate > 1"));


if (strides == 1 && dilation_rate == 1)
{
Expand Down