peal.explainers.counterfactual_explainer.CounterfactualExplainer

class peal.explainers.counterfactual_explainer.CounterfactualExplainer[source]

Bases: ExplainerInterface

This class implements the counterfactual explanation method

Methods

calculate_latent_difference_stats

Measure how sparse and how diverse the counterfactual edits are.

cluster_explanations

This function clusters the explanations.

explain_batch

This function generates a counterfactual for a given batch of inputs.

human_annotate_explanations

Collect free-text human feedback on counterfactual collages.

perfect_false_counterfactuals

This function generates a counterfactual for a given batch of inputs.

predictor_distilled_counterfactual

This function generates a counterfactual for a given batch of inputs.

predictor_distilled_counterfactual_step

Run one gradient step of the SCE counterfactual optimisation.

run

This function runs the explainer.

visualize_interpretations

Turn the collected feedback into one bar chart per class pair.

Attributes

explainer_config

__init__(explainer_config, predictor=None, generator=None, input_type=None, datasource=None, tracking_level=None, test_data_config=None, datasets=None)[source]

This class implements the counterfactual explanation method

Parameters:
  • explainer_config (Union[ dict, str ], optional) – _description_. .

  • predictor (nn.Module) – _description_

  • generator (InvertibleGenerator) – _description_

  • input_type (str) – _description_

  • datasets (list[PealDataset]) – _description_

  • datasource (list)

  • tracking_level (int)

  • test_data_config (str)

perfect_false_counterfactuals(x_in, target_classes, idx_list, mode)[source]

This function generates a counterfactual for a given batch of inputs.

Parameters:

batch (_type_) – _description_

Returns:

_description_

Return type:

_type_

predictor_distilled_counterfactual(x_in, y_target, target_confidence_goal=None, pbar=None, mode='', base_path=None, batch_idx=0, num_attempts=1)[source]

This function generates a counterfactual for a given batch of inputs.

Parameters:

batch (_type_) – _description_

Returns:

_description_

Return type:

_type_

predictor_distilled_counterfactual_step(x_original, optimizer, y_target, i, boolmask_in, gradient_predictor, mode, pbar, batch_idx, x_in, num_attempts, base_path, z_original, best_score, best_z, z, best_mask, target_confidence_goal_current, not_finished_mask, gradient_confidences_old, to_generator, to_predictor, start_activations)[source]

Run one gradient step of the SCE counterfactual optimisation.

The optimised variable z is decoded (through the generator when use_gradient_filtering is set, otherwise it already lives in image space), normalised for the predictor and scored. The loss is the distillation predictor’s classification loss towards y_target, plus an L1 penalty on the distance to z_original and, when orthogonalization_penatly is set, a Frobenius penalty pushing the penultimate-activation changes of the batch towards orthogonality (this is what makes a batch of attempts diverse).

After the optimiser step the sample is optionally repainted with the generator so that everything outside the change mask returns to the original, the new target confidences are measured with the real predictor, and every sample that improved on its previous best is recorded. Samples that reached their confidence goal are switched off via not_finished_mask.

Parameters:
  • x_original (torch.Tensor) – Original images in the pytorch default range, (B, C, H, W).

  • optimizer (torch.optim.Optimizer) – Optimiser over the entries of z.

  • y_target (torch.Tensor) – Target class per sample, shape (B,).

  • i (int) – Index of this gradient step, used for logging and for the final step special cases.

  • boolmask_in (torch.Tensor) – Region the previous attempts are allowed to have changed; the gradient of z[0] is masked with it when inpainting is on.

  • gradient_predictor (nn.Module) – Predictor supplying the gradients (the distilled copy when explainer_config.distilled_predictor is set).

  • mode (str) – Dataset split name, used in progress-bar text and output paths.

  • pbar (tqdm or None) – Progress bar; updated once per step when tracking is enabled.

  • batch_idx (int) – Index of the current batch, used in the gradient dump path.

  • x_in (torch.Tensor) – The unmodified input batch, used only for the visual difference shown in the progress bar.

  • num_attempts (int) – 1-based attempt counter. For later attempts dist_l1 and inpaint are halved per attempt, unless allow_overlap.

  • base_path (str) – Run directory the gradient visualisations are written under.

  • z_original (list of torch.Tensor) – The starting value of the optimised variables, the L1 anchor.

  • best_score (torch.Tensor) – Best target confidence seen per sample so far; updated in place semantics but also returned.

  • best_z (torch.Tensor) – Variable value and repaint mask belonging to best_score.

  • best_mask (torch.Tensor) – Variable value and repaint mask belonging to best_score.

  • z (list of torch.Tensor) – The optimised variables. With iterationwise_encoding the first entry is an image in [0, 1], otherwise a latent code.

  • target_confidence_goal_current (torch.Tensor) – Per-sample confidence that counts as success.

  • not_finished_mask (torch.Tensor) – 1 for samples that are still being optimised, 0 for finished ones, whose gradients are zeroed when use_masking is set.

  • gradient_confidences_old (torch.Tensor) – Confidences of the gradient predictor from the previous step, used for the progress bar only.

  • to_generator (callable) – Resize/normalise helpers into the generator and predictor spaces.

  • to_predictor (callable) – Resize/normalise helpers into the generator and predictor spaces.

  • start_activations (torch.Tensor) – Penultimate activations of the originals, the reference for the orthogonality penalty.

