Self-hosted service
catalyst-team/catalyst avatar
catalyst-team/catalyst

Catalyst: a PyTorch runner that replaces the training loop you keep rewriting

Accelerated deep learning R&D

3,384 stars397 forksPythonApache-2.0

At a glance

What is it?
Catalyst is a PyTorch framework built around reproducibility and codebase reuse, with a SupervisedRunner that owns the train, evaluate and predict cycle. It fits teams that run many similar experiments; it is a poor fit if you need the latest PyTorch features on day one, since the newest tagged release is v22.04 from April 2022.
Who is it for?
Adopt Catalyst if you are running many structurally similar PyTorch experiments and are tired of maintaining a bespoke train loop: the README's own pitch is that you should 'create something new rather than write yet another train loop'. Do not adopt it if you depend on the newest PyTorch APIs, since the latest tagged release is v22.04 (April 2022) and the repository's last push is dated 2026-07-08, a gap you should treat as a signal rather than a guarantee.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 69 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem Catalyst targets: the training loop you write for the fifth time

Every PyTorch project starts with a loop over epochs and batches, and every project ends up with a slightly different version of it. Logging gets bolted on, then checkpointing, then metric aggregation, then mixed-precision, then the validation pass that has to run at a different cadence from training. Catalyst's stated focus is reproducibility, rapid experimentation and codebase reuse, and the README frames the goal bluntly: create something new rather than write yet another train loop. The intended audience is research and R&D teams that run many experiments over similar model families, where the loop is infrastructure rather than the contribution. If your project has exactly one model and one training script that you run once, the abstraction buys you nothing and costs you a layer of indirection between your code and PyTorch.

SupervisedRunner and the dl namespace: the actual mechanism

The entry point in the README example is dl.SupervisedRunner, constructed with four string keys: input_key="features", output_key="logits", target_key="targets" and loss_key="loss". Those keys are the contract between your model and the runner. The runner calls your model, reads the output under output_key, compares it against target_key using criterion, and records the scalar under loss_key. Everything else is delegated to callbacks passed to runner.train, such as dl.AccuracyCallback with topk=(1, 3, 5) and dl.PrecisionRecallF1SupportCallback. The same runner object then handles evaluation through evaluate_loader, streaming inference through predict_loader (the README iterates it and asserts the logits have ten columns), and post-processing through utils.trace_model, utils.quantize_model, utils.prune_model and utils.onnx_export. The design keeps the experiment definition declarative and pushes behaviour into callback objects, which is what makes the same script reusable across datasets and model heads. The cost is that the data flow is implicit: when a metric comes out wrong, the bug is often a key mismatch between your model's forward return and the runner's output_key, not a logic error in a loop you can read top to bottom.

Getting it running: install, the MNIST example, and the keys that must line up

Installation is a single command from the README: pip install -U catalyst. The README's minimal example builds an nn.Sequential with nn.Flatten and nn.Linear(28 * 28, 10), CrossEntropyLoss, Adam at lr=0.02, and a loaders dict with "train" and "valid" entries built from catalyst.contrib.datasets.MNIST. The train call takes model, criterion, optimizer, loaders, num_epochs, callbacks, logdir="./logs", valid_loader="valid", valid_metric="loss", minimize_valid_metric=True and verbose=True. Note the valid_loader and valid_metric pair: the runner needs to know which loader to score and which metric direction counts as improvement, and minimize_valid_metric=True is what tells it that lower loss is better. The README also lists working Python versions 3.6, 3.7 and 3.8, plus Linux, OSX and WSL, which is a narrower support matrix than current PyTorch users may expect. The import line from catalyst import dl, utils is the whole public surface you need for the example; contrib is a separate namespace for datasets and other extras.

Where the abstraction leaks: key mismatches, version drift and callback sprawl

