Configuration System#
Source Files
twiga/core/config/base.py
Twiga follows a configuration-as-code pattern: every component - data preprocessing, model architecture, training orchestration, and uncertainty quantification - is controlled by a Pydantic model that validates inputs at construction time. This page is the complete field reference for every configuration class in the framework.
Class Hierarchy#
The diagram below shows how the configuration classes relate to one another. BaseModelConfig is the root for all model configs; NeuralModelConfig extends it with PyTorch Lightning training parameters. DataPipelineConfig, ExperimentConfig, and ConformalConfig are standalone configuration objects that the TwigaForecaster accepts at construction time.
classDiagram
class BaseSearchSpace {
+model_config: ConfigDict
+validate_search_space() BaseSearchSpace
+get_optuna_params(trial, prefix) dict
+_should_use_log(low, high) bool
}
class BaseModelConfig {
+name: Literal["base_model"]
+domain: Literal["nn"]
+search_space: BaseSearchSpace | None
+get_optuna_params(trial) dict
}
class NeuralModelConfig {
+name: Literal["neural_model"]
+rich_progress_bar: bool
+wandb_logging: bool
+batch_size: int
+max_epochs: int
+patience: int
+seed: int
+from_data_config(data_config) NeuralModelConfig
}
class DataPipelineConfig {
+target_feature: list | str
+period: str
+lookback_window_size: int
+forecast_horizon: int
+calendar_features: list | None
+lags: list | None
}
class ExperimentConfig {
+split_freq: Literal
+train_size: int
+test_size: int
+window: Literal
+project_name: str
+seed: int
}
class ConformalConfig {
+method: Literal
+score_type: Literal
+alpha: float
}
BaseModelConfig --> BaseSearchSpace : search_space
NeuralModelConfig --|> BaseModelConfig : extends
How Configs Flow Through the System#
Each configuration object targets a specific subsystem of the TwigaForecaster. The diagram below illustrates which config drives which component.
flowchart LR
DC[DataPipelineConfig] --> DP[DataPipeline]
FC[ExperimentConfig] --> TF[TwigaForecaster]
MC[Model Configs] --> M[Models]
CC[ConformalConfig] --> CP[Conformal Predictor]
TF --> DP
TF --> M
TF --> CP
TF --> BT[Backtester / TimeBasedCV]
MC -. "ML configs" .-> ML[CatBoost / XGBoost / LightGBM / Linear]
MC -. "NN configs" .-> NN[MLPF / MLPGAM / MLPGAF / NHITS / GANF]
ExperimentConfigcontrols the TwigaForecaster itself - project naming, cross-validation splits, and output directories.DataPipelineConfigcontrols the DataPipeline - feature engineering, scaling, and sequence creation.Model configs (
BaseModelConfigsubclasses for ML models,NeuralModelConfigsubclasses for NN models) define model architecture and training behavior.ConformalConfigcontrols conformal prediction - the method, score type, and significance level used for prediction intervals.
DataPipelineConfig#
DataPipelineConfig defines how raw time series data is transformed into model-ready features. It is passed as data_params to TwigaForecaster and drives the DataPipeline.
Field |
Type |
Default |
Description |
|---|---|---|---|
|
|
required |
Target variable name(s) to forecast. A single string for univariate forecasting, or a list for multivariate. |
|
|
required |
Sampling frequency of the time series, expressed as a pandas offset alias (e.g., |
|
|
required |
Number of past time steps used as model input. |
|
|
required |
Number of future time steps the model predicts. |
|
|
|
Latitude for computing day/night features via solar position. Required when using |
|
|
|
Longitude for computing day/night features via solar position. |
|
|
|
Column names for features with unknown future values (available only during the lookback window). |
|
|
|
Cyclical temporal features derived from the timestamp column (e.g., |
|
|
|
Known future features available over the full lookback + forecast horizon (e.g., weather forecasts). |
|
|
|
Known future features available over the forecast horizon only. |
|
|
|
Scaler for input features. One of |
|
|
|
Scaler for target variable(s). Same choices as |
|
|
|
Lag intervals (in periods) for autoregressive feature engineering (e.g., |
|
|
|
Window sizes for rolling statistics (e.g., |
|
|
|
Aggregation functions applied to rolling windows (e.g., |
|
|
|
Name of the datetime column in the input DataFrame. |
|
|
|
Step between consecutive sliding windows. Default |
|
|
|
Optional HPO search space for pipeline parameters. Supports categorical choices for |
Example#
from twiga.core.config import DataPipelineConfig
data_config = DataPipelineConfig(
target_feature="load_mw",
period="1h",
lookback_window_size=168, # 7 days of hourly data
forecast_horizon=48, # predict 2 days ahead
calendar_features=["hour", "dayofweek", "month"],
known_future_features=["ghi", "temperature"],
latitude=-6.8,
longitude=39.3,
lags=[1, 24, 48, 168],
windows=[24, 48],
window_funcs=["mean", "std"],
input_scaler="standard",
target_scaler="robust",
)
Choosing lags and windows
Pick lags that correspond to meaningful seasonal periods in your data. For hourly electricity data, [1, 24, 48, 168] captures the previous hour, same hour yesterday, two days ago, and one week ago. Rolling windows (windows + window_funcs) smooth out noise and expose trends.
API Reference#
- class twiga.core.config.DataPipelineConfig(**data)#
Bases:
BaseModelConfiguration for a time-series data pipeline.
Captures everything the pipeline needs to know about the raw dataset: which column to forecast, which features are available, how long the lookback and forecast windows are, what scalers to apply, and which lag/rolling-window features to engineer.
Feature category guide — classify each feature by when its values are available:
- Parameters:
target_feature (list[str] | str) – Target variable name(s) to forecast.
period (str) – Sampling frequency using pandas offset aliases (e.g.
"1H","30min").lookback_window_size (int | str) – Number of past timesteps fed to the model as input, or a pandas-compatible duration string that is converted to timesteps using period (e.g.
"7D"withperiod="1H"gives 168 steps).forecast_horizon (int | str) – Number of future timesteps to predict, or a duration string converted in the same way (e.g.
"1D"withperiod="30min"gives 48 steps).latitude (float | None, optional) – Latitude for day/night feature calculation. Defaults to None.
longitude (float | None, optional) – Longitude for day/night feature calculation. Defaults to None.
past_features (list[str] | None, optional) – Features available only in the lookback window (unknown in the forecast horizon). Defaults to None.
calendar_features (list[CalendarFeature] | None, optional) – Temporal features derived from the timestamp column. Accepts raw component names (e.g.
"hour","wday") or Fourier-encoded column names auto-selected by the dataset loader (e.g."hour_cosin","yweek_cos"). SeeCalendarFeaturefor all valid values. Defaults to None.known_future_features (list[str] | None, optional) – Features known over the full lookback + forecast horizon (e.g. weather forecast that was also recorded historically). Defaults to None.
forecast_period_features (list[str] | None, optional) – Features known only during the forecast horizon (e.g. scheduled load). Defaults to None.
input_scaler (ScalerType, optional) – Scaler applied to input features. Defaults to
"passthrough".target_scaler (ScalerType, optional) – Scaler applied to the target variable. Defaults to
"standard".lags (list[int] | None, optional) – Lag intervals in periods for feature engineering. Defaults to None.
windows (list[int] | int | None, optional) – Window sizes for rolling statistics. Defaults to None.
window_funcs (list[str] | str | None, optional) – Aggregation functions applied to rolling windows (e.g.
"mean","std"). Defaults to None.date_column (str, optional) – Name of the datetime column. Defaults to
"timestamp".window_stride (int, optional) – Step between consecutive sliding windows.
1= fully overlapping (maximum data augmentation). Set toforecast_horizonfor non-overlapping windows — recommended for baseline evaluation. Defaults to 1.
- calendar_features: list[Literal['index_num', 'year', 'year_iso', 'yearstart', 'yearend', 'leapyear', 'half', 'quarter', 'quarterstart', 'quarterend', 'month', 'monthstart', 'monthend', 'yweek', 'mweek', 'wday', 'mday', 'qday', 'yday', 'weekend', 'hour', 'minute', 'second', 'msecond', 'nsecond', 'day_night', 'half_sin', 'half_cos', 'half_cosin', 'quarter_sin', 'quarter_cos', 'quarter_cosin', 'month_sin', 'month_cos', 'month_cosin', 'yweek_sin', 'yweek_cos', 'yweek_cosin', 'mweek_sin', 'mweek_cos', 'mweek_cosin', 'wday_sin', 'wday_cos', 'wday_cosin', 'mday_sin', 'mday_cos', 'mday_cosin', 'qday_sin', 'qday_cos', 'qday_cosin', 'yday_sin', 'yday_cos', 'yday_cosin', 'hour_sin', 'hour_cos', 'hour_cosin', 'minute_sin', 'minute_cos', 'minute_cosin', 'second_sin', 'second_cos', 'second_cosin']] | None#
- input_scaler: Literal['standard', 'minmax', 'robust', 'maxabs', 'normalizer', 'quantile_uniform', 'quantile_normal', 'power_yeo_johnson', 'power_box_cox', 'passthrough']#
- model_config: ClassVar[ConfigDict] = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- recommended_lookback_search_space(max_multiplier=7, *, scalers=True)#
Return a search space for lookback window size relative to this config’s forecast horizon.
The range is
[forecast_horizon, max_multiplier * forecast_horizon], which guarantees the lookback is always at least as long as the forecast horizon. Bothforecast_horizonandperiodare read from the config instance, so string horizons (e.g."1D") are resolved correctly before the range is computed.- Parameters:
- Return type:
- Returns:
A
BaseSearchSpaceready to assign tosearch_space.
Example:
cfg = DataPipelineConfig( target_feature="load", period="30min", forecast_horizon="1D", # resolved to 48 steps lookback_window_size=48, # initial value, overridden by HPO ) cfg = cfg.model_copy(update={"search_space": cfg.recommended_lookback_search_space()})
- search_space: BaseSearchSpace | None#
ExperimentConfig#
ExperimentConfig controls the training orchestration layer: how the data is split for backtesting, where outputs are saved, and which evaluation metrics to compute. It is passed as cv_params to TwigaForecaster.
Field |
Type |
Default |
Description |
|---|---|---|---|
|
|
|
Internal domain identifier. Fixed to |
|
|
|
Time unit for |
|
|
|
Length of each test fold in units of |
|
|
|
Length of each training fold in units of |
|
|
|
Number of |
|
|
|
Step size (in |
|
|
|
Cross-validation window strategy. |
|
|
|
Maximum number of cross-validation splits. |
|
|
|
Project name used for organizing output directories and experiment tracking. |
|
|
|
Optional file name prefix for saved artifacts. |
|
|
|
Random seed for reproducibility. |
|
|
|
Name of the datetime column in the input DataFrame. |
|
|
|
Root directory for saving model checkpoints and results. |
|
|
|
Evaluation metrics to compute (e.g., |
|
|
|
Validation window carved from the end of the training fold, in |
|
|
|
Calibration window size in |
|
|
|
Where to draw the calibration set. |
Example#
from twiga.core.config import ExperimentConfig
# Point forecast backtesting: 14 days train, 7 days test
train_config = ExperimentConfig(
split_freq="days",
train_size=14,
test_size=7,
gap=0,
window="expanding",
project_name="MyProject",
root_dir="./outputs",
seed=42,
metrics=["mae", "rmse", "smape"],
)
# Conformal backtesting: 1-month val for early stopping, 1-month calib for conformal
conformal_config = ExperimentConfig(
split_freq="months",
test_size=4,
stride=2,
num_splits=10,
window="expanding",
val_size=1,
calib_size=1,
calib_source="train_tail",
project_name="ConformalBenchmark",
root_dir="./outputs",
metrics=["mae", "rmse", "smape"],
)
Expanding vs. rolling windows
With window="expanding", each successive fold includes all prior training data - the training set grows over time. With window="rolling", the training window is fixed at train_size units and slides forward. Expanding windows generally produce more stable models; rolling windows are better when the data distribution shifts significantly over time. See Backtesting for a detailed comparison.
API Reference#
- class twiga.core.config.ExperimentConfig(**data)#
Bases:
BaseModelConfiguration for the forecaster cross-validation runner.
Controls how the time-series is split for evaluation (split frequency, window type, train/test sizes), and holds project-level metadata such as the project name and output file name.
The
date_columnis intentionally absent here — it is always read fromDataPipelineConfig, which is the single source of truth for dataset structure.- Parameters:
domain (Literal["ml"], optional) – Modelling domain identifier. Fixed to
"ml"; excluded from parameter tuning. Defaults to"ml".split_freq (str, optional) – Unit for
train_size,test_size, andgap. One of"days","hours","weeks","months","years". Defaults to"months".test_size (int, optional) – Number of
split_frequnits in each test fold. Defaults to 1.train_size (int, optional) – Number of
split_frequnits in each training fold (rolling window only). Defaults to 1.gap (int, optional) – Number of
split_frequnits between the end of the training fold and the start of the test fold. Defaults to 0.stride (int | None, optional) – Step size between consecutive splits in
split_frequnits. None usestest_sizeas the stride. Defaults to None.window (Literal["expanding", "rolling"], optional) – Cross-validation window strategy. Defaults to
"expanding".num_splits (int | None, optional) – Maximum number of CV splits. None uses all available splits. Defaults to None.
project_name (str, optional) – Experiment / project name used for logging and output paths. Defaults to
"experiment".file_name (str | None, optional) – Output file name. None auto-generates from the project name. Defaults to None.
seed (int, optional) – Random seed for reproducibility. Defaults to 42.
root_dir (str, optional) – Root directory for output artefacts. Defaults to
"../".metrics (tuple[str] | list[str] | None, optional) – Evaluation metrics to compute and log. None uses the runner’s defaults. Defaults to None.
BaseModelConfig#
BaseModelConfig is the root configuration class for all model types. It provides the name and domain identifiers, an optional search_space for hyperparameter tuning, and the get_optuna_params() method that merges fixed parameters with Optuna trial suggestions.
You do not instantiate BaseModelConfig directly. Instead, each model provides its own subclass (e.g., XGBOOSTConfig, MLPFConfig) that inherits from either BaseModelConfig (for ML models) or NeuralModelConfig (for NN models).
Field |
Type |
Default |
Description |
|---|---|---|---|
|
|
|
Model type identifier. Overridden by each subclass. Excluded from parameter dumps. |
|
|
|
Modeling domain identifier (aliased as |
|
|
|
Optional hyperparameter search space for Optuna-based tuning. Excluded from parameter dumps. |
Key Method: get_optuna_params(trial)#
Combines the model’s fixed parameters (everything except name and search_space) with dynamic suggestions from the search space. During hyperparameter tuning, the TwigaForecaster calls this method inside the Optuna objective function.
def get_optuna_params(self, trial: optuna.Trial) -> dict[str, Any]:
base_params = self.model_dump(exclude={"name", "search_space"})
if self.search_space:
search_params = self.search_space.get_optuna_params(trial, prefix=self.name)
return {**base_params, **search_params}
return base_params
API Reference#
- class twiga.core.config.BaseModelConfig(**data)#
Bases:
BaseModelShared base configuration for all forecasting models.
Provides the
name,domain, andsearch_spacefields that every concrete config is expected to expose, along with a uniformget_optuna_params()that merges fixed config values with any search-space suggestions.Subclass this to define model-specific configurations:
class MyModelConfig(BaseModelConfig): name: Literal["my_model"] = Field(default="my_model", exclude=True) hidden_size: int = 128 dropout: float = 0.3 search_space: BaseSearchSpace = BaseSearchSpace( hidden_size=[64, 128, 256], dropout=(0.0, 0.5), )
- Parameters:
name (Literal["base_model"], optional) – Model type identifier. Excluded from parameter tuning. Defaults to
"base_model".domain (Literal["nn"], optional) – Modelling domain identifier. Excluded from parameter tuning. Defaults to
"nn".search_space (BaseSearchSpace | None, optional) – Hyperparameter search space. When set, its fields are merged into the output of
get_optuna_params()for HPO. Defaults to None.
- get_optuna_params(trial)#
Return fixed config values merged with Optuna search-space suggestions.
Fixed parameters come from
pydantic.BaseModel.model_dump()(withnameandsearch_spaceexcluded). If asearch_spaceis set, its fields are sampled fortrialand override any overlapping fixed values, allowing a single config object to serve both fixed and tuned usage patterns.
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- search_space: BaseSearchSpace | None#
- to_estimator_params()#
Return a parameter dict safe to pass directly to the underlying estimator.
Excludes Twiga-internal fields (
name,domain,search_space) and maps the unifiedseedfield to the library-specific keyword defined by_LIBRARY_SEED_KEY(e.g."random_state"for sklearn estimators).
NeuralModelConfig#
NeuralModelConfig extends BaseModelConfig with parameters specific to PyTorch Lightning training. All neural network models (MLPF, MLPGAM, MLPGAF, NHITS, GANF, and their probabilistic variants) inherit from this class.
Field |
Type |
Default |
Description |
|---|---|---|---|
|
|
|
Model type identifier. Overridden by each NN subclass. Excluded from parameter dumps. |
|
|
|
Modeling domain identifier. Excluded from parameter dumps. |
|
|
|
Enable rich-formatted progress bars during training. |
|
|
|
Enable experiment logging to Weights & Biases. Requires the |
|
|
|
Drop the last incomplete batch if the dataset size is not divisible by the batch size. Prevents shape mismatches. |
|
|
|
Number of worker processes for the PyTorch |
|
|
|
Mini-batch size for training and validation. |
|
|
|
Pin host memory in the |
|
|
|
Maximum number of training epochs. Training may stop earlier if early stopping triggers. |
|
|
|
Metric used to monitor model performance and trigger early stopping (e.g., |
|
|
|
Optimizer configuration dictionary (e.g., |
|
|
|
Learning rate scheduler configuration dictionary (e.g., |
|
|
|
Number of epochs with no improvement before early stopping halts training. |
|
|
|
Resume training from the last saved checkpoint if one exists. |
|
|
|
Random seed for reproducibility. Must be a positive integer ( |
Key Method: from_data_config(data_config, **kwargs)#
A classmethod that constructs a NeuralModelConfig (or any subclass) directly from a DataPipelineConfig. It automatically computes the input and output dimensions that the neural architecture needs:
from twiga.core.config import DataPipelineConfig
from twiga.models.nn.mlpf_model import MLPFConfig
data_config = DataPipelineConfig(
target_feature="load_mw",
period="1h",
lookback_window_size=168,
forecast_horizon=48,
calendar_features=["hour", "dayofweek"],
known_future_features=["ghi"],
)
# Automatically sets num_target_feature, num_calendar_features, etc.
mlpf_config = MLPFConfig.from_data_config(data_config, max_epochs=50, batch_size=128)
The classmethod extracts the following from the DataPipelineConfig:
num_target_feature- count of target variablesnum_past_features- count of past-only feature columnsnum_calendar_features- count of calendar feature columnsnum_known_future_features- count of known-future feature columnsnum_forecast_period_features- count of forecast-period-only feature columnsforecast_horizonandlookback_window_size- passed through directly
Any additional keyword arguments are forwarded to the config constructor, allowing you to override defaults like max_epochs or batch_size.
Always use from_data_config for NN models
Neural models require dimensional parameters (num_target_feature, num_calendar_features, etc.) that must match the data pipeline. Using from_data_config guarantees consistency. Setting these values manually is error-prone and not recommended.
API Reference#
- class twiga.core.config.NeuralModelConfig(**data)#
Bases:
BaseModelConfigConfiguration for neural network-based forecasting models.
Extends
BaseModelConfigwith training infrastructure fields and a shared three-dict HPO system for optimizer, scheduler, and batch-size search. See the module docstring for a full explanation of the search space design.The optimizer and scheduler are selected via
optimizer_typeandlr_scheduler_type. Both are captured bysave_hyperparameters()inBaseNeuralModelat training time, so they must be declared as fields here.Optional fine-grained overrides can be supplied via
optimizer_paramsandscheduler_params. When provided they are merged into the corresponding entry ofBaseNeuralModel.OPTIMIZERS/BaseNeuralModel.SCHEDULERS, allowing partial overrides (e.g. onlylr) without replacing the full dict.- Parameters:
name (Literal["neural_model"], optional) – Model type identifier. Defaults to
"neural_model".domain (Literal["nn"], optional) – Modelling domain identifier. Defaults to
"nn".rich_progress_bar (bool, optional) – Enable rich progress bars. Defaults to True.
drop_last (bool, optional) – Drop the last incomplete batch. Defaults to True.
num_workers (int, optional) – DataLoader worker count. Defaults to 8.
batch_size (int, optional) – Training batch size. Defaults to 64.
pin_memory (bool, optional) – Pin memory for faster GPU transfer. Defaults to True.
max_epochs (int, optional) – Maximum training epochs. Defaults to 10.
early_stop_patience (int | None, optional) – Early-stopping patience in epochs.
Nonedisables early stopping. Defaults to 10.resume_training (bool, optional) – Resume from last checkpoint. Defaults to True.
seed (int, optional) – Positive integer random seed. Defaults to 42.
metric (Literal["mae", "mse", "smape"], optional) – Validation metric. Defaults to
"mae".optimizer_type (Literal[...], optional) – Native
torch.optimoptimizer. Defaults to"adamw".lr_scheduler_type (Literal[...], optional) – Native
torch.optim.lr_schedulerclass. Defaults to"multi_step".optimizer_params (dict | None, optional) – Partial override for the selected optimizer’s default params. Defaults to None.
scheduler_params (dict | None, optional) – Partial override for the selected scheduler’s default params. Defaults to None.
- BASE_TRAINING_SEARCH_SPACE: ClassVar[BaseSearchSpace] = BaseSearchSpace(optimizer_type=['adam', 'adamw'], lr_scheduler_type=['warmup_cosine', 'multi_step', 'reduce_on_plateau'], batch_size=[8, 16, 32, 64])#
- OPTIMIZER_PARAM_SEARCH: ClassVar[dict[str, BaseSearchSpace]] = {'adam': BaseSearchSpace(lr=(0.0001, 0.01), weight_decay=(1e-07, 0.0001)), 'adamw': BaseSearchSpace(lr=(0.0001, 0.01), weight_decay=(1e-06, 0.001)), 'muon': BaseSearchSpace(lr=(0.001, 0.1), momentum=(0.9, 0.99), ns_steps=[4, 6, 8])}#
- SCHEDULER_PARAM_SEARCH: ClassVar[dict[str, BaseSearchSpace]] = {'multi_step': BaseSearchSpace(prob_decay_1=(0.3, 0.6), prob_decay_2=(0.7, 0.95), gamma=[0.1, 0.2, 0.5]), 'reduce_on_plateau': BaseSearchSpace(factor=[0.1, 0.2, 0.5], prob_patience=(0.05, 0.2)), 'warmup_cosine': BaseSearchSpace(warmup_epochs=[3, 5, 10], eta_min=(1e-07, 1e-05))}#
- classmethod from_data_config(data_config, **kwargs)#
Create a config instance with dimensions derived from a DataPipelineConfig.
- Parameters:
data_config (DataPipelineConfig) – Pipeline config providing feature counts and sequence dimensions.
**kwargs – Additional fields forwarded to the constructor, allowing any field to be overridden at instantiation time.
- Returns:
NeuralModelConfig – Populated config instance.
- Raises:
TypeError – If
data_config.target_featureis notstrorlist[str].AttributeError – If
data_configis missingforecast_horizon.
- get_optuna_params(trial)#
Standard HPO sampling for all neural models.
Combines child-specific architecture parameters with the standardized conditional optimizer and scheduler search space.
- Return type:
- lr_scheduler_type: Literal['step', 'multi_step', 'multiplicative', 'exponential', 'constant', 'linear_decay', 'polynomial', 'cosine_annealing', 'cosine_annealing_lr', 'cyclic', 'reduce_on_plateau', 'one_cycle', 'warmup_multi_step', 'warmup_cosine']#
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- optimizer_type: Literal['adam', 'adamw', 'nadam', 'radam', 'adamax', 'adafactor', 'adagrad', 'adadelta', 'rmsprop', 'rprop', 'asgd', 'sgd', 'muon']#
- classmethod sample_training_params(trial)#
Sample optimizer, scheduler, and batch-size using BaseSearchSpace logic.
- Return type:
BaseSearchSpace#
BaseSearchSpace defines the hyperparameter search space for Optuna-based tuning. Each model config can optionally include a search_space field containing a subclass of BaseSearchSpace.
Search spaces use two conventions:
Tuples
(low, high)define numeric ranges. Integer tuples map totrial.suggest_int(); float tuples map totrial.suggest_float().Lists
[a, b, c]define categorical choices and map totrial.suggest_categorical().
Feature |
Encoding |
Optuna Method |
Details |
|---|---|---|---|
Integer range |
|
|
e.g., |
Float range |
|
|
Log scale applied automatically when |
Categorical |
|
|
e.g., |
Validation Rules#
The validate_search_space() model validator enforces the following at construction time:
Tuples must have exactly two numeric elements with
low < high.Lists must contain at least one element and have no duplicates.
All fields must be either tuples or lists - no other types are allowed.
Automatic Log Scale#
The _should_use_log(low, high) static method determines whether Optuna should sample on a logarithmic scale. It returns True when both bounds are positive and their ratio is at least 10. This is useful for parameters like learning rate where the interesting range spans several orders of magnitude (e.g., (0.0001, 0.1)).
Example#
from twiga.core.config import BaseSearchSpace
class XGBoostSearchSpace(BaseSearchSpace):
learning_rate: tuple[float, float] = (0.001, 0.3) # log scale (ratio >= 10)
max_depth: tuple[int, int] = (3, 12) # integer range
n_estimators: tuple[int, int] = (100, 1000) # integer range
subsample: tuple[float, float] = (0.5, 1.0) # linear scale (ratio < 10)
reg_alpha: list[float] = [0.0, 0.1, 1.0, 10.0] # categorical
# Attach to a model config
from twiga.models.ml.xgboost_model import XGBOOSTConfig
config = XGBOOSTConfig(
search_space=XGBoostSearchSpace(),
)
API Reference#
- class twiga.core.config.BaseSearchSpace(**data)#
Bases:
BaseModelPydantic model for validating hyperparameter optimisation search spaces.
Each field must be either:
A
tuple[float, float]ortuple[int, int]representing a continuous range(low, high). Float ranges spanning more than one order of magnitude (high / low >= 10) are sampled on a log scale automatically.A
listof at least one categorical value.
The class uses
extra="allow"so that concrete search spaces can be defined inline without subclassing:space = BaseSearchSpace( latent_size=[64, 128, 256], dropout=(0.0, 0.5), )
- Parameters:
**kwargs – Any keyword argument whose value is a valid range tuple or categorical list.
Examples
>>> space = BaseSearchSpace(lr=(1e-4, 1e-2), activation=["relu", "tanh"]) >>> params = space.get_optuna_params(trial, prefix="mlp")
- get_optuna_params(trial, prefix='')#
Generate Optuna parameter suggestions for all fields.
- Parameters:
trial (
Trial) – Active Optuna trial.prefix (
str) – Prefix prepended to each parameter name in the trial (e.g. the model name) to avoid collisions when multiple search spaces are sampled in the same trial. Defaults to"".
- Return type:
- Returns:
dict[str, Any] –
- Mapping of field names (without prefix) to their
sampled values.
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- validate_against(config)#
Raise ValueError if any search space field name is not present on config.
Catches typos in search space definitions early - before an Optuna trial is run - so that mis-spelled field names produce a clear error instead of silently sampling a parameter that never gets applied.
- Parameters:
config (
BaseModel) – The model config instance (or class) whose fields define the valid parameter names.- Raises:
ValueError – If one or more field names in this search space do not exist on config.
Examples
- Return type:
>>> space = BaseSearchSpace(hiddn_dim=[64, 128]) # typo! >>> space.validate_against(my_model_config) Traceback (most recent call last): ... ValueError: Search space contains unknown fields: {'hiddn_dim'}. ...
- validate_search_space()#
Validate all fields have valid types and structure.
- Return type:
ConformalConfig#
ConformalConfig controls conformal prediction, which wraps any trained model with distribution-free prediction intervals. It is passed as conformal_params to TwigaForecaster.
Field |
Type |
Default |
Description |
|---|---|---|---|
|
|
required |
Conformal prediction method. |
|
|
required |
Type of nonconformity score. |
|
|
required |
Significance level, strictly between 0 and 1. Controls the width of prediction intervals: |
Compatibility Rules#
The validate_field_compatibility() model validator enforces that method and score_type are compatible:
Method |
Allowed Score Types |
|---|---|
|
|
|
|
|
|
Attempting to use an incompatible combination raises a ValueError at construction time.
Extreme alpha values
A field validator warns (but does not reject) when alpha < 0.01 (overly wide intervals) or alpha > 0.5 (overly narrow intervals). Both are technically valid but rarely useful in practice.
Example#
from twiga.core.config import ConformalConfig
# 90% prediction intervals using absolute residuals (via alpha)
conformal_config = ConformalConfig(
method="residual",
score_type="res",
alpha=0.1,
)
# 90% intervals via coverage probability (convenience factory)
conformal_config = ConformalConfig.from_coverage(
coverage=0.9,
method="residual",
score_type="res",
)
# 95% intervals using quantile regression with scaled scores
conformal_qr = ConformalConfig(
method="quantile",
score_type="scaled",
alpha=0.05,
)
API Reference#
- class twiga.core.config.ConformalConfig(**data)#
Bases:
BaseModelConfiguration for conformal prediction methods.
Supports three conformal predictors - residual-based, quantile-based, and residual-fitting - each with compatible nonconformity score types.
- Parameters:
method (Literal["residual", "quantile", "residual-fitting"], optional) –
Conformal prediction method:
"residual"- nonconformity scores based on absolute residuals|y - ŷ|."quantile"- quantile regression for prediction intervals."residual-fitting"- fits a secondary model to predict residuals for adaptive interval widths.
Defaults to
"residual".score_type (str, optional) – Nonconformity score type.
"scaled"/"unscaled"for quantile method;"res"/"sign-res"for residual-based methods. Defaults to"res".alpha (float, optional) – Significance level controlling the confidence level
(1 - alpha)of the prediction intervals. Must be in(0, 1). For examplealpha=0.1→ 90 % coverage. Defaults to 0.1.
- Raises:
ValueError – If
method="quantile"is combined with a residual score type, or if a residual method is combined with a quantile score type.
Examples
>>> ConformalConfig(method="residual", score_type="res", alpha=0.1) ConformalConfig(method='residual', score_type='res', alpha=0.1) >>> ConformalConfig(method="quantile", score_type="scaled", alpha=0.05) ConformalConfig(method='quantile', score_type='scaled', alpha=0.05)
- alpha: Annotated[float, FieldInfo(annotation=NoneType, required=False, default=0.1, description='Significance level for prediction intervals. Controls coverage as (1 - alpha). Example: alpha=0.1 → 90% prediction intervals.', metadata=[Gt(gt=0.0), Lt(lt=1.0)])]#
- calib_method: Annotated[Literal['uniform', 'temporal'], FieldInfo(annotation=NoneType, required=False, default='uniform', description="Quantile estimation method for calibration scores. 'uniform': standard empirical quantile (equal weight per sample). 'temporal': exponentially weighted quantile (Tibshirani et al. 2019) — recent calibration samples receive higher weight, reducing the influence of seasonally misaligned older samples. Only used for 'residual-fitting'.")]#
- classmethod from_coverage(coverage, **kwargs)#
Construct from a coverage level rather than a significance level.
- Parameters:
coverage (
float) – Desired coverage probability, e.g.0.9for 90 % intervals. Must be in(0, 1). Converted toalpha = 1 - coverage.**kwargs – Any additional
ConformalConfigfields (e.g.method,score_type).
- Return type:
- Returns:
ConformalConfigwithalpha = 1 - coverage.
Example
>>> cfg = ConformalConfig.from_coverage(0.9, method="residual") >>> cfg.alpha 0.1
- lambda_: Annotated[float, FieldInfo(annotation=NoneType, required=False, default=1.0, description="Exponential decay rate for temporal calibration weighting. Ignored when calib_method='uniform'. lambda_=0 recovers uniform weights; larger values concentrate weight on the most recent calibration samples.", metadata=[Ge(ge=0.0)])]#
- method: Annotated[Literal['residual', 'quantile', 'residual-fitting'], FieldInfo(annotation=NoneType, required=False, default='residual', description="Conformal prediction method. 'residual': absolute residual scores. 'quantile': quantile regression intervals. 'residual-fitting': secondary model predicts residuals for adaptive widths.")]#
- model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- score_type: Annotated[Literal['scaled', 'unscaled', 'res', 'sign-res'], FieldInfo(annotation=NoneType, required=False, default='res', description="Nonconformity score type. 'scaled'/'unscaled': for quantile method. 'res'/'sign-res': for residual-based methods.")]#
- validate_method_score_compatibility()#
Validate that method and score_type are compatible.
- Return type:
NeuralTrainingConfig#
NeuralTrainingConfig provides a single place to override training-infrastructure parameters across every neural network model in model_params. All fields default to None (meaning “do not override”). Only set the fields you want to change globally.
It is passed as training_params to TwigaForecaster.
Field |
Type |
Default |
Description |
|---|---|---|---|
|
|
|
Training batch size. |
|
|
|
Maximum training epochs. |
|
|
|
Early-stopping patience. |
|
|
|
Random seed for reproducibility. |
|
|
|
DataLoader worker count. |
|
|
|
Pin memory for faster CPU→GPU transfer. |
|
|
|
Drop the last incomplete batch. |
|
|
|
Enable Weights & Biases logging. |
|
|
|
Enable rich progress bars. |
|
|
|
Max gradient norm for clipping. |
|
|
|
Optimizer name (e.g. |
|
|
|
Scheduler name (e.g. |
|
|
|
Partial override for optimizer defaults. |
|
|
|
Partial override for scheduler defaults. |
Usage Example#
from twiga.core.config import NeuralTrainingConfig
from twiga.forecaster.core import TwigaForecaster
from twiga.models.nn.mlpf_model import MLPFConfig
from twiga.models.nn.nhits_model import NHITSConfig
# Override training settings for all NN models at once
training_params = NeuralTrainingConfig(
max_epochs=100,
early_stop_patience=10,
batch_size=256,
optimizer_type="adamw",
lr_scheduler_type="warmup_cosine",
gradient_clip_val=1.0,
)
forecaster = TwigaForecaster(
data_params=data_config,
model_params=[MLPFConfig(), NHITSConfig()],
training_params=training_params,
)
API Reference#
- class twiga.core.config.NeuralTrainingConfig(**data)#
Bases:
BaseModelTraining infrastructure overrides for neural network models.
All fields default to
None, meaning “do not override the model config’s own value.” Only set the fields you want to change globally across all NN models passed to the forecaster.Example — disable early stopping and cap epochs for all models:
training_params = NeuralTrainingConfig(early_stop_patience=None, max_epochs=50) forecaster = TwigaForecaster( data_params=data_cfg, model_params=[MLPFNormalConfig(), MLPFGammaConfig()], training_params=training_params, )
- Parameters:
batch_size (int | None, optional) – Training batch size. Defaults to None.
max_epochs (int | None, optional) – Maximum training epochs. Defaults to None.
early_stop_patience (int | None, optional) – Early-stopping patience in epochs.
Nonedisables early stopping. Defaults to None.seed (int | None, optional) – Random seed for reproducibility. Defaults to None.
num_workers (int | None, optional) – DataLoader worker count. Defaults to None.
pin_memory (bool | None, optional) – Pin memory for faster GPU transfer. Defaults to None.
drop_last (bool | None, optional) – Drop the last incomplete batch. Defaults to None.
rich_progress_bar (bool | None, optional) – Enable rich progress bars. Defaults to None.
gradient_clip_val (float | None, optional) – Max gradient norm for clipping.
Nonedisables clipping. Defaults to None.optimizer_type (str | None, optional) – Optimizer name (e.g.
"adamw"). Defaults to None.lr_scheduler_type (str | None, optional) – Scheduler name (e.g.
"warmup_cosine"). Defaults to None.optimizer_params (dict | None, optional) – Partial override for the selected optimizer’s default params. Defaults to None.
scheduler_params (dict | None, optional) – Partial override for the selected scheduler’s default params. Defaults to None.
- lr_scheduler_type: Literal['step', 'multi_step', 'exponential', 'cosine', 'cosine_restart', 'warmup_cosine', 'reduce_on_plateau', 'cyclic', 'one_cycle', 'linear', 'polynomial', 'constant', 'linear_warmup', 'none'] | None#
- model_config: ClassVar[ConfigDict] = {}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
Putting It All Together#
The following example demonstrates how all configuration objects work together in a complete forecasting workflow.
import pandas as pd
from twiga.core.config import (
DataPipelineConfig,
ExperimentConfig,
ConformalConfig,
)
from twiga.forecaster.core import TwigaForecaster
from twiga.models.ml.xgboost_model import XGBOOSTConfig
from twiga.models.nn.mlpf_model import MLPFConfig
# --- Data pipeline configuration ---
data_config = DataPipelineConfig(
target_feature="load_mw",
period="1h",
lookback_window_size=168,
forecast_horizon=48,
calendar_features=["hour", "dayofweek", "month"],
known_future_features=["ghi", "temperature"],
lags=[1, 24, 48, 168],
windows=[24, 48],
window_funcs=["mean", "std"],
input_scaler="standard",
target_scaler="robust",
)
# --- Model configurations ---
xgb_config = XGBOOSTConfig(device="cpu")
mlpf_config = MLPFConfig.from_data_config(data_config, max_epochs=30, batch_size=128)
# --- Training orchestration ---
train_config = ExperimentConfig(
split_freq="months",
train_size=6,
test_size=1,
window="expanding",
project_name="EnergyForecast",
seed=42,
)
# --- Conformal prediction ---
conformal_config = ConformalConfig(
method="residual",
score_type="res",
alpha=0.1,
)
# --- Assemble and run ---
forecaster = TwigaForecaster(
data_params=data_config,
model_params=[xgb_config, mlpf_config],
cv_params=train_config,
conformal_params=conformal_config,
)
data = pd.read_parquet("data/timeseries.parquet")
train_df = data[data.timestamp <= "2024-06-01"]
val_df = data[(data.timestamp > "2024-05-15") & (data.timestamp <= "2024-07-01")]
test_df = data[data.timestamp > "2024-07-01"]
forecaster.fit(train_df=train_df, val_df=val_df)
forecaster.calibrate(calibrate_df=val_df)
predictions_df, metrics_df = forecaster.evaluate_point_forecast(test_df=test_df)
interval_df, interval_metrics = forecaster.evaluate_interval_forecast(test_df=test_df)
See also: TwigaForecaster | Data Pipeline | Backtesting | Hyperparameter Tuning | Conformal Prediction