use burn::train::metric::{MetricEntry, NumericEntry};
pub(crate) fn numeric_value(entry: &MetricEntry) -> Option<f64> {
NumericEntry::deserialize(&entry.serialize)
.map(|numeric| numeric.current())
.ok()
}
pub(crate) fn metric_identifier(name: &str) -> String {
let mut ident = String::with_capacity(name.len());
for ch in name.chars() {
if ch.is_ascii_alphanumeric() {
ident.push(ch.to_ascii_lowercase());
} else if !ident.ends_with('_') {
ident.push('_');
}
}
ident.truncate(ident.trim_end_matches('_').len());
if ident.is_empty() {
ident.push_str("metric");
}
ident
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::Arc;
#[test]
fn numeric_value_plain_scalar() {
let entry = MetricEntry::new(
Arc::new("loss".to_string()),
"0.42".to_string(),
"0.42".to_string(),
);
assert_eq!(numeric_value(&entry), Some(0.42));
}
#[test]
fn numeric_value_aggregated_metric() {
let entry = MetricEntry::new(
Arc::new("loss".to_string()),
"1.0".to_string(),
"15.0,10".to_string(),
);
assert_eq!(numeric_value(&entry), Some(15.0));
}
#[test]
fn metric_identifier_normalizes_characters() {
assert_eq!(metric_identifier("Train/Loss"), "train_loss");
assert_eq!(metric_identifier("loss value"), "loss_value");
assert_eq!(metric_identifier("Weird---Name!!!"), "weird_name");
}
#[test]
fn metric_identifier_falls_back_to_metric() {
assert_eq!(metric_identifier(" "), "metric");
}
}