torchlight
Torch Light: a lightweight companion for PyTorch.
torchlight gives you a small, readable training loop plus the extras you end
up rewriting in every project: callbacks, metrics, early stopping,
checkpointing and seeding/device helpers. It is a few hundred lines of plain
PyTorch with no other dependencies, so you can read all of it in one sitting.
When you outgrow it, copy the parts you need.
Features
Trainer:fit/evaluate/predictover any iterable of(inputs, targets)batches, with automatic device placement (including nested dicts, lists and tuples), optional gradient-norm clipping, and a per-epochhistory.- Callbacks: hook into fit start, epoch start, batch end, epoch end and
fit end. Built in:
EarlyStopping(withrestore_best_weights),ModelCheckpoint(best-only or every epoch, templated filenames), andPrintLogger. - Metrics: accumulate-then-compute
Accuracy(multi-class logits or binary thresholds) andMeanAbsoluteError. SubclassMetricto add your own. - Checkpoints:
save_checkpoint/load_checkpointfor model and optimizer state plus any extra values. - Utilities:
seed_everything,get_device,to_device,count_parameters.
Install
pip install torchlight
torch>=2.0 is the only dependency. To use the CPU-only PyTorch build, install
it first, for example
pip install torch --index-url https://download.pytorch.org/whl/cpu.
From a source checkout:
python -m venv .venv
.venv/bin/pip install torch --index-url https://download.pytorch.org/whl/cpu
.venv/bin/pip install -e ".[test]"
.venv/bin/python -m pytest
Quickstart
import torch
from torch import nn
from torch.utils.data import DataLoader, TensorDataset
import torchlight as tl
tl.seed_everything(42)
# Synthetic two-class data
x = torch.randn(512, 2)
y = (x[:, 0] + x[:, 1] > 0).long()
train = DataLoader(TensorDataset(x[:400], y[:400]), batch_size=32, shuffle=True)
val = DataLoader(TensorDataset(x[400:], y[400:]), batch_size=64)
model = nn.Sequential(nn.Linear(2, 16), nn.ReLU(), nn.Linear(16, 2))
trainer = tl.Trainer(
model,
optimizer=torch.optim.Adam(model.parameters(), lr=1e-2),
loss_fn=nn.CrossEntropyLoss(),
metrics={"accuracy": tl.Accuracy()},
callbacks=[
tl.EarlyStopping(monitor="val_loss", patience=3, restore_best_weights=True),
tl.ModelCheckpoint("checkpoints/best.pt", monitor="val_accuracy", mode="max"),
tl.PrintLogger(),
],
)
history = trainer.fit(train, val, epochs=20)
print(history["val_accuracy"][-1])
print(trainer.evaluate(val)) # {'loss': ..., 'accuracy': ...}
probs = trainer.predict(val).softmax(dim=1)
# Later: restore the best checkpoint
ckpt = tl.load_checkpoint("checkpoints/best.pt", model)
print(ckpt["epoch"], ckpt["logs"])
API overview
Everything below is importable from the top-level torchlight package.
Trainer
Trainer(model, optimizer, loss_fn, metrics=None, callbacks=None, device=None, grad_clip=None)
| Member | Description |
|---|---|
fit(train_loader, val_loader=None, epochs=1) -> dict[str, list[float]] |
Train for up to epochs epochs and return history. Logs loss and each metric name; with val_loader, also val_loss and val_<metric>. |
evaluate(loader) -> dict[str, float] |
Loss and metrics under torch.no_grad(), in eval mode, with no val_ prefix. |
predict(loader) -> torch.Tensor |
Model outputs concatenated on the CPU. Batches may be (inputs, targets) or bare inputs. |
history |
dict[str, list[float]] of per-epoch values. |
should_stop |
Set to True (usually from a callback) to stop after the current epoch. |
model, optimizer, loss_fn, metrics, callbacks, device, grad_clip, epochs |
The configured objects. epochs is the value passed to the latest fit. |
Batches must be (inputs, targets) pairs. inputs goes straight to
model(inputs), and both halves are moved to trainer.device. The loss is
averaged over samples, with each batch weighted by its size. device
defaults to get_device().
Callbacks
class Callback:
def on_fit_start(self, trainer): ...
def on_epoch_start(self, trainer, epoch): ... # epoch is 0-based
def on_batch_end(self, trainer, batch_idx, loss): ... # loss is a float
def on_epoch_end(self, trainer, epoch, logs): ... # logs: dict[str, float]
def on_fit_end(self, trainer): ... # also runs after an early stop
EarlyStopping(monitor="val_loss", patience=3, mode="min", min_delta=0.0, restore_best_weights=False)setstrainer.should_stopafterpatienceepochs without improvement. Attributes:best,best_epoch,wait,stopped_epoch.ModelCheckpoint(path, monitor="val_loss", mode="min", save_best_only=True)writessave_checkpoint(path, model, optimizer, epoch=..., logs=...).pathmay use{epoch}and any log key as format fields, e.g."ckpt/ep{epoch:02d}-{val_loss:.3f}.pt". Attributes:best,best_path.PrintLogger(precision=4)printsepoch 3/10 loss=0.1234 val_loss=....
If a monitored key is missing from the epoch logs (for example val_loss
without a val_loader), the callback raises KeyError.
Metrics
class Metric:
def update(self, preds, targets) -> None: ...
def compute(self) -> float: ...
def reset(self) -> None: ...
Accuracy(threshold=0.5): usesargmax(dim=1)whenpredshas one more dimension thantargets. Otherwisepreds >= threshold; usethreshold=0.0for raw binary logits.MeanAbsoluteError():predsandtargetsmust have the same shape.Mean(): weighted running mean,update(value, weight=1). The trainer uses it for the loss.
compute() returns nan if nothing has been accumulated.
Checkpoints
save_checkpoint(path, model, optimizer=None, **extra) -> pathlib.Pathsaves{"model": ..., "optimizer": ... or None, **extra}and creates parent directories.load_checkpoint(path, model, optimizer=None, map_location="cpu") -> dictloads weights (and optimizer state, if both are present) in place and returns the full dict. It usestorch.load(..., weights_only=True).
Utilities
seed_everything(seed, deterministic=False) -> intseedsrandom, NumPy (if installed) and torch (CPU and CUDA).get_device(prefer=None) -> torch.devicereturnspreferif given, otherwise the first available of CUDA, MPS and CPU.to_device(data, device)recursively moves tensors in dicts, lists, tuples and named tuples.count_parameters(model, trainable_only=True) -> int.
License
MIT
Metadata
Release files for torchlight 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| torchlight-0.1.0.tar.gz | 14.2 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| torchlight-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 28.0 kB
Release files / torchlight-0.1.0.tar.gz
| Download URL | torchlight-0.1.0.tar.gz |
|---|---|
| Size | 14.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
da534edfe29fe93bdd4f09da7c864ffc751b2d906bf759c3b461e1a4bb8960a0
|
|
BLAKE2b-256 checksum How to use checksums |
1e3258c476f328e3e1d191ebf11af9c4bfb5459991a2e85af4dd88006abf63da
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.5
|
Release files / torchlight-0.1.0-py3-none-any.whl
| Download URL | torchlight-0.1.0-py3-none-any.whl |
|---|---|
| Size | 13.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
00aaa22fb6caa9ac2eaae2b01e4e438bef089974961bc9f850002b33dde59e1a
|
|
BLAKE2b-256 checksum How to use checksums |
32f92c5c8ea0ca946f29536129c712dbe69f9add3647319187572f625c06f93d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.5
|
Security for torchlight 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.