optimization
orchard.optimization
¶
Optuna Hyperparameter Optimization Module.
Provides components for automated hyperparameter search:
- SearchSpaceRegistry: Predefined search distributions
- OptunaObjective: Objective function for optimization
- OptunaOrchestrator: Study lifecycle management
- run_optimization: Convenience function for complete workflow
StudyEarlyStoppingCallback(threshold, direction='maximize', patience=2, enabled=True)
¶
Callback to stop Optuna study when target metric is achieved.
Prevents wasteful computation when near-perfect performance is reached (e.g., AUC > 0.9999 for classification tasks).
Usage
callback = StudyEarlyStoppingCallback( threshold=0.9999, direction="maximize", patience=3 ) study.optimize(objective, callbacks=[callback])
Attributes:
| Name | Type | Description |
|---|---|---|
threshold |
Metric value that triggers early stopping |
|
direction |
"maximize" or "minimize" |
|
patience |
Number of trials meeting threshold before stopping |
|
_count |
Internal counter for consecutive threshold hits |
Initialize early stopping callback.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
threshold
|
float
|
Target metric value (e.g., 0.9999 for AUC) |
required |
direction
|
str
|
"maximize" or "minimize" (should match study direction) |
'maximize'
|
patience
|
int
|
Number of consecutive trials meeting threshold before stop |
2
|
enabled
|
bool
|
Whether callback is active (allows runtime disable) |
True
|
Source code in orchard/optimization/early_stopping.py
__call__(study, trial)
¶
Callback invoked after each trial completion.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
study
|
Study
|
Optuna study instance |
required |
trial
|
FrozenTrial
|
Completed trial |
required |
Side Effects
Calls study.stop() when early stopping criteria are met.
Source code in orchard/optimization/early_stopping.py
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | |
MetricExtractor(metric_name, direction='maximize')
¶
Extracts and tracks metrics from validation results.
Handles metric extraction with validation and maintains the best metric value achieved during training. Direction-aware: uses max() for maximize objectives, min() for minimize.
Attributes:
| Name | Type | Description |
|---|---|---|
metric_name |
Name of metric to track (e.g., 'auc', 'accuracy') |
|
direction |
Optimization direction ('maximize' or 'minimize') |
|
best_metric |
Best metric value achieved so far |
Example
extractor = MetricExtractor("auc", direction="maximize") val_metrics = {"loss": 0.5, "accuracy": 0.85, "auc": 0.92} current = extractor.extract(val_metrics) # 0.92 best = extractor.update_best(current) # 0.92
Initialize metric extractor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
metric_name
|
str
|
Name of metric to track |
required |
direction
|
str
|
'maximize' or 'minimize' |
'maximize'
|
Source code in orchard/optimization/objective/metric_extractor.py
extract(val_metrics)
¶
Extract target metric from validation results.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
val_metrics
|
Mapping[str, float]
|
Dictionary of validation metrics |
required |
Returns:
| Type | Description |
|---|---|
float
|
Value of target metric |
Raises:
| Type | Description |
|---|---|
KeyError
|
If metric_name not found in val_metrics |
Source code in orchard/optimization/objective/metric_extractor.py
reset()
¶
update_best(current_metric)
¶
Update and return best metric achieved within current trial.
Direction-aware: uses max() for maximize, min() for minimize.
NaN values are ignored to prevent poisoning the best-metric state
(max(-inf, NaN) returns NaN in Python, which would permanently
corrupt comparisons).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
current_metric
|
float
|
Current metric value |
required |
Returns:
| Type | Description |
|---|---|
float
|
Best metric value achieved so far |
Source code in orchard/optimization/objective/metric_extractor.py
OptunaObjective(cfg, search_space, device, dataset_loader=None, dataloader_factory=None, model_factory=None, tracker=None)
¶
Optuna objective function with dependency injection.
Orchestrates hyperparameter optimization trials by:
- Building trial-specific configurations
- Creating data loaders, models, and optimizers
- Executing training with pruning
- Tracking and returning best metrics
All external dependencies are injectable for testability:
- dataset_loader: Dataset loading function
- dataloader_factory: DataLoader creation function
- model_factory: Model instantiation function
Attributes:
| Name | Type | Description |
|---|---|---|
cfg |
Base configuration (single source of truth) |
|
search_space |
Hyperparameter search space |
|
device |
Training device (CPU/CUDA/MPS) |
|
config_builder |
Builds trial-specific configs |
|
metric_extractor |
Handles metric extraction |
|
dataset_data |
Cached dataset (loaded once, reused across trials) |
Example
objective = OptunaObjective( ... cfg=config, ... search_space=search_space, ... device=torch.device("cuda"), ... ) study = optuna.create_study(direction="maximize") study.optimize(objective, n_trials=50)
Initialize Optuna objective.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cfg
|
Config
|
Base configuration (reads optuna.* settings) |
required |
search_space
|
Mapping[str, Any]
|
Hyperparameter search space |
required |
device
|
device
|
Training device |
required |
dataset_loader
|
DatasetLoaderProtocol | None
|
Dataset loading function (default: load_dataset) |
None
|
dataloader_factory
|
DataloaderFactoryProtocol | None
|
DataLoader factory (default: get_dataloaders) |
None
|
model_factory
|
ModelFactoryProtocol | None
|
Model factory (default: get_model) |
None
|
tracker
|
TrackerProtocol | None
|
Optional experiment tracker for nested trial logging |
None
|
Source code in orchard/optimization/objective/objective.py
__call__(trial)
¶
Execute single Optuna trial.
Samples hyperparameters, builds trial configuration, trains model, and returns best validation metric. Failed trials return the worst possible metric instead of crashing the study.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trial
|
Trial
|
Optuna trial object |
required |
Returns:
| Type | Description |
|---|---|
float
|
Best validation metric achieved during training, |
float
|
or worst-case metric if the trial fails. |
Raises:
| Type | Description |
|---|---|
TrialPruned
|
If trial is pruned during training |
Source code in orchard/optimization/objective/objective.py
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 | |
TrialConfigBuilder(base_cfg)
¶
Builds trial-specific Config instances for Optuna trials.
Handles parameter mapping from Optuna's flat namespace to Config's hierarchical structure, preserves dataset metadata excluded from serialization, and validates via Pydantic.
Attributes:
| Name | Type | Description |
|---|---|---|
base_cfg |
Base configuration template |
|
optuna_epochs |
Number of epochs for Optuna trials (from cfg.optuna.epochs) |
|
base_metadata |
Cached dataset metadata |
Example
builder = TrialConfigBuilder(base_cfg) trial_params = {"learning_rate": 0.001, "dropout": 0.3} trial_cfg = builder.build(trial_params)
Initialize config builder.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
base_cfg
|
Config
|
Base configuration template |
required |
Source code in orchard/optimization/objective/config_builder.py
build(trial_params)
¶
Build trial-specific Config with parameter overrides.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trial_params
|
dict[str, Any]
|
Sampled hyperparameters from Optuna |
required |
Returns:
| Type | Description |
|---|---|
Config
|
Validated Config instance with trial parameters |
Source code in orchard/optimization/objective/config_builder.py
TrialTrainingExecutor(model, train_loader, val_loader, optimizer, scheduler, criterion, training, optuna, log_interval, device, metric_extractor)
¶
Executes training loop with Optuna pruning integration.
Orchestrates a complete training cycle for a single Optuna trial, including:
- Training and validation epochs
- Metric extraction and tracking
- Pruning decisions with warmup period
- Learning rate scheduling
- Progress logging
Pruning and warmup parameters are read from the optuna sub-config;
training hyperparameters from training.
Attributes:
| Name | Type | Description |
|---|---|---|
model |
PyTorch model to train. |
|
train_loader |
Training data loader. |
|
val_loader |
Validation data loader. |
|
optimizer |
Optimizer instance. |
|
scheduler |
Learning rate scheduler. |
|
criterion |
Loss function. |
|
device |
Training device (CPU/CUDA/MPS). |
|
metric_extractor |
Handles metric extraction and best-value tracking. |
|
enable_pruning |
Whether to enable trial pruning. |
|
warmup_epochs |
Epochs before pruning activates. |
|
monitor_metric |
Name of the metric driving scheduling. |
|
scaler |
GradScaler | None
|
AMP gradient scaler (None when use_amp is False). |
mixup_fn |
callable | None
|
Mixup augmentation function (None when alpha is 0). |
epochs |
Total training epochs. |
|
log_interval |
Epoch interval for progress logging. |
|
_loop |
TrainingLoop
|
Shared epoch kernel for training steps (train only, no validation). |
Example
executor = TrialTrainingExecutor( ... model=model, ... train_loader=train_loader, ... val_loader=val_loader, ... optimizer=optimizer, ... scheduler=scheduler, ... criterion=criterion, ... training=trial_cfg.training, ... optuna=trial_cfg.optuna, ... log_interval=trial_cfg.telemetry.log_interval, ... device=device, ... metric_extractor=MetricExtractor("auc"), ... ) best_metric = executor.execute(trial)
Initialize training executor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
Module
|
PyTorch model to train. |
required |
train_loader
|
DataLoader[Any]
|
Training data loader. |
required |
val_loader
|
DataLoader[Any]
|
Validation data loader. |
required |
optimizer
|
Optimizer
|
Optimizer instance. |
required |
scheduler
|
LRScheduler
|
Learning rate scheduler. |
required |
criterion
|
Module
|
Loss function. |
required |
training
|
TrainingConfig
|
Training hyperparameters sub-config. |
required |
optuna
|
OptunaConfig
|
Optuna pruning/warmup sub-config. |
required |
log_interval
|
int
|
Epoch interval for progress logging. |
required |
device
|
device
|
Training device. |
required |
metric_extractor
|
MetricExtractor
|
Metric extraction and tracking handler. |
required |
Source code in orchard/optimization/objective/training_executor.py
execute(trial)
¶
Execute full training loop with pruning.
Runs training for cfg.training.epochs, reporting metrics to Optuna after each epoch. Applies pruning logic after warmup period.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trial
|
Trial
|
Optuna trial for reporting and pruning |
required |
Returns:
| Type | Description |
|---|---|
float
|
Best validation metric achieved during training |
Raises:
| Type | Description |
|---|---|
TrialPruned
|
If trial should terminate early |
Source code in orchard/optimization/objective/training_executor.py
OptunaOrchestrator(cfg, device, paths, tracker=None)
¶
High-level manager for Optuna hyperparameter optimization studies.
Coordinates the complete optimization lifecycle: study creation, trial execution, and post-processing artifact generation. Integrates with Orchard ML's Config and RunPaths infrastructure, delegating specialized tasks (sampler/pruner building, visualization, export) to focused submodules.
This orchestrator serves as the entry point for hyperparameter tuning, wrapping Optuna's API with Orchard ML-specific configuration and output management.
Attributes:
| Name | Type | Description |
|---|---|---|
cfg |
Config
|
Template configuration that will be overridden per trial |
device |
device
|
Hardware target for training (CPU/CUDA/MPS) |
paths |
RunPaths
|
Output directory structure for artifacts and results |
Example
orchestrator = OptunaOrchestrator(cfg=config, device=device, paths=paths) study = orchestrator.optimize() print(f"Best AUC: {study.best_value:.3f}")
Artifacts saved to paths.figures/ and paths.exports/¶
Initialize orchestrator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cfg
|
Config
|
Base Config to override per trial |
required |
device
|
device
|
PyTorch device for training |
required |
paths
|
RunPaths
|
Root directory for outputs |
required |
tracker
|
TrackerProtocol | None
|
Optional experiment tracker for nested trial logging |
None
|
Source code in orchard/optimization/orchestrator/orchestrator.py
create_study()
¶
Create or load Optuna study with configured sampler and pruner.
Returns:
| Type | Description |
|---|---|
Study
|
Configured Optuna study instance |
Source code in orchard/optimization/orchestrator/orchestrator.py
optimize()
¶
Execute hyperparameter optimization.
Returns:
| Type | Description |
|---|---|
Study
|
Completed study with trial results |
Source code in orchard/optimization/orchestrator/orchestrator.py
TrialData(number, value, params, datetime_start=None, datetime_complete=None, state=None, duration_seconds=None)
dataclass
¶
Immutable snapshot of Optuna trial metadata for serialization.
Attributes:
| Name | Type | Description |
|---|---|---|
number |
int
|
Trial number within the study. |
value |
float | None
|
Objective value (None for incomplete trials). |
params |
dict[str, Any]
|
Hyperparameter values sampled for this trial. |
datetime_start |
str | None
|
ISO-formatted start timestamp. |
datetime_complete |
str | None
|
ISO-formatted completion timestamp. |
state |
str | None
|
Trial state name (COMPLETE, PRUNED, FAIL, etc.). |
duration_seconds |
float | None
|
Wall-clock duration in seconds. |
from_trial(trial)
classmethod
¶
Build from an Optuna FrozenTrial, computing duration if timestamps are available.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trial
|
FrozenTrial
|
Frozen trial from study. |
required |
Returns:
| Type | Description |
|---|---|
TrialData
|
Immutable trial snapshot with computed duration. |
Source code in orchard/optimization/orchestrator/exporters.py
to_dict()
¶
Serialize to plain dictionary for JSON export.
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Dictionary representation with all fields. |
SearchSpaceRegistry(overrides=None)
¶
Centralized registry of hyperparameter search distributions.
Reads bounds from a SearchSpaceOverrides instance, enabling full YAML customization of search ranges without code changes.
Each method returns a dict of {param_name: suggest_function} where suggest_function takes a Trial object and returns a sampled value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
overrides
|
SearchSpaceOverrides | None
|
Configurable search range bounds. Uses defaults if None. |
None
|
Source code in orchard/optimization/search_spaces.py
get_optimization_space()
¶
Core optimization hyperparameters (learning rate, weight decay, etc.).
Returns:
| Type | Description |
|---|---|
Mapping[str, _SamplerFn]
|
Immutable mapping of parameter names to sampling functions |
Source code in orchard/optimization/search_spaces.py
get_loss_space()
¶
Loss function parameters (criterion type, focal gamma, label smoothing).
focal_gamma is only sampled when criterion_type == "focal",
otherwise defaults to 2.0. label_smoothing is only sampled
when criterion_type == "cross_entropy", otherwise defaults to 0.0.
Returns:
| Type | Description |
|---|---|
Mapping[str, _SamplerFn]
|
Immutable mapping of loss-related parameter samplers |
Source code in orchard/optimization/search_spaces.py
get_regularization_space()
¶
Regularization strategies (mixup, dropout).
Returns:
| Type | Description |
|---|---|
Mapping[str, _SamplerFn]
|
Immutable mapping of regularization parameter samplers |
Source code in orchard/optimization/search_spaces.py
get_batch_size_space(resolution=28)
¶
Batch size as categorical (resolution-aware).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
resolution
|
int
|
Input image resolution (e.g. 28, 32, 64, 128, 224) |
28
|
Returns:
| Type | Description |
|---|---|
Mapping[str, _SamplerFn]
|
Immutable mapping with batch_size sampler |
Source code in orchard/optimization/search_spaces.py
get_scheduler_space()
¶
Learning rate scheduler parameters.
Returns:
| Type | Description |
|---|---|
Mapping[str, _SamplerFn]
|
Immutable mapping of scheduler-related samplers |
Source code in orchard/optimization/search_spaces.py
get_augmentation_space()
¶
Data augmentation intensity parameters.
Returns:
| Type | Description |
|---|---|
Mapping[str, _SamplerFn]
|
Immutable mapping of augmentation samplers |
Source code in orchard/optimization/search_spaces.py
get_full_space(resolution=28)
¶
Combined search space with all available parameters.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
resolution
|
int
|
Input image resolution for batch size calculation |
28
|
Returns:
| Type | Description |
|---|---|
Mapping[str, _SamplerFn]
|
Immutable unified mapping of all parameter samplers |
Source code in orchard/optimization/search_spaces.py
get_quick_space(resolution=28)
¶
Reduced search space for fast exploration (most impactful params).
Focuses on:
- Learning rate (most critical)
- Weight decay
- Batch size (resolution-aware)
- Dropout
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
resolution
|
int
|
Input image resolution for batch size calculation |
28
|
Returns:
| Type | Description |
|---|---|
Mapping[str, _SamplerFn]
|
Immutable mapping of high-impact parameter samplers |
Source code in orchard/optimization/search_spaces.py
get_model_space_224()
staticmethod
¶
Search space for 224x224 architectures with weight variants.
Source code in orchard/optimization/search_spaces.py
get_model_space_28()
staticmethod
¶
Search space for 28x28 architectures.
Source code in orchard/optimization/search_spaces.py
get_early_stopping_callback(metric_name, direction, threshold=None, patience=2, enabled=True)
¶
Factory function to create appropriate early stopping callback.
Provides sensible defaults for common metrics.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
metric_name
|
str
|
Name of metric being optimized (e.g., "auc", "accuracy") |
required |
direction
|
str
|
"maximize" or "minimize" |
required |
threshold
|
float | None
|
Custom threshold (if None, uses metric-specific default) |
None
|
patience
|
int
|
Trials meeting threshold before stopping |
2
|
enabled
|
bool
|
Whether callback is active |
True
|
Returns:
| Type | Description |
|---|---|
StudyEarlyStoppingCallback | None
|
Configured callback or None if disabled |
Source code in orchard/optimization/early_stopping.py
export_best_config(study, cfg, paths)
¶
Export best trial configuration as YAML file.
Creates a new Config instance with best hyperparameters applied, validates it, and saves to reports/best_config.yaml.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
study
|
Study
|
Completed Optuna study with at least one successful trial |
required |
cfg
|
Config
|
Template configuration (used for non-optimized parameters) |
required |
paths
|
RunPaths
|
RunPaths instance for output location |
required |
Returns:
| Type | Description |
|---|---|
Path | None
|
Path to exported config file, or None if no completed trials |
Note
Skips export with warning if no completed trials exist.
Source code in orchard/optimization/orchestrator/exporters.py
export_study_summary(study, paths)
¶
Export complete study metadata to JSON.
Serializes all trials with parameters, values, states, timestamps, and durations. Handles studies with zero completed trials gracefully.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
study
|
Study
|
Optuna study (may contain failed/pruned trials) |
required |
paths
|
RunPaths
|
RunPaths instance for output location |
required |
Output structure::
{
"study_name": str,
"direction": str,
"n_trials": int,
"n_completed": int,
"best_trial": {...} or null,
"trials": [...]
}
Source code in orchard/optimization/orchestrator/exporters.py
export_top_trials(study, paths, metric_name, top_k=10)
¶
Export top K trials to Excel spreadsheet with professional formatting.
Creates human-readable comparison table of best-performing trials with hyperparameters, metric values, and durations. Applies professional Excel styling matching TrainingReport format.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
study
|
Study
|
Completed Optuna study with at least one successful trial |
required |
paths
|
RunPaths
|
RunPaths instance for output location |
required |
metric_name
|
str
|
Name of optimization metric (for column header) |
required |
top_k
|
int
|
Number of top trials to export (default: 10) |
10
|
DataFrame Columns:
- Rank: 1-based ranking
- Trial: Trial number
- {METRIC_NAME}: Objective value
- {param_name}: Each hyperparameter
- Duration (s): Trial duration if available
Example
export_top_trials(study, paths, "auc", top_k=10)
Creates: {paths.reports}/top_10_trials.xlsx¶
Source code in orchard/optimization/orchestrator/exporters.py
run_optimization(cfg, device, paths, tracker=None)
¶
Convenience function to run complete optimization pipeline.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cfg
|
Config
|
Global configuration with optuna section |
required |
device
|
device
|
PyTorch device for training |
required |
paths
|
RunPaths
|
RunPaths instance for output management |
required |
tracker
|
TrackerProtocol | None
|
Optional experiment tracker for nested trial logging |
None
|
Returns:
| Type | Description |
|---|---|
Study
|
Completed Optuna study with trial results |
Example
study = run_optimization(cfg=config, device=torch.device("cuda"), paths=paths) print(f"Best AUC: {study.best_value:.3f}")
Source code in orchard/optimization/orchestrator/orchestrator.py
get_search_space(preset='quick', resolution=28, include_models=False, model_pool=None, overrides=None)
¶
Factory function to retrieve a search space preset.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
preset
|
str
|
Name of the preset ("quick", "full", etc.) |
'quick'
|
resolution
|
int
|
Input image resolution (affects batch_size choices) |
28
|
include_models
|
bool
|
If True, includes model architecture selection |
False
|
model_pool
|
list[str] | None
|
Restrict model search to these architectures. When None, uses all built-in models for the target resolution. |
None
|
overrides
|
SearchSpaceOverrides | None
|
Configurable search range bounds (uses defaults if None) |
None
|
Returns:
| Type | Description |
|---|---|
Mapping[str, Any]
|
Immutable mapping of parameter samplers keyed by parameter name |
Raises:
| Type | Description |
|---|---|
OrchardConfigError
|
If preset name not recognized |