Skip to content
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

SHAP Explainer throws an error while using transformers model for abstractive summarization #3442

Open
4 tasks done
SVC04 opened this issue Dec 21, 2023 · 11 comments
Open
4 tasks done
Labels
awaiting feedback Indicates that further information is required from the issue creator bug Indicates an unexpected problem or unintended behaviour

Comments

@SVC04
Copy link

SVC04 commented Dec 21, 2023

Issue Description

Hello,
I am trying to generate an explanation of abstractive text summarization output for a long piece of text input. I have been using various transformers models e.g. Bigbird-Pegasus, LongT5, Lonformer Encoder Decoder etc. But none of it worked and throws different errors. Following is the piece of code I used.

I get the TypeError. 'int object is not callable'.

Minimal Reproducible Example

LONG_ARTICLE = """"anxiety affects quality of life in those living
with parkinson 's disease ( pd ) more so than
overall cognitive status , motor deficits , apathy
, and depression [ 13 ] . although anxiety and
depression are often related and coexist in pd
patients , recent research suggests that anxiety
rather than depression is the most prominent and
prevalent mood disorder in pd [ 5 , 6 ] . yet ,
our current understanding of anxiety and its
impact on cognition in pd , as well as its neural
basis and best treatment practices , remains
meager and lags far behind that of depression ."""

import torch
from transformers import AutoTokenizer, LongT5ForConditionalGeneration

tokenizer = AutoTokenizer.from_pretrained("Stancld/longt5-tglobal-large-16384-pubmed-3k_steps")
model = LongT5ForConditionalGeneration.from_pretrained("Stancld/longt5-tglobal-large-16384-pubmed-3k_steps", return_dict_in_generate=True).to("cuda")
import shap

explainer = shap.Explainer(model, tokenizer)
shap_values = explainer(s)


### Traceback

