Source code for pyreal.explanation_types.example_based

import pandas as pd

from pyreal.explanation_types.base import Explanation, convert_columns_with_dict


[docs]class ExampleBasedExplanation(Explanation): """ A type wrapper for example-based type outputs from explanation algorithms. Example-based types include dictionary linking input rows to DataFrames, and optionally a second dictionary linking the same input rows to Series, where the DataFrames are examples (X) for the corresponding row and the Series are the corresponding target (y) values. The row order wil depend on the specific input type. """ def validate(self): """ Validate that `self.explanation` is of the expected format. Returns: None Raises: AssertionException if `self.explanation` is invalid """ try: example_dict = self.explanation[0] target_dict = self.explanation[1] except TypeError: raise AssertionError( "Example explanations expect a tuple of example-dictionary and target-dictionary" ) if not isinstance(example_dict, dict): raise AssertionError("Example explanations must contain a dictionary of DataFrames") for row_id in example_dict: if not isinstance(example_dict[row_id], pd.DataFrame): raise AssertionError( "All items in example explanations' example dicts must be DataFrames." ) if target_dict is not None and not isinstance(target_dict, dict): raise AssertionError("Example explanation given invalid target dict.") for row_id in target_dict: if not isinstance(target_dict[row_id], pd.Series): raise AssertionError( "All items in example explanations' target dicts must be Series." ) super().validate() def apply_feature_descriptions(self, feature_descriptions): """ Apply feature descriptions to examples Args: feature_descriptions (dict): Dictionary mapping feature names to interpretable descriptions Returns: None """ def func(df): return convert_columns_with_dict(df, feature_descriptions) # Similar examples apply descriptions at produce for optimizations if not isinstance(self, SimilarExampleExplanation): self.update_examples(func) super().apply_feature_descriptions(feature_descriptions) def get_examples(self, row_id=0, rank=None): """ Get the example in rank-th position for the given row_id. Args: row_id (int): ID of row to get explanation of. rank (int): Which example to return (ie, rank=0 returns the first example generated). If none, return all examples Returns: DataFrame Examples for the chosen row_id """ if rank is None: return self.get()[0][row_id] return self.get()[0][row_id].iloc[rank] def get_targets(self, row_id=0, rank=None): """ Get the targets in rank-th position for the given row_id. Args: row_id (int): ID of row to get explanation of. rank (int): Which example to return (ie, rank=0 returns the first example generated). If none, return all examples Returns: Series targets for the chosen row_id """ if rank is None: return self.get()[1][row_id] return self.get()[1][row_id].iloc[rank] def get_row_ids(self): """ Return all row_ids held by this explanation """ return self.get()[0].keys() def update_examples(self, func, inplace=False): """ Update every example using the provided function Args: func (function): Function to apply to every example inplace (Boolean): If True, change the explanation on this object. Otherwise, create a new object identical to this one but with a new explanation Returns: Explanation `self` if `inplace=True`, else the new Explanation object. """ examples = {} for key in self.get()[0]: if inplace: self.get()[0][key] = func(self.get()[0][key]) else: examples[key] = func(self.get()[0][key]) if inplace: explanation = (examples, self.get()[1]) return self.__class__(explanation, self.values) else: return self
[docs]class SimilarExampleExplanation(ExampleBasedExplanation): """ A type wrapper for explanations that include most similar rows from the training set. Contains a dict of dataframes """ def validate(self): """ Validate that `self.explanation` is a valid dict of `DataFrames` Returns: None Raises: AssertionException if `self.explanation` is invalid """ if self.explanation[1] is None: raise AssertionError("Similar example explanations must come with target values.") super().validate() def apply_feature_descriptions(self, feature_descriptions): """ No-op because feature descriptions are applied at produce time for similar examples explanation, to improve performance Args: feature_descriptions: Returns: None """ super().apply_feature_descriptions(feature_descriptions)
class CounterfactualExplanation(ExampleBasedExplanation): """ A type wrapper for explanations that include most similar rows from the training set. Contains a dict of dataframes """ def __init__(self, explanation, values=None): """ Set the wrapped explanation to `explanation` and values to `values` and validate Args: explanation (object): wrapped explanation values (DataFrame of shape (n_instances, n_features) or None): Values corresponding with the object being explained """ explanation = (explanation, None) super().__init__(explanation, values) def validate(self): """ Validate that `self.explanation` is a valid dict of `DataFrames` Returns: None Raises: AssertionException if `self.explanation` is invalid """ super().validate()