2
2
Module to generate diverse counterfactual explanations based on genetic algorithm
3
3
This code is similar to 'GeCo: Quality Counterfactual Explanations in Real Time': https://arxiv.org/pdf/2101.01292.pdf
4
4
"""
5
- import copy
6
- import random
7
- import timeit
8
-
5
+ from dice_ml .explainer_interfaces .explainer_base import ExplainerBase
9
6
import numpy as np
10
7
import pandas as pd
8
+ import random
9
+ import timeit
10
+ import copy
11
11
from sklearn .preprocessing import LabelEncoder
12
12
13
13
from dice_ml import diverse_counterfactuals as exp
14
14
from dice_ml .constants import ModelTypes
15
- from dice_ml .explainer_interfaces .explainer_base import ExplainerBase
16
15
17
16
18
17
class DiceGenetic (ExplainerBase ):
@@ -116,9 +115,8 @@ def do_random_init(self, num_inits, features_to_vary, query_instance, desired_cl
116
115
def do_KD_init (self , features_to_vary , query_instance , cfs , desired_class , desired_range ):
117
116
cfs = self .label_encode (cfs )
118
117
cfs = cfs .reset_index (drop = True )
119
-
120
- self .cfs = np .zeros ((self .population_size , self .data_interface .number_of_features ))
121
- for kx in range (self .population_size ):
118
+ row = []
119
+ for kx in range (self .population_size * 5 ):
122
120
if kx >= len (cfs ):
123
121
break
124
122
one_init = np .zeros (self .data_interface .number_of_features )
@@ -143,16 +141,21 @@ def do_KD_init(self, features_to_vary, query_instance, cfs, desired_class, desir
143
141
one_init [jx ] = query_instance [jx ]
144
142
else :
145
143
one_init [jx ] = np .random .choice (self .feature_range [feature ])
146
- self .cfs [kx ] = one_init
144
+ t = tuple (one_init )
145
+ if t not in row :
146
+ row .append (t )
147
+ if len (row ) == self .population_size :
148
+ break
147
149
kx += 1
150
+ self .cfs = np .array (row )
148
151
149
- new_array = [ tuple ( row ) for row in self .cfs ]
150
- uniques = np . unique ( new_array , axis = 0 )
151
-
152
- if len ( uniques ) != self . population_size :
152
+ #if len(self.cfs) > self.population_size:
153
+ # pass
154
+ if len ( self . cfs ) != self . population_size :
155
+ print ( "Pericolo Loop infinito....!!!!" )
153
156
remaining_cfs = self .do_random_init (
154
- self .population_size - len (uniques ), features_to_vary , query_instance , desired_class , desired_range )
155
- self .cfs = np .concatenate ([uniques , remaining_cfs ])
157
+ self .population_size - len (self . cfs ), features_to_vary , query_instance , desired_class , desired_range )
158
+ self .cfs = np .concatenate ([self . cfs , remaining_cfs ])
156
159
157
160
def do_cf_initializations (self , total_CFs , initialization , algorithm , features_to_vary , desired_range ,
158
161
desired_class ,
@@ -260,7 +263,7 @@ def _generate_counterfactuals(self, query_instance, total_CFs, initialization="k
260
263
(see diverse_counterfactuals.py).
261
264
"""
262
265
263
- self .population_size = 10 * total_CFs
266
+ self .population_size = 3 * total_CFs
264
267
265
268
self .start_time = timeit .default_timer ()
266
269
@@ -514,6 +517,9 @@ def find_counterfactuals(self, query_instance, desired_range, desired_class,
514
517
if len (self .final_cfs ) == self .total_CFs :
515
518
print ('Diverse Counterfactuals found! total time taken: %02d' %
516
519
m , 'min %02d' % s , 'sec' )
520
+ elif len (self .final_cfs ) == 0 :
521
+ print ('No Counterfactuals found for the given configuration, perhaps try with different parameters...' ,
522
+ '; total time taken: %02d' % m , 'min %02d' % s , 'sec' )
517
523
else :
518
524
print ('Only %d (required %d) ' % (len (self .final_cfs ), self .total_CFs ),
519
525
'Diverse Counterfactuals found for the given configuation, perhaps ' ,
0 commit comments