```shell
TypeError                                 Traceback (most recent call last)
Cell In [23], line 1
----> 1 shap_values = explainer(s)

File /usr/local/lib/python3.9/dist-packages/shap/explainers/_partition.py:125, in PartitionExplainer.__call__(self, max_evals, fixed_context, main_effects, error_bounds, batch_size, outputs, silent, *args)
    121 def __call__(self, *args, max_evals=500, fixed_context=None, main_effects=False, error_bounds=False, batch_size="auto",
    122              outputs=None, silent=False):
    123     """ Explain the output of the model on the given arguments.
    124     """
--> 125     return super().__call__(
    126         *args, max_evals=max_evals, fixed_context=fixed_context, main_effects=main_effects, error_bounds=error_bounds, batch_size=batch_size,
    127         outputs=outputs, silent=silent
    128     )

File /usr/local/lib/python3.9/dist-packages/shap/explainers/_explainer.py:267, in Explainer.__call__(self, max_evals, main_effects, error_bounds, batch_size, outputs, silent, *args, **kwargs)
    265     feature_names = [[] for _ in range(len(args))]
    266 for row_args in show_progress(zip(*args), num_rows, self.__class__.__name__+" explainer", silent):
--> 267     row_result = self.explain_row(
    268         *row_args, max_evals=max_evals, main_effects=main_effects, error_bounds=error_bounds,
    269         batch_size=batch_size, outputs=outputs, silent=silent, **kwargs
    270     )
    271     values.append(row_result.get("values", None))
    272     output_indices.append(row_result.get("output_indices", None))

File /usr/local/lib/python3.9/dist-packages/shap/explainers/_partition.py:150, in PartitionExplainer.explain_row(self, max_evals, main_effects, error_bounds, batch_size, outputs, silent, fixed_context, *row_args)
    148 # if not fixed background or no base value assigned then compute base value for a row
    149 if self._curr_base_value is None or not getattr(self.masker, "fixed_background", False):
--> 150     self._curr_base_value = fm(m00.reshape(1, -1), zero_index=0)[0] # the zero index param tells the masked model what the baseline is
    151 f11 = fm(~m00.reshape(1, -1))[0]
    153 if callable(self.masker.clustering):

File /usr/local/lib/python3.9/dist-packages/shap/utils/_masked_model.py:69, in MaskedModel.__call__(self, masks, zero_index, batch_size)
     66         return self._full_masking_call(full_masks, zero_index=zero_index, batch_size=batch_size)
     68 else:
---> 69     return self._full_masking_call(masks, batch_size=batch_size)

File /usr/local/lib/python3.9/dist-packages/shap/utils/_masked_model.py:146, in MaskedModel._full_masking_call(self, masks, zero_index, batch_size)
    143         all_masked_inputs[i].append(v)
    145 joined_masked_inputs = tuple([np.concatenate(v) for v in all_masked_inputs])
--> 146 outputs = self.model(*joined_masked_inputs)
    147 _assert_output_input_match(joined_masked_inputs, outputs)
    148 all_outputs.append(outputs)

File /usr/local/lib/python3.9/dist-packages/shap/models/_model.py:28, in Model.__call__(self, *args)
     27 def __call__(self, *args):
---> 28     out = self.inner_model(*args)
     29     is_tensor = safe_isinstance(out, "torch.Tensor")
     30     out = out.cpu().detach().numpy() if is_tensor else np.array(out)

File /usr/local/lib/python3.9/dist-packages/torch/nn/modules/module.py:1130, in Module._call_impl(self, *input, **kwargs)
   1126 # If we don't have any hooks, we want to skip the rest of the logic in
   1127 # this function, and just call forward.
   1128 if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks
   1129         or _global_forward_hooks or _global_forward_pre_hooks):
-> 1130     return forward_call(*input, **kwargs)
   1131 # Do not call functions when jit is used
   1132 full_backward_hooks, non_full_backward_hooks = [], []

File /usr/local/lib/python3.9/dist-packages/transformers/models/longt5/modeling_longt5.py:1991, in LongT5ForConditionalGeneration.forward(self, input_ids, attention_mask, decoder_input_ids, decoder_attention_mask, head_mask, decoder_head_mask, cross_attn_head_mask, encoder_outputs, past_key_values, inputs_embeds, decoder_inputs_embeds, labels, use_cache, output_attentions, output_hidden_states, return_dict)
   1988 # Encode if needed (training, first prediction pass)
   1989 if encoder_outputs is None:
   1990     # Convert encoder inputs in embeddings if needed
-> 1991     encoder_outputs = self.encoder(
   1992         input_ids=input_ids,
   1993         attention_mask=attention_mask,
   1994         inputs_embeds=inputs_embeds,
   1995         head_mask=head_mask,
   1996         output_attentions=output_attentions,
   1997         output_hidden_states=output_hidden_states,
   1998         return_dict=return_dict,
   1999     )
   2000 elif return_dict and not isinstance(encoder_outputs, BaseModelOutput):
   2001     encoder_outputs = BaseModelOutput(
   2002         last_hidden_state=encoder_outputs[0],
   2003         hidden_states=encoder_outputs[1] if len(encoder_outputs) > 1 else None,
   2004         attentions=encoder_outputs[2] if len(encoder_outputs) > 2 else None,
   2005     )

File /usr/local/lib/python3.9/dist-packages/torch/nn/modules/module.py:1130, in Module._call_impl(self, *input, **kwargs)
   1126 # If we don't have any hooks, we want to skip the rest of the logic in
   1127 # this function, and just call forward.
   1128 if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks
   1129         or _global_forward_hooks or _global_forward_pre_hooks):
-> 1130     return forward_call(*input, **kwargs)
   1131 # Do not call functions when jit is used
   1132 full_backward_hooks, non_full_backward_hooks = [], []

File /usr/local/lib/python3.9/dist-packages/transformers/models/longt5/modeling_longt5.py:1396, in LongT5Stack.forward(self, input_ids, attention_mask, encoder_hidden_states, encoder_attention_mask, inputs_embeds, head_mask, cross_attn_head_mask, past_key_values, use_cache, output_attentions, output_hidden_states, return_dict)
   1392     raise ValueError(
   1393         f"You cannot specify both {err_msg_prefix}input_ids and {err_msg_prefix}inputs_embeds at the same time"
   1394     )
   1395 elif input_ids is not None:
-> 1396     input_shape = input_ids.size()
   1397     input_ids = input_ids.view(-1, input_shape[-1])
   1398 elif inputs_embeds is not None:

TypeError: 'int' object is not callable

```​

Expected Behavior

No response

Bug report checklist

  • I have checked that this issue has not already been reported.
  • I have confirmed this bug exists on the latest release of shap.
  • I have confirmed this bug exists on the master branch of shap.
  • I'd be interested in making a PR to fix this bug

