interpretml / DiCE

Generate Diverse Counterfactual Explanations for any machine learning model.
https://interpretml.github.io/DiCE/
MIT License
1.36k stars 188 forks source link

InvalidArgumentError: Input is not invertible. [Op:MatrixInverse] #11

Closed sina-salek closed 4 years ago

sina-salek commented 4 years ago

Hi again, I understand you must be extremely busy. I appreciate your time.

I was now trying to use the same ANN model as in your notebook, but with the German credit data. The model trains fine. But I get the following error message when I try to run the line: dice_exp = exp.generate_counterfactuals(query_instance, total_CFs=4, desired_class=1)

I have copier the entire error message below. Thanks

divide by zero encountered in double_scalars

InvalidArgumentError Traceback (most recent call last)

in 1 # generate counterfactuals ----> 2 dice_exp = exp.generate_counterfactuals(query_instance, total_CFs=4, desired_class=1) ~\Anaconda3\lib\site-packages\dice_ml\dice_interfaces\dice_tensorflow2.py in generate_counterfactuals(self, query_instance, total_CFs, desired_class, proximity_weight, diversity_weight, categorical_penalty, algorithm, features_to_vary, yloss_type, diversity_loss_type, feature_weights, optimizer, learning_rate, min_iter, max_iter, project_iter, loss_diff_thres, loss_converge_maxiter, verbose, init_near_query_instance, tie_random, stopping_threshold, posthoc_sparsity_param) 92 self.update_hyperparameters(proximity_weight, diversity_weight, categorical_penalty) 93 ---> 94 query_instance, test_pred = self.find_counterfactuals(query_instance, desired_class, optimizer, learning_rate, min_iter, max_iter, project_iter, loss_diff_thres, loss_converge_maxiter, verbose, init_near_query_instance, tie_random, stopping_threshold, posthoc_sparsity_param) 95 96 return exp.CounterfactualExamples(self.data_interface, query_instance, ~\Anaconda3\lib\site-packages\dice_ml\dice_interfaces\dice_tensorflow2.py in find_counterfactuals(self, query_instance, desired_class, optimizer, learning_rate, min_iter, max_iter, project_iter, loss_diff_thres, loss_converge_maxiter, verbose, init_near_query_instance, tie_random, stopping_threshold, posthoc_sparsity_param) 418 419 # get gradients --> 420 grads = tape.gradient(loss_value, self.cfs) 421 422 # freeze features other than feat_to_vary_idxs ~\Anaconda3\lib\site-packages\tensorflow_core\python\eager\backprop.py in gradient(self, target, sources, output_gradients, unconnected_gradients) 1027 output_gradients=output_gradients, 1028 sources_raw=flat_sources_raw, -> 1029 unconnected_gradients=unconnected_gradients) 1030 1031 if not self._persistent: ~\Anaconda3\lib\site-packages\tensorflow_core\python\eager\imperative_grad.py in imperative_grad(tape, target, sources, output_gradients, sources_raw, unconnected_gradients) 75 output_gradients, 76 sources_raw, ---> 77 compat.as_str(unconnected_gradients.value)) ~\Anaconda3\lib\site-packages\tensorflow_core\python\eager\backprop.py in _gradient_function(op_name, attr_tuple, num_inputs, inputs, outputs, out_grads, skip_input_indices) 139 return [None] * num_inputs 140 --> 141 return grad_fn(mock_op, *out_grads) 142 143 ~\Anaconda3\lib\site-packages\tensorflow_core\python\ops\linalg_grad.py in _MatrixDeterminantGrad(op, grad) 362 a = op.inputs[0] 363 c = op.outputs[0] --> 364 a_adj_inv = linalg_ops.matrix_inverse(a, adjoint=True) 365 multipliers = array_ops.reshape(grad * c, 366 array_ops.concat([array_ops.shape(c), [1, 1]], ~\Anaconda3\lib\site-packages\tensorflow_core\python\ops\gen_linalg_ops.py in matrix_inverse(input, adjoint, name) 1401 raise 1402 except _core._NotOkStatusException as e: -> 1403 _ops.raise_from_not_ok_status(e, name) 1404 # Add nodes to the TensorFlow graph. 1405 if adjoint is None: ~\Anaconda3\lib\site-packages\tensorflow_core\python\framework\ops.py in raise_from_not_ok_status(e, name) 6604 message = e.message + (" name: " + name if name is not None else "") 6605 # pylint: disable=protected-access -> 6606 six.raise_from(core._status_to_exception(e.code, message), None) 6607 # pylint: enable=protected-access 6608 ~\Anaconda3\lib\site-packages\six.py in raise_from(value, from_value) InvalidArgumentError: Input is not invertible. [Op:MatrixInverse]
raam93 commented 4 years ago

Not sure why this error occurs, it's hard to say without looking at the code. Can you share your full code? It worked for me with the German credit data. Below is the code:

import dice_ml
from dice_ml.utils import helpers # helper functions
import tensorflow as tf

german = pd.read_csv('german_credit.csv')

german['credits_this_bank']= german['credits_this_bank'].astype(str) # has only 4 values - converting to categorical just for better results.
german['people_under_maintenance']= german['people_under_maintenance'].astype(str)
german_dtypes = german.columns.to_series().groupby(german.dtypes).groups
german_dtypes = {k.name: v.tolist() for k, v in german_dtypes.items()}

continuous_features = german_dtypes['int64']
continuous_features = [feat for feat in continuous_features if feat != 'default']
print(continuous_features) #['duration_in_month', 'credit_amount', 'installment_as_income_perc', 'present_res_since', 'age']

d = dice_ml.Data(dataframe=german, continuous_features=continuous_features, outcome_name='default')

query_instance = {'duration_in_month': 24.0,
 'credit_amount': 1747.0,
 'installment_as_income_perc': 4.0,
 'present_res_since': 1.0,
 'age': 24.0,
 'account_check_status': '< 0 DM',
 'credit_history': 'existing credits paid back duly till now',
 'purpose': 'radio/television',
 'savings': '... < 100 DM',
 'present_emp_since': '... < 1 year ',
 'personal_status_sex': 'male : single',
 'other_debtors': 'co-applicant',
 'property': 'if not A121 : building society savings agreement/ life insurance',
 'other_installment_plans': 'none',
 'housing': 'own',
 'credits_this_bank': '1',
 'job': 'unskilled - resident',
 'people_under_maintenance': '1',
 'telephone': 'none',
 'foreign_worker': 'no'}

backend = 'TF'+tf.__version__[0] # TF2
print(backend)
m = dice_ml.Model(model_path= 'german_dice_ann.h5', backend=backend)
print(m.model.summary()) # trained on a neural net with 1 hidden layer of 20 neurons

dice_exp = exp.generate_counterfactuals(query_instance, total_CFs=4, desired_class="opposite", verbose=0)
dice_exp.visualize_as_dataframe(show_only_changes=True) # outputs 4 valid CFs

Let me know if you still face any difficulty.

sina-salek commented 4 years ago

Hmm! I'm not sure what happened. I just ran my own code and it works fine! Not sure what the problem was yesterday! Thanks again for your time.