Skip to content

Naive CounterFactuals

View colab tutorial | View source | 📰 Paper

Note

The paper referenced here is not exactly the one we implemented as we use a "naive" version of it. However, it is probably the closest in essence of what we implemented.

We define here a "naive" counterfactual method that is based on the Nearest Unlike Neighbor (NUN) concept introduced by Dasarathy in 1991[^1]. In essence, the NUN of a sample \((x, y)\) is the closest sample in the training dataset which has a different label than \(y\).

Thus, in this naive approach to counterfactuals, we yield the \(k\) nearest training instances that have a different label than the target of the input sample in a greedy fashion.

As it is mentioned in the API documentation, by setting a Projection object, one will map the inputs to a space where the distance function is meaningful.

Example

from xplique.example_based import NaiveCounterFactuals
from xplique.example_based.projections import LatentSpaceProjection

# load the training dataset and the model
cases_dataset = ... # load the training dataset
targets_dataset = ... # load the one-hot encoding of predicted labels of the training dataset
model = ...

# load the test samples
test_samples = ... # load the test samples to search for
test_targets = ... # compute a one hot encoding of the model's prediction on the samples

# parameters
k = 5  # number of example for each input
case_returns = "all"  # elements returned by the explain function
distance = "euclidean"
latent_layer = "last_conv"  # where to split your model for the projection

# construct a projection with your model
projection = LatentSpaceProjection(model, latent_layer=latent_layer)

# instantiate the NaiveCounterFactuals object
ncf = NaiveCounterFactuals(
    cases_dataset=cases_dataset,
    targets_dataset=targets_dataset,
    k=k,
    projection=projection,
    case_returns=case_returns,
    distance=distance,
)

# search the CFs for the test samples
output_dict = ncf.explain(
    inputs=test_samples,
    targets=test_targets,
)

Notebooks

NaiveCounterFactuals

This class allows to search for counterfactuals by searching for the closest sample to a query in a projection space that do not have the same model's prediction. It is a naive approach as it follows a greedy approach.

__init__(self,
         cases_dataset: ~DatasetOrTensor,
         targets_dataset: ~DatasetOrTensor,
         labels_dataset: Optional[~DatasetOrTensor] = None,
         k: int = 1,
         projection: Union[xplique.example_based.projections.base.Projection, Callable] = None,
         case_returns: Union[List[str], str] = 'examples',
         batch_size: Optional[int] = None,
         distance: Union[int, str, Callable] = 'euclidean')

Parameters

  • cases_dataset : ~DatasetOrTensor

    • The dataset used to train the model, examples are extracted from this dataset.

      All datasets (cases, labels, and targets) should be of the same type.

      Supported types are: tf.data.Dataset, torch.utils.data.DataLoader, tf.Tensor, np.ndarray, torch.Tensor.

      For datasets with multiple columns, the first column is assumed to be the cases.

      While the second column is assumed to be the labels, and the third the targets.

      Warning: datasets tend to reshuffle at each iteration, ensure the datasets are not reshuffle as we use index in the dataset.

  • targets_dataset : ~DatasetOrTensor

    • Targets associated with the cases_dataset for dataset projection, oftentimes the one-hot encoding of a model's predictions. See projection for detail.

      They are also used to know the prediction of the model on the dataset.

      It should have the same type as cases_dataset.

  • labels_dataset : Optional[~DatasetOrTensor] = None

    • Labels associated with the examples in the cases_dataset.

      It should have the same type as cases_dataset.

  • k : int = 1

    • The number of examples to retrieve per input.

  • projection : Union[xplique.example_based.projections.base.Projection, Callable] = None

    • Projection or Callable that project samples from the input space to the search space.

      The search space should be a space where distances are relevant for the model.

      It should not be None, otherwise, the model is not involved thus not explained. Example of Callable: def custom_projection(inputs: tf.Tensor, np.ndarray, targets: tf.Tensor, np.ndarray = None): ''' Example of projection, inputs are the elements to project.</p><p> targets are optional parameters to orientated the projection.</p><p> ''' projected_inputs = # do some magic on inputs, it should use the model.</p><p> return projected_inputs

  • case_returns : Union[List[str], str] = 'examples'

    • String or list of string with the elements to return in self.explain().

      See the base class returns property for more details.

  • batch_size : Optional[int] = None

    • Number of samples treated simultaneously for projection and search.

      Ignored if cases_dataset is a batched tf.data.Dataset or a batched torch.utils.data.DataLoader is provided.

  • distance : Union[int, str, Callable] = 'euclidean'

    • Distance function for examples search. It can be an integer, a string in {"manhattan", "euclidean", "cosine", "chebyshev", "inf"}, or a Callable, by default "euclidean".

explain(self,
        inputs: Union[tensorflow.python.framework.tensor.Tensor, numpy.ndarray],
        targets: Union[tensorflow.python.framework.tensor.Tensor, numpy.ndarray, None] = None)

Return the relevant examples to explain the (inputs, targets). It projects inputs with self.projection in the search space and find examples with the self.search_method.

Parameters

  • inputs : Union[tensorflow.python.framework.tensor.Tensor, numpy.ndarray]

    • Tensor or Array. Input samples to be explained.

      Expected shape among (N, W), (N, T, W), (N, W, H, C).

      More information in the documentation.

  • targets : Union[tensorflow.python.framework.tensor.Tensor, numpy.ndarray, None] = None

    • Targets associated to the inputs for projection.

      Shape: (n, nb_classes) where n is the number of samples and nb_classes is the number of classes.

      It is used in the projection. But projection can compute it internally.

Return

  • return_dict

    • Dictionary with listed elements in self.returns.

      The elements that can be returned are defined with the _returns_possibilities static attribute of the class.


filter_fn(self,
          _,
          __,
          targets,
          cases_targets) -> tensorflow.python.framework.tensor.Tensor

Filter function to mask the cases for which the model's prediction is different from the model's prediction on the inputs.


[^1] Nearest unlike neighbor (NUN): an aid to decision making