Skip to content
Snippets Groups Projects
Commit 9f9c5f83 authored by Houssem ROUIS's avatar Houssem ROUIS
Browse files

add Accuracy metric tests

parent eedf81f4
No related branches found
No related tags found
2 merge requests!17version 0.2.0,!15Learning backend cuda
/********************************************************************************
* 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 <cmath> //
#include <functional> // std::multiplies, std::plus
#include <memory> // std::make_unique
#include <numeric> // std::accumulate
#include <random> // std::random_device, std::mt19937,
// std::uniform_int_distribution
#include <vector>
#include "aidge/backend/cpu/operator/ArgMaxImpl.hpp"
#include "aidge/backend/cpu/operator/AndImpl.hpp"
#include "aidge/backend/cpu/operator/ReduceSumImpl.hpp"
#include "aidge/learning/metrics/Accuracy.hpp"
#include "aidge/data/Tensor.hpp"
#include "aidge/utils/TensorUtils.hpp"
#if USE_AIDGE_BACKEND_CUDA
#include "aidge/backend/cuda/operator/ArgMaxImpl.hpp"
#include "aidge/backend/cuda/operator/AndImpl.hpp"
#include "aidge/backend/cuda/operator/ReduceSumImpl.hpp"
#endif
namespace Aidge {
TEST_CASE("[metrics] Accuracy", "[metrics][Accuracy]") {
constexpr std::uint16_t NBTRIALS = 10;
// set random variables
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<std::size_t> dimsDist(1, 5);
std::uniform_int_distribution<std::size_t> nbDimsDist(1, 2);
std::uniform_real_distribution<float> valueDist(0.0f, 1.0f);
SECTION("CPU") {
for (std::uint16_t trial = 0; trial < NBTRIALS; ++trial) {
const std::size_t nb_dims = 2; // For Accuracy test, nb_dims is fixed as 2: NbBatch, NbClass
std::vector<std::size_t> dims(2);
std::int32_t classAxis = 1;
for (std::size_t i = 0; i < nb_dims; ++i) { dims[i] = dimsDist(gen); }
std::size_t numClasses = dims[1];
std::size_t numBatchess = dims[0];
const std::size_t nb_elements = std::accumulate(dims.cbegin(), dims.cend(), std::size_t(1), std::multiplies<std::size_t>());
// create random predictions
std::unique_ptr<float[]> pred = std::make_unique<float[]>(nb_elements);
for (std::size_t i = 0; i < nb_elements; ++i) {
pred[i] = valueDist(gen);
}
// create random targets
std::unique_ptr<float[]> targ = std::make_unique<float[]>(nb_elements);
for (std::size_t i = 0; i < nb_elements; ++i) {
targ[i] = valueDist(gen);
}
// Calculate accuracy
int correct_predictions = 0;
for (std::size_t batch = 0; batch < dims[0]; ++batch) {
// Find the index of the maximum value in the current batch (for both pred and targ)
auto pred_start = pred.get() + batch * numClasses;
auto targ_start = targ.get() + batch * numClasses;
std::size_t pred_max_idx = std::distance(pred_start, std::max_element(pred_start, pred_start + numClasses));
std::size_t targ_max_idx = std::distance(targ_start, std::max_element(targ_start, targ_start + numClasses));
// If the indices match, it's a correct prediction
if (pred_max_idx == targ_max_idx) {
correct_predictions++;
}
}
// Calculate accuracy as the proportion of correct predictions
float accuracy = static_cast<float>(correct_predictions);
// compute the Accuracy using Aidge::metric::Accuracy function
std::shared_ptr<Tensor> pred_tensor = std::make_shared<Tensor>(dims);
pred_tensor->setBackend("cpu");
pred_tensor->getImpl()->setRawPtr(pred.get(), nb_elements);
std::shared_ptr<Tensor> targ_tensor = std::make_shared<Tensor>(dims);
targ_tensor->setBackend("cpu");
targ_tensor->getImpl()->setRawPtr(targ.get(), nb_elements);
const Tensor res_function = metrics::Accuracy(pred_tensor, targ_tensor, classAxis);
// compare results
Tensor res_manual_tensor = Tensor(accuracy);
REQUIRE(approxEq<float>(res_manual_tensor, res_function));
}
}
#if USE_AIDGE_BACKEND_CUDA
SECTION("CUDA") {
for (std::uint16_t trial = 0; trial < NBTRIALS; ++trial) {
const std::size_t nb_dims = 2; // For Accuracy test, nb_dims is fixed as 2: NbBatch, NbClass
std::vector<std::size_t> dims(2);
std::int32_t classAxis = 1;
for (std::size_t i = 0; i < nb_dims; ++i) { dims[i] = dimsDist(gen); }
std::size_t numClasses = dims[1];
std::size_t numBatchess = dims[0];
const std::size_t nb_elements = std::accumulate(dims.cbegin(), dims.cend(), std::size_t(1), std::multiplies<std::size_t>());
// create random predictions
std::unique_ptr<float[]> pred = std::make_unique<float[]>(nb_elements);
for (std::size_t i = 0; i < nb_elements; ++i) {
pred[i] = valueDist(gen);
}
float * d_pred;
cudaMalloc(&d_pred, nb_elements * sizeof(float));
cudaMemcpy(d_pred, pred.get(), nb_elements * sizeof(float), cudaMemcpyHostToDevice);
// create random targets
std::unique_ptr<float[]> targ = std::make_unique<float[]>(nb_elements);
for (std::size_t i = 0; i < nb_elements; ++i) {
targ[i] = valueDist(gen);
}
float * d_targ;
cudaMalloc(&d_targ, nb_elements * sizeof(float));
cudaMemcpy(d_targ, targ.get(), nb_elements * sizeof(float), cudaMemcpyHostToDevice);
// Calculate accuracy
int correct_predictions = 0;
for (std::size_t batch = 0; batch < dims[0]; ++batch) {
// Find the index of the maximum value in the current batch (for both pred and targ)
auto pred_start = pred.get() + batch * numClasses;
auto targ_start = targ.get() + batch * numClasses;
std::size_t pred_max_idx = std::distance(pred_start, std::max_element(pred_start, pred_start + numClasses));
std::size_t targ_max_idx = std::distance(targ_start, std::max_element(targ_start, targ_start + numClasses));
// If the indices match, it's a correct prediction
if (pred_max_idx == targ_max_idx) {
correct_predictions++;
}
}
// Calculate accuracy as the proportion of correct predictions
float accuracy = static_cast<float>(correct_predictions);
// compute the MSE using Aidge::loss::MSE function
std::shared_ptr<Tensor> pred_tensor = std::make_shared<Tensor>(dims);
pred_tensor->setBackend("cuda");
pred_tensor->getImpl()->setRawPtr(d_pred, nb_elements);
std::shared_ptr<Tensor> targ_tensor = std::make_shared<Tensor>(dims);
targ_tensor->setBackend("cuda");
targ_tensor->getImpl()->setRawPtr(d_targ, nb_elements);
const Tensor res_function = metrics::Accuracy(pred_tensor, targ_tensor, classAxis);
// compare results
Tensor res_manual_tensor = Tensor(accuracy);
REQUIRE(approxEq<float>(res_manual_tensor, res_function));
cudaFree(d_pred);
cudaFree(d_targ);
}
}
#endif
}
} // 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