Skill Tracer
Skills › Scientific Agent Skills › pytorch-lightning › lightning_module.md

lightning_module.md

126 lines · skills/pytorch-lightning/references/lightning_module.md at 5f2bc03

Open on GitHub

Most marks come from matching words in the file, so treat them as pointers.

1# LightningModule contracts
2
3Reviewed against Lightning 2.6.6. The executable example is
4[`template_lightning_module.py`](../scripts/template_lightning_module.py).
5Fragments with project-defined names below are illustrative.
6

LightningModule contracts

Reviewed against Lightning 2.6.6. The executable example is [template_lightning_module.py](../scripts/template_lightning_module.py). Fragments with project-defined names below are illustrative.

Raw lines 1 to 6
Runs code scripts/template_lightning_module.py :4
7## Model and hooks
8
9Implement `__init__`, `forward`, `training_step`, and `configure_optimizers`.
10Validation, test, and prediction are separate hooks; `fit()` does not run `test()`.
11Automatic optimization expects a differentiable scalar loss or a dictionary with
12`loss`. Returning `None` intentionally skips that training batch; it is not a
13substitute for returning the loss when training is intended.
15`validation_step` and `test_step` run in evaluation mode with gradients disabled;
16`predict_step` also runs through the evaluation machinery. For derivative-based
17scientific inference, use `Trainer(inference_mode=False)` and explicitly enable
18gradients in the appropriate step. After evaluation, Lightning restores the
19previous training mode. Do not keep stochastic training augmentation in an
20evaluation DataLoader merely because dropout is disabled.
22Use `on_train_epoch_end` / `on_validation_epoch_end` for epoch work. The old
23`training_epoch_end(outputs)` / `validation_epoch_end(outputs)` hooks are removed.
24If you keep outputs yourself, detach them and clear them after reduction. A
25TorchMetrics state usually uses less memory than retaining every prediction.
26`setup(stage)` runs for fit/validate/test/predict; `configure_model()` can create
27large layers in a strategy-aware context and must be idempotent. The old
28`configure_sharded_model()` hook is deprecated.

Model and hooks

Implement __init__, forward, training_step, and configure_optimizers. Validation, test, and prediction are separate hooks; fit() does not run test(). Automatic optimization expects a differentiable scalar loss or a dictionary with loss. Returning None intentionally skips that training batch; it is not a substitute for returning the loss when training is intended.

validation_step and test_step run in evaluation mode with gradients disabled; predict_step also runs through the evaluation machinery. For derivative-based scientific inference, use Trainer(inference_mode=False) and explicitly enable gradients in the appropriate step. After evaluation, Lightning restores the previous training mode. Do not keep stochastic training augmentation in an evaluation DataLoader merely because dropout is disabled.

Use on_train_epoch_end / on_validation_epoch_end for epoch work. The old training_epoch_end(outputs) / validation_epoch_end(outputs) hooks are removed. If you keep outputs yourself, detach them and clear them after reduction. A TorchMetrics state usually uses less memory than retaining every prediction. setup(stage) runs for fit/validate/test/predict; configure_model() can create large layers in a strategy-aware context and must be idempotent. The old configure_sharded_model() hook is deprecated.

Raw lines 7 to 29
30## Optimizers
32Automatic optimization supports one optimizer. For a monitored scheduler:
34```python
35def configure_optimizers(self):
36 optimizer = torch.optim.Adam(self.parameters(), lr=self.hparams.learning_rate)
37 scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode="min")
38 return {
39 "optimizer": optimizer,
40 "lr_scheduler": {
41 "scheduler": scheduler,
42 "monitor": "val/loss",
43 "interval": "epoch",
44 "frequency": 1,
45 "strict": True,
46 },
47 }
48```
50Log that exact key on every scheduled validation pass. Align scheduler frequency
51with `check_val_every_n_epoch`; the bundled template assumes validation every
52epoch. `ReduceLROnPlateau` no longer accepts `verbose`. For a per-step scheduler,
53set `interval="step"`; `trainer.estimated_stepping_batches` includes accumulation
54and is useful for `OneCycleLR(total_steps=...)`.
56Multiple optimizers require `self.automatic_optimization = False`. An illustrative
57manual step for one of them is:
59```python
60opt_g, opt_d = self.optimizers()
61self.toggle_optimizer(opt_g)
62opt_g.zero_grad()
63g_loss = self.generator_loss(batch)
64self.manual_backward(g_loss)
65self.clip_gradients(opt_g, gradient_clip_val=1.0, gradient_clip_algorithm="norm")
66opt_g.step()
67self.untoggle_optimizer(opt_g)
68# Compute a fresh discriminator loss and repeat with opt_d.
69```
71Manual optimization owns zeroing, backward, stepping, accumulation, clipping,
72and scheduler steps. Trainer automatic-optimization settings do not implement
73those operations for you. Use Lightning's optimizer wrappers and
74`manual_backward` to preserve precision/strategy integration.

Optimizers

Automatic optimization supports one optimizer. For a monitored scheduler:

def configure_optimizers(self):
    optimizer = torch.optim.Adam(self.parameters(), lr=self.hparams.learning_rate)
    scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode="min")
    return {
        "optimizer": optimizer,
        "lr_scheduler": {
            "scheduler": scheduler,
            "monitor": "val/loss",
            "interval": "epoch",
            "frequency": 1,
            "strict": True,
        },
    }

