18
18
"""
19
19
This module implements the abstract base classes for all attacks.
20
20
"""
21
- from __future__ import absolute_import , division , print_function , unicode_literals
21
+ from __future__ import absolute_import , division , print_function , unicode_literals , annotations
22
22
23
23
import abc
24
24
import logging
25
- from typing import Any , Dict , List , Optional , Tuple , Union , TYPE_CHECKING
25
+ from typing import Any , TYPE_CHECKING
26
26
27
27
import numpy as np
28
28
38
38
39
39
class InputFilter (abc .ABCMeta ): # pragma: no cover
40
40
"""
41
- Metaclass to ensure that inputs are ndarray for all of the subclass generate and extract calls
41
+ Metaclass to ensure that inputs are ndarray for all the subclass generate and extract calls
42
42
"""
43
43
44
- # pylint: disable=W0613
45
- def __init__ (cls , name , bases , clsdict ): # pylint: disable=W0231
44
+ def __init__ (cls , name , bases , clsdict ):
46
45
"""
47
46
This function overrides any existing generate or extract methods with a new method that
48
47
ensures the input is an `np.ndarray`. There is an assumption that the input object has implemented
49
48
__array__ with np.array calls.
50
49
"""
51
50
51
+ super ().__init__ ()
52
+
52
53
def make_replacement (fdict , func_name ):
53
54
"""
54
55
This function overrides creates replacement functions dynamically
@@ -94,17 +95,17 @@ class Attack(abc.ABC):
94
95
Abstract base class for all attack abstract base classes.
95
96
"""
96
97
97
- attack_params : List [str ] = []
98
+ attack_params : list [str ] = []
98
99
# The _estimator_requirements define the requirements an estimator must satisfy to be used as a target for an
99
100
# attack. They should be a tuple of requirements, where each requirement is either a class the estimator must
100
101
# inherit from, or a tuple of classes which define a union, i.e. the estimator must inherit from at least one class
101
102
# in the requirement tuple.
102
- _estimator_requirements : Optional [ Union [ Tuple [ Any , ...], Tuple [()]]] = None
103
+ _estimator_requirements : tuple [ Any , ...] | tuple [()] | None = None
103
104
104
105
def __init__ (
105
106
self ,
106
107
estimator ,
107
- summary_writer : Union [ str , bool , SummaryWriter ] = False ,
108
+ summary_writer : str | bool | SummaryWriter = False ,
108
109
):
109
110
"""
110
111
:param estimator: An estimator.
@@ -126,7 +127,7 @@ def __init__(
126
127
127
128
self ._estimator = estimator
128
129
self ._summary_writer_arg = summary_writer
129
- self ._summary_writer : Optional [ SummaryWriter ] = None
130
+ self ._summary_writer : SummaryWriter | None = None
130
131
131
132
if isinstance (summary_writer , SummaryWriter ): # pragma: no cover
132
133
self ._summary_writer = summary_writer
@@ -212,13 +213,13 @@ def __init__(self, **kwargs) -> None:
212
213
super ().__init__ (** kwargs )
213
214
214
215
@abc .abstractmethod
215
- def generate (self , x : np .ndarray , y : Optional [ np .ndarray ] = None , ** kwargs ) -> np .ndarray :
216
+ def generate (self , x : np .ndarray , y : np .ndarray | None = None , ** kwargs ) -> np .ndarray :
216
217
"""
217
218
Generate adversarial examples and return them as an array. This method should be overridden by all concrete
218
219
evasion attack implementations.
219
220
220
221
:param x: An array with the original inputs to be attacked.
221
- :param y: Correct labels or target labels for `x`, depending if the attack is targeted
222
+ :param y: Correct labels or target labels for `x`, depending on if the attack is targeted
222
223
or not. This parameter is only used by some of the attacks.
223
224
:return: An array holding the adversarial examples.
224
225
"""
@@ -241,14 +242,14 @@ class PoisoningAttack(Attack):
241
242
Abstract base class for poisoning attack classes
242
243
"""
243
244
244
- def __init__ (self , classifier : Optional [ "CLASSIFIER_TYPE" ] ) -> None :
245
+ def __init__ (self , classifier : "CLASSIFIER_TYPE" | None ) -> None :
245
246
"""
246
247
:param classifier: A trained classifier (or none if no classifier is needed)
247
248
"""
248
249
super ().__init__ (classifier )
249
250
250
251
@abc .abstractmethod
251
- def poison (self , x : np .ndarray , y = Optional [ np .ndarray ] , ** kwargs ) -> Tuple [np .ndarray , np .ndarray ]:
252
+ def poison (self , x : np .ndarray , y : np .ndarray | None = None , ** kwargs ) -> tuple [np .ndarray , np .ndarray ]:
252
253
"""
253
254
Generate poisoning examples and return them as an array. This method should be overridden by all concrete
254
255
poisoning attack implementations.
@@ -310,14 +311,8 @@ class PoisoningAttackTransformer(PoisoningAttack):
310
311
These attacks have an additional method, `poison_estimator`, that returns the poisoned classifier.
311
312
"""
312
313
313
- def __init__ (self , classifier : Optional ["CLASSIFIER_TYPE" ]) -> None :
314
- """
315
- :param classifier: A trained classifier (or none if no classifier is needed)
316
- """
317
- super ().__init__ (classifier )
318
-
319
314
@abc .abstractmethod
320
- def poison (self , x : np .ndarray , y = Optional [ np .ndarray ] , ** kwargs ) -> Tuple [np .ndarray , np .ndarray ]:
315
+ def poison (self , x : np .ndarray , y : np .ndarray | None = None , ** kwargs ) -> tuple [np .ndarray , np .ndarray ]:
321
316
"""
322
317
Generate poisoning examples and return them as an array. This method should be overridden by all concrete
323
318
poisoning attack implementations.
@@ -354,16 +349,16 @@ def __init__(self):
354
349
@abc .abstractmethod
355
350
def poison (
356
351
self ,
357
- x : Union [ np .ndarray , List [np .ndarray ] ],
358
- y : List [ Dict [str , np .ndarray ]],
352
+ x : np .ndarray | list [np .ndarray ],
353
+ y : list [ dict [str , np .ndarray ]],
359
354
** kwargs ,
360
- ) -> Tuple [ Union [ np .ndarray , List [np .ndarray ]], List [ Dict [str , np .ndarray ]]]:
355
+ ) -> tuple [ np .ndarray | list [np .ndarray ], list [ dict [str , np .ndarray ]]]:
361
356
"""
362
357
Generate poisoning examples and return them as an array. This method should be overridden by all concrete
363
358
poisoning attack implementations.
364
359
365
360
:param x: An array with the original inputs to be attacked.
366
- :param y: True labels of type `List[Dict [np.ndarray]]`, one dictionary per input image.
361
+ :param y: True labels of type `list[dict [np.ndarray]]`, one dictionary per input image.
367
362
The keys and values of the dictionary are:
368
363
- boxes [N, 4]: the boxes in [x1, y1, x2, y2] format, with 0 <= x1 < x2 <= W and 0 <= y1 < y2 <= H.
369
364
- labels [N]: the labels for each image
@@ -385,7 +380,7 @@ def __init__(self):
385
380
super ().__init__ (None ) # type: ignore
386
381
387
382
@abc .abstractmethod
388
- def poison (self , x : np .ndarray , y : Optional [ np .ndarray ] = None , ** kwargs ) -> Tuple [np .ndarray , np .ndarray ]:
383
+ def poison (self , x : np .ndarray , y : np .ndarray | None = None , ** kwargs ) -> tuple [np .ndarray , np .ndarray ]:
389
384
"""
390
385
Generate poisoning examples and return them as an array. This method should be overridden by all concrete
391
386
poisoning attack implementations.
@@ -403,7 +398,7 @@ class PoisoningAttackWhiteBox(PoisoningAttack):
403
398
"""
404
399
405
400
@abc .abstractmethod
406
- def poison (self , x : np .ndarray , y : Optional [ np .ndarray ] = None , ** kwargs ) -> Tuple [np .ndarray , np .ndarray ]:
401
+ def poison (self , x : np .ndarray , y : np .ndarray | None = None , ** kwargs ) -> tuple [np .ndarray , np .ndarray ]:
407
402
"""
408
403
Generate poisoning examples and return them as an array. This method should be overridden by all concrete
409
404
poisoning attack implementations.
@@ -422,7 +417,7 @@ class ExtractionAttack(Attack):
422
417
"""
423
418
424
419
@abc .abstractmethod
425
- def extract (self , x : np .ndarray , y : Optional [ np .ndarray ] = None , ** kwargs ) -> "CLASSIFIER_TYPE" :
420
+ def extract (self , x : np .ndarray , y : np .ndarray | None = None , ** kwargs ) -> "CLASSIFIER_TYPE" :
426
421
"""
427
422
Extract models and return them as an ART classifier. This method should be overridden by all concrete extraction
428
423
attack implementations.
@@ -448,7 +443,7 @@ def __init__(self, estimator):
448
443
super ().__init__ (estimator )
449
444
450
445
@abc .abstractmethod
451
- def infer (self , x : np .ndarray , y : Optional [ np .ndarray ] = None , ** kwargs ) -> np .ndarray :
446
+ def infer (self , x : np .ndarray , y : np .ndarray | None = None , ** kwargs ) -> np .ndarray :
452
447
"""
453
448
Infer sensitive attributes from the targeted estimator. This method
454
449
should be overridden by all concrete inference attack implementations.
@@ -467,7 +462,7 @@ class AttributeInferenceAttack(InferenceAttack):
467
462
468
463
attack_params = InferenceAttack .attack_params + ["attack_feature" ]
469
464
470
- def __init__ (self , estimator , attack_feature : Union [ int , slice ] = 0 ):
465
+ def __init__ (self , estimator , attack_feature : int | slice = 0 ):
471
466
"""
472
467
:param estimator: A trained estimator targeted for inference attack.
473
468
:type estimator: :class:`.art.estimators.estimator.BaseEstimator`
@@ -478,7 +473,7 @@ def __init__(self, estimator, attack_feature: Union[int, slice] = 0):
478
473
self .attack_feature = get_feature_index (attack_feature )
479
474
480
475
@abc .abstractmethod
481
- def infer (self , x : np .ndarray , y : Optional [ np .ndarray ] = None , ** kwargs ) -> np .ndarray :
476
+ def infer (self , x : np .ndarray , y : np .ndarray | None = None , ** kwargs ) -> np .ndarray :
482
477
"""
483
478
Infer sensitive attributes from the targeted estimator. This method
484
479
should be overridden by all concrete inference attack implementations.
@@ -490,7 +485,7 @@ def infer(self, x: np.ndarray, y: Optional[np.ndarray] = None, **kwargs) -> np.n
490
485
raise NotImplementedError
491
486
492
487
@staticmethod
493
- def _check_attack_feature (attack_feature : Union [ int , slice ] ) -> None :
488
+ def _check_attack_feature (attack_feature : int | slice ) -> None :
494
489
if not isinstance (attack_feature , int ) and not isinstance (attack_feature , slice ):
495
490
raise ValueError ("Attack feature must be either an integer or a slice object." )
496
491
@@ -506,16 +501,8 @@ class MembershipInferenceAttack(InferenceAttack):
506
501
Abstract base class for membership inference attack classes.
507
502
"""
508
503
509
- def __init__ (self , estimator ):
510
- """
511
- :param estimator: A trained estimator targeted for inference attack.
512
- :type estimator: :class:`.art.estimators.estimator.BaseEstimator`
513
- :param attack_feature: The index of the feature to be attacked.
514
- """
515
- super ().__init__ (estimator )
516
-
517
504
@abc .abstractmethod
518
- def infer (self , x : np .ndarray , y : Optional [ np .ndarray ] = None , ** kwargs ) -> np .ndarray :
505
+ def infer (self , x : np .ndarray , y : np .ndarray | None = None , ** kwargs ) -> np .ndarray :
519
506
"""
520
507
Infer membership status of samples from the target estimator. This method
521
508
should be overridden by all concrete inference attack implementations.
@@ -552,7 +539,7 @@ def __init__(self, estimator):
552
539
super ().__init__ (estimator )
553
540
554
541
@abc .abstractmethod
555
- def reconstruct (self , x : np .ndarray , y : Optional [ np .ndarray ] = None , ** kwargs ) -> Tuple [np .ndarray , np .ndarray ]:
542
+ def reconstruct (self , x : np .ndarray , y : np .ndarray | None = None , ** kwargs ) -> tuple [np .ndarray , np .ndarray ]:
556
543
"""
557
544
Reconstruct the training dataset of and from the targeted estimator. This method
558
545
should be overridden by all concrete inference attack implementations.
0 commit comments