Returns:

(best_score, best_z, best_mask, not_finished_mask, z, target_confidence_goal_current, gradient_confidences_old, all_finished), where the last entry is True once every sample reached its confidence goal.

Return type:

tuple

Notes

The per-sample gradient of z[0] is rescaled so that learning_rate * max|grad| never exceeds explainer_config.gradient_clipping. With tracking_level >= 5 and visualize_gradients every step is dumped as a png under <base_path>/<mode>_explainer_gradients/<batch>_<attempt>/.

explain_batch(batch, base_path='collages', start_idx=0, y_target_goal_confidence_in=None, remove_below_threshold=False, pbar=None, mode='', explainer_path=None, batchwise_clustering=False)[source]

This function generates a counterfactual for a given batch of inputs.

Parameters:
  • batch (dict) – The batch to explain.

  • base_path (str, optional) – The base path to save the counterfactuals to. Defaults to “collages”.

  • start_idx (int, optional) – The start index for the counterfactuals. Defaults to 0.

  • y_target_goal_confidence_in (int, optional) – The target confidence for the counterfactuals. Defaults to None.

  • remove_below_threshold (bool, optional) – The flag to remove counterfactuals with a confidence below the

  • True. (target confidence. Defaults to)

  • explainer_path

  • mode

  • pbar

Returns:

The batch with the counterfactuals added.

Return type:

dict

cluster_explanations(explanations_dict, batch_size=2, n_clusters=2)[source]

This function clusters the explanations.

calculate_latent_difference_stats(explanations_dict, explainer_stats_clusters=None, visualize_latent_sparsity=False, visualize_latent_diversity=False, base_dir=None)[source]

Measure how sparse and how diverse the counterfactual edits are.

Two ways of obtaining a low-dimensional edit vector are supported. If the validation dataset exposes sample_to_2d_latent (the synthetic datasets with known generative factors), the edit is the difference of the ground-truth latents. Otherwise, if hint masks are available, the edit is summarised by the mean absolute pixel change inside and outside the hint mask, i.e. a two-dimensional (foreground, background) vector. Without either, no statistics are produced.

Only samples that actually flipped count: a sample enters the sparsity average when the first active cluster flipped both the original and the distilled predictor (confidence > 0.5), and the diversity average when all active clusters flipped both. Sparsity per sample is the normalised Hoyer measure of the edit vector, diversity is one minus the absolute cosine similarity between the edits of the first two active clusters. Both are averaged and reported as 1 - mean.

Parameters:
  • explanations_dict (dict) – Flattened explanations. clusters<i> lists are derived from x_counterfactual_list when missing, by striding with explainer_config.num_attempts.

  • explainer_stats_clusters (sequence of int, optional) – Which attempt indices to use; defaults to the first two (or one, if only one attempt was run).

  • visualize_latent_sparsity (bool, optional) – Also write the collages produced by _generate_sparsity_collages / _generate_diversity_collages (requires base_dir).

  • visualize_latent_diversity (bool, optional) – Also write the collages produced by _generate_sparsity_collages / _generate_diversity_collages (requires base_dir).

  • base_dir (str, optional) – Directory the collages are written to.

Returns:

{"latent_sparsity": ..., "latent_diversity": ...}, or an empty dict when no edit vectors could be computed. Both values are 0.0 when no sample passed the flip gate.

Return type:

dict

run(oracle_path=None, confounder_oracle_path=None)[source]

This function runs the explainer.

human_annotate_explanations(collage_path_list, y_source_list=None, y_target_list=None, **kwargs)[source]

Collect free-text human feedback on counterfactual collages.

Serves a small Flask app in a background thread that shows the collages one after another and records what the annotator types. The collages are copied into a freshly created static/ directory next to the working directory so that Flask can serve them; the port is explainer_config.port, incremented until a free one is found. The call blocks (polling once a second with a progress bar) until as many feedback strings as collages have arrived.

Parameters:
  • collage_path_list (list of str) – Paths of the collage images to show, in order.

  • y_source_list (list, optional) – Source and target classes of each collage; not used here, they are passed on to visualize_interpretations().

  • y_target_list (list, optional) – Source and target classes of each collage; not used here, they are passed on to visualize_interpretations().

  • **kwargs – Ignored; keeps the signature interchangeable with the automated teachers.

Returns:

One feedback string per collage. The same lines are written to <explanations_dir>/feedback.txt.

Return type:

list of str

Raises:

ImportError – If the optional flask dependency is not installed.

visualize_interpretations(feedback, y_source_list, y_target_list)[source]

Turn the collected feedback into one bar chart per class pair.

For every unordered pair of classes the feedback strings of all explanations that go from one to the other (in either direction) are counted, and the histogram is written as <explanations_dir>/interpretations/<source>vs<target>.

Parameters:
  • feedback (list of str or str) – The feedback strings, or the path of a file with one per line.

  • y_source_list (list of int) – Source and target class of each explanation, aligned with feedback.

  • y_target_list (list of int) – Source and target class of each explanation, aligned with feedback.

Returns:

The result is written to disk.

Return type:

None