autoLRP 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. autolrp-0.1.0/LICENSE +21 -0
  2. autolrp-0.1.0/PKG-INFO +207 -0
  3. autolrp-0.1.0/README.md +176 -0
  4. autolrp-0.1.0/autoLRP/__init__.py +55 -0
  5. autolrp-0.1.0/autoLRP/backward/__init__.py +5 -0
  6. autolrp-0.1.0/autoLRP/backward/analysis.py +423 -0
  7. autolrp-0.1.0/autoLRP/backward/engine.py +299 -0
  8. autolrp-0.1.0/autoLRP/backward/install.py +850 -0
  9. autolrp-0.1.0/autoLRP/backward/lrp_utils.py +353 -0
  10. autolrp-0.1.0/autoLRP/backward/resolve.py +51 -0
  11. autolrp-0.1.0/autoLRP/backward/rules.py +294 -0
  12. autolrp-0.1.0/autoLRP/backward/strategies.py +288 -0
  13. autolrp-0.1.0/autoLRP/compat.py +54 -0
  14. autolrp-0.1.0/autoLRP/config.py +284 -0
  15. autolrp-0.1.0/autoLRP/eval.py +357 -0
  16. autolrp-0.1.0/autoLRP/forward/__init__.py +3 -0
  17. autolrp-0.1.0/autoLRP/forward/intercept.py +511 -0
  18. autolrp-0.1.0/autoLRP/forward/ops.py +176 -0
  19. autolrp-0.1.0/autoLRP/recipes.py +150 -0
  20. autolrp-0.1.0/autoLRP/tensor.py +111 -0
  21. autolrp-0.1.0/autoLRP/utils.py +21 -0
  22. autolrp-0.1.0/autoLRP.egg-info/PKG-INFO +207 -0
  23. autolrp-0.1.0/autoLRP.egg-info/SOURCES.txt +40 -0
  24. autolrp-0.1.0/autoLRP.egg-info/dependency_links.txt +1 -0
  25. autolrp-0.1.0/autoLRP.egg-info/requires.txt +9 -0
  26. autolrp-0.1.0/autoLRP.egg-info/top_level.txt +1 -0
  27. autolrp-0.1.0/pyproject.toml +41 -0
  28. autolrp-0.1.0/setup.cfg +4 -0
  29. autolrp-0.1.0/tests/test_addressing.py +343 -0
  30. autolrp-0.1.0/tests/test_config.py +250 -0
  31. autolrp-0.1.0/tests/test_conservation.py +242 -0
  32. autolrp-0.1.0/tests/test_eval.py +258 -0
  33. autolrp-0.1.0/tests/test_explain.py +71 -0
  34. autolrp-0.1.0/tests/test_integration.py +214 -0
  35. autolrp-0.1.0/tests/test_loud_fallback.py +43 -0
  36. autolrp-0.1.0/tests/test_modes.py +109 -0
  37. autolrp-0.1.0/tests/test_ops.py +266 -0
  38. autolrp-0.1.0/tests/test_parity.py +183 -0
  39. autolrp-0.1.0/tests/test_recipes.py +192 -0
  40. autolrp-0.1.0/tests/test_registration_api.py +40 -0
  41. autolrp-0.1.0/tests/test_rules.py +520 -0
  42. autolrp-0.1.0/tests/test_strategies.py +228 -0
