-
Notifications
You must be signed in to change notification settings - Fork 893
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TFTExplainer: getting explanations when trained on multiple time series #2489
Comments
Hi @sikhapentyala, I did a bit of investigation and as expected, the size of the attention heads does not depend on the number of series but on the batch size (which is set to 32 by default). This means (and it's not documented, kind of a bug), that the maximum number of series that can be explained with import pandas as pd
import numpy as np
from darts import TimeSeries
from darts.models import TFTModel
from darts.explainability.tft_explainer import TFTExplainer
from darts.utils.timeseries_generation import datetime_attribute_timeseries, sine_timeseries
batch_size = 4
model = TFTModel(
input_chunk_length=10,
output_chunk_length=2,
pl_trainer_kwargs={"accelerator":"cpu"},
n_epochs=1,
batch_size=batch_size,
)
possible_starts = [pd.Timestamp(date) for date in ["2000-01-01", "2005-01-01", "2010-01-01"]]
possible_ends = [pd.Timestamp(date) for date in ["2010-01-01", "2015-01-01", "2020-01-01"]]
training_series = [
sine_timeseries(
value_frequency=i,
start=np.random.choice(possible_starts),
end=np.random.choice(possible_ends),
freq="M"
) for i in range (batch_size+1)
]
future_cov = datetime_attribute_timeseries(pd.date_range(start=pd.Timestamp("1900-01-01"), end=pd.Timestamp("2025-01-01"), freq="M"), "month", cyclic=True)
model.fit(series=training_series, future_covariates=[future_cov]*batch_size+1,)
# works
explainer = TFTExplainer(model,
background_series=training_series[:batch_size],
background_future_covariates=[future_cov]*batch_size,
)
explanations = explainer.explain()
# does not work
explainer = TFTExplainer(model,
background_series=training_series[:batch_size+1],
background_future_covariates=[future_cov]*(batch_size+1),
)
explanations = explainer.explain()
# workaround
nb_batches = len(training_series)//batch_size
if len(training_series) % batch_size != 0:
nb_batches += 1
explanations = []
for batch_idx in range(nb_batches):
print(batch_size*batch_idx)
print(batch_size*(batch_idx+1))
bg_series = training_series[batch_size*batch_idx:batch_size*(batch_idx+1)]
fut_cov = [future_cov]*len(bg_series)
explainer = TFTExplainer(
model,
background_series=bg_series,
background_future_covariates=fut_cov,
)
explanations.append(explainer.explain()) Just out of curiosity, what do you expect to learn from applying this to all 350 series in you training set? |
Thank you. My understanding is that TFT interpretations output "...the general relationships it has learned" (Section 7 in the paper). For example, Table 3 in the paper gives the variable importance not for a single series but for all series (A single series is the time series for a given store_item pair i.e. 1 entity). Through interpretations, I wanted to see what the model has learned something similar to global interpretations rather than on a batch of examples. |
Nice, thank you for pointing this out. The interpretability analysis described in Table 3 of the paper is slightly different than what is implemented in You should be able to obtain a similar table if you access those attributes and analyze them. |
Hi @madtoinou The parameters for _create_model (i.e., train_sample) are indeed expected to be a tuple of six tensors:
Each of these tensors is expected to have the shape (n_timesteps, n_variables), meaning they are 2D tensors (or arrays). However, my goal is to input multiple sequences for global interpretability analysis, which would typically require 3D tensors with an additional dimension for batch size, i.e., (batch_size, n_timesteps, n_variables).The key challenge here is that the _create_model method appears to only accept 2D tensors, which suggests it is designed for single sequences or individual samples.So, how do i solve this problem |
Hi @Tanbuliaobei, First of all, the parameters of As explained in one of my message above, if you want to use the If you want to look at the features selection weights (which is probably what you mean by "global interpretability"), you access the following attributes of the models; from darts.datasets import AirPassengersDataset
from darts.models import TFTModel
from darts.utils.timeseries_generation import datetime_attribute_timeseries
series = AirPassengersDataset().load()
ts1, ts2 = series.split_after(0.6)
fut_cov = datetime_attribute_timeseries(
time_index=series.time_index,
attribute="weekday",
cyclic=True,
add_length=10
)
# fit the model so that the weights actually have meaning
model = TFTModel(input_chunk_length=3, output_chunk_length=1, n_epochs=5)
model.fit(series=[ts1, ts2], future_covariates=[fut_cov, fut_cov])
# work exactly the same for decoder_vsn
list(model.model.encoder_vsn.prescalers.keys())
>>> ['target_0', 'future_covariate_0', 'future_covariate_1']
list(x.weight.detach().numpy() for x in model.model.encoder_vsn.prescalers.values())
>>> [array([[-0.58796742], ... Let me know if it solves your problem |
I have trained TFT on multiple time series (for example: trained on a retail dataset with 350 time series, each having target, past and future covariates). My understanding was that TFTExplainer would give importance (temporal and variable) based on what it learned from all the time series. To get these, I pass the backgorund_series (and other covariates) that I had used for training to the TFTExplainer. i.e. I pass all 350 series. This gives me the following error
Traceback (most recent call last):
File "/main.py", line 90, in
results = explainer.explain()
File "/lib/python3.9/site-packages/darts/explainability/tft_explainer.py", line 224, in explain
values=np.take(attention_heads[idx], horizon_idx, axis=0).T,
IndexError: index 30 is out of bounds for axis 0 with size 30
I found that in TFTExplainer.explain(), the size of attention_heads is 30 and not 350.
When I pass only one series as background series, it works (size of attention_heads is 1).
How can I get global explanations for the TFT model when it is trained on multiple time series?
Thank you.
The text was updated successfully, but these errors were encountered: