SHAP with a self-defined function

Question:

For example, I have a self defined function

def f(x):
  ## x is a 3D vector
  return x[0] + 2*x[1] - 3*x[2]

data = np.random.rand(10,3)

explainer = shap.Explainer(f)

shap_values = explainer(data)

The last line gives the following error

TypeError                                 Traceback (most recent call last)
/tmp/ipykernel_16518/3954986287.py in <module>
----> 1 shap_values = explainer(data)

/opt/oss/conda3/lib/python3.7/site-packages/shap/explainers/_permutation.py in __call__(self, max_evals, main_effects, error_bounds, batch_size, outputs, silent, *args)
     74         return super().__call__(
     75             *args, max_evals=max_evals, main_effects=main_effects, error_bounds=error_bounds, batch_size=batch_size,
---> 76             outputs=outputs, silent=silent
     77         )
     78 

/opt/oss/conda3/lib/python3.7/site-packages/shap/explainers/_explainer.py in __call__(self, max_evals, main_effects, error_bounds, batch_size, outputs, silent, *args, **kwargs)
    258             row_result = self.explain_row(
    259                 *row_args, max_evals=max_evals, main_effects=main_effects, error_bounds=error_bounds,
--> 260                 batch_size=batch_size, outputs=outputs, silent=silent, **kwargs
    261             )
    262             values.append(row_result.get("values", None))

/opt/oss/conda3/lib/python3.7/site-packages/shap/explainers/_permutation.py in explain_row(self, max_evals, main_effects, error_bounds, batch_size, outputs, silent, *row_args)
    130 
    131                 # evaluate the masked model
--> 132                 outputs = fm(masks, zero_index=0, batch_size=batch_size)
    133 
    134                 if row_values is None:

/opt/oss/conda3/lib/python3.7/site-packages/shap/utils/_masked_model.py in __call__(self, masks, zero_index, batch_size)
     62                 full_masks = np.zeros((int(np.sum(masks >= 0)), self._masker_cols), dtype=np.bool)
     63                 _convert_delta_mask_to_full(masks, full_masks)
---> 64                 return self._full_masking_call(full_masks, zero_index=zero_index, batch_size=batch_size)
     65 
     66         else:

/opt/oss/conda3/lib/python3.7/site-packages/shap/utils/_masked_model.py in _full_masking_call(self, masks, zero_index, batch_size)
     91                     masked_inputs = self.masker(delta_ind, *self.args).copy()
     92                 else:
---> 93                     masked_inputs = self.masker(mask, *self.args)
     94 
     95                 # wrap the masked inputs if they are not already in a tuple

TypeError: 'NoneType' object is not callable
Asked By: user1901690

||

Answers:

After some changes, it works now.

def f(x):
  ## x is a 3D vector
  return x[:, 0] + 2*x[:,1] - 3*x[:,2]

data = np.random.rand(10,3)

explainer = shap.KernelExplainer(f, data)

shap_values = explainer.shap_values(data)
Answered By: user1901690

This works for me:

def f(x):
  ## x is a 3D vector
  return x[:, 0] + 2*x[:,1] - 3*x[:,2]

data = np.random.rand(10,3)
explainer = shap.Explainer(f, data, algorithm='permutation')
shap_values = explainer(data)
print(shap_values)

Outputs:

.values =
array([[ 0.23537819,  0.0606696 , -0.21229479],
       [-0.16138455, -0.83381384, -0.21107154],
       [ 0.07831417, -0.22484657,  0.10450653],
       [-0.32232342,  1.05445985, -0.63448369],
       [ 0.20923138,  0.29177588,  0.56478016],
       [ 0.0463936 ,  0.79051488, -0.19142801],
       [ 0.30677047, -0.51483703,  1.50863618],
       [-0.25096378, -0.12473288, -1.29590395],
       [-0.3577495 , -0.01636693, -0.04306942],
       [ 0.21633345, -0.48282296,  0.41032853]])

.base_values =
array([-0.2995886, -0.2995886, -0.2995886, -0.2995886, -0.2995886,
       -0.2995886, -0.2995886, -0.2995886, -0.2995886, -0.2995886])

.data =
array([[0.72822002, 0.47841992, 0.63363182],
       [0.33145728, 0.0311782 , 0.63322407],
       [0.571156  , 0.33566183, 0.52803138],
       [0.17051841, 0.97531504, 0.77436145],
       [0.70207321, 0.59397305, 0.37460683],
       [0.53923543, 0.84334256, 0.62667622],
       [0.7996123 , 0.1906666 , 0.05998816],
       [0.24187806, 0.38571868, 0.99483487],
       [0.13509234, 0.43990165, 0.57722336],
       [0.70917529, 0.20667363, 0.42609071]])

And to explain one sample:

explainer.explain_row(
    data[0],
    batch_size=1,
    max_evals=10,
    main_effects=True,
    error_bounds=True,
    outputs=True,
    silent=True
)

Outputs:

{'values': array([ 0.23537819,  0.0606696 , -0.21229479]),
 'expected_values': -0.2995885959832238,
 'mask_shapes': [(3,)],
 'main_effects': array([ 0.23537819,  0.0606696 , -0.21229479]),
 'clustering': None,
 'error_std': array([5.55111512e-17, 5.55111512e-17, 0.00000000e+00]),
 'output_names': None}
Answered By: Iván Sánchez
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.