Skip to content

Documentation for Labelflipping Module

This module provides a function for label flipping in datasets, allowing for the simulation of label noise as a form of data poisoning. The main function modifies the labels of specific samples in a dataset based on a specified percentage and target conditions.

Function: - labelFlipping: Flips the labels of a specified portion of a dataset to random values or to a specific target label.

LabelFlippingAttack

Bases: DatasetAttack

Implements an attack that flips the labels of a portion of the training dataset.

This attack alters the labels of certain data points in the training set to mislead the training process.

Source code in nebula/addons/attacks/dataset/labelflipping.py
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
class LabelFlippingAttack(DatasetAttack):
    """
    Implements an attack that flips the labels of a portion of the training dataset.

    This attack alters the labels of certain data points in the training set to
    mislead the training process.
    """
    def __init__(self, engine, attack_params):
        """
        Initializes the LabelFlippingAttack with the engine and attack parameters.

        Args:
            engine: The engine managing the attack context.
            attack_params (dict): Parameters for the attack, including the percentage of
                                  poisoned data, targeting options, and label specifications.
        """
        super().__init__(engine)
        self.datamodule = engine._trainer.datamodule
        self.poisoned_percent = float(attack_params["poisoned_percent"])
        self.targeted = attack_params["targeted"]
        self.target_label = int(attack_params["target_label"])
        self.target_changed_label = int(attack_params["target_changed_label"])
        self.round_start_attack = int(attack_params["round_start_attack"])
        self.round_stop_attack = int(attack_params["round_stop_attack"])

    def labelFlipping(
        self,
        dataset,
        indices,
        poisoned_percent=0,
        targeted=False,
        target_label=4,
        target_changed_label=7,
    ):
        """
        Flips the labels of a specified portion of a dataset to random values or to a specific target label.

        This function modifies the labels of selected samples in the dataset based on the specified
        poisoning percentage. Labels can be flipped either randomly or targeted to change from a specific
        label to another specified label.

        Args:
            dataset (Dataset): The dataset containing training data, expected to be a PyTorch dataset
                               with a `.targets` attribute.
            indices (list of int): The list of indices in the dataset to consider for label flipping.
            poisoned_percent (float, optional): The ratio of labels to change, expressed as a fraction
                                                (0 <= poisoned_percent <= 1). Default is 0.
            targeted (bool, optional): If True, flips only labels matching `target_label` to `target_changed_label`.
                                       Default is False.
            target_label (int, optional): The label to change when `targeted` is True. Default is 4.
            target_changed_label (int, optional): The label to which `target_label` will be changed. Default is 7.

        Returns:
            Dataset: A deep copy of the original dataset with modified labels in `.targets`.

        Raises:
            ValueError: If `poisoned_percent` is not between 0 and 1, or if `flipping_percent` is invalid.

        Notes:
            - When not in targeted mode, labels are flipped for a random selection of indices based on the specified
              `poisoned_percent`. The new label is chosen randomly from the existing classes.
            - In targeted mode, labels that match `target_label` are directly changed to `target_changed_label`.
        """
        new_dataset = copy.deepcopy(dataset)

        targets = torch.tensor(new_dataset.targets) if isinstance(new_dataset.targets, list) else new_dataset.targets
        targets = targets.detach().clone()

        num_indices = len(indices)
        # classes = new_dataset.classes
        # class_to_idx = new_dataset.class_to_idx
        # class_list = [class_to_idx[i] for i in classes]
        class_list = list(set(targets.tolist()))
        if not targeted:
            num_flipped = int(poisoned_percent * num_indices)
            if num_indices == 0:
                return new_dataset
            if num_flipped > num_indices:
                return new_dataset
            flipped_indice = random.sample(indices, num_flipped)

            for i in flipped_indice:
                t = targets[i]
                flipped = torch.tensor(random.sample(class_list, 1)[0])
                while t == flipped:
                    flipped = torch.tensor(random.sample(class_list, 1)[0])
                targets[i] = flipped
        else:
            for i in indices:
                if int(targets[i]) == int(target_label):
                    targets[i] = torch.tensor(target_changed_label)
        new_dataset.targets = targets
        return new_dataset

    def get_malicious_dataset(self):
        """
        Creates a malicious dataset by flipping the labels of selected data points.

        Returns:
            Dataset: The modified dataset with flipped labels.
        """
        return self.labelFlipping(
            self.datamodule.train_set, 
            self.datamodule.train_set_indices, 
            self.poisoned_percent, 
            self.targeted, 
            self.target_label, 
            self.target_changed_label)

__init__(engine, attack_params)

Initializes the LabelFlippingAttack with the engine and attack parameters.

Parameters:

Name Type Description Default
engine

The engine managing the attack context.

required
attack_params dict

Parameters for the attack, including the percentage of poisoned data, targeting options, and label specifications.

