Skip to main content

somatize_study/
lib.rs

1//! Level 3: what is above one training run.
2//!
3//! The graph is a network — one `forward`. The `Trainer` is a training run — an
4//! afternoon. This is the level above, and it **has no type**: N training runs
5//! are a `for`. What lives here are the pieces that `for` asks for, and they all
6//! have one shape:
7//!
8//! > indices and keys in, indices out. **Never a tensor.**
9//!
10//! That is what lets all of it be Rust while the loop stays in Python. The step
11//! that cannot move here is *train*, because training is torch — and a trait
12//! that calls back out for it is not an abstraction, it is the loop leaking. The
13//! original measured this: its `TrialExecutor` has one implementor, a closure.
14//!
15//! | cutting the samples | |
16//! |---|---|
17//! | [`Samples`] | how many, and their class and group |
18//! | [`KFold`] | `k` parts, each held out in turn |
19//! | [`Stratified`] | a k-fold **inside each class** |
20//! | [`Grouped`] | a k-fold **over the groups**, so a group never splits |
21//! | [`StratifiedGrouped`] | both, as far as both can be had at once |
22//! | [`TimeSeries`] | growing prefixes, so nothing trains on its own future |
23//! | [`Partition`], [`Fold`] | the family, and one cut |
24//!
25//! | where to look next | looks at |
26//! |---|---|
27//! | [`Space`], [`Point`] | the knobs, and one configuration — also a trial's name |
28//! | [`Grid`] | **the space's shape**, and the one that runs out |
29//! | [`Random`] | **nothing**; over a space where few knobs matter it beats a grid |
30//! | [`Halton`], [`Sobol`] | nothing either, but uniform for **every prefix** |
31//! | [`Tpe`] | **what already happened** |
32//! | [`Sampler`] | the family |
33//!
34//! `ask` is a function of the **index** and not of what was asked before, so a
35//! machine that claimed trial 7 out of a shared folder derives the same point
36//! without replaying six. [`Tpe`] is the exception and says so. Uniform for
37//! every prefix is what stops two machines proposing neighbours — [`Random`] is
38//! uniform only in expectation, so it merely makes it unlikely.
39//!
40//! | when to give up | judged against |
41//! |---|---|
42//! | [`Percentile`] | **the others** at the same step; the median pruner is `p = 50` |
43//! | [`Threshold`] | **a constant** already known to be hopeless |
44//! | [`Patience`] | **itself**: it has stopped improving |
45//! | [`Pruner`], [`Goal`] | the family, and which way is better |
46//!
47//! A pruner stops nothing: it answers [`Verdict`] and the loop stops calling the
48//! trainer, so none of this added a line to level 2.
49//!
50//! Five cutting schemes and not sklearn's fifteen, because stratifying and
51//! grouping are not different algorithms and the rest are parameters:
52//! `LeaveOneOut` is `KFold { k: n }` and purged cross-validation is
53//! `TimeSeries { gap }`. Not called `Split`, because `somatize.torch.Split` is
54//! already split learning.
55
56#![forbid(unsafe_code)]
57#![warn(missing_docs)]
58
59mod goal;
60mod partition;
61mod point;
62mod pruner;
63mod sampler;
64mod samples;
65mod space;
66
67pub use goal::{Goal, GoalError};
68pub use partition::{
69    Fold, Grouped, KFold, Partition, PartitionError, Stratified, StratifiedGrouped, TimeSeries,
70};
71pub use point::{Point, Setting};
72pub use pruner::{Patience, Percentile, Pruner, Reason, Threshold, Verdict};
73pub use sampler::{Grid, Halton, KNOBS, Random, Sampler, Sobol, Tpe};
74pub use samples::{Samples, SamplesError};
75pub use space::{Dimension, ReadError, Space, SpaceError};