Skip to main content

Diagnostic autopsy for PyTorch training runs

Project description

🩻 torchmortem

Diagnostic autopsy for PyTorch training runs.

torchmortem hooks into your PyTorch training loop and produces a "postmortem" diagnostic report telling you why your training might be broken and how to fix it.

If you need full-fledged experiment tracking, hyperparameter sweeps, or collaborative dashboards, this is probably not the right tool. Instead, go look at platforms like Weights & Biases or TensorBoard.

Installation

Install into a virtual environment with uv:

uv venv .venv
source .venv/bin/activate
uv pip install -e ".[dev]"

Or install from PyPI:

pip install torchmortem

Requires Python >=3.10 and PyTorch >=2.0.

Quick Start

from torchmortem import Autopsy

with Autopsy(model, optimizer=optimizer) as autopsy:
    for epoch in range(num_epochs):
        for batch in dataloader:
            loss = model(batch)
            loss.backward()
            optimizer.step()
            autopsy.step(loss=loss.item())

autopsy.report("autopsy_report.html")

How it works

torchmortem is built using a plugin architecture for maximum extensibility.

  • Collectors (implementing Collector in collectors/base.py) attach PyTorch hooks to a model and record raw signals during training.
  • Detectors (implementing Detector in detectors/base.py) analyze the collected signals and return findings.
  • The interpreter (DefaultInterpreter in interpreters/default.py, override-able via the protocol in interpreters/base.py) synthesizes the findings from all detectors by applying the rules defined in interpreters/rules.
  • The interpreter produces human-readable reports using renderers (defined in renderers/).

Built-in feature set

Individual detectors:

  • Vanishing / exploding gradients -- inter-layer gradient ratio analysis
  • Dead units -- persistently inactive neurons (dead ReLU problem)
  • Activation saturation -- sigmoid/tanh layers stuck in flat regions
  • Unhealthy update ratios -- ||update||/||weight|| deviating from ~1e-3
  • Loss dynamics -- catapult phase, edge-of-stability, plateaus, divergence
  • Rank collapse -- representation dimensionality shrinking over training
  • Weight norm pathologies -- explosion, stagnation, inter-layer imbalance
  • Gradient noise -- SNR and batch size efficiency

Cross-signal insights (correlation rules):

  • Gradient starvation -- vanishing gradients + dead units
  • Instability feedback loop -- exploding gradients + weight explosion
  • Representation bottleneck -- rank collapse + loss stagnation
  • Curvature traps -- edge-of-stability + plateau

Report features:

  • Executive summary -- 3-5 sentence assessment with the top recommendation
  • Per-layer health scores -- 0-1 score for each layer, visualized as a heatmap
  • Interactive charts -- loss curve, gradient norms, weight norms, update ratios, dead unit fractions, effective rank
  • Cross-signal insights -- root-cause explanations synthesized from multiple detectors
  • Findings -- each with severity, explanation, affected layers, remediation, and references
  • JSON output -- for CI pipelines and programmatic analysis

Sampling Configuration

Control the overhead/detail tradeoff:

# Presets
Autopsy(model, sampling="thorough")  # max detail
Autopsy(model, sampling="balanced")  # default
Autopsy(model, sampling="fast")      # minimal overhead

# Granular control
from torchmortem import SamplingConfig
Autopsy(model, sampling=SamplingConfig(
    default_interval=1,
    expensive_interval=50,
    overrides={"curvature": 20},
))

Examples

See the examples/ directory:

  • basic_mlp.py -- Deep MLP with sigmoid activations (vanishing gradients, dead units)
  • healthy_resnet.py -- Well-configured residual network
  • transformer_debug.py -- Transformer with high LR and no clipping
  • cnn_overfit.py -- Small CNN that overfits on a toy image dataset
  • lstm_vanishing.py -- Vanilla LSTM with extreme sequence length

Contributing

Contributions are welcome! The plugin architecture aims to make it relatively easy for contributors to add new features. Please refer to CONTRIBUTING.md for guidelines.

Custom detector example

Here is a complete example of a custom detector that flags any layer whose gradient norm exceeds a configurable threshold:

import numpy as np
from torchmortem.registry import register_detector
from torchmortem.types import CollectorState, Finding, RunMetadata, Severity


@register_detector
class LargeGradientDetector:
    """Flags layers where the gradient norm exceeds a fixed threshold."""

    name: str = "large_gradient"
    required_collectors: list[str] = ["gradient"]

    def __init__(self, threshold: float = 100.0) -> None:
        self._threshold = threshold

    def analyze(
        self,
        collector_states: dict[str, CollectorState],
        metadata: RunMetadata,
    ) -> list[Finding]:
        grad_state = collector_states["gradient"]
        norms = grad_state.series.get("grad_norm")
        if norms is None or len(grad_state.steps) == 0:
            return []

        findings: list[Finding] = []
        for idx, layer in enumerate(grad_state.layers):
            layer_norms = norms[:, idx]
            max_norm = float(np.max(layer_norms))
            if max_norm > self._threshold:
                findings.append(Finding(
                    detector=self.name,
                    severity=Severity.WARNING,
                    category="gradient_flow",
                    title=f"Large gradient in {layer}",
                    summary=f"Gradient norm in {layer} reached {max_norm:.1f}, exceeding the {self._threshold:.1f} threshold.",
                    detail=f"The maximum gradient L2 norm observed in {layer} was {max_norm:.1f}. Large gradients can destabilize training and cause weight explosion.",
                    affected_layers=[layer],
                    step_range=(int(grad_state.steps[0]), int(grad_state.steps[-1])),
                    remediation=[
                        "Add gradient clipping (torch.nn.utils.clip_grad_norm_).",
                        "Reduce the learning rate.",
                    ],
                ))
        return findings

The detector will be picked up automatically once the module containing it is imported before the Autopsy context manager is entered.

License

torchmortem is provided under the MIT License.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

torchmortem-0.1.1.tar.gz (111.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

torchmortem-0.1.1-py3-none-any.whl (61.6 kB view details)

Uploaded Python 3

File details

Details for the file torchmortem-0.1.1.tar.gz.

File metadata

  • Download URL: torchmortem-0.1.1.tar.gz
  • Upload date:
  • Size: 111.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for torchmortem-0.1.1.tar.gz
Algorithm Hash digest
SHA256 c4fb64b93c2930e6f2f61cd1885941f3685733db56279c6214e53b2b31f28296
MD5 df3a9b0911bedd036cf5ac085a1c5049
BLAKE2b-256 07ff496213a5a577f8c12aad98fda1ae3dbba101ba2e375e8b6325b29cad2bca

See more details on using hashes here.

Provenance

The following attestation bundles were made for torchmortem-0.1.1.tar.gz:

Publisher: publish.yml on sebseager/torchmortem

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file torchmortem-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: torchmortem-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 61.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for torchmortem-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 4446803434457735917207466a7147ee3e6f3e070c225d479ba4dd82983e73ca
MD5 2cd6d630080285dd5e947fadf40d37d0
BLAKE2b-256 830f8e0d2a0e57a6bd798343cd0b8b3ca6017ad858f38991d433da5120dc9985

See more details on using hashes here.

Provenance

The following attestation bundles were made for torchmortem-0.1.1-py3-none-any.whl:

Publisher: publish.yml on sebseager/torchmortem

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page