autoLRP
A model agnostic PyTorch implementation of Layer-wise Relevance Propagation.
It works at the operation level, so it needs no module rewriting and no module
names: wrap your input in autolrp.tensor(), run the model as it is, pick an
output scalar, and call .lrp(). It follows the philosophy of autograd, hence
autoLRP.
import autolrp
from autolrp import LRPConfig, BASE
x = autolrp.tensor(image) # the input you want relevance for
out = model(x) # run the model unchanged
out[0, pred].lrp() # relevance of class `pred`
heatmap = x.relevance # same shape as `image`
pip install autolrp
Examples
Every figure below is produced by a notebook in
examples/showcase. The input is wrapped, the model runs
untouched, and .lrp() fills .relevance.
Image classification (VGG-16, ViT-B/16)
The same image through a CNN and a vision transformer: relevance on the pixels that drive the tiger shark class, from the same three lines of code.
Next-token prediction (GPT-2)
Which context tokens drive the next word.
Notebook: GPT-2
Sentiment (BERT)
Which words carry the sentiment decision.
Notebook: BERT sentiment
Image similarity (BiLRP)
Beyond single predictions: decompose the dot-product similarity of two VGG-16 embeddings into the patch pairs that make the images look alike. Red pairs support the similarity, blue pairs oppose it.
Notebook: BiLRP
Contrastive attribution (CLRP)
Separating two classes present in one image. Plain LRP for zebra and elephant highlights both animals; CLRP subtracts the shared evidence so each target keeps only what is distinctive to it.
Notebook: CLRP
Attention rule variant (CP-LRP)
One keyword changes how attention is propagated. attn='cplrp' treats the
attention weights as constants (Ali et al. 2022) instead of propagating through
them.
out[0, pred].lrp(config=LRPConfig(attn='cplrp'))
Notebook: attention presets
How it works
.lrp() never rewrites your model. It works on the autograd graph the forward
pass already built:
- wrap.
autolrp.tensor(x)marks the input. A handful of ops (add,sum,softmax, fused attention, and a few more) are replaced by versions that save the activations the rules need. Gradients stay native, so the graph is otherwise unchanged. - walk. After the forward pass, the autograd graph is traversed into an ordered plan of nodes.
- analyze. Analyzers tag nodes with facts, for example which operand of an attention product is the softmax weights.
- resolve. Each node gets one rule, chosen by the config from a fact on the node when it has one, otherwise from the node name.
- backward. One
backwardpass runs those rules as hooks that turn the incoming gradient into relevance. Whatever reaches the wrapped input isx.relevance.
Configuration
Every rule-bearing node is addressed by its autograd name without the version
digit, or by a fact an analyzer attached to it. BASE is the starting table:
>>> print(BASE)
{'AddmmBackward': 'epsilon', 'MmBackward': 'epsilon', 'ConvolutionBackward': 'epsilon',
'BmmBackward': 'epsilon', 'MulBackward': 'proportional', 'DivBackward': 'proportional',
'AddBackward': 'proportional', 'SubBackward': 'proportional',
'statistic_operand': ('detach', {'by': 'statistic_operand'})}
Override entries on it, or use a preset:
LRPConfig(rule={**BASE, 'AddmmBackward': 'zplus'})
LRPConfig(rule={**BASE, 'ConvolutionBackward': ('gamma', {'gamma': 0.25})})
LRPConfig.composite() # z+ on conv, epsilon elsewhere
LRPConfig(attn='attnlrp') # epsilon products, Jacobian softmax
LRPConfig(attn='cplrp') # attention weights treated as constants
LRPConfig(attn='uniform')
The config says exactly what runs. A key that is not a node name or a registered fact, a rule the key's family cannot run, and a node that no entry addresses are all errors:
LRPConfig(rule={**BASE, 'linear': 'zplus'})
ValueError: unknown rule key 'linear': not a node name [...]
LRPConfig(rule={**BASE, 'MulBackward': 'zbox'})
ValueError: rule entry 'MulBackward'='zbox': 'zbox' is not a choice here. Choices: [...]
Rule tables, by family:
| family | node names | rules |
|---|---|---|
| linear | AddmmBackward, MmBackward, ConvolutionBackward |
epsilon, zplus, gamma, gamma_montavon, alpha_beta, zbox |
| bilinear | BmmBackward |
epsilon, uniform, detach_lhs, detach_rhs |
| product | MulBackward, DivBackward |
proportional, detach_lhs, detach_rhs |
| sum | AddBackward, SubBackward |
proportional, equal, fixed, detach_lhs, detach_rhs |
Citing
If you use autoLRP in your research, please cite it:
@software{alasad2026autolrp,
author = {Alasad, Waleed},
title = {autoLRP: Layer-wise Relevance Propagation on the PyTorch autograd graph},
year = {2026},
version = {0.1.2},
url = {https://github.com/Wa-lead/autoLRP}
}
License
autoLRP is released under the MIT License. See LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file autolrp-0.1.2.tar.gz.
File metadata
- Download URL: autolrp-0.1.2.tar.gz
- Upload date:
- Size: 82.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
053e424e076e3125736a87b52d3aa78e9c71cd998c5c32ce1a11c47758b0f66c
|
|
| MD5 |
9a664f6225df8429fc82432d712d3c4a
|
|
| BLAKE2b-256 |
674b58cb19bee73b46bbd145c6f991dcf267d3902d5fb0f02f35e0c727274240
|
File details
Details for the file autolrp-0.1.2-py3-none-any.whl.
File metadata
- Download URL: autolrp-0.1.2-py3-none-any.whl
- Upload date:
- Size: 60.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e862fe88327c780aa02299b77b52febc592a9a82542c8b054e8e32da1476d1ec
|
|
| MD5 |
7331865c3da827d63fa5791a5d52f542
|
|
| BLAKE2b-256 |
6bb64b215017817ebeb5173f900817dfe060dcf1664ace60860013c2ecf54b54
|