diff --git a/include/aidge/operator/AvgPooling.hpp b/include/aidge/operator/AvgPooling.hpp index f1a7723ea64d713e497b039ca2eb5bb2f4620e62..709cad727ee49d3da88931c25997539049170da4 100644 --- a/include/aidge/operator/AvgPooling.hpp +++ b/include/aidge/operator/AvgPooling.hpp @@ -24,14 +24,15 @@ #include "aidge/utils/Types.h" namespace Aidge { -enum class AvgPoolingAttr { StrideDims, KernelDims }; +enum class AvgPoolingAttr { StrideDims, KernelDims, CountIncludePad }; template <DimIdx_t DIM> class AvgPooling_Op : public OperatorTensor, public Registrable<AvgPooling_Op<DIM>, std::string, std::shared_ptr<OperatorImpl>(const AvgPooling_Op<DIM> &)>, public StaticAttributes<AvgPoolingAttr, std::array<DimSize_t, DIM>, - std::array<DimSize_t, DIM>> { + std::array<DimSize_t, DIM>, + bool> { public: static const std::string Type; @@ -40,15 +41,18 @@ public: using Attributes_ = StaticAttributes<AvgPoolingAttr, std::array<DimSize_t, DIM>, - std::array<DimSize_t, DIM>>; + std::array<DimSize_t, DIM>, + bool>; template <AvgPoolingAttr e> using attr = typename Attributes_::template attr<e>; constexpr AvgPooling_Op(const std::array<DimSize_t, DIM> &kernel_dims, - const std::array<DimSize_t, DIM> &stride_dims = create_array<DimSize_t,DIM>(1)) + const std::array<DimSize_t, DIM> &stride_dims = create_array<DimSize_t,DIM>(1), + bool countIncludePad = false) : OperatorTensor(Type, {InputCategory::Data}, 1), Attributes_(attr<AvgPoolingAttr::StrideDims>(stride_dims), - attr<AvgPoolingAttr::KernelDims>(kernel_dims)) {} + attr<AvgPoolingAttr::KernelDims>(kernel_dims), + attr<AvgPoolingAttr::CountIncludePad>(countIncludePad)) {} /** * @brief Copy-constructor. Copy the operator attributes and its output tensor(s), but not its input tensors (the new operator has no input associated). @@ -87,9 +91,10 @@ public: template <std::array<DimSize_t, 1>::size_type DIM> inline std::shared_ptr<Node> AvgPooling(const std::array<DimSize_t, DIM> &kernel_dims, const std::string& name = "", - const std::array<DimSize_t, DIM> &stride_dims = create_array<DimSize_t,DIM>(1)) { + const std::array<DimSize_t, DIM> &stride_dims = create_array<DimSize_t,DIM>(1), + bool count_include_pad = false) { static_assert(DIM<=MaxDim,"Too many kernel dimensions required by AvgPooling, not supported"); - return std::make_shared<Node>(std::make_shared<AvgPooling_Op<static_cast<DimIdx_t>(DIM)>>(kernel_dims, stride_dims), name); + return std::make_shared<Node>(std::make_shared<AvgPooling_Op<static_cast<DimIdx_t>(DIM)>>(kernel_dims, stride_dims, count_include_pad), name); } // helper with C-style array instead of std::array for kernel_dims to allow automatic template DIM deduction @@ -97,9 +102,10 @@ template <DimSize_t DIM> inline std::shared_ptr<Node> AvgPooling( DimSize_t const (&kernel_dims)[DIM], const std::string& name = "", - const std::array<DimSize_t, DIM> &stride_dims = create_array<DimSize_t,DIM>(1)) { + const std::array<DimSize_t, DIM> &stride_dims = create_array<DimSize_t,DIM>(1), + bool count_include_pad = false) { static_assert(DIM<=MaxDim,"Too many kernel dimensions required by AvgPooling, not supported"); - return AvgPooling(to_array(kernel_dims), name, stride_dims); + return AvgPooling(to_array(kernel_dims), name, stride_dims, count_include_pad); } @@ -113,7 +119,7 @@ extern template class Aidge::AvgPooling_Op<4>; namespace { template <> const char *const EnumStrings<Aidge::AvgPoolingAttr>::data[] = {"StrideDims", - "KernelDims"}; + "KernelDims", "CountIncludePad"}; } #endif /* AIDGE_CORE_OPERATOR_AVGPOOLING_H_ */ diff --git a/include/aidge/operator/MetaOperatorDefs.hpp b/include/aidge/operator/MetaOperatorDefs.hpp index 51681629cbae215fd529b6e7bb568d07264dd63e..e413d819237c49c380daa6592a9ffa0302e02198 100644 --- a/include/aidge/operator/MetaOperatorDefs.hpp +++ b/include/aidge/operator/MetaOperatorDefs.hpp @@ -139,20 +139,23 @@ template <std::array<DimSize_t, 1>::size_type DIM> extern std::shared_ptr<Node> PaddedAvgPooling(const std::array<DimSize_t, DIM> &kernel_dims, const std::string& name = "", const std::array<DimSize_t, DIM> &stride_dims = create_array<DimSize_t,DIM>(1), - const std::array<DimSize_t, 2*DIM> &padding_dims = create_array<DimSize_t,2*DIM>(0)); + const std::array<DimSize_t, 2*DIM> &padding_dims = create_array<DimSize_t,2*DIM>(0), + bool count_include_pad = false); template <std::array<DimSize_t, 1>::size_type DIM> extern std::shared_ptr<MetaOperator_Op> PaddedAvgPooling_Op(const std::array<DimSize_t, DIM> &kernel_dims, const std::array<DimSize_t, DIM> &stride_dims = create_array<DimSize_t,DIM>(1), - const std::array<DimSize_t, 2*DIM> &padding_dims = create_array<DimSize_t,2*DIM>(0)); + const std::array<DimSize_t, 2*DIM> &padding_dims = create_array<DimSize_t,2*DIM>(0), + bool count_include_pad = false); // helper with C-style array instead of std::array for kernel_dims to allow automatic template DIM deduction template <DimSize_t DIM> extern std::shared_ptr<Node> PaddedAvgPooling(DimSize_t const (&kernel_dims)[DIM], const std::string& name = "", const std::array<DimSize_t, DIM> &stride_dims = create_array<DimSize_t,DIM>(1), - const std::array<DimSize_t, 2*DIM> &padding_dims = create_array<DimSize_t,2*DIM>(0)); + const std::array<DimSize_t, 2*DIM> &padding_dims = create_array<DimSize_t,2*DIM>(0), + bool count_include_pad = false); //////////////////////////////////////////////////////////////////////////////// diff --git a/python_binding/operator/pybind_AvgPooling.cpp b/python_binding/operator/pybind_AvgPooling.cpp index 966def88033dee8cd6cee06d80dc32114050b430..e44bd92d95505a47a684358528f0b83e9109e586 100644 --- a/python_binding/operator/pybind_AvgPooling.cpp +++ b/python_binding/operator/pybind_AvgPooling.cpp @@ -31,9 +31,11 @@ template <DimIdx_t DIM> void declare_AvgPoolingOp(py::module &m) { m, pyClassName.c_str(), py::multiple_inheritance()) .def(py::init<const std::array<DimSize_t, DIM> &, - const std::array<DimSize_t, DIM> &>(), + const std::array<DimSize_t, DIM> &, + bool>(), py::arg("kernel_dims"), - py::arg("stride_dims")) + py::arg("stride_dims"), + py::arg("count_include_pad")) .def("get_inputs_name", &AvgPooling_Op<DIM>::getInputsName) .def("get_outputs_name", &AvgPooling_Op<DIM>::getOutputsName) .def("attributes_name", &AvgPooling_Op<DIM>::staticGetAttrsName); @@ -42,14 +44,16 @@ template <DimIdx_t DIM> void declare_AvgPoolingOp(py::module &m) { m.def(("AvgPooling" + std::to_string(DIM) + "D").c_str(), [](const std::vector<DimSize_t>& kernel_dims, const std::string& name, - const std::vector<DimSize_t> &stride_dims) { + const std::vector<DimSize_t> &stride_dims, + bool count_include_pad) { AIDGE_ASSERT(kernel_dims.size() == DIM, "kernel_dims size [{}] does not match DIM [{}]", kernel_dims.size(), DIM); AIDGE_ASSERT(stride_dims.size() == DIM, "stride_dims size [{}] does not match DIM [{}]", stride_dims.size(), DIM); - return AvgPooling<DIM>(to_array<DIM>(kernel_dims.begin()), name, to_array<DIM>(stride_dims.begin())); + return AvgPooling<DIM>(to_array<DIM>(kernel_dims.begin()), name, to_array<DIM>(stride_dims.begin()), count_include_pad); }, py::arg("kernel_dims"), py::arg("name") = "", - py::arg("stride_dims") = std::vector<DimSize_t>(DIM,1)); + py::arg("stride_dims") = std::vector<DimSize_t>(DIM,1), + py::arg("count_include_pad") = false); } diff --git a/python_binding/operator/pybind_MetaOperatorDefs.cpp b/python_binding/operator/pybind_MetaOperatorDefs.cpp index d021a79c5ff4e337bebf424465458ddabf056a56..d7bf569fbab043b39e0284abf3bb20ba13bcfef0 100644 --- a/python_binding/operator/pybind_MetaOperatorDefs.cpp +++ b/python_binding/operator/pybind_MetaOperatorDefs.cpp @@ -110,29 +110,33 @@ template <DimIdx_t DIM> void declare_PaddedAvgPoolingOp(py::module &m) { m.def(("PaddedAvgPooling" + std::to_string(DIM) + "D").c_str(), [](const std::vector<DimSize_t>& kernel_dims, const std::string& name, const std::vector<DimSize_t> &stride_dims, - const std::vector<DimSize_t> &padding_dims) + const std::vector<DimSize_t> &padding_dims, + bool count_include_pad) { AIDGE_ASSERT(kernel_dims.size() == DIM, "kernel_dims size [{}] does not match DIM [{}]", kernel_dims.size(), DIM); AIDGE_ASSERT(stride_dims.size() == DIM, "stride_dims size [{}] does not match DIM [{}]", stride_dims.size(), DIM); AIDGE_ASSERT(padding_dims.size() == 2*DIM, "padding_dims size [{}] does not match DIM [{}]", padding_dims.size(), 2*DIM); - return PaddedAvgPooling<DIM>(to_array<DIM>(kernel_dims.begin()), name, to_array<DIM>(stride_dims.begin()), to_array<2*DIM>(padding_dims.begin())); + return PaddedAvgPooling<DIM>(to_array<DIM>(kernel_dims.begin()), name, to_array<DIM>(stride_dims.begin()), to_array<2*DIM>(padding_dims.begin()), count_include_pad); }, py::arg("kernel_dims"), py::arg("name") = "", py::arg("stride_dims") = std::vector<DimSize_t>(DIM,1), - py::arg("padding_dims") = std::vector<DimSize_t>(2*DIM,0)); + py::arg("padding_dims") = std::vector<DimSize_t>(2*DIM,0), + py::arg("count_include_pad") = false); m.def(("PaddedAvgPoolingOp" + std::to_string(DIM) + "D").c_str(), [](const std::vector<DimSize_t>& kernel_dims, const std::vector<DimSize_t> &stride_dims, - const std::vector<DimSize_t> &padding_dims) + const std::vector<DimSize_t> &padding_dims, + bool count_include_pad) { AIDGE_ASSERT(kernel_dims.size() == DIM, "kernel_dims size [{}] does not match DIM [{}]", kernel_dims.size(), DIM); AIDGE_ASSERT(stride_dims.size() == DIM, "stride_dims size [{}] does not match DIM [{}]", stride_dims.size(), DIM); AIDGE_ASSERT(padding_dims.size() == 2*DIM, "padding_dims size [{}] does not match DIM [{}]", padding_dims.size(), 2*DIM); - return PaddedAvgPooling_Op<DIM>(to_array<DIM>(kernel_dims.begin()), to_array<DIM>(stride_dims.begin()), to_array<2*DIM>(padding_dims.begin())); + return PaddedAvgPooling_Op<DIM>(to_array<DIM>(kernel_dims.begin()), to_array<DIM>(stride_dims.begin()), to_array<2*DIM>(padding_dims.begin()), count_include_pad); }, py::arg("kernel_dims"), py::arg("stride_dims") = std::vector<DimSize_t>(DIM,1), - py::arg("padding_dims") = std::vector<DimSize_t>(2*DIM,0)); + py::arg("padding_dims") = std::vector<DimSize_t>(2*DIM,0), + py::arg("count_include_pad") = false); } template <DimIdx_t DIM> void declare_PaddedMaxPoolingOp(py::module &m) { diff --git a/src/operator/MetaOperatorDefs/PaddedAvgPooling.cpp b/src/operator/MetaOperatorDefs/PaddedAvgPooling.cpp index ef319ef38ad18de9eaed0a1d4a92c3877ee7cf8e..65ce251a7ffba8f0292c29bef048a8f791ea0c16 100644 --- a/src/operator/MetaOperatorDefs/PaddedAvgPooling.cpp +++ b/src/operator/MetaOperatorDefs/PaddedAvgPooling.cpp @@ -34,31 +34,33 @@ template <std::array<DimSize_t, 1>::size_type DIM> std::shared_ptr<Node> PaddedAvgPooling(const std::array<DimSize_t, DIM> &kernel_dims, const std::string& name, const std::array<DimSize_t, DIM> &stride_dims, - const std::array<DimSize_t, 2*DIM> &padding_dims) + const std::array<DimSize_t, 2*DIM> &padding_dims, + bool count_include_pad) { auto graph = Sequential({ Pad<DIM>(padding_dims, (!name.empty()) ? name + "_pad" : ""), - AvgPooling(kernel_dims, (!name.empty()) ? name + "_avgpooling" : "", stride_dims) + AvgPooling(kernel_dims, (!name.empty()) ? name + "_avgpooling" : "", stride_dims, count_include_pad) }); return MetaOperator("PaddedAvgPooling", graph, name); } -template std::shared_ptr<Node> PaddedAvgPooling<1>(const std::array<DimSize_t,1>&, const std::string&, const std::array<DimSize_t,1>&, const std::array<DimSize_t,2>&); -template std::shared_ptr<Node> PaddedAvgPooling<2>(const std::array<DimSize_t,2>&, const std::string&, const std::array<DimSize_t,2>&, const std::array<DimSize_t,4>&); +template std::shared_ptr<Node> PaddedAvgPooling<1>(const std::array<DimSize_t,1>&, const std::string&, const std::array<DimSize_t,1>&, const std::array<DimSize_t,2>&, bool count_include_pad); +template std::shared_ptr<Node> PaddedAvgPooling<2>(const std::array<DimSize_t,2>&, const std::string&, const std::array<DimSize_t,2>&, const std::array<DimSize_t,4>&, bool count_include_pad); // helper with C-style array instead of std::array for kernel_dims to allow automatic template DIM deduction template <DimSize_t DIM> std::shared_ptr<Node> PaddedAvgPooling(const DimSize_t (&kernel_dims)[DIM], const std::string& name, const std::array<DimSize_t, DIM> &stride_dims, - const std::array<DimSize_t, 2*DIM> &padding_dims) + const std::array<DimSize_t, 2*DIM> &padding_dims, + bool count_include_pad) { - return PaddedAvgPooling(to_array(kernel_dims), name, stride_dims, padding_dims); + return PaddedAvgPooling(to_array(kernel_dims), name, stride_dims, padding_dims, count_include_pad); } -template std::shared_ptr<Node> PaddedAvgPooling<1>(const DimSize_t (&kernel_dims)[1], const std::string&, const std::array<DimSize_t,1>&, const std::array<DimSize_t,2>&); -template std::shared_ptr<Node> PaddedAvgPooling<2>(const DimSize_t (&kernel_dims)[2], const std::string&, const std::array<DimSize_t,2>&, const std::array<DimSize_t,4>&); +template std::shared_ptr<Node> PaddedAvgPooling<1>(const DimSize_t (&kernel_dims)[1], const std::string&, const std::array<DimSize_t,1>&, const std::array<DimSize_t,2>&, bool count_include_pad); +template std::shared_ptr<Node> PaddedAvgPooling<2>(const DimSize_t (&kernel_dims)[2], const std::string&, const std::array<DimSize_t,2>&, const std::array<DimSize_t,4>&, bool count_include_pad); ////////////////////////////////// @@ -68,17 +70,18 @@ template std::shared_ptr<Node> PaddedAvgPooling<2>(const DimSize_t (&kernel_dims template <std::array<DimSize_t, 1>::size_type DIM> inline std::shared_ptr<MetaOperator_Op> PaddedAvgPooling_Op(const std::array<DimSize_t, DIM> &kernel_dims, const std::array<DimSize_t, DIM> &stride_dims, - const std::array<DimSize_t, 2*DIM> &padding_dims) + const std::array<DimSize_t, 2*DIM> &padding_dims, + bool count_include_pad) { auto graph = Sequential({ Pad<DIM>(padding_dims, ""), - AvgPooling(kernel_dims, "", stride_dims) + AvgPooling(kernel_dims, "", stride_dims, count_include_pad) }); return std::make_shared<MetaOperator_Op>("PaddedAvgPooling", graph); } -template std::shared_ptr<MetaOperator_Op> PaddedAvgPooling_Op<1>(const std::array<DimSize_t,1>&, const std::array<DimSize_t,1>&, const std::array<DimSize_t,2>&); -template std::shared_ptr<MetaOperator_Op> PaddedAvgPooling_Op<2>(const std::array<DimSize_t,2>&, const std::array<DimSize_t,2>&, const std::array<DimSize_t,4>&); +template std::shared_ptr<MetaOperator_Op> PaddedAvgPooling_Op<1>(const std::array<DimSize_t,1>&, const std::array<DimSize_t,1>&, const std::array<DimSize_t,2>&, bool count_include_pad); +template std::shared_ptr<MetaOperator_Op> PaddedAvgPooling_Op<2>(const std::array<DimSize_t,2>&, const std::array<DimSize_t,2>&, const std::array<DimSize_t,4>&, bool count_include_pad); } // namespace Aidge