tslens 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.
- tslens-0.1.0/LICENSE +21 -0
- tslens-0.1.0/PKG-INFO +145 -0
- tslens-0.1.0/README.md +219 -0
- tslens-0.1.0/docs/pypi_readme.md +90 -0
- tslens-0.1.0/pyproject.toml +62 -0
- tslens-0.1.0/setup.cfg +4 -0
- tslens-0.1.0/src/tslens/__init__.py +18 -0
- tslens-0.1.0/src/tslens/attr/__init__.py +50 -0
- tslens-0.1.0/src/tslens/attr/gate_mask.py +139 -0
- tslens-0.1.0/src/tslens/attr/gatemasknn.py +449 -0
- tslens-0.1.0/src/tslens/attr/tsr.py +262 -0
- tslens-0.1.0/src/tslens/attr/winit.py +158 -0
- tslens-0.1.0/src/tslens/attr/wintsr.py +478 -0
- tslens-0.1.0/src/tslens/functional.py +83 -0
- tslens-0.1.0/src/tslens.egg-info/PKG-INFO +145 -0
- tslens-0.1.0/src/tslens.egg-info/SOURCES.txt +18 -0
- tslens-0.1.0/src/tslens.egg-info/dependency_links.txt +1 -0
- tslens-0.1.0/src/tslens.egg-info/requires.txt +12 -0
- tslens-0.1.0/src/tslens.egg-info/top_level.txt +1 -0
- tslens-0.1.0/tests/test_wintsr.py +335 -0
tslens-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Md. Khairul Islam
|
|
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.
|
tslens-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tslens
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A consistent PyTorch interface to attribution methods for time series deep learning models, including WinTSR
|
|
5
|
+
Author: Judy Fox
|
|
6
|
+
Author-email: Md Khairul Islam <khairulislam@virginia.edu>
|
|
7
|
+
License: MIT License
|
|
8
|
+
|
|
9
|
+
Copyright (c) 2023 Md. Khairul Islam
|
|
10
|
+
|
|
11
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
12
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
13
|
+
in the Software without restriction, including without limitation the rights
|
|
14
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
15
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
16
|
+
furnished to do so, subject to the following conditions:
|
|
17
|
+
|
|
18
|
+
The above copyright notice and this permission notice shall be included in all
|
|
19
|
+
copies or substantial portions of the Software.
|
|
20
|
+
|
|
21
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
22
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
23
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
24
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
25
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
26
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
27
|
+
SOFTWARE.
|
|
28
|
+
|
|
29
|
+
Project-URL: Homepage, https://github.com/khairulislam/tslens
|
|
30
|
+
Project-URL: Repository, https://github.com/khairulislam/tslens
|
|
31
|
+
Project-URL: Paper, https://arxiv.org/abs/2412.04532
|
|
32
|
+
Keywords: time-series,interpretability,explainable-ai,xai,saliency,captum,pytorch,forecasting
|
|
33
|
+
Classifier: Development Status :: 4 - Beta
|
|
34
|
+
Classifier: Intended Audience :: Science/Research
|
|
35
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
36
|
+
Classifier: Programming Language :: Python :: 3
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
40
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
41
|
+
Requires-Python: >=3.9
|
|
42
|
+
Description-Content-Type: text/markdown
|
|
43
|
+
License-File: LICENSE
|
|
44
|
+
Requires-Dist: torch>=1.13
|
|
45
|
+
Requires-Dist: numpy
|
|
46
|
+
Requires-Dist: captum>=0.6
|
|
47
|
+
Requires-Dist: time-interpret>=0.3.0
|
|
48
|
+
Provides-Extra: dev
|
|
49
|
+
Requires-Dist: pytest>=7; extra == "dev"
|
|
50
|
+
Requires-Dist: matplotlib; extra == "dev"
|
|
51
|
+
Provides-Extra: docs
|
|
52
|
+
Requires-Dist: mkdocs-material>=9; extra == "docs"
|
|
53
|
+
Requires-Dist: mkdocstrings[python]>=0.25; extra == "docs"
|
|
54
|
+
Dynamic: license-file
|
|
55
|
+
|
|
56
|
+
# tslens
|
|
57
|
+
|
|
58
|
+
**Which time steps and which features did your time series model actually use?**
|
|
59
|
+
|
|
60
|
+
tslens is a Captum-compatible interpretability toolkit for deep time series models,
|
|
61
|
+
giving you a consistent PyTorch interface to WinTSR and other established attribution
|
|
62
|
+
methods. WinTSR (Windowed Temporal Saliency Rescaling), the native flagship method,
|
|
63
|
+
accounts for the temporal dependency between neighbouring time steps and scores the
|
|
64
|
+
time and feature dimensions jointly rather than separately — unlike attribution
|
|
65
|
+
methods borrowed from vision and NLP.
|
|
66
|
+
|
|
67
|
+
Paper: [arXiv:2412.04532](https://arxiv.org/abs/2412.04532) ·
|
|
68
|
+
Code: [github.com/khairulislam/tslens](https://github.com/khairulislam/tslens)
|
|
69
|
+
|
|
70
|
+
## Install
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
pip install tslens
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Use
|
|
77
|
+
|
|
78
|
+
Works with any PyTorch model that maps `(batch, seq_len, n_features)` to predictions.
|
|
79
|
+
No training framework to adopt, no dataset format to conform to.
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
import torch
|
|
83
|
+
from tslens import WinTSR
|
|
84
|
+
|
|
85
|
+
inputs = torch.randn(16, 96, 7) # (batch, seq_len, n_features)
|
|
86
|
+
attr = WinTSR(model).attribute(
|
|
87
|
+
inputs,
|
|
88
|
+
baselines=torch.zeros_like(inputs),
|
|
89
|
+
threshold=0.5, # skip the least relevant time steps
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
attr.shape # (16, n_output, 96, 7) -- (batch, n_output, seq_len, n_features)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Plot it as a heatmap over `(seq_len, n_features)` and you can read off what the model used.
|
|
96
|
+
|
|
97
|
+
### Options that matter
|
|
98
|
+
|
|
99
|
+
| Argument | Effect |
|
|
100
|
+
| --- | --- |
|
|
101
|
+
| `threshold` | Quantile of time-relevance below which steps are skipped in stage two. Higher is faster and sparser; `0.0` keeps every step. |
|
|
102
|
+
| `sliding_window_shapes` | Window over `(time, features)`. Defaults to `(1, 1)`. Widen the first entry to attribute over multi-step windows. |
|
|
103
|
+
| `baselines` | Replacement values for occluded regions. Defaults to zeros; `tslens.get_baseline(inputs, "normal")` gives other options. |
|
|
104
|
+
| `unflatten` | `True` (default) returns `(batch, n_output, seq_len, n_features)`. `False` returns the flat `(batch * n_output, ...)` layout used internally. |
|
|
105
|
+
| `legacy_normalize` | Constructor flag. Restores the exact normalization used to produce the published numbers — see below. |
|
|
106
|
+
|
|
107
|
+
### Multi-input models
|
|
108
|
+
|
|
109
|
+
Pass a tuple, get a tuple back. This is how you explain a
|
|
110
|
+
[TSlib](https://github.com/thuml/Time-Series-Library) model (DLinear, iTransformer,
|
|
111
|
+
TimesNet, ...) — its four forward arguments split into two attributed inputs and two
|
|
112
|
+
context tensors, with no wrapper class:
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
attr_enc, attr_mark = WinTSR(model).attribute(
|
|
116
|
+
inputs=(x_enc, x_mark_enc),
|
|
117
|
+
baselines=(torch.zeros_like(x_enc), torch.zeros_like(x_mark_enc)),
|
|
118
|
+
additional_forward_args=(x_dec, x_mark_dec),
|
|
119
|
+
)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### More recipes
|
|
123
|
+
|
|
124
|
+
The [integration cookbook](https://github.com/khairulislam/tslens/blob/main/docs/integration.md)
|
|
125
|
+
has copy-paste snippets for dict/tuple model outputs, classification models, baseline
|
|
126
|
+
choice, explaining a single forecast horizon, speed tuning, and troubleshooting. Two
|
|
127
|
+
runnable notebooks:
|
|
128
|
+
[quickstart](https://colab.research.google.com/github/khairulislam/tslens/blob/main/notebooks/quickstart.ipynb)
|
|
129
|
+
and
|
|
130
|
+
[TSlib models](https://colab.research.google.com/github/khairulislam/tslens/blob/main/notebooks/tslib_models.ipynb).
|
|
131
|
+
|
|
132
|
+
## Requirements
|
|
133
|
+
|
|
134
|
+
`torch`, `numpy`, `captum`, and [`time-interpret`](https://github.com/josephenguehard/time_interpret).
|
|
135
|
+
|
|
136
|
+
## Citation
|
|
137
|
+
|
|
138
|
+
```bibtex
|
|
139
|
+
@article{islam2024wintsr,
|
|
140
|
+
title={WinTSR: A Windowed Temporal Saliency Rescaling Method for Interpreting Time Series Deep Learning Models},
|
|
141
|
+
author={Islam, Md Khairul and Fox, Judy},
|
|
142
|
+
journal={arXiv preprint arXiv:2412.04532},
|
|
143
|
+
year={2024}
|
|
144
|
+
}
|
|
145
|
+
```
|
tslens-0.1.0/README.md
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# tslens
|
|
2
|
+
|
|
3
|
+
### A consistent PyTorch interface to time-series attribution methods
|
|
4
|
+
|
|
5
|
+
[](https://arxiv.org/abs/2412.04532)
|
|
6
|
+
[](https://colab.research.google.com/github/khairulislam/tslens/blob/main/notebooks/quickstart.ipynb)
|
|
7
|
+
[](https://khairulislam.github.io/tslens/)
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
|
|
10
|
+
**Which time steps and features did your time-series model actually use?**
|
|
11
|
+
|
|
12
|
+
tslens is a drop-in, Captum-compatible interpretability toolkit for PyTorch
|
|
13
|
+
time-series models. Every method produces a saliency map over the input window so you
|
|
14
|
+
can inspect *when* and *where* a model found evidence for its prediction.
|
|
15
|
+
|
|
16
|
+
Explaining time series models is hard for two reasons that attribution methods borrowed
|
|
17
|
+
from vision and NLP do not handle: subsequent time steps are strongly dependent, and
|
|
18
|
+
feature importance varies over time. Existing studies (1) do not consider the temporal
|
|
19
|
+
dependencies among the feature vectors in the input window, and (2) consider the time
|
|
20
|
+
dimension separately from the feature dimension when calculating importance scores.
|
|
21
|
+
**Windowed Temporal Saliency Rescaling (WinTSR)**, the toolkit's native flagship
|
|
22
|
+
method, addresses both.
|
|
23
|
+
|
|
24
|
+

|
|
25
|
+
|
|
26
|
+
## Why tslens?
|
|
27
|
+
|
|
28
|
+
- **Model-agnostic:** explain any callable PyTorch model with the expected input shape.
|
|
29
|
+
- **Time-aware:** preserve relationships between neighbouring observations, via WinTSR.
|
|
30
|
+
- **Joint attribution:** identify important time–feature regions, not just global features.
|
|
31
|
+
- **Practical:** support multi-input models, custom baselines, classification, and forecasting.
|
|
32
|
+
- **One interface:** compare established attribution methods from Captum, Time Interpret,
|
|
33
|
+
and this package's own native implementations side by side.
|
|
34
|
+
|
|
35
|
+
## Quickstart
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pip install tslens
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Requires Python 3.9+ and PyTorch 1.13+. Works with any PyTorch model mapping
|
|
42
|
+
`(batch, seq_len, n_features)` to predictions — no training framework to adopt, no
|
|
43
|
+
dataset format to conform to:
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
import torch
|
|
47
|
+
from tslens import WinTSR
|
|
48
|
+
|
|
49
|
+
inputs = torch.randn(16, 96, 7) # (batch, seq_len, n_features)
|
|
50
|
+
attr = WinTSR(model).attribute(
|
|
51
|
+
inputs,
|
|
52
|
+
baselines=torch.zeros_like(inputs),
|
|
53
|
+
threshold=0.5,
|
|
54
|
+
)
|
|
55
|
+
attr.shape # (16, n_output, 96, 7)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
For local development, install the package with its test and documentation tools:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
pip install -e ".[dev,docs]"
|
|
62
|
+
pytest
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Plot `attr` as a heatmap over `(seq_len, n_features)` to read off what the model used.
|
|
66
|
+
|
|
67
|
+
### Getting started
|
|
68
|
+
|
|
69
|
+
| | |
|
|
70
|
+
| --- | --- |
|
|
71
|
+
| **[Quickstart notebook](https://colab.research.google.com/github/khairulislam/tslens/blob/main/notebooks/quickstart.ipynb)** | 60 seconds, no dataset download. Plants a known signal, trains a small GRU, checks WinTSR recovers it. |
|
|
72
|
+
| **[TSlib models notebook](https://colab.research.google.com/github/khairulislam/tslens/blob/main/notebooks/tslib_models.ipynb)** | Explaining DLinear, iTransformer, TimesNet and friends. No wrapper class needed. |
|
|
73
|
+
| **[Classification notebook](https://colab.research.google.com/github/khairulislam/tslens/blob/main/notebooks/classification.ipynb)** | `n_output` becomes the class count; a padding mask goes through as context, not as an attributed input. |
|
|
74
|
+
| **[Baselines notebook](https://colab.research.google.com/github/khairulislam/tslens/blob/main/notebooks/baselines.ipynb)** | Why the baseline matters, `get_baseline`'s four modes compared by attribution quality, and how to use a custom one. |
|
|
75
|
+
| **[Custom outputs notebook](https://colab.research.google.com/github/khairulislam/tslens/blob/main/notebooks/custom_outputs.ipynb)** | Wrapping models that return a dict or tuple (TimeLLM-style) with a one-line lambda. |
|
|
76
|
+
| **[Integration cookbook](https://khairulislam.github.io/tslens/integration/)** | Copy-paste recipes: dict/tuple outputs, classification, baselines, single horizons, speed, troubleshooting. |
|
|
77
|
+
| **[Interpretation methods](https://khairulislam.github.io/tslens/methods/)** | What WinTSR, TSR, WinIT and GateMask each do differently, and when to reach for which one. |
|
|
78
|
+
| **[API reference](https://khairulislam.github.io/tslens/reference/wintsr/)** | Every argument, generated from the docstrings, including `legacy_normalize=True` to reproduce the published numbers. |
|
|
79
|
+
|
|
80
|
+
Already have a TSlib model? It takes four tensors, so split them into what you want
|
|
81
|
+
attributed and what is just context:
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
attr_enc, attr_mark = WinTSR(model).attribute(
|
|
85
|
+
inputs=(x_enc, x_mark_enc),
|
|
86
|
+
baselines=(torch.zeros_like(x_enc), torch.zeros_like(x_mark_enc)),
|
|
87
|
+
additional_forward_args=(x_dec, x_mark_dec),
|
|
88
|
+
)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Interpretation methods
|
|
92
|
+
|
|
93
|
+
tslens gives you a broad set of attribution methods through one interface, and works
|
|
94
|
+
with any PyTorch time series model. WinTSR, TSR, WinIT, and GateMask are implemented
|
|
95
|
+
natively here; the rest call [Captum](https://captum.ai/docs/introduction) and
|
|
96
|
+
[tint](https://josephenguehard.github.io/time_interpret/build/html/index.html) directly.
|
|
97
|
+
See [Interpretation methods](https://khairulislam.github.io/tslens/methods/) for what
|
|
98
|
+
each one does differently and when to use it.
|
|
99
|
+
|
|
100
|
+
<details>
|
|
101
|
+
<summary><b>Supported methods</b> (click to expand)</summary>
|
|
102
|
+
|
|
103
|
+
| Method | Type | Paper |
|
|
104
|
+
| --- | --- | --- |
|
|
105
|
+
| WinTSR | Perturbation | [Islam & Fox, arXiv:2412.04532](https://arxiv.org/abs/2412.04532) |
|
|
106
|
+
| TSR | Gradient | [Ismail et al., NeurIPS 2020](https://proceedings.neurips.cc/paper_files/paper/2020/file/47a3893cc405396a5c30d91320572d6d-Paper.pdf) |
|
|
107
|
+
| WinIT | Perturbation | [Leung et al., ICLR 2023](https://arxiv.org/abs/2107.14317) |
|
|
108
|
+
| GateMask | Learned mask | [Liu et al., ICLR 2024](https://arxiv.org/abs/2401.08552) |
|
|
109
|
+
| Occlusion | Perturbation | [Zeiler & Fergus, ECCV 2014](https://arxiv.org/abs/1311.2901) |
|
|
110
|
+
| Feature Ablation | Perturbation | [Kokhlikyan et al., arXiv:2009.07896](https://arxiv.org/abs/2009.07896) |
|
|
111
|
+
| Feature Permutation | Perturbation | [Kokhlikyan et al., arXiv:2009.07896](https://arxiv.org/abs/2009.07896) |
|
|
112
|
+
| Augmented Occlusion | Perturbation | [Enguehard, ICML 2023](https://proceedings.mlr.press/v202/enguehard23a.html) |
|
|
113
|
+
| Integrated Gradients | Gradient | [Sundararajan et al., ICML 2017](https://arxiv.org/abs/1703.01365) |
|
|
114
|
+
| Gradient SHAP | Gradient | [Lundberg & Lee, NeurIPS 2017](https://arxiv.org/abs/1705.07874) |
|
|
115
|
+
| FIT | Perturbation | [Tonekaboni et al., NeurIPS 2020](https://proceedings.neurips.cc/paper/2020/hash/08fa43588c2571ade19bc0fa5936e028-Abstract.html) |
|
|
116
|
+
| Dyna Mask | Learned mask | [Crabbé & van der Schaar, ICML 2021](https://proceedings.mlr.press/v139/crabbe21a.html) |
|
|
117
|
+
| Extremal Mask | Learned mask | [Enguehard, ICML 2023](https://proceedings.mlr.press/v202/enguehard23a.html) |
|
|
118
|
+
| Lime | Surrogate | [Ribeiro et al., KDD 2016](https://arxiv.org/abs/1602.04938) |
|
|
119
|
+
|
|
120
|
+
Full comparison matrix (model requirement, baseline, API doc):
|
|
121
|
+
[Interpretation methods](https://khairulislam.github.io/tslens/methods/).
|
|
122
|
+
</details>
|
|
123
|
+
|
|
124
|
+
## Supported models
|
|
125
|
+
|
|
126
|
+
tslens attributes any callable that maps `(batch, seq_len, n_features)` — or a tuple of
|
|
127
|
+
tensors — to predictions, so nothing here is hard-coded to a specific architecture. The
|
|
128
|
+
list below is what this package and its [research harness](https://github.com/khairulislam/WinTSR-research)
|
|
129
|
+
have actually been run against.
|
|
130
|
+
|
|
131
|
+
<details>
|
|
132
|
+
<summary><b>Supported model architectures</b> (click to expand)</summary>
|
|
133
|
+
|
|
134
|
+
| Model | Family | Paper |
|
|
135
|
+
| --- | --- | --- |
|
|
136
|
+
| DLinear | Linear | [Zeng et al., AAAI 2023](https://arxiv.org/abs/2205.13504) |
|
|
137
|
+
| LightTS | Linear/MLP | [Zhang et al., arXiv:2207.01186](https://arxiv.org/abs/2207.01186) |
|
|
138
|
+
| TiDE | Linear/MLP | [Das et al., TMLR 2023](https://arxiv.org/abs/2304.08424) |
|
|
139
|
+
| FiLM | Linear/MLP | [Zhou et al., NeurIPS 2022](https://arxiv.org/abs/2205.08897) |
|
|
140
|
+
| TSMixer | MLP-Mixer | [Chen et al., TMLR 2023](https://arxiv.org/abs/2303.06053) |
|
|
141
|
+
| FreTS | Frequency-domain MLP | [Yi et al., NeurIPS 2023](https://arxiv.org/abs/2311.06184) |
|
|
142
|
+
| MICN | Convolutional | [Wang et al., ICLR 2023](https://openreview.net/pdf?id=zt53IDUR1U) |
|
|
143
|
+
| Crossformer | Transformer | [Zhang & Yan, ICLR 2023](https://openreview.net/pdf?id=vSVLM2j9eie) |
|
|
144
|
+
| PatchTST | Transformer | [Nie et al., ICLR 2023](https://arxiv.org/abs/2211.14730) |
|
|
145
|
+
| Pyraformer | Transformer | [Liu et al., ICLR 2022](https://openreview.net/pdf?id=0EXmFzUn5I) |
|
|
146
|
+
| SegRNN | Recurrent | [Lin et al., arXiv:2308.11200](https://arxiv.org/abs/2308.11200) |
|
|
147
|
+
| Koopa | Koopman operator | [Liu et al., NeurIPS 2023](https://arxiv.org/abs/2305.18803) |
|
|
148
|
+
| LSTM | Recurrent | [Hochreiter & Schmidhuber, Neural Computation 1997](https://www.bioinf.jku.at/publications/older/2604.pdf) |
|
|
149
|
+
| TCN | Convolutional | [Bai et al., arXiv:1803.01271](https://arxiv.org/abs/1803.01271) |
|
|
150
|
+
| CALF | LLM-backed foundation model | [Liu et al., arXiv:2403.07300](https://arxiv.org/abs/2403.07300) |
|
|
151
|
+
| OFA (GPT4TS) | LLM-backed foundation model | [Zhou et al., NeurIPS 2023](https://arxiv.org/abs/2302.11939) |
|
|
152
|
+
| TimeLLM | LLM-backed foundation model | [Jin et al., ICLR 2024](https://arxiv.org/abs/2310.01728) |
|
|
153
|
+
| Transformer | Transformer | [Vaswani et al., NeurIPS 2017](https://proceedings.neurips.cc/paper/2017/file/3f5ee243547dee91fbd053c1c4a845aa-Paper.pdf) |
|
|
154
|
+
| Informer | Transformer | [Zhou et al., AAAI 2021](https://ojs.aaai.org/index.php/AAAI/article/view/17325) |
|
|
155
|
+
| Autoformer | Transformer | [Wu et al., NeurIPS 2021](https://openreview.net/pdf?id=I55UqU-M11y) |
|
|
156
|
+
| FEDformer | Transformer | [Zhou et al., ICML 2022](https://proceedings.mlr.press/v162/zhou22g.html) |
|
|
157
|
+
| ETSformer | Transformer | [Woo et al., arXiv:2202.01381](https://arxiv.org/abs/2202.01381) |
|
|
158
|
+
| Nonstationary Transformer | Transformer | [Liu et al., NeurIPS 2022](https://openreview.net/pdf?id=ucNDIDRNjjv) |
|
|
159
|
+
| Reformer | Transformer | [Kitaev et al., ICLR 2020](https://openreview.net/forum?id=rkgNKkHtvB) |
|
|
160
|
+
| iTransformer | Transformer | [Liu et al., ICLR 2024](https://arxiv.org/abs/2310.06625) |
|
|
161
|
+
| TimeXer | Transformer | [Wang et al., NeurIPS 2024](https://arxiv.org/abs/2402.19072) |
|
|
162
|
+
| TimeMixer | MLP-Mixer | [Wang et al., ICLR 2024](https://arxiv.org/abs/2405.14616) |
|
|
163
|
+
| TimesNet | Convolutional | [Wu et al., ICLR 2023](https://openreview.net/pdf?id=ju_Uqw384Oq) |
|
|
164
|
+
| RNN | Recurrent | [Hochreiter & Schmidhuber, Neural Computation 1997](https://www.bioinf.jku.at/publications/older/2604.pdf) |
|
|
165
|
+
|
|
166
|
+
Calling convention (single vs. dual-input) and trained checkpoints:
|
|
167
|
+
[Supported models](https://khairulislam.github.io/tslens/models/).
|
|
168
|
+
</details>
|
|
169
|
+
|
|
170
|
+
## Repository layout
|
|
171
|
+
|
|
172
|
+
| Path | What it is |
|
|
173
|
+
| --- | --- |
|
|
174
|
+
| [src/tslens/](/src/tslens/) | The installable library. `WinTSR` plus the paper's baseline methods (`TSR`, `WinIT`, `GateMask`). |
|
|
175
|
+
| [notebooks/](/notebooks/) | Runnable quickstart and TSlib walkthrough. |
|
|
176
|
+
| [tests/](/tests/) | Test suite, including a numerical-equivalence check against the pre-refactor implementation. |
|
|
177
|
+
| [docs/](/docs/) | Source for the [docs site](https://khairulislam.github.io/tslens/): tutorials, method explainer, API reference, and the PyPI-page library reference. |
|
|
178
|
+
|
|
179
|
+
This repo is the library only. The training/interpretation harness that produced the
|
|
180
|
+
paper's results — model zoo, experiment scripts, saved results — lives in
|
|
181
|
+
[WinTSR-research](https://github.com/khairulislam/WinTSR-research) and depends on this
|
|
182
|
+
package the same way any user would (`pip install tslens`).
|
|
183
|
+
|
|
184
|
+
## Reproducing the paper
|
|
185
|
+
|
|
186
|
+
Training the models, running the full benchmark, and the paper's saved results live in
|
|
187
|
+
[WinTSR-research](https://github.com/khairulislam/WinTSR-research), which installs this
|
|
188
|
+
package as a regular dependency. That repo also has the model zoo — DLinear,
|
|
189
|
+
iTransformer, TimesNet, CALF, TimeLLM and 25 others from
|
|
190
|
+
[TSlib](https://github.com/thuml/Time-Series-Library) — dataset download instructions,
|
|
191
|
+
and Docker/Singularity definitions.
|
|
192
|
+
|
|
193
|
+
## Citation
|
|
194
|
+
|
|
195
|
+
Find our paper on [arXiv](https://arxiv.org/pdf/2412.04532). Please cite the following if you use our work
|
|
196
|
+
(also available as [CITATION.cff](CITATION.cff), used by GitHub's "Cite this repository" button).
|
|
197
|
+
|
|
198
|
+
```bibtex
|
|
199
|
+
@article{islam2024wintsr,
|
|
200
|
+
title={WinTSR: A Windowed Temporal Saliency Rescaling Method for Interpreting Time Series Deep Learning Models},
|
|
201
|
+
author={Islam, Md Khairul and Fox, Judy},
|
|
202
|
+
journal={arXiv preprint arXiv:2412.04532},
|
|
203
|
+
year={2024}
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## License
|
|
208
|
+
|
|
209
|
+
MIT — see [LICENSE](LICENSE).
|
|
210
|
+
|
|
211
|
+
## Core libraries
|
|
212
|
+
|
|
213
|
+
tslens builds on these open-source projects:
|
|
214
|
+
|
|
215
|
+
- **[Captum](https://captum.ai/docs/introduction)** — model interpretability library for PyTorch.
|
|
216
|
+
- **[Time Interpret (tint)](https://josephenguehard.github.io/time_interpret/build/html/index.html)** — extends Captum with methods designed for time series.
|
|
217
|
+
- **[Time-Series-Library (TSlib)](https://github.com/thuml/Time-Series-Library)** — deep time series analysis models used in the benchmark.
|
|
218
|
+
|
|
219
|
+
<!-- add here https://github.com/thuml/OpenLTM, https://github.com/thuml/Large-Time-Series-Model, https://github.com/fzi-forschungszentrum-informatik/TSInterpret.git -->
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# tslens
|
|
2
|
+
|
|
3
|
+
**Which time steps and which features did your time series model actually use?**
|
|
4
|
+
|
|
5
|
+
tslens is a Captum-compatible interpretability toolkit for deep time series models,
|
|
6
|
+
giving you a consistent PyTorch interface to WinTSR and other established attribution
|
|
7
|
+
methods. WinTSR (Windowed Temporal Saliency Rescaling), the native flagship method,
|
|
8
|
+
accounts for the temporal dependency between neighbouring time steps and scores the
|
|
9
|
+
time and feature dimensions jointly rather than separately — unlike attribution
|
|
10
|
+
methods borrowed from vision and NLP.
|
|
11
|
+
|
|
12
|
+
Paper: [arXiv:2412.04532](https://arxiv.org/abs/2412.04532) ·
|
|
13
|
+
Code: [github.com/khairulislam/tslens](https://github.com/khairulislam/tslens)
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install tslens
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Use
|
|
22
|
+
|
|
23
|
+
Works with any PyTorch model that maps `(batch, seq_len, n_features)` to predictions.
|
|
24
|
+
No training framework to adopt, no dataset format to conform to.
|
|
25
|
+
|
|
26
|
+
```python
|
|
27
|
+
import torch
|
|
28
|
+
from tslens import WinTSR
|
|
29
|
+
|
|
30
|
+
inputs = torch.randn(16, 96, 7) # (batch, seq_len, n_features)
|
|
31
|
+
attr = WinTSR(model).attribute(
|
|
32
|
+
inputs,
|
|
33
|
+
baselines=torch.zeros_like(inputs),
|
|
34
|
+
threshold=0.5, # skip the least relevant time steps
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
attr.shape # (16, n_output, 96, 7) -- (batch, n_output, seq_len, n_features)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Plot it as a heatmap over `(seq_len, n_features)` and you can read off what the model used.
|
|
41
|
+
|
|
42
|
+
### Options that matter
|
|
43
|
+
|
|
44
|
+
| Argument | Effect |
|
|
45
|
+
| --- | --- |
|
|
46
|
+
| `threshold` | Quantile of time-relevance below which steps are skipped in stage two. Higher is faster and sparser; `0.0` keeps every step. |
|
|
47
|
+
| `sliding_window_shapes` | Window over `(time, features)`. Defaults to `(1, 1)`. Widen the first entry to attribute over multi-step windows. |
|
|
48
|
+
| `baselines` | Replacement values for occluded regions. Defaults to zeros; `tslens.get_baseline(inputs, "normal")` gives other options. |
|
|
49
|
+
| `unflatten` | `True` (default) returns `(batch, n_output, seq_len, n_features)`. `False` returns the flat `(batch * n_output, ...)` layout used internally. |
|
|
50
|
+
| `legacy_normalize` | Constructor flag. Restores the exact normalization used to produce the published numbers — see below. |
|
|
51
|
+
|
|
52
|
+
### Multi-input models
|
|
53
|
+
|
|
54
|
+
Pass a tuple, get a tuple back. This is how you explain a
|
|
55
|
+
[TSlib](https://github.com/thuml/Time-Series-Library) model (DLinear, iTransformer,
|
|
56
|
+
TimesNet, ...) — its four forward arguments split into two attributed inputs and two
|
|
57
|
+
context tensors, with no wrapper class:
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
attr_enc, attr_mark = WinTSR(model).attribute(
|
|
61
|
+
inputs=(x_enc, x_mark_enc),
|
|
62
|
+
baselines=(torch.zeros_like(x_enc), torch.zeros_like(x_mark_enc)),
|
|
63
|
+
additional_forward_args=(x_dec, x_mark_dec),
|
|
64
|
+
)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### More recipes
|
|
68
|
+
|
|
69
|
+
The [integration cookbook](https://github.com/khairulislam/tslens/blob/main/docs/integration.md)
|
|
70
|
+
has copy-paste snippets for dict/tuple model outputs, classification models, baseline
|
|
71
|
+
choice, explaining a single forecast horizon, speed tuning, and troubleshooting. Two
|
|
72
|
+
runnable notebooks:
|
|
73
|
+
[quickstart](https://colab.research.google.com/github/khairulislam/tslens/blob/main/notebooks/quickstart.ipynb)
|
|
74
|
+
and
|
|
75
|
+
[TSlib models](https://colab.research.google.com/github/khairulislam/tslens/blob/main/notebooks/tslib_models.ipynb).
|
|
76
|
+
|
|
77
|
+
## Requirements
|
|
78
|
+
|
|
79
|
+
`torch`, `numpy`, `captum`, and [`time-interpret`](https://github.com/josephenguehard/time_interpret).
|
|
80
|
+
|
|
81
|
+
## Citation
|
|
82
|
+
|
|
83
|
+
```bibtex
|
|
84
|
+
@article{islam2024wintsr,
|
|
85
|
+
title={WinTSR: A Windowed Temporal Saliency Rescaling Method for Interpreting Time Series Deep Learning Models},
|
|
86
|
+
author={Islam, Md Khairul and Fox, Judy},
|
|
87
|
+
journal={arXiv preprint arXiv:2412.04532},
|
|
88
|
+
year={2024}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=64", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "tslens"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "A consistent PyTorch interface to attribution methods for time series deep learning models, including WinTSR"
|
|
9
|
+
readme = "docs/pypi_readme.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = { file = "LICENSE" }
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Md Khairul Islam", email = "khairulislam@virginia.edu" },
|
|
14
|
+
{ name = "Judy Fox" },
|
|
15
|
+
]
|
|
16
|
+
keywords = [
|
|
17
|
+
"time-series",
|
|
18
|
+
"interpretability",
|
|
19
|
+
"explainable-ai",
|
|
20
|
+
"xai",
|
|
21
|
+
"saliency",
|
|
22
|
+
"captum",
|
|
23
|
+
"pytorch",
|
|
24
|
+
"forecasting",
|
|
25
|
+
]
|
|
26
|
+
classifiers = [
|
|
27
|
+
"Development Status :: 4 - Beta",
|
|
28
|
+
"Intended Audience :: Science/Research",
|
|
29
|
+
"License :: OSI Approved :: MIT License",
|
|
30
|
+
"Programming Language :: Python :: 3",
|
|
31
|
+
"Programming Language :: Python :: 3.9",
|
|
32
|
+
"Programming Language :: Python :: 3.10",
|
|
33
|
+
"Programming Language :: Python :: 3.11",
|
|
34
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
35
|
+
]
|
|
36
|
+
dependencies = [
|
|
37
|
+
"torch>=1.13",
|
|
38
|
+
"numpy",
|
|
39
|
+
"captum>=0.6",
|
|
40
|
+
"time-interpret>=0.3.0",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
[project.optional-dependencies]
|
|
44
|
+
dev = ["pytest>=7", "matplotlib"]
|
|
45
|
+
docs = ["mkdocs-material>=9", "mkdocstrings[python]>=0.25"]
|
|
46
|
+
|
|
47
|
+
[project.urls]
|
|
48
|
+
Homepage = "https://github.com/khairulislam/tslens"
|
|
49
|
+
Repository = "https://github.com/khairulislam/tslens"
|
|
50
|
+
Paper = "https://arxiv.org/abs/2412.04532"
|
|
51
|
+
|
|
52
|
+
[tool.setuptools]
|
|
53
|
+
# src-layout: only what lives under src/ ships. The training/interpretation
|
|
54
|
+
# harness that reproduces the paper's results lives in a separate repo, see
|
|
55
|
+
# the Homepage README.
|
|
56
|
+
package-dir = { "" = "src" }
|
|
57
|
+
|
|
58
|
+
[tool.setuptools.packages.find]
|
|
59
|
+
where = ["src"]
|
|
60
|
+
|
|
61
|
+
[tool.pytest.ini_options]
|
|
62
|
+
testpaths = ["tests"]
|
tslens-0.1.0/setup.cfg
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""tslens: attribution methods for time series deep learning models.
|
|
2
|
+
|
|
3
|
+
A drop-in, Captum-compatible interpretability toolkit for any PyTorch model
|
|
4
|
+
that consumes ``(batch, seq_len, n_features)`` tensors. Includes WinTSR and
|
|
5
|
+
other natively implemented methods, plus a consistent interface over Captum
|
|
6
|
+
and Time Interpret baselines.
|
|
7
|
+
|
|
8
|
+
>>> from tslens import WinTSR
|
|
9
|
+
>>> attr = WinTSR(model).attribute(inputs, baselines=torch.zeros_like(inputs))
|
|
10
|
+
|
|
11
|
+
WinTSR paper: https://arxiv.org/abs/2412.04532
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from .attr import WinTSR
|
|
15
|
+
from .functional import get_baseline, normalize_scale
|
|
16
|
+
|
|
17
|
+
__version__ = "0.1.0"
|
|
18
|
+
__all__ = ["WinTSR", "get_baseline", "normalize_scale", "__version__"]
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""Attribution methods for time series models.
|
|
2
|
+
|
|
3
|
+
:class:`WinTSR` is the method introduced in the paper it's named after.
|
|
4
|
+
:class:`TSR`, :class:`WinIT` and :class:`GateMask` are the baselines used in
|
|
5
|
+
its evaluation. All four work from a plain ``pip install tslens`` -- none of
|
|
6
|
+
them require the research harness under ``research/``.
|
|
7
|
+
|
|
8
|
+
The baselines are imported lazily so that ``import tslens`` stays cheap and
|
|
9
|
+
does not drag in ``pytorch_lightning`` or ``sklearn`` unless a method that
|
|
10
|
+
needs them is actually requested.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from typing import TYPE_CHECKING
|
|
14
|
+
|
|
15
|
+
from .wintsr import WinTSR
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING: # pragma: no cover
|
|
18
|
+
from .gate_mask import GateMask
|
|
19
|
+
from .tsr import TSR
|
|
20
|
+
from .winit import WinIT
|
|
21
|
+
|
|
22
|
+
_LAZY = {"TSR": ".tsr", "WinIT": ".winit", "GateMask": ".gate_mask"}
|
|
23
|
+
|
|
24
|
+
__all__ = ["WinTSR", "TSR", "WinIT", "GateMask"]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def __getattr__(name: str):
|
|
28
|
+
"""PEP 562 lazy import for the baseline methods."""
|
|
29
|
+
if name not in _LAZY:
|
|
30
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
31
|
+
|
|
32
|
+
from importlib import import_module
|
|
33
|
+
|
|
34
|
+
try:
|
|
35
|
+
module = import_module(_LAZY[name], __name__)
|
|
36
|
+
except ImportError as exc:
|
|
37
|
+
raise ImportError(
|
|
38
|
+
f"{name} could not be imported. It is a baseline method whose "
|
|
39
|
+
"dependencies normally arrive with `time-interpret`; a broken or "
|
|
40
|
+
"partial install is the usual cause. Try reinstalling with "
|
|
41
|
+
f"`pip install --force-reinstall tslens`. Original error: {exc}"
|
|
42
|
+
) from exc
|
|
43
|
+
|
|
44
|
+
value = getattr(module, name)
|
|
45
|
+
globals()[name] = value # cache so __getattr__ runs once per name
|
|
46
|
+
return value
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def __dir__():
|
|
50
|
+
return sorted(__all__)
|