use crate::Tensor;
use aprender::primitives::Vector;
use super::Metric;
fn tensor_to_vector(t: &Tensor) -> Vector<f32> {
Vector::from_slice(t.data().as_slice().expect("contiguous tensor data"))
}
#[derive(Debug, Clone, Copy, Default)]
pub struct R2Score;
impl Metric for R2Score {
fn compute(&self, predictions: &Tensor, targets: &Tensor) -> f32 {
assert_eq!(predictions.len(), targets.len());
if predictions.is_empty() {
return 0.0;
}
let y_pred = tensor_to_vector(predictions);
let y_true = tensor_to_vector(targets);
let r2 = aprender::metrics::r_squared(&y_pred, &y_true);
if r2 == 0.0 {
let ss_res: f32 = predictions
.data()
.iter()
.zip(targets.data().iter())
.map(|(&p, &t)| (t - p).powi(2))
.sum();
if ss_res == 0.0 {
return 1.0;
}
}
r2
}
fn name(&self) -> &'static str {
"R²"
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct MAE;
impl Metric for MAE {
fn compute(&self, predictions: &Tensor, targets: &Tensor) -> f32 {
assert_eq!(predictions.len(), targets.len());
if predictions.is_empty() {
return 0.0;
}
let y_pred = tensor_to_vector(predictions);
let y_true = tensor_to_vector(targets);
aprender::metrics::mae(&y_pred, &y_true)
}
fn name(&self) -> &'static str {
"MAE"
}
fn higher_is_better(&self) -> bool {
false
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct RMSE;
impl Metric for RMSE {
fn compute(&self, predictions: &Tensor, targets: &Tensor) -> f32 {
assert_eq!(predictions.len(), targets.len());
if predictions.is_empty() {
return 0.0;
}
let y_pred = tensor_to_vector(predictions);
let y_true = tensor_to_vector(targets);
aprender::metrics::rmse(&y_pred, &y_true)
}
fn name(&self) -> &'static str {
"RMSE"
}
fn higher_is_better(&self) -> bool {
false
}
}