Installed Versions

Latest version used from github repo.

@SVC04 SVC04 added the bug Indicates an unexpected problem or unintended behaviour label Dec 21, 2023
@CloseChoice
Copy link
Collaborator

I can reproduce your example on master but do not think that this is really a shap issue here. The following lines already result in similar errors:

>>> model([LONG_ARTICLE])
AttributeError: 'list' object has no attribute 'size'
>>> model(LONG_ARTICLE)
AttributeError: 'str' object has no attribute 'size'

Can you somehow get this to run so that the model actually returns something?

@CloseChoice CloseChoice added deep explainer Relating to DeepExplainer, tensorflow or pytorch awaiting feedback Indicates that further information is required from the issue creator and removed deep explainer Relating to DeepExplainer, tensorflow or pytorch labels Dec 24, 2023
@SVC04
Copy link
Author

SVC04 commented Jan 9, 2024

I have tried but it didn't work.

@CloseChoice
Copy link
Collaborator

Okay, this indicates that we do not really have a shap error here since the model is not running at all.

@SVC04
Copy link
Author

SVC04 commented Jan 10, 2024

The hugging face model works well and generates the output summary.
I have also tried bigbird pegasus model in place of this model it did not work either.

LONG_ARTICLE = """"anxiety affects quality of life in those living
with parkinson 's disease ( pd ) more so than
overall cognitive status , motor deficits , apathy
, and depression [ 13 ] . although anxiety and
depression are often related and coexist in pd
patients , recent research suggests that anxiety
rather than depression is the most prominent and
prevalent mood disorder in pd [ 5 , 6 ] . yet ,
our current understanding of anxiety and its
impact on cognition in pd , as well as its neural
basis and best treatment practices , remains
meager and lags far behind that of depression .
overall , neuropsychiatric symptoms in pd have
been shown to be negatively associated with
cognitive performance .


s = [LONG_ARTICLE]

from transformers import BigBirdPegasusForConditionalGeneration, AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("google/bigbird-pegasus-large-pubmed")
model = BigBirdPegasusForConditionalGeneration.from_pretrained("google/bigbird-pegasus-large-pubmed")

import shap

explainer = shap.Explainer(model, tokenizer)
shap_values = explainer(s)

It also throws an error below.

AttributeError: 'numpy.ndarray' object has no attribute 'new_zeros'

Below is the full error trace.

1516             return self._compiled_call_impl(*args, **kwargs)  # type: ignore[misc]
   1517         else:
-> 1518             return self._call_impl(*args, **kwargs)
   1519 
   1520     def _call_impl(self, *args, **kwargs):

[/usr/local/lib/python3.10/dist-packages/torch/nn/modules/module.py](https://localhost:8080/#) in _call_impl(self, *args, **kwargs)
   1525                 or _global_backward_pre_hooks or _global_backward_hooks
   1526                 or _global_forward_hooks or _global_forward_pre_hooks):
-> 1527             return forward_call(*args, **kwargs)
   1528 
   1529         try:

[/usr/local/lib/python3.10/dist-packages/transformers/models/bigbird_pegasus/modeling_bigbird_pegasus.py](https://localhost:8080/#) in forward(self, input_ids, attention_mask, decoder_input_ids, decoder_attention_mask, head_mask, decoder_head_mask, cross_attn_head_mask, encoder_outputs, past_key_values, inputs_embeds, decoder_inputs_embeds, labels, use_cache, output_attentions, output_hidden_states, return_dict)
   2510                 )
   2511 
-> 2512         outputs = self.model(
   2513             input_ids,
   2514             attention_mask=attention_mask,

[/usr/local/lib/python3.10/dist-packages/torch/nn/modules/module.py](https://localhost:8080/#) in _wrapped_call_impl(self, *args, **kwargs)
   1516             return self._compiled_call_impl(*args, **kwargs)  # type: ignore[misc]
   1517         else:
-> 1518             return self._call_impl(*args, **kwargs)
   1519 
   1520     def _call_impl(self, *args, **kwargs):

[/usr/local/lib/python3.10/dist-packages/torch/nn/modules/module.py](https://localhost:8080/#) in _call_impl(self, *args, **kwargs)
   1525                 or _global_backward_pre_hooks or _global_backward_hooks
   1526                 or _global_forward_hooks or _global_forward_pre_hooks):
-> 1527             return forward_call(*args, **kwargs)
   1528 
   1529         try:

[/usr/local/lib/python3.10/dist-packages/transformers/models/bigbird_pegasus/modeling_bigbird_pegasus.py](https://localhost:8080/#) in forward(self, input_ids, attention_mask, decoder_input_ids, decoder_attention_mask, head_mask, decoder_head_mask, cross_attn_head_mask, encoder_outputs, past_key_values, inputs_embeds, decoder_inputs_embeds, use_cache, output_attentions, output_hidden_states, return_dict)
   2364                 )
   2365 
-> 2366             decoder_input_ids = shift_tokens_right(
   2367                 input_ids, self.config.pad_token_id, self.config.decoder_start_token_id
   2368             )

[/usr/local/lib/python3.10/dist-packages/transformers/models/bigbird_pegasus/modeling_bigbird_pegasus.py](https://localhost:8080/#) in shift_tokens_right(input_ids, pad_token_id, decoder_start_token_id)
     67     Shift input ids one token to the right.
     68     """
