Skip to content
Snippets Groups Projects
Commit 18071fd6 authored by Grégoire Kubler's avatar Grégoire Kubler
Browse files

feat : added GlobalAveragePooling operator

parent 8f9ea42d
No related branches found
No related tags found
2 merge requests!105version 0.2.0,!91Feat/operator global average pooling
......@@ -44,6 +44,7 @@
#include "aidge/operator/FC.hpp"
#include "aidge/operator/Gather.hpp"
#include "aidge/operator/GenericOperator.hpp"
#include "aidge/operator/GlobalAveragePooling.hpp"
#include "aidge/operator/MatMul.hpp"
#include "aidge/operator/MaxPooling.hpp"
#include "aidge/operator/MetaOperator.hpp"
......
/********************************************************************************
* Copyright (c) 2023 CEA-List
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
********************************************************************************/
#ifndef AIDGE_CORE_OPERATOR_GLOBAL_AVERAGE_POOLING_H_
#define AIDGE_CORE_OPERATOR_GLOBAL_AVERAGE_POOLING_H_
#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/graph/Node.hpp"
#include "aidge/utils/Types.h"
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 ;
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;
}
std::shared_ptr<Operator> clone() const override { return std::make_shared<GlobalAveragePooling_Op>(*this); }
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);
}
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);
}
}
#endif /* AIDGE_CORE_OPERATOR_GLOBAL_AVERAGE_POOLING_H_ */
\ No newline at end of file
/********************************************************************************
* Copyright (c) 2023 CEA-List
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
********************************************************************************/
#include <pybind11/pybind11.h>
#include "aidge/operator/GlobalAveragePooling.hpp"
#include "aidge/operator/OperatorTensor.hpp"
#include "aidge/utils/Attributes.hpp"
namespace py = pybind11;
namespace Aidge {
void init_GlobalAveragePooling(py::module& m) {
py::class_<GlobalAveragePooling_Op, std::shared_ptr<GlobalAveragePooling_Op>, OperatorTensor, Attributes>(m, "GlobalAveragePooling", py::multiple_inheritance())
.def("get_inputs_name", &GlobalAveragePooling_Op::getInputsName)
.def("get_outputs_name", &GlobalAveragePooling_Op::getOutputsName);
m.def("Hardmax", &Hardmax, py::arg("name") = "");
}
} // namespace Aidge
\ No newline at end of file
......@@ -37,6 +37,7 @@ void init_Erf(py::module&);
void init_FC(py::module&);
void init_Gather(py::module&);
void init_GenericOperator(py::module&);
void init_GlobalAveragePooling(py::module&);
void init_LeakyReLU(py::module&);
void init_MatMul(py::module&);
void init_MaxPooling(py::module&);
......@@ -95,6 +96,7 @@ void init_Aidge(py::module& m){
init_FC(m);
init_Gather(m);
init_GenericOperator(m);
init_GlobalAveragePooling(m);
init_LeakyReLU(m);
init_MatMul(m);
init_MaxPooling(m);
......
/********************************************************************************
* Copyright (c) 2023 CEA-List
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
********************************************************************************/
#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);
}
}
/********************************************************************************
* Copyright (c) 2023 CEA-List
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
********************************************************************************/
#include <catch2/catch_test_macros.hpp>
#include <cstddef> // std::size_t
#include <memory>
#include <random> // std::random_device, std::mt19937, std::uniform_int_distribution
#include <vector>
#include "aidge/data/Tensor.hpp"
#include "aidge/operator/GlobalAveragePooling.hpp"
#include "aidge/operator/OperatorTensor.hpp"
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());
// 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;
}
input_T->resize(dims0);
REQUIRE_NOTHROW(op->computeOutputDims());
REQUIRE((op->getOutput(0)->dims().size()) == static_cast<size_t>(2));
}
}
}
} // namespace Aidge
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment