feat(traits,algorithms): add PartialProblem trait and Hyperband
Multi-fidelity optimization. Hyperband (Li et al. 2017) and its
foundation Successive Halving (Karnin et al. 2013) tune
hyperparameters by allocating *uneven* compute across configurations:
sample many cheap-to-evaluate-at-low-budget configs, then promote
the survivors to higher budgets. Crucial for ML hyperparameter
tuning where each evaluation is a partial training run.
This requires a new trait — `Problem::evaluate` is a single-shot
black box, but Hyperband needs to evaluate the SAME decision at
different fidelity budgets:
pub trait PartialProblem {
type Decision: Clone;
fn objectives(&self) -> ObjectiveSpace;
fn evaluate_at_budget(&self, decision: &Self::Decision,
budget: f64) -> Evaluation;
}
`PartialProblem` is intentionally NOT a sub-trait of `Problem`.
Implementors who already have a `Problem` and want their
`evaluate_at_budget` to ignore budget can write a one-line wrapper.
`Hyperband` is the optimizer:
pub struct HyperbandConfig {
max_budget: f64, eta: f64, max_brackets: usize, seed: u64,
}
pub struct Hyperband<I> { config, initializer, ... }
Single-objective only. The decision sampler is an `Initializer<D>` so
it works the same way as every other heuropt algorithm. Generic over
decision type.
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
pub mod candidate;
|
||||
pub mod evaluation;
|
||||
pub mod objective;
|
||||
pub mod partial_problem;
|
||||
pub mod population;
|
||||
pub mod problem;
|
||||
pub mod result;
|
||||
@@ -11,6 +12,7 @@ pub mod rng;
|
||||
pub use candidate::*;
|
||||
pub use evaluation::*;
|
||||
pub use objective::*;
|
||||
pub use partial_problem::*;
|
||||
pub use population::*;
|
||||
pub use problem::*;
|
||||
pub use result::*;
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
//! Trait for multi-fidelity optimization problems.
|
||||
|
||||
use crate::core::evaluation::Evaluation;
|
||||
use crate::core::objective::ObjectiveSpace;
|
||||
|
||||
/// A problem whose evaluation cost can be controlled by a fidelity
|
||||
/// "budget" parameter — for example, an ML training run that gets
|
||||
/// trained for `budget` epochs, a CFD simulation that runs for `budget`
|
||||
/// timesteps, or a Monte Carlo evaluation that draws `budget` samples.
|
||||
///
|
||||
/// Multi-fidelity optimizers (Hyperband, Successive Halving, BOHB) use
|
||||
/// this trait to evaluate cheap low-budget previews of many
|
||||
/// configurations, then "promote" the survivors to higher budgets.
|
||||
///
|
||||
/// `PartialProblem` is intentionally NOT a sub-trait of [`Problem`]
|
||||
/// because the evaluation contract is different: `Problem::evaluate`
|
||||
/// is single-shot, while `evaluate_at_budget` is parameterized by
|
||||
/// fidelity. Implementors who already have a `Problem` and want their
|
||||
/// `evaluate_at_budget` to ignore the budget can write a one-line
|
||||
/// wrapper that just calls `Problem::evaluate`.
|
||||
///
|
||||
/// [`Problem`]: crate::core::Problem
|
||||
pub trait PartialProblem {
|
||||
/// The thing the optimizer changes. Same constraints as
|
||||
/// [`Problem::Decision`](crate::core::Problem::Decision).
|
||||
type Decision: Clone;
|
||||
|
||||
/// Return the objectives for this problem.
|
||||
fn objectives(&self) -> ObjectiveSpace;
|
||||
|
||||
/// Evaluate `decision` at the given fidelity `budget`.
|
||||
///
|
||||
/// Higher `budget` should give a more accurate (and more expensive)
|
||||
/// estimate of the same underlying objective. Hyperband requires
|
||||
/// monotonicity: a higher-budget evaluation should not be worse
|
||||
/// than a lower-budget evaluation by chance — though some noise is
|
||||
/// fine and expected.
|
||||
fn evaluate_at_budget(&self, decision: &Self::Decision, budget: f64) -> Evaluation;
|
||||
}
|
||||
Reference in New Issue
Block a user