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
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)
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}
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
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)
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}