I have an autoregressive model which produces output for 20 time steps per observation (continuous variable), so the output of my model is #batch_size x 20 time steps. I was testing out IntegratedGradients to analyze how much each of the model input is contributing to each time step in my model output.
Testing this on one observation with n_steps set to default (50), I hit an error when I do not pass the target.
AssertionError: Target not provided when necessary, cannot take gradient with respect to multiple outputs.
When I pass the target with dimension 1 observation x 20 time steps, I hit the following error:
AssertionError: Tensor target dimension torch.Size([50, 20]) is not valid. torch.Size([50, 20])
I tried the other approaches, flattening both the target and the output of the model, etc. But have not found anything that works. Also, I noticed that the tutorials are very single output and classification driven. Although I do understand that most of pytorch users are focused on these use cases, I do hope that there will be more tutorials covering different type of models (e.g. models with multiple outputs and continuous variables).
Sample code for model inference:
model(test_input, test_input_2, test_input_3, test_input_4, test_input_5, test_input_6, test_input_7, test_input_8, test_input_9, bal_clip_min, bal_clip_max)
Which outputs:
tensor([[-0.3450, -0.3596, -0.2906, 0.6870, -0.1398, -0.1252, -0.1664, -0.0447,
-0.0400, -0.1811, -0.2172, -0.0851, -0.0307, 0.2869, -0.0123, -0.0123,
-0.1946, -0.2083, -0.1973, -0.2847]], grad_fn=<SliceBackward>)
Target I pass in:
tensor([[-0.3924, -0.3924, 1.7474, 2.7700, 0.2136, 0.2136, -0.3088, -0.3088,
-0.3088, -0.3088, -0.3088, -0.3088, -0.3922, -0.3009, 5.3519, 5.3519,
-0.3664, -0.3664, -0.3664, -0.3866]])
Code for IG attribution
ig = IntegratedGradients(model)
ig.attribute(
inputs=(test_input, test_input_2, test_input_3, test_input_4, test_input_5, test_input_6, test_input_7, test_input_8, test_input_9),
baselines=(baseline_input, test_input_2, test_input_3, test_input_4, baseline_input_5, test_input_6, test_input_7, test_input_8, test_input_9)),
additional_forward_args=(bal_clip_min, bal_clip_max),
target=torch.from_numpy(sample_train_Y[:1,1].astype(np.float32))
)
Hi @hchong-ml ,
currently Captum can compute attribution for a single neuron per input sample.
You can run your code with target = [[k]] to compute the attribution for the k-th output value.
You can repeat the process to find attributions for each output neuron.
You can also define a wrapper than converts a multi-dimensional output to scalar value, if this makes sense in your use case, and attribute this value to the input. An upcoming tutorial (PR 380) uses this route to analyze segmentation problems.
Hope this helps
Hi @hchong-ml , as @bilalsal mentioned, you can use a single scalar target value to compute attributions with respect to a particular output step, for instance, for the last output step value, with something like this:
ig = ig.attribute(inputs= ... , baselines=.., additional_forward_args=... , target=19)
Alternatively, an example of the wrapper solution, where you can compute attributions for some function (e.g. sum) of the output values, can be found in this answer #377 or in this upcoming tutorial #380.
It might also be helpful to look at the answer to the first question in our FAQ here, which details the purpose of the target argument and how it should be used generally.
Thanks a lot for reverting so quickly, both the workarounds work perfectly! @vivekmig and @bilalsal
Most helpful comment
Hi @hchong-ml ,
currently Captum can compute attribution for a single neuron per input sample.
You can run your code with target = [[k]] to compute the attribution for the k-th output value.
You can repeat the process to find attributions for each output neuron.
You can also define a wrapper than converts a multi-dimensional output to scalar value, if this makes sense in your use case, and attribute this value to the input. An upcoming tutorial (PR 380) uses this route to analyze segmentation problems.
Hope this helps