Log that exact key on every scheduled validation pass. Align scheduler frequency with check_val_every_n_epoch; the bundled template assumes validation every epoch. ReduceLROnPlateau no longer accepts verbose. For a per-step scheduler, set interval="step"; trainer.estimated_stepping_batches includes accumulation and is useful for OneCycleLR(total_steps=...).

Multiple optimizers require self.automatic_optimization = False. An illustrative manual step for one of them is:

opt_g, opt_d = self.optimizers()
self.toggle_optimizer(opt_g)
opt_g.zero_grad()
g_loss = self.generator_loss(batch)
self.manual_backward(g_loss)
self.clip_gradients(opt_g, gradient_clip_val=1.0, gradient_clip_algorithm="norm")
opt_g.step()
self.untoggle_optimizer(opt_g)
# Compute a fresh discriminator loss and repeat with opt_d.

Manual optimization owns zeroing, backward, stepping, accumulation, clipping, and scheduler steps. Trainer automatic-optimization settings do not implement those operations for you. Use Lightning's optimizer wrappers and manual_backward to preserve precision/strategy integration.

Raw lines 30 to 75
76## Metrics and gradients
78For a per-example mean, specify its batch size:
80```python
81self.log("val/loss", loss, on_step=False, on_epoch=True,
82 batch_size=y.size(0), sync_dist=True)
83```
85Lightning weights batch means by sample count. `sync_dist` defaults to false;
86all ranks must call a synchronized log in the same order. A global AUROC/F1 is
87not the average of batch or rank AUROC/F1 values: use independent train/val/test
88TorchMetrics instances and log the metric object. See [logging](logging.md).
90`on_after_backward` sees scaled FP16 gradients before unscaling. Inspect unscaled
91gradients in `on_before_optimizer_step(self, optimizer)`, after accumulation.
92For logging, compute norms without mutating gradients; use Trainer clipping in
93automatic optimization. Calling `clip_grad_norm_` just to inspect norms can
94silently change training, especially before unscaling.

Metrics and gradients

For a per-example mean, specify its batch size:

self.log("val/loss", loss, on_step=False, on_epoch=True,
         batch_size=y.size(0), sync_dist=True)

Lightning weights batch means by sample count. sync_dist defaults to false; all ranks must call a synchronized log in the same order. A global AUROC/F1 is not the average of batch or rank AUROC/F1 values: use independent train/val/test TorchMetrics instances and log the metric object. See logging.

on_after_backward sees scaled FP16 gradients before unscaling. Inspect unscaled gradients in on_before_optimizer_step(self, optimizer), after accumulation. For logging, compute norms without mutating gradients; use Trainer clipping in automatic optimization. Calling clip_grad_norm_ just to inspect norms can silently change training, especially before unscaling.

Raw lines 76 to 95
96## Checkpoint and inference
98Call `save_hyperparameters()` in `__init__`; exclude modules, data, credentials,
99and other unsuitable constructor arguments with `ignore=[...]`. Supply excluded
100arguments explicitly when loading. `current_epoch` is zero based;
101`global_step` counts optimizer steps, not batches.
103```python
104model = TemplateLightningModule.load_from_checkpoint(
105 "checkpoints/last.ckpt", map_location="cpu", weights_only=True,
107model.eval()
108with torch.inference_mode():
109 predictions = model(data)
110```
112This restores the module's parameters and constructor hyperparameters. To resume
113optimizer/scheduler/loop/callback state, use a new Trainer with
114`fit(model, datamodule=dm, ckpt_path=path, weights_only=True)` instead. Do not
115confuse `weights_only=True` (restricted deserialization) with
116`ModelCheckpoint(save_weights_only=True)` (omits training state).
118Lightning 2.6.6 patches checkpoint class/instantiator validation vulnerabilities.
119Still load only provenance-checked checkpoints. Never switch to
120`weights_only=False` merely to bypass an error from an unknown checkpoint.
121Custom checkpoint values should be tensors and simple serializable values when
122using restricted loading.
124Sources: [2.6.6 module API/source](https://github.com/Lightning-AI/pytorch-lightning/blob/2.6.6/src/lightning/pytorch/core/module.py),
125[optimization guide](https://github.com/Lightning-AI/pytorch-lightning/blob/2.6.6/docs/source-pytorch/common/optimization.rst),
126[checkpoint fixes](https://github.com/Lightning-AI/pytorch-lightning/releases/tag/2.6.6).

Checkpoint and inference

Call save_hyperparameters() in __init__; exclude modules, data, credentials, and other unsuitable constructor arguments with ignore=[...]. Supply excluded arguments explicitly when loading. current_epoch is zero based; global_step counts optimizer steps, not batches.

model = TemplateLightningModule.load_from_checkpoint(
    "checkpoints/last.ckpt", map_location="cpu", weights_only=True,
)
model.eval()
with torch.inference_mode():
    predictions = model(data)

This restores the module's parameters and constructor hyperparameters. To resume optimizer/scheduler/loop/callback state, use a new Trainer with fit(model, datamodule=dm, ckpt_path=path, weights_only=True) instead. Do not confuse weights_only=True (restricted deserialization) with ModelCheckpoint(save_weights_only=True) (omits training state).

Lightning 2.6.6 patches checkpoint class/instantiator validation vulnerabilities. Still load only provenance-checked checkpoints. Never switch to weights_only=False merely to bypass an error from an unknown checkpoint. Custom checkpoint values should be tensors and simple serializable values when using restricted loading.

Sources: 2.6.6 module API/source, optimization guide, checkpoint fixes.

Raw lines 96 to 126