---> 69     shifted_input_ids = input_ids.new_zeros(input_ids.shape)
     70     shifted_input_ids[:, 1:] = input_ids[:, :-1].clone()
     71     shifted_input_ids[:, 0] = decoder_start_token_id

AttributeError: 'numpy.ndarray' object has no attribute 'new_zeros'

I suppose there can be a version mismatch issue.
Can you please suggest what should be done.? Would be very helpful.

@CloseChoice
Copy link
Collaborator

Can you show me how to generate the output with the model you are using? That's what I tried above but that failed.

@SVC04
Copy link
Author

SVC04 commented Jan 10, 2024

Following is a piece of code to generate the output using longt5.

!pip install transformers[sentencepiece] datasets sacrebleu rouge_score py7zr -q
LONG_ARTICLE = """"anxiety affects quality of life in those living
with parkinson 's disease ( pd ) more so than
overall cognitive status , motor deficits , apathy
, and depression [ 13 ] . although anxiety and
depression are often related and coexist in pd
patients , recent research suggests that anxiety
rather than depression is the most prominent and
prevalent mood disorder in pd [ 5 , 6 ] . yet ,
our current understanding of anxiety and its
impact on cognition in pd , as well as its neural
basis and best treatment practices , remains
meager and lags far behind that of depression ."""

import torch
from transformers import AutoTokenizer, LongT5ForConditionalGeneration

tokenizer = AutoTokenizer.from_pretrained("Stancld/longt5-tglobal-large-16384-pubmed-3k_steps")
input_ids = tokenizer(LONG_ARTICLE, return_tensors="pt").input_ids

model = LongT5ForConditionalGeneration.from_pretrained("Stancld/longt5-tglobal-large-16384-pubmed-3k_steps", return_dict_in_generate=True)

sequences = model.generate(input_ids).sequences

summary = tokenizer.batch_decode(sequences)

For the second model bigbird pegasus the output can be generated using the code below.


from transformers import BigBirdPegasusForConditionalGeneration, AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("google/bigbird-pegasus-large-pubmed")
model = BigBirdPegasusForConditionalGeneration.from_pretrained("google/bigbird-pegasus-large-pubmed")

text = "text article"
inputs = tokenizer(text, return_tensors='pt')
prediction = model.generate(**inputs)
prediction = tokenizer.batch_decode(prediction)

@Yangliule
Copy link

Hey I encountered a similar issue. I think the issue is SHAP passed in a numpy array instead of tensor object when calling transformers API.

@SVC04
Copy link
Author

SVC04 commented Jan 25, 2024

@Yangliule Did you find any solution.?

@Yangliule
Copy link

Hey @SVC04, I solved the issue by reverting transformers version and pytorch version. Also, make sure you are using AutoModelForSeq2SeqLM.

@CloseChoice
Copy link
Collaborator

@Yangliule could you please show the versions that are working?

@Yangliule
Copy link

Hey @CloseChoice , I'm using transformers 4.12.0 and torch 1.10. Basically I reverted back to when the text SHAP feature was added.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
awaiting feedback Indicates that further information is required from the issue creator bug Indicates an unexpected problem or unintended behaviour
Projects
None yet
Development

No branches or pull requests

3 participants