diff --git a/include/aidge/operator/GlobalAveragePooling.hpp b/include/aidge/operator/GlobalAveragePooling.hpp index 71b332bf1dacae1990a0d0ea89c139ce7be38ec2..2ce78052d2dce4cf01f902c22ba3978d2cfc416e 100644 --- a/include/aidge/operator/GlobalAveragePooling.hpp +++ b/include/aidge/operator/GlobalAveragePooling.hpp @@ -14,53 +14,62 @@ #include <memory> -#include "aidge/utils/Registrar.hpp" -#include "aidge/operator/OperatorTensor.hpp" #include "aidge/backend/OperatorImpl.hpp" -#include "aidge/data/Tensor.hpp" #include "aidge/data/Data.hpp" +#include "aidge/data/Tensor.hpp" #include "aidge/graph/Node.hpp" +#include "aidge/operator/OperatorTensor.hpp" +#include "aidge/utils/Registrar.hpp" #include "aidge/utils/Types.h" -namespace Aidge -{ +namespace Aidge { - /** - * @brief Description for the tensor data structure. - * @details Sets the properties of the tensor without actually containing any data. - * Contains a pointer to an actual contiguous implementation of data. - */ - class GlobalAveragePooling_Op : public OperatorTensor, - public Registrable<GlobalAveragePooling_Op, std::string, std::unique_ptr<OperatorImpl>(const GlobalAveragePooling_Op &)> - { - public: - static const std::string Type ; +/** + * @brief Description for the tensor data structure. + * @details Sets the properties of the tensor without actually containing any + * data. Contains a pointer to an actual contiguous implementation of data. + */ +class GlobalAveragePooling_Op + : public OperatorTensor, + public Registrable<GlobalAveragePooling_Op, std::string, + std::unique_ptr<OperatorImpl>( + const GlobalAveragePooling_Op &)> { +public: + static const std::string Type; - GlobalAveragePooling_Op() : OperatorTensor(Type, 1, 0, 1) {} + GlobalAveragePooling_Op() : OperatorTensor(Type, 1, 0, 1) {} - GlobalAveragePooling_Op(const GlobalAveragePooling_Op &op) : OperatorTensor(op) - { - mImpl = op.mImpl ? Registrar<GlobalAveragePooling_Op>::create(op.mOutputs[0]->getImpl()->backend())(*this) : nullptr; - } + GlobalAveragePooling_Op(const GlobalAveragePooling_Op &op) + : OperatorTensor(op) { + mImpl = op.mImpl ? Registrar<GlobalAveragePooling_Op>::create( + op.mOutputs[0]->getImpl()->backend())(*this) + : nullptr; + } - std::shared_ptr<Operator> clone() const override { return std::make_shared<GlobalAveragePooling_Op>(*this); } + std::shared_ptr<Operator> clone() const override { + return std::make_shared<GlobalAveragePooling_Op>(*this); + } - void computeOutputDims() override final; + void computeOutputDims() override final; - void setBackend(const std::string &name, DeviceIdx_t device = 0) override - { - mImpl = Registrar<GlobalAveragePooling_Op>::create(name)(*this); - mOutputs[0]->setBackend(name, device); - } + void setBackend(const std::string &name, DeviceIdx_t device = 0) override { + mImpl = Registrar<GlobalAveragePooling_Op>::create(name)(*this); + mOutputs[0]->setBackend(name, device); + } - static const std::vector<std::string> getInputsName() { return {"data_input"}; } - static const std::vector<std::string> getOutputsName() { return {"data_output"}; } - }; + static const std::vector<std::string> getInputsName() { + return {"data_input"}; + } + static const std::vector<std::string> getOutputsName() { + return {"data_output"}; + } +}; - inline std::shared_ptr<Node> GlobalAveragePooling(const std::string &name = "") - { - return std::make_shared<Node>(std::make_shared<GlobalAveragePooling_Op>(), name); - } +inline std::shared_ptr<Node> +GlobalAveragePooling(const std::string &name = "") { + return std::make_shared<Node>(std::make_shared<GlobalAveragePooling_Op>(), + name); } +} // namespace Aidge -#endif /* AIDGE_CORE_OPERATOR_GLOBAL_AVERAGE_POOLING_H_ */ \ No newline at end of file +#endif /* AIDGE_CORE_OPERATOR_GLOBAL_AVERAGE_POOLING_H_ */ diff --git a/src/operator/GlobalAveragePooling.cpp b/src/operator/GlobalAveragePooling.cpp index 39b5fa65a507be6c42feec38ba39d2e3f2ab2e5b..f2cfdc8bdd335dd24bba4fffdef192fc3f8cb591 100644 --- a/src/operator/GlobalAveragePooling.cpp +++ b/src/operator/GlobalAveragePooling.cpp @@ -9,28 +9,30 @@ * ********************************************************************************/ +#include <string> #include <vector> #include "aidge/operator/GlobalAveragePooling.hpp" const std::string Aidge::GlobalAveragePooling_Op::Type = "GlobalAveragePooling"; -void Aidge::GlobalAveragePooling_Op::computeOutputDims() -{ - // error checking - if (!getInput(0)) - { - AIDGE_THROW_OR_ABORT(std::runtime_error, "At least one input was not connected"); - } - else if (getInput(0)->dims().size() < 3) - { - AIDGE_THROW_OR_ABORT(std::runtime_error, "GlobalAveragePool needs at least 3 dimensions input, number of input dim : %lu", getInput(0)->dims().size()); - } - else - { - // Global average pooling takes each filter, averages its values and uses it as an output(Much like a fancier flatten). - //1st dim is batch 2nd is number of filter - const std::vector<DimSize_t> out_dims(getInput(0)->dims().at(0), getInput(0)->dims().at(1)); - mOutputs[0]->resize(out_dims); - } +void Aidge::GlobalAveragePooling_Op::computeOutputDims() { + // error checking + if (!getInput(0)) { + AIDGE_THROW_OR_ABORT(std::runtime_error, + "GlobalAveragePooling : The input was not connected"); + } else if (getInput(0)->dims().size() < 3) { + AIDGE_THROW_OR_ABORT( + std::runtime_error, + "GlobalAveragePooling : needs at least 3 dimensions input, " + "number of input dim : %lu", + getInput(0)->dims().size()); + } else { + // Global average pooling takes each filter, averages its values and uses it + // as an output(Much like a fancier flatten). + // 1st dim is batch 2nd is number of filter + const std::vector<DimSize_t> out_dims{getInput(0)->dims().at(0), + getInput(0)->dims().at(1)}; + mOutputs[0]->resize(out_dims); + } } diff --git a/unit_tests/operator/Test_GlobalAveragePooling_Op.cpp b/unit_tests/operator/Test_GlobalAveragePooling_Op.cpp index 355aeb20ba4b5884b01ba0ea84b7db145d7a0829..ad36c7450c6f93ddd195bc6480264209164e6a84 100644 --- a/unit_tests/operator/Test_GlobalAveragePooling_Op.cpp +++ b/unit_tests/operator/Test_GlobalAveragePooling_Op.cpp @@ -18,62 +18,54 @@ #include "aidge/data/Tensor.hpp" #include "aidge/operator/GlobalAveragePooling.hpp" #include "aidge/operator/OperatorTensor.hpp" +#include "aidge/utils/Types.h" -namespace Aidge -{ - TEST_CASE("[core/operator] GlobalAveragePooling_Op(computeOutputDims)", "[GlobalAveragePooling][computeOutputDims]") - { - constexpr std::uint16_t NB_TRIALS = 10; - // Create a random number generator - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_int_distribution<std::size_t> dimsDist(1, 10); - std::uniform_int_distribution<std::size_t> inf3DimsDistribution(0, 2); - std::uniform_int_distribution<std::size_t> sup3DimsDistribution(3, 10); +namespace Aidge { +TEST_CASE("[core/operator] GlobalAveragePooling_Op(computeOutputDims)", + "[GlobalAveragePooling][computeOutputDims]") { + constexpr std::uint16_t NB_TRIALS = 10; + // Create a random number generator + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<std::size_t> dimsDist(1, 10); + std::uniform_int_distribution<std::size_t> inf3DimsDistribution(0, 2); + std::uniform_int_distribution<std::size_t> sup3DimsDistribution(3, 10); - // Create the GlobalAveragePooling Operator - std::shared_ptr<Node> myGlobAvgPool = GlobalAveragePooling(); - auto op = std::static_pointer_cast<OperatorTensor>(myGlobAvgPool->getOperator()); + // Create the GlobalAveragePooling Operator + std::shared_ptr<Node> myGlobAvgPool = GlobalAveragePooling(); + auto op = + std::static_pointer_cast<OperatorTensor>(myGlobAvgPool->getOperator()); - // input_0 - std::shared_ptr<Tensor> input_T = std::make_shared<Tensor>(); - SECTION("input association") - { - REQUIRE_THROWS(op->computeOutputDims()); - } - op->associateInput(0, input_T); + // input_0 + std::shared_ptr<Tensor> input_T = std::make_shared<Tensor>(); + SECTION("input association") { REQUIRE_THROWS(op->computeOutputDims()); } + op->associateInput(0, input_T); - SECTION("nbDim < 3") - { - const std::size_t nb_dims = inf3DimsDistribution(gen) + 1; - for (uint16_t trial; trial < NB_TRIALS; ++trial) - { - std::vector<std::size_t> dims0(nb_dims); - for (uint16_t i; i < nb_dims; ++i) - { - dims0[i] = dimsDist(gen) + 1; - } - - input_T->resize(dims0); - REQUIRE_THROWS(op->computeOutputDims()); - } - } - - SECTION("nbDim > 3") - { - const std::size_t nb_dims = inf3DimsDistribution(gen) + 1; - for (uint16_t trial; trial < NB_TRIALS; ++trial) - { - std::vector<std::size_t> dims0(nb_dims); - for (uint16_t i; i < nb_dims; ++i) - { - dims0[i] = dimsDist(gen) + 1; - } + SECTION("nbDim < 3") { + for (uint16_t trial = 0; trial < NB_TRIALS; ++trial) { + const std::size_t nb_dims = inf3DimsDistribution(gen); + std::vector<std::size_t> dims(nb_dims); + for (uint16_t i = 0; i < nb_dims; ++i) { + dims[i] = dimsDist(gen); + } + input_T->resize(dims); + REQUIRE_THROWS(op->computeOutputDims()); + } + } - input_T->resize(dims0); - REQUIRE_NOTHROW(op->computeOutputDims()); - REQUIRE((op->getOutput(0)->dims().size()) == static_cast<size_t>(2)); - } - } + SECTION("nbDim > 3") { + for (uint16_t trial = 0; trial < NB_TRIALS; ++trial) { + const std::size_t nb_dims = sup3DimsDistribution(gen); + std::vector<std::size_t> dims(nb_dims); + for (uint16_t i = 0; i < nb_dims; ++i) { + dims[i] = dimsDist(gen) + 1; + } + std::vector<DimSize_t> dims_out{dims[0], dims[1]}; + input_T->resize(dims); + REQUIRE_NOTHROW(op->computeOutputDims()); + REQUIRE(op->getOutput(0)->dims() == dims_out); + REQUIRE((op->getOutput(0)->dims().size()) == static_cast<size_t>(2)); } + } +} } // namespace Aidge