niteshade.simulation.Simulator

class niteshade.simulation.Simulator(X, y, model, attacker=None, defender=None, batch_size=1, num_episodes=1, save=False)

Bases: object

Class used to simulate data poisoning attacks during online learning. It is important to note the distinction between batch size and num_episodes in simulating data poisoning attacks during online learning; the batch size here refers to the size of the mini-batches the specified model is trained on, while the number of episodes refers to the number of times the data becomes available for the model to train on (which is equivalent to the number of times the attacker and defender are able to intervene in the learning process). The default batch size and number of episodes is 1, implying that the model is trained one sample at a time (no mini-batches) and the data comes in all at once (i.e attacker and defender only intervene once in this scenario).

Parameters
  • X (np.ndarray, torch.Tensor) – stream of input data to train the model with during supervised learning.

  • y (np.ndarray, torch.Tensor) – stream of target data (labels to the inputs) to train the model with during supervised learning.

  • model (torch.nn.Module) – neural network model inheriting from torch.nn.Module to be trained during online learning. Must present a .step() method that performs a gradient descent step on a batch of input and target data (X_batch and y_batch).

  • attacker (Attacker) – Attacker object that presents a .attack() method with an implementation of a data poisoning attack strategy.

  • defender (Defender) – Defender object that presents a .defend() method with an implementation of a data poisoning defense strategy.

  • batch_size (int) – batch size of model.

  • num_episodes (int) – Number of ‘episodes’ that X and y span over. Here, we refer to an episode as the time period over which a stream of incoming data would be collected and subsequently passed on to the model to be trained.

__init__(X, y, model, attacker=None, defender=None, batch_size=1, num_episodes=1, save=False) None

Methods

__init__(X, y, model[, attacker, defender, ...])

run([defender_args, attacker_args, ...])

Runs a simulation of an online learning setting where, if specified, an attacker will "poison" incoming data points in an episode according to an implemented attack strategy (via its .attack() method) and a defender (also, if specified) will reject/modify points deemed poisoned by its defence strategy (via its .defend() method).

run(defender_args={}, attacker_args={}, attacker_requires_model=False, defender_requires_model=False, shuffle=False) None

Runs a simulation of an online learning setting where, if specified, an attacker will “poison” incoming data points in an episode according to an implemented attack strategy (via its .attack() method) and a defender (also, if specified) will reject/modify points deemed poisoned by its defence strategy (via its .defend() method).

NOTE: If the attacker/defender require a model for their attack/defense strategies, the user should only set attacker_requires_model=True/defender_requires_model=True. The .attack()/.defend() method should then contain the argument ‘model’; this argument will be added as a key to attacker_args/defender_args and updated with the new model after each gradient descent step as online learning progresses.

Metadata:

As the simulation progresses –> each episodes original, post-attack, and post-defense inputs and labels will be saved in self.results (a dictionary) in a list under the keys: “original”, “post-attack”, and “post-defense”, respectively. All the datapoints in an episode are saved as values in a dictionary where the keys are labels indicating if a point is unperturbed (in which case the label is simply the index of the point in the inputted X and y), poisoned (labelled as “p_n” where n is an integer indicating that it is the nth poisoned point), or modified by the defender (labelled as “d_n” where n is an integer indicating that it is the nth defended point). If the defender rejects a point in episode i, it can be inferred by inspecting the points missing from self.results[“post_defense”][i] with respect to self.results[“post_attack”][i].

Data on how the atacker and defender have influenced the training points can be found on the attributes: poisoned, not_poisoned, correctly_defended, incorrectly_defended, training_points, original_points.

Parameters
  • defender_args (dict) – dictionary containing extra arguments (other than the episode inputs X and labels y) for defender .defend() method.

  • attacker_args (dict) – dictionary containing extra arguments (other than the episode inputs X and labels y) for attacker .attack() method.

  • attacker_requires_model (bool) – specifies if the .attack() method of the attacker requires the updated model at each episode.

  • defender_requires_model (bool) – specifies if the .defend() method of the defender requires the updated model at each episode.

  • shuffle (bool) – Boolean indicating if passed X and y should be shuffled in DataLoader.