autolrp-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Waleed Alasad
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
autolrp-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,207 @@
1
+ Metadata-Version: 2.4
2
+ Name: autoLRP
3
+ Version: 0.1.0
4
+ Summary: Layer-wise relevance propagation on the PyTorch autograd graph
5
+ Author: Waleed Alasad
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/Wa-lead/autoLRP
8
+ Project-URL: Repository, https://github.com/Wa-lead/autoLRP
9
+ Keywords: lrp,layer-wise-relevance-propagation,explainability,xai,interpretability,attribution,pytorch
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Requires-Python: >=3.9
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: torch>=2.1
24
+ Requires-Dist: numpy
25
+ Provides-Extra: test
26
+ Requires-Dist: pytest; extra == "test"
27
+ Requires-Dist: pytest-randomly; extra == "test"
28
+ Provides-Extra: parity
29
+ Requires-Dist: zennit; extra == "parity"
30
+ Dynamic: license-file
31
+
32
+ <p align="center">
33
+ <picture>
34
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/Wa-lead/autoLRP/main/assets/autolrp-lockup-dark.png">
35
+ <img src="https://raw.githubusercontent.com/Wa-lead/autoLRP/main/assets/autolrp-lockup-light.png" alt="autoLRP" width="360">
36
+ </picture>
37
+ </p>
38
+
39
+ # autoLRP
40
+
41
+ Layer-wise relevance propagation on the PyTorch autograd graph. No
42
+ model rewriting, no module names: wrap the input, run the model as it
43
+ is, pick the output scalar, call `.lrp()`.
44
+
45
+ ```python
46
+ import torch.nn as nn
47
+ import autoLRP
48
+ from autoLRP import LRPConfig, BASE
49
+
50
+ x = autoLRP.tensor(image) # the input you want relevance for
51
+ out = model(x)
52
+ out[0, pred].lrp() # relevance of class `pred`
53
+ heatmap = x.relevance # same shape as `image`
54
+ ```
55
+
56
+ ## How it works
57
+
58
+ `autoLRP.tensor` returns a tensor subclass. While the model runs, a
59
+ few ops are replaced by our own (`add`, `sub`, `mean`, `sum`, `cumsum`,
60
+ `softmax`, fused attention) so that the backward graph keeps the values
61
+ the rules need; their gradients are the native ones, so the graph is
62
+ otherwise unchanged. `.lrp()` walks the autograd graph, attaches a
63
+ label ("fact") to some nodes (for example, which operand of a product
64
+ is the softmax weights), installs one hook per node that turns the
65
+ arriving gradient into relevance, and runs `backward`. Whatever reaches
66
+ the wrapped input is its relevance.
67
+
68
+ ## Configuration
69
+
70
+ Every rule-bearing node is addressed by its autograd name without the
71
+ version digit, or by a fact an analyzer attached to it. `BASE` is the
72
+ starting table:
73
+
74
+ ```python
75
+ >>> print(BASE)
76
+ {'AddmmBackward': 'epsilon', 'MmBackward': 'epsilon', 'ConvolutionBackward': 'epsilon',
77
+ 'BmmBackward': 'epsilon', 'MulBackward': 'proportional', 'DivBackward': 'proportional',
78
+ 'AddBackward': 'proportional', 'SubBackward': 'proportional',
79
+ 'statistic_operand': ('detach', {'by': 'statistic_operand'})}
80
+ ```
81
+
82
+ Override entries on it, or use a preset:
83
+
84
+ ```python
85
+ LRPConfig(rule={**BASE, 'AddmmBackward': 'zplus'})
86
+ LRPConfig(rule={**BASE, 'ConvolutionBackward': ('gamma', {'gamma': 0.25})})
87
+ LRPConfig.composite() # z+ on conv, epsilon elsewhere
88
+ LRPConfig(attn='attnlrp') # epsilon products, Jacobian softmax
89
+ LRPConfig(attn='cplrp') # attention weights treated as constants
90
+ LRPConfig(attn='uniform')
91
+ ```
92
+
93
+ The config says exactly what runs. A key that is not a node name or a
94
+ registered fact, a rule the key's family cannot run, and a node that
95
+ no entry addresses are errors:
96
+
97
+ ```
98
+ LRPConfig(rule={**BASE, 'linear': 'zplus'})
99
+ ValueError: unknown rule key 'linear': not a node name [...]
100
+ LRPConfig(rule={**BASE, 'MulBackward': 'zbox'})
101
+ ValueError: rule entry 'MulBackward'='zbox': 'zbox' is not a choice here. Choices: [...]
102
+ ```
103
+
104
+ Rule tables, by family:
105
+
106
+ | family | node names | rules |
107
+ | --- | --- | --- |
108
+ | linear | `AddmmBackward`, `MmBackward`, `ConvolutionBackward` | `epsilon`, `zplus`, `gamma`, `gamma_montavon`, `alpha_beta`, `zbox` |
109
+ | bilinear | `BmmBackward` | `epsilon`, `uniform`, `detach_lhs`, `detach_rhs` |
110
+ | product | `MulBackward`, `DivBackward` | `proportional`, `detach_lhs`, `detach_rhs` |
111
+ | sum | `AddBackward`, `SubBackward` | `proportional`, `equal`, `fixed`, `detach_lhs`, `detach_rhs` |
112
+
113
+ Names are positional: `detach_lhs` zeros the operand written on the
114
+ left of that op, always. The one virtual name `'detach'` takes
115
+ `by=<fact>` and picks the side per node from the fact's value.
116
+
117
+ Which family a product node belongs to is decided by which of its
118
+ operands come from the wrapped input, not by its name. One operand:
119
+ the op is a linear layer whose weight is the other operand (a constant,
120
+ a parameter, or any tensor you did not wrap). Two: the op is bilinear.
121
+ Frozen models (`requires_grad=False`) work like trainable ones.
122
+
123
+ Softmax, layer norm and activation nodes are set by their own fields:
124
+ `softmax=` (`passthrough`, `jacobian`, `detach`), `layernorm=`
125
+ (`identity`, `passthrough`, `yx`, `detach_std`), `activation=`
126
+ (`passthrough`, `yx`).
127
+
128
+ ## Reading back what ran
129
+
130
+ `explain` installs the hooks, records the config entry and the rule
131
+ function at every node, removes the hooks again, and runs no backward.
132
+ `explain_summary` prints one line per distinct combination:
133
+
134
+ ```python
135
+ from autoLRP import explain, explain_summary
136
+ rows = explain(model(autoLRP.tensor(x))[0, pred], LRPConfig(attn='cplrp'))
137
+ print(explain_summary([r for r in rows if r[2] != 'native gradient']))
138
+ ```
139
+
140
+ ```
141
+ count node key what
142
+ 4 AddmmBackward0 AddmmBackward epsilon
143
+ 2 AddBackward AddBackward residual_proportional
144
+ 2 NativeLayerNormBackward0 None layernorm=identity
145
+ 1 BmmBackward0 weights_operand detach_lhs_bmm
146
+ 1 BmmBackward0 BmmBackward epsilon_bmm
147
+ 1 DivBackward0 None passthrough (constant operand)
148
+ 1 SoftmaxBackward None softmax=passthrough
149
+ ```
150
+
151
+ `key` is the entry that addressed the node, `what` the function it
152
+ picked; `native gradient` rows are shape ops, where the gradient is
153
+ already the routing.
154
+
155
+ ## Facts and your own analyzers
156
+
157
+ Built-in facts: `statistic_operand` (the normalization statistic in a
158
+ mul, div or sub, detached by `BASE`), `weights_operand` (the softmax
159
+ weights in a bmm), `input_conv` (the first convolution). An analyzer is
160
+ a function over all nodes that returns the nodes carrying its fact; its
161
+ registered name is the config key. The value is the fact's value:
162
+ `True` for a plain tag, a slot number (0 or 1) for a side that a
163
+ `('detach', {'by': ...})` entry can read:
164
+
165
+ ```python
166
+ from autoLRP import register_analyzer
167
+
168
+ @register_analyzer('first_linear')
169
+ def first_linear(nodes):
170
+ hits = [n for n in nodes if 'AddmmBackward' in n.name()]
171
+ return {hits[-1]: True} if hits else {}
172
+
173
+ LRPConfig(rule={**BASE, 'first_linear': ('zbox', {'low': -3.0, 'high': 3.0})})
174
+ ```
175
+
176
+ ## Conventions worth knowing
177
+
178
+ - A constant that multiplies, divides or negates passes relevance
179
+ through unchanged. A constant that is added is a bias, and a bias
180
+ absorbs its share (`apply_bias_split`), so a layer with a bias emits
181
+ less than it receives.
182
+ - Fused `scaled_dot_product_attention` is decomposed into
183
+ matmul, softmax, matmul by default; `set_decompose_attention(False)`
184
+ keeps the fused node, which is handled by its own installer and gives
185
+ the same relevance to 1e-13.
186
+ - An op with no installer runs its native gradient and warns once,
187
+ if it lies on the path to the wrapped input.
188
+ - `BASE` with the default `eps=1e-11` is LRP-0; on deep networks it
189
+ can be numerically unstable, and the recipes (`composite`, gamma,
190
+ z+) are what to use there.
191
+
192
+ ## Recipes and evaluation
193
+
194
+ `autoLRP.bilrp(model, x_a, x_b)` (second-order, similarity models),
195
+ `autoLRP.clrp(...)` (contrastive), and `autoLRP.eval` with
196
+ `perturbation_curve`, `aopc`, `sanity_check_cascade`,
197
+ `sensitivity_correlation`.
198
+
199
+ ## Tests
200
+
201
+ ```
202
+ python -m pytest -q
203
+ ```
204
+
205
+ 352 tests; two modules skip without `zennit` and the examples file.
206
+ The notebooks under `examples/showcase` are the showcases; the four in
207
+ `extras/` run without downloads.
@@ -0,0 +1,176 @@
1
+ <p align="center">
2
+ <picture>
3
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/Wa-lead/autoLRP/main/assets/autolrp-lockup-dark.png">
4
+ <img src="https://raw.githubusercontent.com/Wa-lead/autoLRP/main/assets/autolrp-lockup-light.png" alt="autoLRP" width="360">
5
+ </picture>
6
+ </p>
7
+
8
+ # autoLRP
9
+
10
+ Layer-wise relevance propagation on the PyTorch autograd graph. No
11
+ model rewriting, no module names: wrap the input, run the model as it
12
+ is, pick the output scalar, call `.lrp()`.
13
+
14
+ ```python
15
+ import torch.nn as nn
16
+ import autoLRP
17
+ from autoLRP import LRPConfig, BASE
18
+
19
+ x = autoLRP.tensor(image) # the input you want relevance for
20
+ out = model(x)
21
+ out[0, pred].lrp() # relevance of class `pred`
22
+ heatmap = x.relevance # same shape as `image`
23
+ ```
24
+
25
+ ## How it works
26
+
27
+ `autoLRP.tensor` returns a tensor subclass. While the model runs, a
28
+ few ops are replaced by our own (`add`, `sub`, `mean`, `sum`, `cumsum`,
29
+ `softmax`, fused attention) so that the backward graph keeps the values
30
+ the rules need; their gradients are the native ones, so the graph is
31
+ otherwise unchanged. `.lrp()` walks the autograd graph, attaches a
32
+ label ("fact") to some nodes (for example, which operand of a product
33
+ is the softmax weights), installs one hook per node that turns the
34
+ arriving gradient into relevance, and runs `backward`. Whatever reaches
35
+ the wrapped input is its relevance.
36
+
37
+ ## Configuration
38
+
39
+ Every rule-bearing node is addressed by its autograd name without the
40
+ version digit, or by a fact an analyzer attached to it. `BASE` is the
41
+ starting table:
42
+
43
+ ```python
44
+ >>> print(BASE)
45
+ {'AddmmBackward': 'epsilon', 'MmBackward': 'epsilon', 'ConvolutionBackward': 'epsilon',
46
+ 'BmmBackward': 'epsilon', 'MulBackward': 'proportional', 'DivBackward': 'proportional',
47
+ 'AddBackward': 'proportional', 'SubBackward': 'proportional',
48
+ 'statistic_operand': ('detach', {'by': 'statistic_operand'})}
49
+ ```
50
+
51
+ Override entries on it, or use a preset:
52
+
53
+ ```python
54
+ LRPConfig(rule={**BASE, 'AddmmBackward': 'zplus'})
55
+ LRPConfig(rule={**BASE, 'ConvolutionBackward': ('gamma', {'gamma': 0.25})})
56
+ LRPConfig.composite() # z+ on conv, epsilon elsewhere
57
+ LRPConfig(attn='attnlrp') # epsilon products, Jacobian softmax
58
+ LRPConfig(attn='cplrp') # attention weights treated as constants
59
+ LRPConfig(attn='uniform')
60
+ ```
61
+
62
+ The config says exactly what runs. A key that is not a node name or a
63
+ registered fact, a rule the key's family cannot run, and a node that
64
+ no entry addresses are errors:
65
+
66
+ ```
67
+ LRPConfig(rule={**BASE, 'linear': 'zplus'})
68
+ ValueError: unknown rule key 'linear': not a node name [...]
69
+ LRPConfig(rule={**BASE, 'MulBackward': 'zbox'})
70
+ ValueError: rule entry 'MulBackward'='zbox': 'zbox' is not a choice here. Choices: [...]
71
+ ```
72
+
73
+ Rule tables, by family:
74
+
75
+ | family | node names | rules |
76
+ | --- | --- | --- |
77
+ | linear | `AddmmBackward`, `MmBackward`, `ConvolutionBackward` | `epsilon`, `zplus`, `gamma`, `gamma_montavon`, `alpha_beta`, `zbox` |
78
+ | bilinear | `BmmBackward` | `epsilon`, `uniform`, `detach_lhs`, `detach_rhs` |
79
+ | product | `MulBackward`, `DivBackward` | `proportional`, `detach_lhs`, `detach_rhs` |
80
+ | sum | `AddBackward`, `SubBackward` | `proportional`, `equal`, `fixed`, `detach_lhs`, `detach_rhs` |
81
+
82
+ Names are positional: `detach_lhs` zeros the operand written on the
83
+ left of that op, always. The one virtual name `'detach'` takes
84
+ `by=<fact>` and picks the side per node from the fact's value.
85
+
86
+ Which family a product node belongs to is decided by which of its
87
+ operands come from the wrapped input, not by its name. One operand:
88
+ the op is a linear layer whose weight is the other operand (a constant,
89
+ a parameter, or any tensor you did not wrap). Two: the op is bilinear.
90
+ Frozen models (`requires_grad=False`) work like trainable ones.
91
+
92
+ Softmax, layer norm and activation nodes are set by their own fields:
93
+ `softmax=` (`passthrough`, `jacobian`, `detach`), `layernorm=`
94
+ (`identity`, `passthrough`, `yx`, `detach_std`), `activation=`
95
+ (`passthrough`, `yx`).
96
+
97
+ ## Reading back what ran
98
+
99
+ `explain` installs the hooks, records the config entry and the rule
100
+ function at every node, removes the hooks again, and runs no backward.
101
+ `explain_summary` prints one line per distinct combination:
102
+
103
+ ```python
104
+ from autoLRP import explain, explain_summary
105
+ rows = explain(model(autoLRP.tensor(x))[0, pred], LRPConfig(attn='cplrp'))
106
+ print(explain_summary([r for r in rows if r[2] != 'native gradient']))
107
+ ```
108
+
109
+ ```
110
+ count node key what
111
+ 4 AddmmBackward0 AddmmBackward epsilon
112
+ 2 AddBackward AddBackward residual_proportional
113
+ 2 NativeLayerNormBackward0 None layernorm=identity
114
+ 1 BmmBackward0 weights_operand detach_lhs_bmm
115
+ 1 BmmBackward0 BmmBackward epsilon_bmm
116
+ 1 DivBackward0 None passthrough (constant operand)
117
+ 1 SoftmaxBackward None softmax=passthrough
118
+ ```
119
+
120
+ `key` is the entry that addressed the node, `what` the function it
121
+ picked; `native gradient` rows are shape ops, where the gradient is
122
+ already the routing.
123
+
124
+ ## Facts and your own analyzers
125
+
126
+ Built-in facts: `statistic_operand` (the normalization statistic in a
127
+ mul, div or sub, detached by `BASE`), `weights_operand` (the softmax
128
+ weights in a bmm), `input_conv` (the first convolution). An analyzer is
129
+ a function over all nodes that returns the nodes carrying its fact; its
130
+ registered name is the config key. The value is the fact's value:
131
+ `True` for a plain tag, a slot number (0 or 1) for a side that a
132
+ `('detach', {'by': ...})` entry can read:
133
+
134
+ ```python
135
+ from autoLRP import register_analyzer
136
+
137
+ @register_analyzer('first_linear')
138
+ def first_linear(nodes):
139
+ hits = [n for n in nodes if 'AddmmBackward' in n.name()]
140
+ return {hits[-1]: True} if hits else {}
141
+
142
+ LRPConfig(rule={**BASE, 'first_linear': ('zbox', {'low': -3.0, 'high': 3.0})})
143
+ ```
144
+
145
+ ## Conventions worth knowing
146
+
147
+ - A constant that multiplies, divides or negates passes relevance
148
+ through unchanged. A constant that is added is a bias, and a bias
149
+ absorbs its share (`apply_bias_split`), so a layer with a bias emits
150
+ less than it receives.
151
+ - Fused `scaled_dot_product_attention` is decomposed into
152
+ matmul, softmax, matmul by default; `set_decompose_attention(False)`
153
+ keeps the fused node, which is handled by its own installer and gives
154
+ the same relevance to 1e-13.
155
+ - An op with no installer runs its native gradient and warns once,
156
+ if it lies on the path to the wrapped input.
157
+ - `BASE` with the default `eps=1e-11` is LRP-0; on deep networks it
158
+ can be numerically unstable, and the recipes (`composite`, gamma,
159
+ z+) are what to use there.
160
+
161
+ ## Recipes and evaluation
162
+
163
+ `autoLRP.bilrp(model, x_a, x_b)` (second-order, similarity models),
164
+ `autoLRP.clrp(...)` (contrastive), and `autoLRP.eval` with
165
+ `perturbation_curve`, `aopc`, `sanity_check_cascade`,
166
+ `sensitivity_correlation`.
167
+
168
+ ## Tests
169
+
170
+ ```
171
+ python -m pytest -q
172
+ ```
173
+
174
+ 352 tests; two modules skip without `zennit` and the examples file.
175
+ The notebooks under `examples/showcase` are the showcases; the four in
176
+ `extras/` run without downloads.
@@ -0,0 +1,55 @@
1
+ r"""autoLRP: layer-wise relevance propagation on the autograd graph.
2
+
3
+ Wrap the input, run the model, pick the output scalar, call ``.lrp()``::
4
+
5
+ import autoLRP
6
+ from autoLRP import LRPConfig, BASE
7
+
8
+ x = autoLRP.tensor(image)
9
+ out = model(x)
10
+ out[0, pred].lrp() # BASE: epsilon on linear
11
+ heatmap = x.relevance # families, proportional elsewhere
12
+
13
+ Every rule-bearing node in the graph is addressed by its name without
14
+ the version digit, or by a fact an analyzer attached to it. ``BASE`` is
15
+ the printed starting table; override entries on it::
16
+
17
+ out[0, pred].lrp(config=LRPConfig(rule={**BASE, 'BmmBackward': 'uniform'}))
18
+ out[0, pred].lrp(config=LRPConfig(attn='attnlrp'))
19
+
20
+ Anything that is not a node name or a registered fact, a rule the
21
+ node's family cannot run, or a node no entry addresses, is an error.
22
+ """
23
+ __version__ = '0.1.0'
24
+
25
+ from .compat import run_selfcheck
26
+ run_selfcheck()
27
+
28
+ from .config import LRPConfig, BASE
29
+ from .tensor import LRPTensor, tensor
30
+ from .forward.intercept import (
31
+ register_rewrite, REWRITES,
32
+ set_decompose_attention, get_decompose_attention, decompose_attention,
33
+ )
34
+ from .backward.strategies import (
35
+ register_installer, installer, merge, match_installer, is_shape_node,
36
+ EXPLICIT_STRATEGY, INSTALLERS,
37
+ )
38
+ from .backward.analysis import (
39
+ register_analyzer, ANALYZERS, node_facts,
40
+ )
41
+ from .backward.engine import graph_lrp, walk, plan_report, explain, explain_summary
42
+ from .recipes import bilrp, clrp
43
+ from . import eval
44
+
45
+ __all__ = [
46
+ 'LRPConfig', 'BASE', 'LRPTensor', 'tensor',
47
+ 'register_rewrite', 'REWRITES',
48
+ 'set_decompose_attention', 'get_decompose_attention',
49
+ 'decompose_attention',
50
+ 'register_installer', 'installer', 'merge', 'match_installer',
51
+ 'is_shape_node', 'EXPLICIT_STRATEGY', 'INSTALLERS',
52
+ 'register_analyzer', 'ANALYZERS', 'node_facts',
53
+ 'graph_lrp', 'walk', 'plan_report', 'explain', 'explain_summary',
54
+ 'bilrp', 'clrp', 'eval',
55
+ ]
@@ -0,0 +1,5 @@
1
+ r"""Backward side: ``rules`` (tables), ``lrp_utils`` (machinery),
2
+ ``install`` (hook installers), ``strategies`` (node name to
3
+ installer), ``analysis`` (facts), ``resolve`` (config key to node),
4
+ ``engine`` (walk and run).
5
+ """