required
Source code in nebula/addons/attacks/dataset/labelflipping.py
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
def __init__(self, engine, attack_params):
    """
    Initializes the LabelFlippingAttack with the engine and attack parameters.

    Args:
        engine: The engine managing the attack context.
        attack_params (dict): Parameters for the attack, including the percentage of
                              poisoned data, targeting options, and label specifications.
    """
    super().__init__(engine)
    self.datamodule = engine._trainer.datamodule
    self.poisoned_percent = float(attack_params["poisoned_percent"])
    self.targeted = attack_params["targeted"]
    self.target_label = int(attack_params["target_label"])
    self.target_changed_label = int(attack_params["target_changed_label"])
    self.round_start_attack = int(attack_params["round_start_attack"])
    self.round_stop_attack = int(attack_params["round_stop_attack"])

get_malicious_dataset()

Creates a malicious dataset by flipping the labels of selected data points.

Returns:

Name Type Description
Dataset

The modified dataset with flipped labels.

Source code in nebula/addons/attacks/dataset/labelflipping.py
112
113
114
115
116
117
118
119
120
121
122
123
124
125
def get_malicious_dataset(self):
    """
    Creates a malicious dataset by flipping the labels of selected data points.

    Returns:
        Dataset: The modified dataset with flipped labels.
    """
    return self.labelFlipping(
        self.datamodule.train_set, 
        self.datamodule.train_set_indices, 
        self.poisoned_percent, 
        self.targeted, 
        self.target_label, 
        self.target_changed_label)

labelFlipping(dataset, indices, poisoned_percent=0, targeted=False, target_label=4, target_changed_label=7)

Flips the labels of a specified portion of a dataset to random values or to a specific target label.

This function modifies the labels of selected samples in the dataset based on the specified poisoning percentage. Labels can be flipped either randomly or targeted to change from a specific label to another specified label.

Parameters:

Name Type Description Default
dataset Dataset

The dataset containing training data, expected to be a PyTorch dataset with a .targets attribute.

required
indices list of int

The list of indices in the dataset to consider for label flipping.

required
poisoned_percent float

The ratio of labels to change, expressed as a fraction (0 <= poisoned_percent <= 1). Default is 0.

0
targeted bool

If True, flips only labels matching target_label to target_changed_label. Default is False.

False
target_label int

The label to change when targeted is True. Default is 4.

4
target_changed_label int

The label to which target_label will be changed. Default is 7.

7

Returns:

Name Type Description
Dataset

A deep copy of the original dataset with modified labels in .targets.

Raises:

Type Description
ValueError

If poisoned_percent is not between 0 and 1, or if flipping_percent is invalid.

Notes
  • When not in targeted mode, labels are flipped for a random selection of indices based on the specified poisoned_percent. The new label is chosen randomly from the existing classes.
  • In targeted mode, labels that match target_label are directly changed to target_changed_label.
Source code in nebula/addons/attacks/dataset/labelflipping.py
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
def labelFlipping(
    self,
    dataset,
    indices,
    poisoned_percent=0,
    targeted=False,
    target_label=4,
    target_changed_label=7,
):
    """
    Flips the labels of a specified portion of a dataset to random values or to a specific target label.

    This function modifies the labels of selected samples in the dataset based on the specified
    poisoning percentage. Labels can be flipped either randomly or targeted to change from a specific
    label to another specified label.

    Args:
        dataset (Dataset): The dataset containing training data, expected to be a PyTorch dataset
                           with a `.targets` attribute.
        indices (list of int): The list of indices in the dataset to consider for label flipping.
        poisoned_percent (float, optional): The ratio of labels to change, expressed as a fraction
                                            (0 <= poisoned_percent <= 1). Default is 0.
        targeted (bool, optional): If True, flips only labels matching `target_label` to `target_changed_label`.
                                   Default is False.
        target_label (int, optional): The label to change when `targeted` is True. Default is 4.
        target_changed_label (int, optional): The label to which `target_label` will be changed. Default is 7.

    Returns:
        Dataset: A deep copy of the original dataset with modified labels in `.targets`.

    Raises:
        ValueError: If `poisoned_percent` is not between 0 and 1, or if `flipping_percent` is invalid.

    Notes:
        - When not in targeted mode, labels are flipped for a random selection of indices based on the specified
          `poisoned_percent`. The new label is chosen randomly from the existing classes.
        - In targeted mode, labels that match `target_label` are directly changed to `target_changed_label`.
    """
    new_dataset = copy.deepcopy(dataset)

    targets = torch.tensor(new_dataset.targets) if isinstance(new_dataset.targets, list) else new_dataset.targets
    targets = targets.detach().clone()

    num_indices = len(indices)
    # classes = new_dataset.classes
    # class_to_idx = new_dataset.class_to_idx
    # class_list = [class_to_idx[i] for i in classes]
    class_list = list(set(targets.tolist()))
    if not targeted:
        num_flipped = int(poisoned_percent * num_indices)
        if num_indices == 0:
            return new_dataset
        if num_flipped > num_indices:
            return new_dataset
        flipped_indice = random.sample(indices, num_flipped)

        for i in flipped_indice:
            t = targets[i]
            flipped = torch.tensor(random.sample(class_list, 1)[0])
            while t == flipped:
                flipped = torch.tensor(random.sample(class_list, 1)[0])
            targets[i] = flipped
    else:
        for i in indices:
            if int(targets[i]) == int(target_label):
                targets[i] = torch.tensor(target_changed_label)
    new_dataset.targets = targets
    return new_dataset