Skip to content

Commit 8aa8c01

Browse files
authored
Merge pull request #1757 from Trusted-AI/dev_1.11.0
Update to ART 1.11.0
2 parents 7b952e7 + 9b99b6f commit 8aa8c01

File tree

107 files changed

+10760
-332
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

107 files changed

+10760
-332
lines changed

.github/actions/yolo/Dockerfile

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Get base from a pytorch image
2+
FROM pytorch/pytorch:1.11.0-cuda11.3-cudnn8-runtime
3+
4+
# Set to install things in non-interactive mode
5+
ENV DEBIAN_FRONTEND noninteractive
6+
7+
# Install system wide software
8+
RUN apt-get update \
9+
&& apt-get install -y \
10+
libgl1-mesa-glx \
11+
libx11-xcb1 \
12+
git \
13+
gcc \
14+
mono-mcs \
15+
cmake \
16+
libavcodec-extra \
17+
ffmpeg \
18+
curl \
19+
wget \
20+
&& apt-get clean all \
21+
&& rm -r /var/lib/apt/lists/*
22+
23+
RUN pip install six setuptools tqdm
24+
RUN pip install numpy==1.21.6 scipy==1.8.1 scikit-learn==1.1.1 numba==0.55.1
25+
RUN pip install torch==1.11.0
26+
RUN pip install tensorflow==2.9.1
27+
RUN pip install pytest-cov
28+
29+
# Install necessary libraries for Yolo v3
30+
RUN pip install pytorchyolo==1.6.2
31+
32+
RUN cd /tmp/ && git clone https://github.com/eriklindernoren/PyTorch-YOLOv3.git
33+
RUN cd PyTorch-YOLOv3/weights && ./download_weights.sh

.github/actions/yolo/action.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
name: 'Test YOLO'
2+
description: 'Run tests for YOLO'
3+
runs:
4+
using: 'composite'
5+
steps:
6+
- run: $GITHUB_ACTION_PATH/run.sh
7+
shell: bash

.github/actions/yolo/run.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/bash
2+
3+
exit_code=0
4+
5+
pytest --cov-report=xml --cov=art --cov-append -q -vv tests/estimators/object_detection/test_pytorch_yolo.py --framework=pytorch --durations=0
6+
if [[ $? -ne 0 ]]; then exit_code=1; echo "Failed estimators/speech_recognition/test_pytorch_yolo tests"; fi
7+
8+
exit ${exit_code}

.github/workflows/ci-yolo.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: CI PyTorchYolo
2+
on:
3+
# Run on manual trigger
4+
workflow_dispatch:
5+
6+
# Run on pull requests
7+
pull_request:
8+
paths-ignore:
9+
- '*.md'
10+
11+
# Run when pushing to main or dev branches
12+
push:
13+
branches:
14+
- main
15+
- dev*
16+
17+
# Run scheduled CI flow daily
18+
schedule:
19+
- cron: '0 8 * * 0'
20+
21+
jobs:
22+
test_deepspeech_v3_torch_1_10:
23+
name: PyTorchYolo
24+
runs-on: ubuntu-latest
25+
container: adversarialrobustnesstoolbox/art_testing_envs:yolo
26+
steps:
27+
- name: Checkout Repo
28+
uses: actions/checkout@v3
29+
- name: Run Test Action
30+
uses: ./.github/actions/yolo
31+
- name: Upload coverage to Codecov
32+
uses: codecov/codecov-action@v3
33+
with:
34+
fail_ci_if_error: true

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@
1616
- IMT Atlantique
1717
- Johns Hopkins University
1818
- Troj.AI
19+
- VMware Inc.

art/attacks/evasion/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
from art.attacks.evasion.iterative_method import BasicIterativeMethod
3131
from art.attacks.evasion.laser_attack.laser_attack import LaserAttack
3232
from art.attacks.evasion.lowprofool import LowProFool
33+
from art.attacks.evasion.momentum_iterative_method import MomentumIterativeMethod
3334
from art.attacks.evasion.newtonfool import NewtonFool
3435
from art.attacks.evasion.pe_malware_attack import MalwareGDTensorFlow
3536
from art.attacks.evasion.pixel_threshold import PixelAttack
@@ -56,3 +57,4 @@
5657
from art.attacks.evasion.virtual_adversarial import VirtualAdversarialMethod
5758
from art.attacks.evasion.wasserstein import Wasserstein
5859
from art.attacks.evasion.zoo import ZooAttack
60+
from art.attacks.evasion.sign_opt import SignOPTAttack

art/attacks/evasion/adversarial_patch/adversarial_patch.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class AdversarialPatch(EvasionAttack):
5656
"learning_rate",
5757
"max_iter",
5858
"batch_size",
59+
"targeted",
5960
"verbose",
6061
]
6162

@@ -71,6 +72,7 @@ def __init__(
7172
max_iter: int = 500,
7273
batch_size: int = 16,
7374
patch_shape: Optional[Tuple[int, int, int]] = None,
75+
targeted: bool = True,
7476
verbose: bool = True,
7577
):
7678
"""
@@ -89,6 +91,7 @@ def __init__(
8991
:param patch_shape: The shape of the adversarial patch as a tuple of shape (width, height, nb_channels).
9092
Currently only supported for `TensorFlowV2Classifier`. For classifiers of other frameworks
9193
the `patch_shape` is set to the shape of the input samples.
94+
:param targeted: Indicates whether the attack is targeted (True) or untargeted (False).
9295
:param verbose: Show progress bars.
9396
"""
9497
super().__init__(estimator=classifier)
@@ -106,6 +109,7 @@ def __init__(
106109
max_iter=max_iter,
107110
batch_size=batch_size,
108111
patch_shape=patch_shape,
112+
targeted=targeted,
109113
verbose=verbose,
110114
)
111115
elif isinstance(self.estimator, PyTorchClassifier):
@@ -121,6 +125,7 @@ def __init__(
121125
batch_size=batch_size,
122126
patch_shape=patch_shape,
123127
patch_type="circle",
128+
targeted=targeted,
124129
verbose=verbose,
125130
)
126131
else:
@@ -134,6 +139,7 @@ def __init__(
134139
learning_rate=learning_rate,
135140
max_iter=max_iter,
136141
batch_size=batch_size,
142+
targeted=targeted,
137143
verbose=verbose,
138144
)
139145
self._check_params()
@@ -241,5 +247,8 @@ def _check_params(self) -> None:
241247
if not self._attack.batch_size > 0:
242248
raise ValueError("The batch size must be greater than 0.")
243249

250+
if not isinstance(self._attack.targeted, bool):
251+
raise ValueError("The argument `targeted` has to be of type bool.")
252+
244253
if not isinstance(self._attack.verbose, bool):
245254
raise ValueError("The argument `verbose` has to be of type bool.")

art/attacks/evasion/adversarial_patch/adversarial_patch_numpy.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ def __init__(
7474
max_iter: int = 500,
7575
clip_patch: Union[list, tuple, None] = None,
7676
batch_size: int = 16,
77+
targeted: bool = True,
7778
verbose: bool = True,
7879
) -> None:
7980
"""
@@ -92,6 +93,8 @@ def __init__(
9293
:param clip_patch: The minimum and maximum values for each channel in the form
9394
[(float, float), (float, float), (float, float)].
9495
:param batch_size: The size of the training batch.
96+
:param targeted: Indicates whether the attack is targeted (True) or untargeted (False). Currently only targeted
97+
attacks are supported.
9598
:param verbose: Show progress bars.
9699
"""
97100
super().__init__(estimator=classifier)
@@ -104,6 +107,7 @@ def __init__(
104107
self.max_iter = max_iter
105108
self.batch_size = batch_size
106109
self.clip_patch = clip_patch
110+
self.targeted = targeted
107111
self.verbose = verbose
108112
self._check_params()
109113

@@ -299,6 +303,12 @@ def _check_params(self) -> None:
299303
if self.batch_size <= 0:
300304
raise ValueError("The batch size must be greater than 0.")
301305

306+
if not isinstance(self.targeted, bool) and not self.targeted:
307+
raise ValueError(
308+
"The argument `targeted` has to be of type bool. Currently AdversarialPatchNumpy only supports targeted"
309+
"attacks."
310+
)
311+
302312
if not isinstance(self.verbose, bool):
303313
raise ValueError("The argument `verbose` has to be of type bool.")
304314

art/attacks/evasion/auto_attack.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ def generate(self, x: np.ndarray, y: Optional[np.ndarray] = None, **kwargs) -> n
159159
"""
160160
x_adv = x.astype(ART_NUMPY_DTYPE)
161161
if y is not None:
162-
y = check_and_transform_label_format(y, self.estimator.nb_classes)
162+
y = check_and_transform_label_format(y, nb_classes=self.estimator.nb_classes)
163163

164164
if y is None:
165165
y = get_labels_np_array(self.estimator.predict(x, batch_size=self.batch_size))
@@ -207,7 +207,9 @@ def generate(self, x: np.ndarray, y: Optional[np.ndarray] = None, **kwargs) -> n
207207
if np.sum(sample_is_robust) == 0:
208208
break
209209

210-
target = check_and_transform_label_format(targeted_labels[:, i], self.estimator.nb_classes)
210+
target = check_and_transform_label_format(
211+
targeted_labels[:, i], nb_classes=self.estimator.nb_classes
212+
)
211213

212214
x_adv, sample_is_robust = self._run_attack(
213215
x=x_adv,

art/attacks/evasion/auto_projected_gradient_descent.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ def generate(self, x: np.ndarray, y: Optional[np.ndarray] = None, **kwargs) -> n
376376
mask = kwargs.get("mask")
377377

378378
if y is not None:
379-
y = check_and_transform_label_format(y, self.estimator.nb_classes)
379+
y = check_and_transform_label_format(y, nb_classes=self.estimator.nb_classes)
380380

381381
if y is None:
382382
if self.targeted:

0 commit comments

Comments
 (0)