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

BUG: SHAP fails when running on transformers for QA #3328

Open
3 of 4 tasks
mnishant2 opened this issue Oct 12, 2023 · 0 comments
Open
3 of 4 tasks

BUG: SHAP fails when running on transformers for QA #3328

mnishant2 opened this issue Oct 12, 2023 · 0 comments
Labels
bug Indicates an unexpected problem or unintended behaviour

Comments

@mnishant2
Copy link

mnishant2 commented Oct 12, 2023

Issue Description

When running [SHAP for QA] on transformer models(BERT) trained for Question Answering on the SQuaD dataset, it throws an error. When masking the input it spuriously breaks names/last names into two parts/tokens and when either part is masked, the output size of the model on the masked input(question+[sep]+context) changes leading to concatenation error due to non-homogenous shape. It is also mostly observed only with the questions and not context. It is seemingly an edge-case issue and is seen ONLY for proper names.

Minimal Reproducible Example

Example data
Context: The Review of Politics was founded in 1939 by Gurian, modeled after German Catholic journals. It quickly emerged as part of an international Catholic intellectual revival, offering an alternative vision to positivist philosophy. For 44 years, the Review was edited by Gurian, Matthew Fitzsimons, Frederick Crosson, and Thomas Stritch. Intellectual leaders included Gurian, Jacques Maritain, Frank O'Malley, Leo Richard Ward, F. A. Hermens, and John U. Nef. It became a major forum for political ideas and modern political concerns, especially from a Catholic and scholastic tradition.
Question: Gurian created what in 1939 at Notre Dame?

The iteration(masked batch) which gives the error for this example has the following two masked inputs(with their sizes, and context removed for brevity) in the batch which give variable-sized outputs leading to the error shown in traceback
["Gu [MASK]created what in 1939 at Notre Dame?[SEP]The Review of Politics was .....] 633
["[MASK]rian created what in 1939 at Notre Dame?[SEP]The Review of Politics was ......"] 635
As you can see, the only difference is how the name Gurian is tokenized and masked.

Another example is "Which individual offered land to Father Edward Sorin?"(original question)
["Which individual offered land to Father Edward So [MASK] [MASK][SEP].....] 637 
["Which individual offered land to Father Edward [MASK]rin [MASK][SEP].....] 637
Here the inputs are the same size but the name Sorin is broken and masked differently and the outputs differ in dimension.

These can be reproduced by running shap for transformers in QA(https://shorturl.at/dnLQ0) on a pre-trained (BERT) model on the SQuAD dataset.

Traceback

ValueError                                Traceback (most recent call last)
/home/nmishra/semantic_match/debug_shap.ipynb Cell 9 line 1
      9 start_time = time.time()
     10 explainer_start = shap.Explainer(f_start, model.tokenizer, seed=42)
---> 11 shap_values_start = explainer_start(data)
     12 elapsed = time.time() - start_time

File ~/miniconda/lib/python3.10/site-packages/shap/explainers/_partition.py:128, in Partition.__call__(self, max_evals, fixed_context, main_effects, error_bounds, batch_size, outputs, silent, *args)
    124 def __call__(self, *args, max_evals=500, fixed_context=None, main_effects=False, error_bounds=False, batch_size="auto",
    125              outputs=None, silent=False):
    126     """ Explain the output of the model on the given arguments.
    127     """
--> 128     return super().__call__(
    129         *args, max_evals=max_evals, fixed_context=fixed_context, main_effects=main_effects, error_bounds=error_bounds, batch_size=batch_size,
    130         outputs=outputs, silent=silent
    131     )

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

File ~/miniconda/lib/python3.10/site-packages/shap/explainers/_partition.py:176, in Partition.explain_row(self, max_evals, main_effects, error_bounds, batch_size, outputs, silent, fixed_context, *row_args)
    173 self.values = np.zeros(out_shape)
    174 self.dvalues = np.zeros(out_shape)
--> 176 self.owen(fm, self._curr_base_value, f11, max_evals - 2, outputs, fixed_context, batch_size, silent)
    178 # if False:
    179 #     if self.multi_output:
    180 #         return [self.dvalues[:,i] for i in range(self.dvalues.shape[1])], oinds
   (...)
    183 # else:
    184 # drop the interaction terms down onto self.values
    185 self.values[:] = self.dvalues

File ~/miniconda/lib/python3.10/site-packages/shap/explainers/_partition.py:288, in Partition.owen(self, fm, f00, f11, max_evals, output_indexes, fixed_context, batch_size, silent)
    286 # run the batch
    287 if len(batch_args) > 0:
--> 288     fout = fm(batch_masks)
    289     if output_indexes is not None:
    290         fout = fout[:,output_indexes]

File ~/miniconda/lib/python3.10/site-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 ~/miniconda/lib/python3.10/site-packages/shap/utils/_masked_model.py:152, in MaskedModel._full_masking_call(self, masks, zero_index, batch_size)
    149     _assert_output_input_match(joined_masked_inputs, outputs)
    150     all_outputs.append(outputs)
--> 152 outputs = np.concatenate(all_outputs)
    154 if self.linearize_link and self.link != links.identity and self._linearizing_weights is None:
    155     self.background_outputs = outputs[batch_positions[zero_index]:batch_positions[zero_index+1]]

File <__array_function__ internals>:200, in concatenate(*args, **kwargs)

ValueError: setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions. The detected shape was (6,) + inhomogeneous part.

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

0.42.1

@mnishant2 mnishant2 added the bug Indicates an unexpected problem or unintended behaviour label Oct 12, 2023
@mnishant2 mnishant2 changed the title BUG: BUG: SHAP fails when running on transformers for QA Oct 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Indicates an unexpected problem or unintended behaviour
Projects
None yet
Development

No branches or pull requests

1 participant