///|
/// Reproducible experiment records for comparing posterior updates.
pub struct ExperimentPoint {
step : Int
metric : Double
baseline : Double
} derive(Debug, Eq, ToJson, FromJson)
///|
pub fn ExperimentPoint::step(self : ExperimentPoint) -> Int {
self.step
}
///|
pub fn ExperimentPoint::metric(self : ExperimentPoint) -> Double {
self.metric
}
///|
pub fn ExperimentPoint::error(self : ExperimentPoint) -> Double {
self.metric - self.baseline
}
///|
pub struct ExperimentLog {
name : String
points : Array[ExperimentPoint]
} derive(Debug, Eq, ToJson, FromJson)
///|
pub fn ExperimentLog::new(name : String) -> ExperimentLog {
{ name, points: [] }
}
///|
pub fn ExperimentLog::record(
self : ExperimentLog,
metric : Double,
baseline : Double,
) -> ExperimentLog {
let points = self.points.copy()
points.push({ step: points.length(), metric, baseline })
{ ..self, points, }
}
///|
pub fn ExperimentLog::name(self : ExperimentLog) -> String {
self.name
}
///|
pub fn ExperimentLog::len(self : ExperimentLog) -> Int {
self.points.length()
}
///|
pub fn ExperimentLog::points(self : ExperimentLog) -> Array[ExperimentPoint] {
self.points.copy()
}
///|
pub fn ExperimentLog::metrics(self : ExperimentLog) -> Array[Double] {
self.points.map(fn(point) { point.metric() })
}
///|
pub fn ExperimentLog::errors(self : ExperimentLog) -> Array[Double] {
self.points.map(fn(point) { point.error() })
}
///|
pub fn ExperimentLog::mean_metric(self : ExperimentLog) -> Double {
mean(self.metrics())
}
///|
pub fn ExperimentLog::metric_variance(self : ExperimentLog) -> Double {
variance(self.metrics())
}
///|
pub fn ExperimentLog::best_step(self : ExperimentLog) -> Int {
if self.points.length() == 0 {
abort("ExperimentLog: no points")
}
let mut best = 0
for index in 1.. ExperimentPoint {
if self.points.length() == 0 {
abort("ExperimentLog: no points")
}
self.points[self.points.length() - 1]
}
///|
pub fn ExperimentLog::improvement(self : ExperimentLog) -> Double {
if self.points.length() < 2 {
0.0
} else {
self.points[0].metric() - self.last().metric()
}
}
///|
pub fn ExperimentLog::merge(
self : ExperimentLog,
other : ExperimentLog,
) -> ExperimentLog {
let result = { ..self, points: self.points.copy() }
other.points.fold(init=result, (log, point) => {
log.record(point.metric(), point.baseline)
})
}