use burn::train::{
logger::MetricLogger,
metric::{MetricEntry, NumericEntry},
};
#[cfg(feature = "rerun")]
use crate::{
metric::{metric_identifier, numeric_value},
rerun::RerunLogger,
};
#[cfg(feature = "rerun")]
use std::sync::Arc;
#[cfg(feature = "rerun")]
pub struct RerunMetricLogger {
split: String,
logger: Arc<RerunLogger>,
step: usize,
current_epoch: usize,
last_epoch_step: Option<usize>,
}
#[cfg(feature = "rerun")]
impl RerunMetricLogger {
pub fn new(split: impl Into<String>, logger: Arc<RerunLogger>) -> Self {
Self {
split: split.into(),
logger,
step: 0,
current_epoch: 1,
last_epoch_step: None,
}
}
}
#[cfg(feature = "rerun")]
impl MetricLogger for RerunMetricLogger {
fn log(&mut self, item: &MetricEntry) {
if self.last_epoch_step != Some(self.step) {
let entity = metrics_epoch_entity_path(&self.split);
self.logger
.log_scalar(&entity, self.current_epoch as f64, self.step);
self.last_epoch_step = Some(self.step);
}
let entity = metric_entity_path(&self.split, item.name.as_ref());
if let Some(value) = numeric_value(item) {
self.logger.log_scalar(&entity, value, self.step);
} else {
self.logger
.log_text(&format!("{entity}/text"), &item.formatted, self.step);
}
self.step += 1;
}
fn end_epoch(&mut self, epoch: usize) {
self.current_epoch = epoch + 1;
}
fn read_numeric(&mut self, _name: &str, _epoch: usize) -> Result<Vec<NumericEntry>, String> {
Err("Rerun metric logger does not support reading metrics".into())
}
}
#[cfg(feature = "rerun")]
pub fn rerun_metric_logger_pair(
logger: Arc<RerunLogger>,
) -> (RerunMetricLogger, RerunMetricLogger) {
(
RerunMetricLogger::new("train", logger.clone()),
RerunMetricLogger::new("valid", logger),
)
}
#[cfg(feature = "rerun")]
fn metric_entity_path(split: &str, name: &str) -> String {
format!("metrics/{split}/{}", metric_identifier(name))
}
#[cfg(feature = "rerun")]
fn metrics_epoch_entity_path(split: &str) -> String {
format!("metrics/{split}/epoch")
}