Source code for alf_core.model.base_model
# Copyright 2026 InstaDeep Ltd. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import annotations
import abc
from dataclasses import dataclass
from typing import TYPE_CHECKING, Any, Literal
import numpy as np
from alf_core.dataclasses import Candidate, LabelledCandidates, Predictions
from alf_core.utils.enums import ProblemType
if TYPE_CHECKING:
from alf_core.dataclasses.surrogate_epoch_metrics import SurrogateEpochMetrics
from alf_core.dataset.base_dataset import BaseDataset
from torch import dtype as TorchDtype
[docs]
@dataclass
class BaseTrainConfig:
"""Base configuration shared by all model training configs.
Args:
learning_rate: Learning rate for the optimizer.
log_frequency: How often (in epochs/iterations) to log training metrics.
normalise_inputs_strategy: Which input normalisation to apply before
training: `minmax` (scale features to [0, 1]) or `zscore` (zero
mean, unit variance). None disables input normalisation. Defaults
to None.
standardise_outputs: Whether to apply Z-score standardisation to
outputs before training. Defaults to False.
label_dtype: dtype for label tensors during training. None means each
model uses its own default (e.g. float32 for regression, long for
classification). Override to force a specific dtype.
"""
learning_rate: float = 1e-3
log_frequency: int = 10
normalise_inputs_strategy: Literal["minmax", "zscore"] | None = None
standardise_outputs: bool = False
label_dtype: "TorchDtype | None" = None
[docs]
class BaseModel(abc.ABC):
"""Base class for all models.
Several components of the framework can be treated as models, such as the surrogate, oracle,
and the generator defined as model based search.
"""
problem_type: ProblemType
output_dim: int
[docs]
@abc.abstractmethod
def featurise(self, inputs: list[Candidate]) -> Any:
"""Convert inputs into feature representations.
Args:
inputs: List of Candidate objects to featurize.
Returns:
Feature representation of the inputs (format depends on implementation).
"""
pass
[docs]
@abc.abstractmethod
def train(
self,
train_data: LabelledCandidates,
val_data: LabelledCandidates | None = None,
) -> None:
"""Train the model on the provided training and validation data.
Args:
train_data: Labeled candidates for training.
val_data: Labeled candidates for validation. When None, the model
should skip validation metrics or handle the absence gracefully.
"""
pass
[docs]
@abc.abstractmethod
def predict(self, candidate_points: list[Candidate]) -> Predictions:
"""Predict scores for the given candidate points.
Args:
candidate_points: List of Candidate objects to make predictions for.
Returns:
Predictions object containing means and optionally variances
and empirical distributions.
"""
pass
[docs]
@abc.abstractmethod
def sample(self, condition: Any | None = None) -> list[Candidate]:
"""Sample candidate points from the model.
Args:
condition: Optional conditioning information for sampling.
Returns:
List of sampled candidate points.
"""
pass
[docs]
def setup(self, dataset: "BaseDataset") -> None:
"""Configure the model for the given dataset. Called once before training begins.
For BINARY this is 1 (single logit, sigmoid-activated); see
dataset.num_classes for the number of distinct classes.
Args:
dataset: The dataset this model will be trained on.
"""
self.problem_type = dataset.config.problem_type
self.output_dim = dataset.num_classes if self.problem_type == ProblemType.MULTICLASS else 1
[docs]
def get_epoch_metrics(self) -> list[SurrogateEpochMetrics]:
"""Return per-epoch training metrics from the most recent train() call.
Returns:
List of SurrogateEpochMetrics, one per epoch trained. Returns an empty list
by default; subclasses that record per-epoch metrics should override.
"""
return []
[docs]
def get_training_summary_metrics(self) -> dict[str, float | int | np.number]:
"""Get summary metrics from the most recent training run.
Returns:
Dictionary of metric names to values. Returns empty dict by default;
subclasses should override to provide metrics.
"""
return {}
[docs]
def cleanup(self) -> None:
"""Clean up temporary files and resources.
Deletes any temporary files, checkpoints, or other resources that aren't
being persisted. Subclasses should override to implement cleanup logic.
"""
pass