tsCaptum 0.0.1__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.
tscaptum-0.0.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 MLGIG: Machine Learning Georgiana Ifrim Group
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.
@@ -0,0 +1,54 @@
1
+ Metadata-Version: 2.1
2
+ Name: tsCaptum
3
+ Version: 0.0.1
4
+ Summary: A Captum wrapper for Time Series XAI
5
+ Author-email: Davide Serramazza <davide.serramazza@ucdconnect.ie>
6
+ Project-URL: Homepage, https://github.com/mlgig/tscaptum/
7
+ Requires-Python: <3.12,>=3.8
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: scikit-learn
11
+ Requires-Dist: aeon
12
+ Requires-Dist: openpyxl
13
+ Requires-Dist: tqdm
14
+ Requires-Dist: torch>=2.0.0
15
+ Requires-Dist: captum==0.7.0
16
+
17
+ # tsCaptum - A library for univariate and multivariate time series explanation
18
+
19
+ tsCaptum is a library that adapts the popular post-hoc attribution methods implemented in the Captum
20
+ framework to work with time series. Unlike previous libraries tsCaptum is :
21
+ 1) Fully compatible with scikit-learn and popular time-series frameworks such as aeon and sktime (e.g., so it is easy to combine ROCKET with SHAP).
22
+ 2) Takes advantage of TS locality by using time series segmentation (so SHAP runs fast with long time series and suffers less from vanishing attribution weights)
23
+ 3) It's extremely easy to use requiring almost no effort by the users
24
+
25
+ ```
26
+ from aeon.classification.convolution_based import RocketClassifier
27
+ clf = RocketClassifier(n_jobs=-1)
28
+ clf.fit(MP_X_train,MP_y_train)
29
+
30
+ from tsCaptum.explainers import Feature_Ablation
31
+ myFA = Feature_Ablation(clf)
32
+ exp = myFA.explain(samples=CMJ_X_test_samples, labels=CMJ_y_test_samples, n_segments=10, normalise=False, baseline=0)
33
+
34
+ from tsCaptum.explainers import Shapley_Value_Sampling as SHAP
35
+ mySHAP = SHAP(clf)
36
+ exp = mySHAP.explain(CMJ_X_test_samples, labels=CMJ_y_test_samples, n_segments=10, normalise=False, baseline=0)
37
+
38
+ ```
39
+
40
+ It can be installed by typing the command "pip install tsCaptum" or in case you have problems
41
+ installing torch (e.g. you use Linux as OS and you want a lighter installation) use
42
+ "pip3 install torch --index-url https://download.pytorch.org/whl/cpu && pip install tsCaptum"
43
+
44
+ In case you use this library please cite:
45
+ ```
46
+ @misc{tsCaptum,
47
+ author = {Davide Italo Serramazza, Thach Le Nguyen, Georgiana Ifrim},
48
+ title = {tsCaptum: adapting Captum explainers for time series and scikit-learn-like predictors},
49
+ howpublished = {GitHub},
50
+ year = {2024},
51
+ note = {Temporary bibitex entry},
52
+ url = { https://github.com/mlgig/tscaptum },
53
+ }
54
+ ```
@@ -0,0 +1,38 @@
1
+ # tsCaptum - A library for univariate and multivariate time series explanation
2
+
3
+ tsCaptum is a library that adapts the popular post-hoc attribution methods implemented in the Captum
4
+ framework to work with time series. Unlike previous libraries tsCaptum is :
5
+ 1) Fully compatible with scikit-learn and popular time-series frameworks such as aeon and sktime (e.g., so it is easy to combine ROCKET with SHAP).
6
+ 2) Takes advantage of TS locality by using time series segmentation (so SHAP runs fast with long time series and suffers less from vanishing attribution weights)
7
+ 3) It's extremely easy to use requiring almost no effort by the users
8
+
9
+ ```
10
+ from aeon.classification.convolution_based import RocketClassifier
11
+ clf = RocketClassifier(n_jobs=-1)
12
+ clf.fit(MP_X_train,MP_y_train)
13
+
14
+ from tsCaptum.explainers import Feature_Ablation
15
+ myFA = Feature_Ablation(clf)
16
+ exp = myFA.explain(samples=CMJ_X_test_samples, labels=CMJ_y_test_samples, n_segments=10, normalise=False, baseline=0)
17
+
18
+ from tsCaptum.explainers import Shapley_Value_Sampling as SHAP
19
+ mySHAP = SHAP(clf)
20
+ exp = mySHAP.explain(CMJ_X_test_samples, labels=CMJ_y_test_samples, n_segments=10, normalise=False, baseline=0)
21
+
22
+ ```
23
+
24
+ It can be installed by typing the command "pip install tsCaptum" or in case you have problems
25
+ installing torch (e.g. you use Linux as OS and you want a lighter installation) use
26
+ "pip3 install torch --index-url https://download.pytorch.org/whl/cpu && pip install tsCaptum"
27
+
28
+ In case you use this library please cite:
29
+ ```
30
+ @misc{tsCaptum,
31
+ author = {Davide Italo Serramazza, Thach Le Nguyen, Georgiana Ifrim},
32
+ title = {tsCaptum: adapting Captum explainers for time series and scikit-learn-like predictors},
33
+ howpublished = {GitHub},
34
+ year = {2024},
35
+ note = {Temporary bibitex entry},
36
+ url = { https://github.com/mlgig/tscaptum },
37
+ }
38
+ ```
@@ -0,0 +1,22 @@
1
+ [build-system]
2
+ requires = ["setuptools>=69.5.1"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "tsCaptum"
7
+ version = "0.0.1"
8
+ authors = [ { name="Davide Serramazza", email="davide.serramazza@ucdconnect.ie" },]
9
+ description = "A Captum wrapper for Time Series XAI"
10
+ readme = "README.md"
11
+ requires-python = ">=3.8,<3.12"
12
+ dependencies = [
13
+ "scikit-learn",
14
+ "aeon",
15
+ "openpyxl",
16
+ "tqdm",
17
+ "torch>=2.0.0",
18
+ "captum==0.7.0"
19
+ ]
20
+
21
+ [project.urls]
22
+ "Homepage" = "https://github.com/mlgig/tscaptum/"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,47 @@
1
+ import numpy as np
2
+ import torch
3
+
4
+
5
+ # documentation for each method!
6
+
7
+ class _Forwarder:
8
+ """
9
+ class automatically detecting the right forward function to use with the captum explainers
10
+ """
11
+
12
+ # TODO specify possible clf type as aeonClf | SktimeClf | ....
13
+
14
+ def __init__(self, predictor, predictor_type):
15
+ """
16
+ init function for this class
17
+
18
+ :param predictor: the predictor to be explained
19
+ :
20
+ param predictor_type: (optional) the predictor variable's type i.e. regressor or classifier
21
+ """
22
+ # TODO should I make the following two variables private?
23
+ self.predictor = predictor
24
+ if predictor_type == "regressor":
25
+ self.raw_result_func = self.predictor.predict
26
+ elif predictor_type == "classifier":
27
+ self.raw_result_func = self.predictor.predict_proba
28
+ else:
29
+ raise " provided model not recognized. Please specify whether is a classifier or regressor "
30
+
31
+ def forward(self, X):
32
+ """
33
+ function adapting scikit-learn-like predictor to captum explainers
34
+
35
+ :param X: instances to be explained
36
+
37
+ :return: predictor's output as a torch tensor
38
+ """
39
+
40
+ # convert X to pytorch tensor
41
+ X_numpy: np.array = X.detach().numpy()
42
+ # use the model forward function
43
+ preds: np.array = self.raw_result_func(X_numpy)
44
+ # return result as torch tensor as expected by captum attribution method
45
+ preds_torch: torch.tensor = torch.tensor(preds)
46
+
47
+ return preds_torch
@@ -0,0 +1,15 @@
1
+ from torch.utils.data import Dataset
2
+
3
+
4
+ class _tsCaptum_loader(Dataset):
5
+
6
+ def __init__(self, X, labels):
7
+ super().__init__()
8
+ self.X = X
9
+ self.labels = labels
10
+
11
+ def __len__(self):
12
+ return self.X.shape[0]
13
+
14
+ def __getitem__(self, idx):
15
+ return self.X[idx], self.labels[idx]
@@ -0,0 +1,118 @@
1
+ import numpy as np
2
+ import torch
3
+ from torch.utils.data import DataLoader
4
+ from sklearn.preprocessing import LabelEncoder
5
+
6
+ from ._tsCaptum_loader import _tsCaptum_loader
7
+
8
+
9
+ # TODO check to aeon, sktime, torch and captum how function in utils are called (with or without leading _) ?
10
+
11
+ def _equal_length_segmentation(n_chunks: int, n_channels: int, series_length: int):
12
+ r"""
13
+ function returning how to group time points into time Series accordingly to the given arguments
14
+ To be noted that it operates channel-wise i.e. each channel is divided into 'n_chunks' chunks
15
+
16
+ :param n_chunks: number of chunks to be used
17
+
18
+ :param n_channels: number of channel of each instance in the dataset
19
+
20
+ :param series_length: length of each channel of each instance in the dataset
21
+
22
+ :return: a torch tensor representing how to group time points
23
+ """
24
+ quotient, reminder = np.floor(series_length / n_chunks).astype(int), series_length % n_chunks
25
+
26
+ first_group = np.array([[i + j * n_chunks for i in range(reminder)] for j in range(n_channels)])
27
+ first_group = np.expand_dims(np.repeat(first_group, (quotient + 1), axis=1), 0)
28
+
29
+ second_group = np.array([[i + j * n_chunks for i in range(reminder, n_chunks)] for j in range(n_channels)])
30
+ second_group = np.expand_dims(np.repeat(second_group, quotient, axis=1), 0)
31
+
32
+ final_group = np.concatenate((first_group, second_group), axis=-1)
33
+ return torch.tensor(final_group).to(torch.int64)
34
+
35
+
36
+ def _normalise_result(X):
37
+ """
38
+ function to normalize obtained saliency map
39
+
40
+ :param X: the saliency map to be normalized
41
+
42
+ :return: normalized version of X
43
+ """
44
+
45
+ assert len(X.shape) == 3
46
+ results = []
47
+ for x in X:
48
+ scaling_factor = 1 / max(np.abs(x.max()), np.abs(x.min()))
49
+ results.append(scaling_factor * x)
50
+ return results
51
+
52
+
53
+ def _check_labels(labels, predictor_type):
54
+ r"""
55
+ function checking the label argument provided to explain method and converting them into integer representation as
56
+ required by captum
57
+
58
+ :param labels: provided labels
59
+
60
+ :param predictor_type: predictor's type i.e. classifier or regressor
61
+
62
+ :return: label encoder and relative integer indices
63
+ """
64
+ if predictor_type == "classifier":
65
+ # transform to numeric labels
66
+ le = LabelEncoder()
67
+ labels_idx = torch.tensor(le.fit_transform(labels)).type(torch.int64)
68
+
69
+ elif predictor_type == "regressor":
70
+ if labels is not None:
71
+ raise ValueError(
72
+ "specified labels when predictor type is regressor"
73
+ )
74
+ le = None
75
+ labels_idx = None
76
+
77
+ else:
78
+ raise (
79
+ " provided predictor type not recognized. Please specify whether is a classifier or regressor "
80
+ )
81
+
82
+ return le, labels_idx
83
+
84
+
85
+ def _check_convert_data_format(X, labels, batch_size):
86
+ r"""
87
+ function checking and converting provided samples and labels to explain method
88
+
89
+ :param X: sample to explain. Can be provided as numpy array or as torch tensor
90
+
91
+ :param labels: labels provided to explain method
92
+
93
+ :param batch_size: batch size provided to explain method
94
+
95
+ :return: data loader to be used in the explain method
96
+ """
97
+
98
+ if X is None and labels is not None:
99
+ if X.shape[0] != labels.shape[0]:
100
+ # if both X and labels are provided having no matching dimensions
101
+ raise ValueError(
102
+ "provided samples and labels have different dimensions"
103
+ )
104
+
105
+ if isinstance(X, np.ndarray):
106
+ X = torch.tensor(X).type(torch.float)
107
+ elif isinstance(X, torch.Tensor):
108
+ X = X.type(torch.float)
109
+ else:
110
+ raise TypeError(
111
+ " Data format has to be either numpy array or torch tensor "
112
+ )
113
+
114
+ if labels is None:
115
+ labels = torch.ones(X.shape[0]) * -1
116
+ loader = DataLoader(_tsCaptum_loader(X, labels), shuffle=False, batch_size=batch_size)
117
+
118
+ return loader
@@ -0,0 +1,231 @@
1
+ from tqdm import tqdm
2
+ import warnings
3
+
4
+ from captum.attr._utils.attribution import PerturbationAttribution
5
+ from captum.attr import (FeatureAblation as _FeatureAblationCaptum,
6
+ FeaturePermutation as _FeaturePermutationCaptum,
7
+ KernelShap as _KernelShapCaptum,
8
+ Lime as _LimeCaptum,
9
+ ShapleyValueSampling as _ShapleyValueSamplingCaptum)
10
+
11
+ from ._forwarder import _Forwarder
12
+ from ._utils import _check_convert_data_format, _check_labels, _normalise_result, _equal_length_segmentation
13
+ from ._utils import *
14
+
15
+
16
+ class _tsCaptum_Method:
17
+ """
18
+ super class for all attribution methods
19
+ """
20
+
21
+ def __init__(self, explainer, predictor, predictor_type: str = None):
22
+ r"""
23
+ init method for the superclass
24
+
25
+ :param explainer: the actual explainer that will be used for computing the saliency maps.
26
+ Each subclass fix this argument as the corresponding Captum explainer
27
+
28
+ :param predictor: the predictor that will be explained
29
+ :param predictor_type: which type the predictor is i.e. classifier or regressor
30
+ """
31
+
32
+ # check argument values
33
+ if not issubclass(explainer, PerturbationAttribution):
34
+ raise (
35
+ " provided explainer has to be an instance of 'captum.attr._utils.attribution.PerturbationAttribution' ")
36
+
37
+ if predictor_type not in ["classifier", "regressor", None]:
38
+ raise (
39
+ " clf_type argument has to be either 'classifier' or 'regressor' ")
40
+
41
+ # in case predictor_type argument isn't provided tell it calling the predict_proba method:
42
+ # if it's present the predictor is a classifier otherwise is a regressor
43
+ self.predictor_type = predictor_type
44
+ if self.predictor_type is None:
45
+ self.predictor_type = "classifier"
46
+ try:
47
+ predictor.predict_proba
48
+ except AttributeError:
49
+ self.predictor_type = "regressor"
50
+
51
+ # set also forward function and explainer to be used
52
+ self._Forwarder = _Forwarder(predictor, self.predictor_type)
53
+ self._explainer = explainer(self._Forwarder.forward)
54
+
55
+ def explain(self, samples, labels=None, batch_size=8, n_segments=10, normalise=False, baseline=0):
56
+ r"""
57
+ main method to get a saliency map by the selected explainer
58
+
59
+ :param samples: samples to be explained
60
+
61
+ :param labels: labels associated to samples in case of classification
62
+
63
+ :param batch_size: the batch_size to be used i.e. number of samples to be explained at the same time
64
+
65
+ :param n_segments: number of segments the timeseries is dived to. If you want to explain point-wise provide -1 as
66
+ value #TODO should we put more information about how it works?
67
+
68
+ :param normalise: whether or not to normalise the result
69
+
70
+ :param baseline: the baseline which will substitute time series's values when ablated. It can be either a scalar
71
+ (each time series's value is substituted by this scalar) or a single time series
72
+ (both as numpy array or torch.tensor)
73
+
74
+ :return: the saliency maps as a 3D tensor ( samples, channels, time points)
75
+ """
76
+
77
+ # check arguments and get a DataLoader
78
+ n_2explain, n_channels, series_length = samples.shape
79
+ le, labels_idx = _check_labels(labels, self.predictor_type)
80
+ loader = _check_convert_data_format(samples, labels_idx, batch_size)
81
+
82
+ explanations = []
83
+ with tqdm(total=n_2explain) as pbar:
84
+ with torch.no_grad():
85
+ for n, (X, y) in enumerate(loader):
86
+ # fix kwargs for the relative captum method
87
+ kwargs = self._define_kwargs(baseline, n_channels, n_segments, series_length, y)
88
+ # get the current saliency maps, convert it to numpy array and store it to a temp list
89
+ current_exps = self._explainer.attribute(X, **kwargs)
90
+ explanations.append(
91
+ _normalise_result(current_exps.detach().numpy())) if normalise \
92
+ else explanations.append(current_exps.detach().numpy())
93
+ pbar.update(batch_size)
94
+ pbar.close()
95
+
96
+ # convert the list to numpy array and return it as result
97
+ explanations = np.concatenate(explanations)
98
+ return explanations
99
+
100
+ def _define_kwargs(self, baseline, n_channels, n_segments, series_length, y):
101
+ r"""
102
+ inner function that checking provided argument to explain, define the correct kwarg dictionary
103
+
104
+ :return: kwarg dictionary for the relative captum method
105
+ """
106
+ kwargs = {}
107
+
108
+ # checking baseline
109
+ if not isinstance(self, Feature_Permutation):
110
+ if np.isscalar(baseline):
111
+ kwargs['baselines'] = baseline
112
+ elif type(baseline) is np.ndarray:
113
+ kwargs['baselines'] = torch.tensor(baseline)
114
+ elif type(baseline) is torch.Tensor:
115
+ kwargs['baselines'] = baseline
116
+
117
+ # labels
118
+ if self.predictor_type == "classifier":
119
+ kwargs['target'] = y
120
+
121
+ # define feature mask looking at the desired number of segment
122
+ if n_segments != -1:
123
+ groups = _equal_length_segmentation(n_segments, n_channels, series_length)
124
+ kwargs['feature_mask'] = groups
125
+
126
+ return kwargs
127
+
128
+
129
+ class Feature_Ablation(_tsCaptum_Method):
130
+ r"""
131
+ Wrapper for Feature Ablation method
132
+ """
133
+
134
+ def __init__(self, clf, clf_type=None):
135
+ super().__init__(_FeatureAblationCaptum, clf, clf_type)
136
+
137
+
138
+ class Feature_Permutation(_tsCaptum_Method):
139
+ r"""
140
+ Wrapper for feature permutation method
141
+ """
142
+
143
+ def __init__(self, clf, clf_type=None):
144
+ super().__init__(_FeaturePermutationCaptum, clf, clf_type)
145
+
146
+ def explain(self, samples, **kwargs):
147
+ r"""
148
+ extending _tsCaptum_Method's explain by fixing some arguments as defined by Captum implementation.
149
+ For Feature Permutation takes care of the batch_size > 2 and baseline which can't be provided
150
+
151
+ :param samples: samples to be explained
152
+
153
+ :param kwargs: additional arguments
154
+
155
+ :calling: _tsCaptum_Method'e explain
156
+ """
157
+ if 'batch_size' in kwargs and kwargs['batch_size'] != 1:
158
+ warnings.warn(
159
+ "batch_size set to 2 as Feature Permutation require more than 1 sample to work"
160
+ )
161
+ kwargs['batch_size'] = 2
162
+
163
+ if 'baseline' in kwargs:
164
+ warnings.warn(
165
+ "specified baseline will be ignored as Feature Permutation algorithm has its own baseline"
166
+ )
167
+ return super().explain(samples, **kwargs)
168
+
169
+
170
+ class Kernel_Shap(_tsCaptum_Method):
171
+ r"""
172
+ Wrapper for KernelSHAP method
173
+ """
174
+
175
+ def __init__(self, clf, clf_type=None):
176
+ super().__init__(_KernelShapCaptum, clf, clf_type)
177
+
178
+ def explain(self, samples, **kwargs):
179
+ r"""
180
+ extending _tsCaptum_Method'e explain by fixing some arguments as defined by Captum implementation.
181
+ For KernelSHAP takes care of the batch_size suggested to be equal to 1
182
+
183
+ :param samples: samples to be explained
184
+
185
+ :param kwargs: additional arguments
186
+
187
+ :calling: _tsCaptum_Method's explain
188
+ """
189
+ if 'batch_size' in kwargs and kwargs['batch_size'] != 1:
190
+ warnings.warn(
191
+ "batch_size set to 1 as suggested by Captum for Lime and KernelSHAP"
192
+ )
193
+ kwargs['batch_size'] = 1
194
+ return super().explain(samples, **kwargs)
195
+
196
+
197
+ class LIME(_tsCaptum_Method):
198
+ r"""
199
+ Wrapper for LIME method
200
+ """
201
+
202
+ def __init__(self, clf, clf_type=None):
203
+ super().__init__(_LimeCaptum, clf, clf_type)
204
+
205
+ def explain(self, samples, **kwargs):
206
+ r"""
207
+ extending _tsCaptum_Method'e explain by fixing some arguments as defined by Captum implementation.
208
+ For LIME takes care of the batch_size suggested to be equal to 1
209
+
210
+ :param samples: samples to be explained
211
+
212
+ :param kwargs: additional arguments
213
+
214
+ :calling: _tsCaptum_Method's explain
215
+ """
216
+ if 'batch_size' in kwargs and kwargs['batch_size'] != 1:
217
+ warnings.warn(
218
+ "batch_size set to 1 as suggested by Captum for Lime and KernelSHAP"
219
+ )
220
+ kwargs['batch_size'] = 1
221
+ return super().explain(samples, **kwargs)
222
+
223
+
224
+ class Shapley_Value_Sampling(_tsCaptum_Method):
225
+ r"""
226
+ Wrapper for Shapley Value Sampling method. Most of the time this is the best approximation of the intractable
227
+ Shapley values
228
+ """
229
+
230
+ def __init__(self, clf, clf_type=None):
231
+ super().__init__(_ShapleyValueSamplingCaptum, clf, clf_type)
@@ -0,0 +1,27 @@
1
+ import numpy as np
2
+ import matplotlib.pyplot as plt
3
+ from scipy.interpolate import interp1d
4
+
5
+ def plot_saliency_map_uni(sample, attribution, title = 'Saliency map'):
6
+
7
+ def transform(X):
8
+ ma,mi = np.max(X), np.min(X)
9
+ X = (X - mi)/(ma-mi)
10
+ return X*100
11
+
12
+ weight = transform(abs(attribution))
13
+ ts = np.squeeze(sample)
14
+
15
+ max_length1, max_length2 = ts.shape[0],10000 #
16
+ x1 = np.linspace(0,max_length1,num = max_length1)
17
+ x2 = np.linspace(0,max_length1,num = max_length2)
18
+ y1 = ts
19
+
20
+ f = interp1d(x1, y1) # interpolate time series
21
+ fcas = interp1d(x1, weight) # interpolate weight color
22
+ weight = fcas(x2) # convert vector of original weight vector to new weight vector
23
+
24
+ plt.figure(figsize=(6, 2))
25
+ plt.scatter(x2,f(x2), c = weight, cmap = 'jet', marker='.', s= 1,vmin=0,vmax = 100)
26
+ plt.title(title)
27
+ plt.show()
@@ -0,0 +1,54 @@
1
+ Metadata-Version: 2.1
2
+ Name: tsCaptum
3
+ Version: 0.0.1
4
+ Summary: A Captum wrapper for Time Series XAI
5
+ Author-email: Davide Serramazza <davide.serramazza@ucdconnect.ie>
6
+ Project-URL: Homepage, https://github.com/mlgig/tscaptum/
7
+ Requires-Python: <3.12,>=3.8
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: scikit-learn
11
+ Requires-Dist: aeon
12
+ Requires-Dist: openpyxl
13
+ Requires-Dist: tqdm
14
+ Requires-Dist: torch>=2.0.0
15
+ Requires-Dist: captum==0.7.0
16
+
17
+ # tsCaptum - A library for univariate and multivariate time series explanation
18
+
19
+ tsCaptum is a library that adapts the popular post-hoc attribution methods implemented in the Captum
20
+ framework to work with time series. Unlike previous libraries tsCaptum is :
21
+ 1) Fully compatible with scikit-learn and popular time-series frameworks such as aeon and sktime (e.g., so it is easy to combine ROCKET with SHAP).
22
+ 2) Takes advantage of TS locality by using time series segmentation (so SHAP runs fast with long time series and suffers less from vanishing attribution weights)
23
+ 3) It's extremely easy to use requiring almost no effort by the users
24
+
25
+ ```
26
+ from aeon.classification.convolution_based import RocketClassifier
27
+ clf = RocketClassifier(n_jobs=-1)
28
+ clf.fit(MP_X_train,MP_y_train)
29
+
30
+ from tsCaptum.explainers import Feature_Ablation
31
+ myFA = Feature_Ablation(clf)
32
+ exp = myFA.explain(samples=CMJ_X_test_samples, labels=CMJ_y_test_samples, n_segments=10, normalise=False, baseline=0)
33
+
34
+ from tsCaptum.explainers import Shapley_Value_Sampling as SHAP
35
+ mySHAP = SHAP(clf)
36
+ exp = mySHAP.explain(CMJ_X_test_samples, labels=CMJ_y_test_samples, n_segments=10, normalise=False, baseline=0)
37
+
38
+ ```
39
+
40
+ It can be installed by typing the command "pip install tsCaptum" or in case you have problems
41
+ installing torch (e.g. you use Linux as OS and you want a lighter installation) use
42
+ "pip3 install torch --index-url https://download.pytorch.org/whl/cpu && pip install tsCaptum"
43
+
44
+ In case you use this library please cite:
45
+ ```
46
+ @misc{tsCaptum,
47
+ author = {Davide Italo Serramazza, Thach Le Nguyen, Georgiana Ifrim},
48
+ title = {tsCaptum: adapting Captum explainers for time series and scikit-learn-like predictors},
49
+ howpublished = {GitHub},
50
+ year = {2024},
51
+ note = {Temporary bibitex entry},
52
+ url = { https://github.com/mlgig/tscaptum },
53
+ }
54
+ ```
@@ -0,0 +1,13 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ src/tsCaptum/_forwarder.py
5
+ src/tsCaptum/_tsCaptum_loader.py
6
+ src/tsCaptum/_utils.py
7
+ src/tsCaptum/explainers.py
8
+ src/tsCaptum/visualization.py
9
+ src/tsCaptum.egg-info/PKG-INFO
10
+ src/tsCaptum.egg-info/SOURCES.txt
11
+ src/tsCaptum.egg-info/dependency_links.txt
12
+ src/tsCaptum.egg-info/requires.txt
13
+ src/tsCaptum.egg-info/top_level.txt
@@ -0,0 +1,6 @@
1
+ scikit-learn
2
+ aeon
3
+ openpyxl
4
+ tqdm
5
+ torch>=2.0.0
6
+ captum==0.7.0
@@ -0,0 +1 @@
1
+ tsCaptum