Source code for xailib.explainers.lore_explainer

from xailib.xailib_tabular import TabularExplainer, TabularExplanation
from xailib.models.bbox import AbstractBBox
import pandas as pd
from lore_explainer.datamanager import prepare_dataset
from lore_explainer.lorem import LOREM
from lore_explainer.explanation import ExplanationEncoder
import json
from IPython.display import HTML


[docs] class LoreTabularExplanation(TabularExplanation): def __init__(self, lore_exp): super().__init__() self.exp = lore_exp self.expDict = json.loads(json.dumps(self.exp, cls=ExplanationEncoder))
[docs] def getFeaturesImportance(self): return None
[docs] def getExemplars(self): return None
[docs] def getCounterExemplars(self): return None
[docs] def getRules(self): return self.expDict['rule']
[docs] def getCounterfactualRules(self): return self.expDict['crules']
[docs] def plotRules(self): htmlStyle=HTML(""" <style> .red { background-color:firebrick; padding:3px 5px 3px 5px; border-radius:5px; color:white; } .rules{ margin-top:10px; font-weight: 400; } .rule{ padding:5px 20px 5px 20px; border-radius:5px; margin-right:5px; font-size:12px; line-height:20px; display: block; margin-bottom: 10px; width: fit-content; color:white; background-color:firebrick; opacity:0.8; } </style> """ ) htmlPrediction=HTML( ''' <h3>Why the predicted value for class <span class='red'>%s</span> is <span class='red'>%s</span> ?</h3> '''%(self.expDict['rule']['class_name'],self.expDict['rule']['cons']) ) htmlExplanation=HTML(''' <p>Because all the following conditions happen:</p> ''') rulesSpans="" for el in self.expDict['rule']['premise']: rulesSpans+="<span class='rule'>"+el['att'].replace("_"," ")+ " <strong>" + el['op']+ "</strong> "+ str("%.2f" %el['thr'])+"</span>" htmlRules=HTML("<p class='rules'>%s</p>"%(rulesSpans)) display(htmlStyle) display(htmlPrediction) display(htmlExplanation) display(htmlRules)
[docs] def plotCounterfactualRules(self): htmlStyle=HTML(""" <style> .red { background-color:firebrick; padding:3px 5px 3px 5px; border-radius:5px; color:white; } .crules{ margin-top:10px; font-weight: 400; } .crule{ padding:5px 20px 5px 20px; border-radius:5px; margin-right:5px; font-size:12px; line-height:20px; display: block; margin-bottom: 10px; width: fit-content; color:#202020; background-color:gold; } </style> """ ) display(htmlStyle) htmlTitleCRules=HTML(''' <h3>The predicted value for class <span class='red'>%s</span> is <span class='red'>%s</span>.</h3> <h3>It would have been:</h3> '''%(self.expDict['rule']['class_name'], self.expDict['bb_pred']) ) display(htmlTitleCRules) cRulesDiv='' for idx,el in enumerate(self.expDict['crules']): cRulesTitle= el['cons'] cRulesSpans="" for p in el['premise']: cRulesSpans+="<span class='crule'>"+p['att'].replace("_"," ")+ " " + p['op']+ " "+ str("%.2f" %p['thr'])+"</span>" display(HTML(''' <div class='crules'> <div> <h4><span class='red'>%s</span> if the following condition holds</h4> </br>%s </div> </div> '''%(cRulesTitle,cRulesSpans)) )
[docs] class LoreTabularExplainer(TabularExplainer): lore_explainer = None random_state = 0 bb = None # The Black Box to be explained def __init__(self, bb: AbstractBBox): super().__init__() self.bb = bb
[docs] def fit(self, _df: pd.DataFrame, class_name, config): df, feature_names, class_values, numeric_columns, \ rdf, real_feature_names, features_map = prepare_dataset(_df, class_name) neigh_type = config['neigh_type'] if 'neigh_type' in config else 'geneticp' size = config['size'] if 'size' in config else 1000 ocr = config['ocr'] if 'ocr' in config else 0.1 ngen = config['ngen'] if 'ngen' in config else 10 self.lore_explainer = LOREM(rdf[real_feature_names].values, self.bb.predict, feature_names, class_name, class_values, numeric_columns, features_map, neigh_type=neigh_type, categorical_use_prob=True, continuous_fun_estimation=False, size=size, ocr=ocr, random_state=self.random_state, ngen=ngen, bb_predict_proba=self.bb.predict_proba, verbose=False)
[docs] def explain(self, x): exp = self.lore_explainer.explain_instance(x, samples=1000, use_weights=True) return LoreTabularExplanation(exp)