Source code for peal.teachers.baseline_teacher

"""
A teacher that answers with a fixed or random verdict.

Teachers are PEAL's sources of feedback on counterfactuals: given an original
sample and its counterfactual they say whether the change was a valid
("true") or spurious ("false") reason for the classifier's decision. The
``BaselineTeacher`` ignores the images entirely and answers according to a
strategy (random / always true / always false). It serves as a control
condition for adaptors such as CFKD.
"""

import numpy as np

from peal.teachers.interfaces import TeacherInterface


[docs] class BaselineTeacher(TeacherInterface): """ Content-agnostic teacher used as a baseline for CFKD experiments. The feedback for every counterfactual is decided by ``strategy`` without looking at the sample, unless the counterfactual is disqualified first (student originally wrong on a one-sided counterfactual, or student not swapped to the target class). Parameters ---------- strategy : {"random", "true", "false"} ``"random"`` draws a fair coin per counterfactual, ``"true"`` and ``"false"`` always give that verdict. dataset : peal dataset, optional Only needed for ``tracking_level >= 5``; its ``generate_contrastive_collage`` is used to render the feedback. tracking_level : int Verbosity level; ``>= 5`` writes collage images to ``base_dir``. counterfactual_type : {"1sided", "2sided"} With ``"1sided"`` a counterfactual whose original prediction was wrong gets the feedback ``"student originally wrong!"``. """
[docs] def __init__( self, strategy="random", dataset=None, tracking_level=0, counterfactual_type="1sided", ): self.strategy = strategy self.dataset = dataset self.tracking_level = tracking_level self.counterfactual_type = counterfactual_type
[docs] def get_feedback( self, x_counterfactual_list, y_source_list, x_list, y_list, y_target_end_confidence_list, base_dir=None, y_target_list=None, student=None, **kwargs, ): """ Produce one feedback string per counterfactual. Parameters ---------- x_counterfactual_list : list of torch.Tensor Counterfactual images. y_source_list : list Class the student predicted for each original sample. x_list : list of torch.Tensor Original images. y_list : list Ground-truth labels of the originals. y_target_end_confidence_list : list of float Student confidence for the target class on the counterfactual. base_dir : str, optional Directory the collage is written to when ``tracking_level >= 5``. y_target_list : list, optional Target class of each counterfactual. student : torch.nn.Module The classifier being explained; only used to determine the device. **kwargs Forwarded to ``dataset.generate_contrastive_collage``. Returns ------- list of str One of ``"true"``, ``"false"``, ``"student originally wrong!"`` or ``"student not swapped!"`` per counterfactual. """ feedback = [] teacher_original = [] teacher_counterfactual = [] device = "cuda" if next(student.parameters()).is_cuda else "cpu" for idx, counterfactual in enumerate(x_counterfactual_list): if ( self.counterfactual_type == "1sided" and y_list[idx] != y_source_list[idx] ): feedback.append("student originally wrong!") elif y_target_end_confidence_list[idx] < 0.5: feedback.append("student not swapped!") else: if self.strategy == "random": f = np.random.randint(0, 2) feedback.append("true" if f else "false") elif self.strategy == "false": feedback.append("false") elif self.strategy == "true": feedback.append("true") teacher_original.append(-1) teacher_counterfactual.append(-1) if self.tracking_level >= 5: self.dataset.generate_contrastive_collage( y_counterfactual_teacher_list=teacher_counterfactual, y_original_teacher_list=teacher_original, feedback_list=feedback, x_counterfactual_list=x_counterfactual_list, y_source_list=y_source_list, y_target_list=y_target_list, x_list=x_list, y_list=y_list, y_target_end_confidence_list=y_target_end_confidence_list, base_path=base_dir, **kwargs, ) return feedback