Skip to content

Commit 59f47ea

Browse files
authored
Merge pull request #556 from Trusted-AI/development_shadow_attack
Update test of ShadowAttack
2 parents 7345c83 + 5bf3fa5 commit 59f47ea

File tree

4 files changed

+18
-18
lines changed

4 files changed

+18
-18
lines changed

art/attacks/evasion/shadow_attack.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,16 @@ def __init__(
109109

110110
def generate(self, x: np.ndarray, y: Optional[np.ndarray] = None, **kwargs) -> np.ndarray:
111111
"""
112-
Generate adversarial samples and return them in an array.
112+
Generate adversarial samples and return them in an array. This requires a lot of memory, therefore it accepts
113+
only a single samples as input, e.g. a batch of size 1.
113114
114-
:param x: An array with the original inputs.
115-
:param y: An array with the target labels.
115+
:param x: An array of a single original input sample.
116+
:param y: An array of a single target label.
116117
:return: An array with the adversarial examples.
117118
"""
119+
if x.shape[0] > 1 or y.shape[0] > 1:
120+
raise ValueError("This attack only accepts a single sample as input.")
121+
118122
y = check_and_transform_label_format(y, self.estimator.nb_classes)
119123

120124
if y is None:

run_tests.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ export TF_CPP_MIN_LOG_LEVEL="3"
99
pytest -q tests/attacks/evasion/ --mlFramework="tensorflow" --durations=0
1010
if [[ $? -ne 0 ]]; then exit_code=1; echo "Failed attacks/evasion tests"; fi
1111

12+
pytest -q -s tests/attacks/evasion/test_shadow_attack.py --mlFramework="pytorch" --durations=0
13+
if [[ $? -ne 0 ]]; then exit_code=1; echo "Failed attacks/evasion/test_shadow_attack.py"; fi
14+
1215
mlFrameworkList=("tensorflow" "scikitlearn")
1316
for mlFramework in "${mlFrameworkList[@]}"; do
1417
pytest -q tests/attacks/inference/ --mlFramework=$mlFramework --durations=0

tests/attacks/evasion/test_shadow_attack.py

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import pytest
2020

2121
import numpy as np
22+
import tensorflow as tf
2223

2324
from art.attacks.evasion import ShadowAttack
2425
from art.estimators.estimator import BaseEstimator, LossGradientsMixin
@@ -34,18 +35,15 @@ def fix_get_mnist_subset(get_mnist_dataset):
3435
(x_train_mnist, y_train_mnist), (x_test_mnist, y_test_mnist) = get_mnist_dataset
3536
n_train = 100
3637
n_test = 11
37-
yield (x_train_mnist[:n_train], y_train_mnist[:n_train], x_test_mnist[:n_test], y_test_mnist[:n_test])
38+
yield x_train_mnist[:n_train], y_train_mnist[:n_train], x_test_mnist[:n_test], y_test_mnist[:n_test]
3839

3940

40-
@pytest.mark.only_with_platform("pytorch")
41+
@pytest.mark.skipif(tf.__version__[0] == "1", reason="Skip for TensorFlow 1.x")
42+
@pytest.mark.skipMlFramework("keras", "scikitlearn")
4143
def test_generate(fix_get_mnist_subset, get_image_classifier_list_for_attack):
4244

4345
classifier_list = get_image_classifier_list_for_attack(ShadowAttack)
4446

45-
if classifier_list is None:
46-
logging.warning("Couldn't perform this test because no classifier is defined")
47-
return
48-
4947
for classifier in classifier_list:
5048
attack = ShadowAttack(
5149
estimator=classifier,
@@ -61,15 +59,13 @@ def test_generate(fix_get_mnist_subset, get_image_classifier_list_for_attack):
6159

6260
(x_train_mnist, y_train_mnist, x_test_mnist, y_test_mnist) = fix_get_mnist_subset
6361

64-
if attack.framework == "pytorch":
65-
x_train_mnist = x_train_mnist.transpose((0, 3, 1, 2))
66-
6762
x_train_mnist_adv = attack.generate(x=x_train_mnist[0:1], y=y_train_mnist[0:1])
6863

69-
assert np.max(np.abs(x_train_mnist_adv - x_train_mnist[0:1])) == pytest.approx(0.34966960549354553, 0.06)
64+
assert np.max(np.abs(x_train_mnist_adv - x_train_mnist[0:1])) == pytest.approx(0.34966960549354553, abs=0.06)
7065

7166

72-
@pytest.mark.only_with_platform("pytorch")
67+
@pytest.mark.skipif(tf.__version__[0] == "1", reason="Skip for TensorFlow 1.x")
68+
@pytest.mark.skipMlFramework("keras", "scikitlearn")
7369
def test_get_regularisation_loss_gradients(fix_get_mnist_subset, get_image_classifier_list_for_attack):
7470

7571
classifier_list = get_image_classifier_list_for_attack(ShadowAttack)
@@ -90,9 +86,6 @@ def test_get_regularisation_loss_gradients(fix_get_mnist_subset, get_image_class
9086

9187
(x_train_mnist, _, _, _) = fix_get_mnist_subset
9288

93-
if attack.framework == "pytorch":
94-
x_train_mnist = x_train_mnist.transpose((0, 3, 1, 2))
95-
9689
gradients = attack._get_regularisation_loss_gradients(x_train_mnist[0:1])
9790

9891
gradients_expected = np.array(

tests/attacks/evasion/test_square_attack.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def test_generate(fix_get_mnist_subset, get_image_classifier_list_for_attack):
5252

5353
x_train_mnist_adv = attack.generate(x=x_train_mnist, y=y_train_mnist)
5454

55-
assert np.mean(np.abs(x_train_mnist_adv - x_train_mnist)) == pytest.approx(0.0535, abs=0.015)
55+
assert np.mean(np.abs(x_train_mnist_adv - x_train_mnist)) == pytest.approx(0.03636, abs=0.015)
5656
assert np.max(np.abs(x_train_mnist_adv - x_train_mnist)) == pytest.approx(0.3, abs=0.05)
5757

5858

0 commit comments

Comments
 (0)