The runner model is only as good as the naming contract around it. If your model returns a dict, a tuple, or a bare tensor, you have to reshape it into something the configured output_key can address, and the README example sidesteps this by using a plain nn.Sequential that returns a tensor. Teams with multi-head models, auxiliary losses or custom sampling logic will spend time writing adapters, and that work is not obviously less than writing the loop. The second limitation is version drift. The most recent tagged release is v22.04, dated 2022-04-29, preceded by v22.02.1 and v22.02. The repository shows a last push of 2026-07-08, which indicates activity after the last tag, but a four-year gap between releases and the current date means you should not assume the framework tracks recent PyTorch changes. Verify against your installed torch version before planning around it. Third, callbacks accumulate: the README example already stacks two metric callbacks, and larger projects can end up with a long callback list whose interaction order matters and is not obvious from the train call alone.

Catalyst against plain PyTorch and PyTorch Lightning

The honest alternative for many teams is no framework at all. A hand-written loop is maybe sixty lines, and you can read every step. Catalyst's return on that investment appears when the same loop has to serve several models, several datasets and a shared metric suite, because the loop is written once and the variation moves into callbacks and config. The closer comparison is PyTorch Lightning, which also owns the training loop but organizes the code around a LightningModule: you subclass it and implement training_step, validation_step and configure_optimizers. Catalyst keeps your model as a plain nn.Module and puts the wiring in the runner plus callbacks, so the model file stays framework-agnostic and can be reused outside Catalyst. That is a real difference in approach, not a cosmetic one. If you want the training logic to live inside the model class, Lightning's shape will feel natural. If you want the model untouched and the experiment described externally, Catalyst's shape is the closer match.

Maintenance, release cadence and the Apache-2.0 licence

Catalyst is licensed Apache-2.0, which permits commercial and closed-source use and includes an explicit patent grant from contributors. That is the permissive end of the spectrum and requires no source disclosure from you; it also means you are not obliged to contribute changes back. The practical maintenance question is cadence. Three releases are listed, all from 2022, with v22.04 as the newest. The last push timestamp is 2026-07-08, so the repository is not archived and shows some activity, but the tagged-release history does not show a comparable recent release. For a dependency that sits underneath your training code, that distinction matters: an active default branch is not the same as a maintained release line. If you adopt Catalyst, plan to pin the version in your requirements and to test upgrades deliberately rather than tracking the branch. This is a description of the licence terms as stated in the repository metadata, not legal advice; review Apache-2.0 against your own distribution model if you ship modified copies.

Who should pick this up, and what to check before you do

Catalyst makes sense for a team that already has several PyTorch projects with near-identical training structure and wants one runner plus a callback library to cover metrics, checkpointing and export. The README's post-processing utilities (trace_model, quantize_model, prune_model, onnx_export) are a genuine convenience if you need those steps, since they are one call each from the same runner object you trained with. It makes less sense for a single-model research spike, for a codebase that needs PyTorch features added after 2022, or for a team that prefers the training logic to live inside the model class. The concrete checks before adopting: confirm pip install -U catalyst resolves on your Python version, run the README's MNIST example unchanged and confirm the runner accepts your key names, and confirm that the callbacks you rely on exist in dl rather than only in contrib. If the MNIST example runs and your model's output keys fit the runner's contract, the rest of the framework is a matter of how much you want to move into callbacks.

Editorial conclusion

Adopt Catalyst if you are running many structurally similar PyTorch experiments and are tired of maintaining a bespoke train loop: the README's own pitch is that you should 'create something new rather than write yet another train loop'. Do not adopt it if you depend on the newest PyTorch APIs, since the latest tagged release is v22.04 (April 2022) and the repository's last push is dated 2026-07-08, a gap you should treat as a signal rather than a guarantee. Before committing, verify three things against your own environment: that pip install -U catalyst resolves on your Python version, that dl.SupervisedRunner.train accepts your model's input_key, output_key and target_key naming without an adapter, and that the callbacks you need exist in the dl namespace rather than only in contrib.

Official sources

  1. catalyst-team/catalyst on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Community notes

Community notes