Source code for greatx.attack.untargeted.untargeted_attacker

from greatx.attack.flip_attacker import FlipAttacker


[docs]class UntargetedAttacker(FlipAttacker): r"""Base class for adversarial non-targeted attack. Parameters ---------- data : Data PyG-like data denoting the input graph device : str, optional the device of the attack running on, by default "cpu" seed : Optional[int], optional the random seed for reproducing the attack, by default None name : Optional[str], optional name of the attacker, if None, it would be :obj:`__class__.__name__`, by default None kwargs : additional arguments of :class:`greatx.attack.Attacker`, Raises ------ TypeError unexpected keyword argument in :obj:`kwargs` Note ---- :class:`greatx.attack.targeted.UntargetedAttacker` is a subclass of :class:`greatx.attack.FlipAttacker`. It belongs to graph modification attack (GMA). """
[docs] def reset(self) -> "UntargetedAttacker": """Reset the state of the Attacker Returns ------- UntargetedAttacker the attacker itself """ super().reset() self.num_budgets = None self.structure_attack = None self.feature_attack = None return self
[docs] def attack(self, num_budgets, structure_attack, feature_attack) -> "UntargetedAttacker": """Base method that describes the adversarial untargeted attack. Parameters ---------- num_budgets : int or float the number/percentage of perturbations allowed to attack structure_attack : bool, optional whether to conduct structure attack, i.e., modify the graph structure (edges), feature_attack : bool, optional whether to conduct feature attack, i.e., modify the node features, """ _is_setup = getattr(self, "_is_setup", True) if not _is_setup: raise RuntimeError( f'{self.__class__.__name__} requires ' 'a surrogate model to conduct attack. ' 'Use `attacker.setup_surrogate(surrogate_model)`.') if not self._is_reset: raise RuntimeError('Before calling attack, you must reset ' 'your attacker. Call `attacker.reset()`.') if not (structure_attack or feature_attack): raise RuntimeError( 'Either `structure_attack` or `feature_attack` must be True.') if feature_attack and not self._allow_feature_attack: raise RuntimeError( f"{self.name} does NOT support attacking features.") if structure_attack and not self._allow_structure_attack: raise RuntimeError( f"{self.name} does NOT support attacking structures.") num_budgets = self._check_budget(num_budgets, max_perturbations=self.num_edges // 2) self.num_budgets = num_budgets self.structure_attack = structure_attack self.feature_attack = feature_attack self._is_reset = False return self