use crate::{
Sample,
State,
Booster,
WeakLearner,
CombinedHypothesis,
common::ObjectiveFunction,
};
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
use std::time::Instant;
const HEADER: &str = "ObjectiveValue,TrainLoss,TestLoss,Time\n";
pub struct Logger<'a, B, W, F, G> {
booster: B,
weak_learner: W,
objective_func: F,
loss_func: G,
train: &'a Sample,
test: &'a Sample,
}
impl<'a, B, W, F, G> Logger<'a, B, W, F, G> {
pub fn new(
booster: B,
weak_learner: W,
objective_func: F,
loss_func: G,
train: &'a Sample,
test: &'a Sample,
) -> Self
{
Self { booster, weak_learner, loss_func, objective_func, train, test }
}
}
impl<'a, H, B, W, F, G> Logger<'a, B, W, F, G>
where B: Booster<H> + Research<H>,
W: WeakLearner<Hypothesis = H>,
F: ObjectiveFunction<H>,
G: Fn(&Sample, &CombinedHypothesis<H>) -> f64,
{
pub fn run<P: AsRef<Path>>(&mut self, file: P)
-> std::io::Result<CombinedHypothesis<H>>
{
let mut file = File::create(file)?;
file.write_all(HEADER.as_bytes())?;
self.booster.preprocess(&self.weak_learner);
let mut time_acc = 0;
for it in 1.. {
let now = Instant::now();
let state = self.booster.boost(&self.weak_learner, it);
let time = now.elapsed().as_millis();
time_acc += time;
let hypothesis = self.booster.current_hypothesis();
let obj = self.objective_func.eval(self.train, &hypothesis);
let train = (self.loss_func)(self.train, &hypothesis);
let test = (self.loss_func)(self.test, &hypothesis);
let line = format!("{obj},{train},{test},{time_acc}\n");
file.write_all(line.as_bytes())?;
if state == State::Terminate {
break;
}
}
let f = self.booster.postprocess(&self.weak_learner);
Ok(f)
}
}
pub trait Research<H> {
fn current_hypothesis(&self) -> CombinedHypothesis<H>;
}