pathforge.training¶
Trainer abstractions and the PyTorch Lightning implementation. Trainers are
registered in TRAINERS and resolved by
name at runtime.
Base Abstractions¶
- class pathforge.training.base.TrainerBase[source]¶
Bases:
ABCFramework agnostic trainer base class.
- abstractmethod fit(model: MILModelBase, dataset_train: DatasetBase, dataset_val: DatasetBase, loss_func: BaseLoss) Any[source]¶
Train a model on train/validation datasets and return trainer-specific results.
- Parameters:
model (MILModelBase)
dataset_train (DatasetBase)
dataset_val (DatasetBase)
loss_func (BaseLoss)
- Return type:
Any
- abstractmethod predict(model: MILModelBase, dataset: DatasetBase) Any[source]¶
Run inference on a dataset using a trained model.
- Parameters:
model (MILModelBase)
dataset (DatasetBase)
- Return type:
Any
- class pathforge.training.base.MILTrainer[source]¶
Bases:
objectConvenience façade specifically for MIL use cases.
This constrains the types to MILModelBase + BagDatasetBase, which matches the architecture diagram’s “MILTrainer” box.
- trainer: TrainerBase¶
- model: MILModelBase¶
- dataset_train: BagDatasetBase¶
- dataset_val: BagDatasetBase¶
- __init__(trainer: TrainerBase, model: MILModelBase, dataset_train: BagDatasetBase, dataset_val: BagDatasetBase, loss: BaseLoss) None¶
- Parameters:
trainer (TrainerBase)
model (MILModelBase)
dataset_train (BagDatasetBase)
dataset_val (BagDatasetBase)
loss (BaseLoss)
- Return type:
None
Lightning Trainer¶
The Lightning trainer is registered as "lightning" in
TRAINERS.
- class pathforge.training.lightning.LightningModuleAdapter[source]¶
Bases:
LightningModuleAdapter: Wraps a PathForge MILModelBase into a PL LightningModule. Handles optimization logic, logging, and scheduler configuration via Config. Pass loss_fn=None only for inference (predict_step does not use it).
- __init__(model: MILModelBase, loss_fn: BaseLoss | None, config: Config)[source]¶
- Parameters:
model (MILModelBase)
loss_fn (BaseLoss | None)
config (Config)
- forward(*args, **kwargs)[source]¶
Same as
torch.nn.Module.forward().- Parameters:
*args – Whatever you decide to pass into the forward method.
**kwargs – Keyword arguments are also possible.
- Returns:
Your model’s output
- training_step(batch: Any, batch_idx: int) Tensor[source]¶
Here you compute and return the training loss and some additional metrics for e.g. the progress bar or logger.
- Parameters:
batch (Any) – The output of your data iterable, normally a
DataLoader.batch_idx (int) – The index of this batch.
dataloader_idx – The index of the dataloader that produced this batch. (only if multiple dataloaders used)
- Returns:
Tensor- The loss tensordict- A dictionary which can include any keys, but must include the key'loss'in the case of automatic optimization.None- In automatic optimization, this will skip to the next batch (but is not supported for multi-GPU, TPU, or DeepSpeed). For manual optimization, this has no special meaning, as returning the loss is not required.
- Return type:
Tensor
In this step you’d normally do the forward pass and calculate the loss for a batch. You can also do fancier things like multiple forward passes or something model specific.
Example:
def training_step(self, batch, batch_idx): x, y, z = batch out = self.encoder(x) loss = self.loss(out, x) return loss
To use multiple optimizers, you can switch to ‘manual optimization’ and control their stepping:
def __init__(self): super().__init__() self.automatic_optimization = False # Multiple optimizers (e.g.: GANs) def training_step(self, batch, batch_idx): opt1, opt2 = self.optimizers() # do training_step with encoder ... opt1.step() # do training_step with decoder ... opt2.step()
Note
When
accumulate_grad_batches> 1, the loss returned here will be automatically normalized byaccumulate_grad_batchesinternally.
- validation_step(batch: Any, batch_idx: int) Tensor[source]¶
Operates on a single batch of data from the validation set. In this step you’d might generate examples or calculate anything of interest like accuracy.
- Parameters:
batch (Any) – The output of your data iterable, normally a
DataLoader.batch_idx (int) – The index of this batch.
dataloader_idx – The index of the dataloader that produced this batch. (only if multiple dataloaders used)
- Returns:
Tensor- The loss tensordict- A dictionary. Can include any keys, but must include the key'loss'.None- Skip to the next batch.
- Return type:
Tensor
# if you have one val dataloader: def validation_step(self, batch, batch_idx): ... # if you have multiple val dataloaders: def validation_step(self, batch, batch_idx, dataloader_idx=0): ...
Examples:
# CASE 1: A single validation dataset def validation_step(self, batch, batch_idx): x, y = batch # implement your own out = self(x) loss = self.loss(out, y) # log 6 example images # or generated text... or whatever sample_imgs = x[:6] grid = torchvision.utils.make_grid(sample_imgs) self.logger.experiment.add_image('example_images', grid, 0) # calculate acc labels_hat = torch.argmax(out, dim=1) val_acc = torch.sum(y == labels_hat).item() / (len(y) * 1.0) # log the outputs! self.log_dict({'val_loss': loss, 'val_acc': val_acc})
If you pass in multiple val dataloaders,
validation_step()will have an additional argument. We recommend setting the default value of 0 so that you can quickly switch between single and multiple dataloaders.# CASE 2: multiple validation dataloaders def validation_step(self, batch, batch_idx, dataloader_idx=0): # dataloader_idx tells you which dataset this is. x, y = batch # implement your own out = self(x) if dataloader_idx == 0: loss = self.loss0(out, y) else: loss = self.loss1(out, y) # calculate acc labels_hat = torch.argmax(out, dim=1) acc = torch.sum(y == labels_hat).item() / (len(y) * 1.0) # log the outputs separately for each dataloader self.log_dict({f"val_loss_{dataloader_idx}": loss, f"val_acc_{dataloader_idx}": acc})
Note
If you don’t need to validate you don’t need to implement this method.
Note
When the
validation_step()is called, the model has been put in eval mode and PyTorch gradients have been disabled. At the end of validation, the model goes back to training mode and gradients are enabled.
- predict_step(batch: Any, batch_idx: int, dataloader_idx: int = 0) Tensor[source]¶
Step function called during
predict(). By default, it callsforward(). Override to add any processing logic.The
predict_step()is used to scale inference on multi-devices.To prevent an OOM error, it is possible to use
BasePredictionWritercallback to write the predictions to disk or database after each batch or on epoch end.The
BasePredictionWritershould be used while using a spawn based accelerator. This happens forTrainer(strategy="ddp_spawn")or training on 8 TPU cores withTrainer(accelerator="tpu", devices=8)as predictions won’t be returned.- Parameters:
batch (Any) – The output of your data iterable, normally a
DataLoader.batch_idx (int) – The index of this batch.
dataloader_idx (int) – The index of the dataloader that produced this batch. (only if multiple dataloaders used)
- Returns:
Predicted output (optional).
- Return type:
Tensor
Example
class MyModel(LightningModule): def predict_step(self, batch, batch_idx, dataloader_idx=0): return self(batch) dm = ... model = MyModel() trainer = Trainer(accelerator="gpu", devices=2) predictions = trainer.predict(model, dm)
- on_validation_epoch_start() None[source]¶
Called in the validation loop at the very beginning of the epoch.
- Return type:
None
- class pathforge.training.lightning.LightningTrainer[source]¶
Bases:
TrainerBaseTrainer implementation using PyTorch Lightning.
Config Usage: - mil.epochs -> max_epochs - mil.accumulate_grad_batches - mil.gradient_clip_val - experiment.num_workers
- __init__(config: Config, extra_callbacks: List[Callback] | None = None)[source]¶
- Parameters:
config (Config)
extra_callbacks (List[Callback] | None)
- fit(model: MILModelBase, dataset_train: Dataset, dataset_val: Dataset, loss_func: BaseLoss) Tuple[str, float][source]¶
Train the model. :returns: (best_model_path, best_model_score)
- Parameters:
model (MILModelBase)
dataset_train (Dataset)
dataset_val (Dataset)
loss_func (BaseLoss)
- Return type:
Tuple[str, float]
- predict(model: MILModelBase, dataset: Dataset) Tensor[source]¶
Run inference. loss_fn is not used during prediction.
- Parameters:
model (MILModelBase)
dataset (Dataset)
- Return type:
Tensor
Callbacks¶
Metrics¶
- class pathforge.training.metrics.TaskEvaluationArtifacts[source]¶
Bases:
objectPersisted evaluation outputs for one trained model.
- Variables:
metrics_path (pathlib.Path) – JSON file containing scalar task metrics.
curve_data_path (pathlib.Path) – JSON file containing inspectable curve coordinates.
figure_paths (dict[str, pathlib.Path]) – Mapping from figure name to the saved PNG path.
- metrics_path: Path¶
- curve_data_path: Path¶
- figure_paths: dict[str, Path]¶
- __init__(metrics_path: Path, curve_data_path: Path, figure_paths: dict[str, Path]) None¶
- Parameters:
metrics_path (Path)
curve_data_path (Path)
figure_paths (dict[str, Path])
- Return type:
None
- pathforge.training.metrics.compute_task_metrics(predictions: Tensor, target: Any, *, task: str, selected_metrics: list[str] | None = None) dict[str, float][source]¶
Compute scalar validation metrics for one PathForge task.
- Parameters:
predictions (Tensor) – Model output tensor. Classification expects logits shaped
[B]or[B, C]. Continuous survival expects risk/log-hazard shaped[B]or[B, 1]. Discrete survival expects logits shaped[B, T].target (Any) – Task target. Classification expects integer labels shaped
[B]. Survival tasks expect a dictionary withtimeandeventtensors shaped[B].task (str) – PathForge task name.
selected_metrics (list[str] | None)
- Returns:
Finite-or-NaN scalar metrics ready for Lightning logging and JSON serialization.
- Return type:
dict[str, float]
- pathforge.training.metrics.save_task_evaluation_artifacts(predictions: Tensor, target: Any, *, task: str, output_dir: Path, prefix: str, selected_metrics: list[str] | None = None) TaskEvaluationArtifacts[source]¶
Write scalar metrics plus task-specific visualization artifacts.
- Parameters:
predictions (Tensor) – Task prediction tensor with the same shape contract as
compute_task_metrics().target (Any) – Task target object with the same contract as
compute_task_metrics().task (str) – PathForge task name.
output_dir (Path) – Directory receiving JSON and PNG artifacts.
prefix (str) – Output prefix such as
"val".selected_metrics (list[str] | None)
- Returns:
Paths to the persisted JSON and PNG files.
- Return type:
Scikit-Learn Trainer¶
Trainer for scikit-learn / scikit-survival slide-level estimators.
Usage:
from pathforge.core.models.sklearn_slide import SklearnLogisticRegressionClassifier
from pathforge.training.sklearn_trainer import SklearnSlideTrainer
model = SklearnLogisticRegressionClassifier()
trainer = SklearnSlideTrainer(output_dir=Path("runs/lr"), task="classification")
model_path, score = trainer.fit(model, X_train, y_train, X_val, y_val)
- class pathforge.training.sklearn_trainer.SklearnSlideTrainer[source]¶
Bases:
TrainerBaseFit a
ScikitBaseestimator on slide-level numpy feature arrays and persist evaluation artefacts.This trainer does not use PyTorch Lightning; it calls sklearn’s
fit/predictdirectly and then runs the samesave_task_evaluation_artifacts()pipeline used byLightningTrainer.- Parameters:
output_dir – Root directory; model pickle and artifacts go here.
task – PathForge task name — one of
"classification","regression","survival","survival_discrete".selected_metrics – Optional list of metric names to compute; defaults to all metrics for the task.
- __init__(output_dir: Path | str, task: str, selected_metrics: list[str] | None = None) None[source]¶
- Parameters:
output_dir (Path | str)
task (str)
selected_metrics (list[str] | None)
- Return type:
None
- fit(model: ScikitBase, X_train: ndarray, y_train: Any, X_val: ndarray, y_val: Any) tuple[str, float][source]¶
Fit model and evaluate on the validation set.
- Parameters:
model (ScikitBase) – Unfitted sklearn estimator wrapper.
X_train (ndarray) – Training feature matrix shaped
[N_train, D].y_train (Any) – Training targets. For classification/regression: a 1-D numpy array; for survival: a dict with
"time"and"event"keys (1-D numpy arrays).X_val (ndarray) – Validation feature matrix shaped
[N_val, D].y_val (Any) – Validation targets with the same structure as y_train.
- Returns:
Tuple of
(model_pickle_path, best_scalar_score)where the score is the primary validation metric for the task (balanced_accuracyfor classification,c_indexfor survival,r2for regression).- Return type:
tuple[str, float]
- predict(model: ScikitBase, dataset: ndarray) Tensor[source]¶
Run prediction for a slide-level feature matrix shaped
[N, D].- Parameters:
model (ScikitBase)
dataset (ndarray)
- Return type:
Tensor