diff --git a/src/operators/im2sequence_op.cpp b/src/operators/im2sequence_op.cpp new file mode 100644 index 0000000000000000000000000000000000000000..932dd654fc90e19d8d3146912c1e790c80edf983 --- /dev/null +++ b/src/operators/im2sequence_op.cpp @@ -0,0 +1,55 @@ +/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#include "operators/im2sequence_op.h" + +namespace paddle_mobile { +namespace operators { + +int Im2SequenceOutputSize(int input_size, int kernel, int padding_1, int padding_2, + int stride) { + int output_size = 1 + (padding_1 + padding_2 + input_size - kernel + stride - 1) / stride; + return output_size; +} + +template +void Im2SequenceOp::InferShape() const { + + auto in_dims = param_.Input()->dims(); + + const std::vector &kernels = param_.Kernels(); + + const std::vector &strides = param_.Strides(); + + std::vector paddings = param_.Paddings(); + + std::vector output_shape({in_dims[0], in_dims[0]}); + for (size_t i = 0; i < strides.size(); ++i) { + output_shape.push_back(Im2SequenceOutputSize(in_dims[i + 2], kernels[i], + paddings[i], paddings[i + 2], + strides[i])); + } + + framework::DDim ddim = framework::make_ddim(output_shape); + param_.Output()->Resize(ddim); +} + +template class Im2SequenceOp; + +} // namespace operators +} // namespace paddle_mobile + +namespace ops = paddle_mobile::operators; +USE_OP(im2sequence); +REGISTER_OPERATOR(im2sequence, ops::Im2SequenceOp); diff --git a/src/operators/im2sequence_op.h b/src/operators/im2sequence_op.h new file mode 100644 index 0000000000000000000000000000000000000000..e501821e5812d201ead0af052f6c8498ea5abc5f --- /dev/null +++ b/src/operators/im2sequence_op.h @@ -0,0 +1,50 @@ +/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#pragma once + +#include "framework/operator.h" +#include "operators/kernel/im2sequence_kernel.h" +#include + +namespace paddle_mobile { +namespace operators { + +using namespace framework; + +template +class Im2SequenceOp : public framework::OperatorWithKernel { + public: + Im2SequenceOp(const std::string &type, const VariableNameMap &inputs, + const VariableNameMap &outputs, const framework::AttributeMap &attrs, + std::shared_ptr scope) + : framework::OperatorWithKernel(type, inputs, outputs, attrs, + scope), + param_(inputs, outputs, attrs, *scope) {} + + using framework::OperatorWithKernel::OperatorWithKernel; + void InferShape() const override; + + void RunImpl() const { + operators::Im2SequenceKernel kernel; + kernel.Compute(param_); + this->ClearVariables({"Input"}); + } + + private: + Im2SequenceParam param_; +}; + +} // namespace operators +} // namespace paddle_mobile diff --git a/src/operators/kernel/arm/im2sequence_kernel.cpp b/src/operators/kernel/arm/im2sequence_kernel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..54fee566d877f212e9130aff62c3d5cd6341ea84 --- /dev/null +++ b/src/operators/kernel/arm/im2sequence_kernel.cpp @@ -0,0 +1,82 @@ +/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#include "operators/kernel/im2sequence_kernel.h" + +namespace paddle_mobile { +namespace operators { + +bool IsExpand(const std::vector &kernels, + const std::vector &strides, + const std::vector &paddings) { + bool kernels_1 = true, strides_1 = true, padding_0 = true; + for (size_t j = 0; j < strides.size(); ++j) { + kernels_1 = kernels_1 && (kernels[j] == 1); + strides_1 = strides_1 && (strides[j] == 1); + padding_0 = padding_0 && (paddings[j] == 0); + } + return !(kernels_1 && strides_1 && padding_0); +} + +inline int Im2SeqOutputSize(int input_size, int filter_size, int padding_0, + int padding_1, int stride) { + const int output_size = + (input_size + padding_0 + padding_1 - filter_size) / stride + 1; + return output_size; +} + +template <> +void Im2SequenceKernel::Compute(const Im2SequenceParam ¶m) const { + //LOG(kLOG_DEBUG) << param; + + const Tensor *input = param.Input(); + Tensor *output = param.Output(); + output->mutable_data(); + + std::vector kernels = param.Kernels(); + std::vector strides = param.Strides(); + std::vector paddings = param.Paddings(); + + auto in_dim = input->dims(); + const int batch_size = static_cast(in_dim[0]); + const int img_channels = static_cast(in_dim[1]); + const int img_height = static_cast(in_dim[2]); + const int img_width = static_cast(in_dim[3]); + + int output_height = Im2SeqOutputSize(img_height, kernels[0], paddings[0], + paddings[2], strides[0]); + int output_width = Im2SeqOutputSize(img_width, kernels[1], paddings[1], + paddings[3], strides[1]); + const std::vector dilations({1, 1}); + + //TODO: verify + auto out_dims = output->dims(); + output->Resize({batch_size, output->numel() / batch_size}); + + for (int i = 0; i < batch_size; i++) { + const Tensor src = + input->Slice(i, i + 1).Resize({img_channels, img_height, img_width}); + Tensor dst = output->Slice(i, i + 1).Resize( + {output_height, output_width, img_channels, kernels[0], kernels[1]}); + + math::Im2ColFunctor f; + f(src, dilations, strides, paddings, &dst); + } + output->Resize(out_dims); +} + +template class Im2SequenceKernel; + +} // namespace operators +} // namespace paddle_mobile diff --git a/src/operators/kernel/im2sequence_kernel.h b/src/operators/kernel/im2sequence_kernel.h new file mode 100644 index 0000000000000000000000000000000000000000..e50788901d6d36c0f522e9ffd928b0521bc5cd7f --- /dev/null +++ b/src/operators/kernel/im2sequence_kernel.h @@ -0,0 +1,34 @@ +/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#include "framework/operator.h" +#include "operators/math/im2col.h" +#include "operators/math/math_function.h" +#include "operators/math/vol2col.h" +#include "operators/op_param.h" + +#pragma once; + +namespace paddle_mobile { +namespace operators { + +using namespace framework; + +template +class Im2SequenceKernel : public framework::OpKernelBase { + public: + void Compute(const Im2SequenceParam ¶m) const; +}; +} // namespace operators +} // namespace paddle_mobile diff --git a/src/operators/op_param.h b/src/operators/op_param.h index 0ce187c084975c53e433b9428ad14bf11212a5a1..9595a22723bb24b9c8e63a675bd06e14e332ed9c 100644 --- a/src/operators/op_param.h +++ b/src/operators/op_param.h @@ -752,5 +752,34 @@ class FushionFcParam : public OpParam { int axis_; }; +class Im2SequenceParam : public OpParam { + public: + Im2SequenceParam(const VariableNameMap &inputs, const VariableNameMap &outputs, + const AttributeMap &attrs, const Scope &scope) { + input_ = InputFrom(inputs, scope); + output_ = OutputFrom(outputs, scope); + kernels_ = GetAttr>("kernels", attrs); + strides_ = GetAttr>("strides", attrs); + paddings_ = GetAttr>("paddings", attrs); + } + + const Tensor *Input() const { return input_; } + + Tensor *Output() const { return output_; } + + const vector &Kernels() const { return kernels_; } + + const vector &Strides() const { return strides_; } + + const vector &Paddings() const { return paddings_; } + + private: + Tensor *input_; + Tensor *output_; + vector kernels_; + vector strides_; + vector paddings_; +}; + } // namespace operators } // namespace paddle_mobile