adv-lib 0.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- adv_lib-0.2.2/LICENSE +29 -0
- adv_lib-0.2.2/PKG-INFO +170 -0
- adv_lib-0.2.2/README.md +118 -0
- adv_lib-0.2.2/adv_lib/__init__.py +1 -0
- adv_lib-0.2.2/adv_lib/attacks/__init__.py +13 -0
- adv_lib-0.2.2/adv_lib/attacks/augmented_lagrangian.py +243 -0
- adv_lib-0.2.2/adv_lib/attacks/auto_pgd.py +523 -0
- adv_lib-0.2.2/adv_lib/attacks/boundary_projection_tf.py +170 -0
- adv_lib-0.2.2/adv_lib/attacks/carlini_wagner/__init__.py +2 -0
- adv_lib-0.2.2/adv_lib/attacks/carlini_wagner/l2.py +151 -0
- adv_lib-0.2.2/adv_lib/attacks/carlini_wagner/linf.py +158 -0
- adv_lib-0.2.2/adv_lib/attacks/decoupled_direction_norm.py +113 -0
- adv_lib-0.2.2/adv_lib/attacks/fast_adaptive_boundary/__init__.py +1 -0
- adv_lib-0.2.2/adv_lib/attacks/fast_adaptive_boundary/fast_adaptive_boundary.py +215 -0
- adv_lib-0.2.2/adv_lib/attacks/fast_adaptive_boundary/projections.py +164 -0
- adv_lib-0.2.2/adv_lib/attacks/fast_minimum_norm.py +218 -0
- adv_lib-0.2.2/adv_lib/attacks/perceptual_color_attacks/__init__.py +1 -0
- adv_lib-0.2.2/adv_lib/attacks/perceptual_color_attacks/differential_color_functions.py +181 -0
- adv_lib-0.2.2/adv_lib/attacks/perceptual_color_attacks/perceptual_color_distance_al.py +128 -0
- adv_lib-0.2.2/adv_lib/attacks/primal_dual_gradient_descent.py +379 -0
- adv_lib-0.2.2/adv_lib/attacks/projected_gradient_descent.py +109 -0
- adv_lib-0.2.2/adv_lib/attacks/segmentation/__init__.py +4 -0
- adv_lib-0.2.2/adv_lib/attacks/segmentation/alma_prox.py +283 -0
- adv_lib-0.2.2/adv_lib/attacks/segmentation/asma.py +92 -0
- adv_lib-0.2.2/adv_lib/attacks/segmentation/dense_adversary.py +83 -0
- adv_lib-0.2.2/adv_lib/attacks/segmentation/primal_dual_gradient_descent.py +349 -0
- adv_lib-0.2.2/adv_lib/attacks/self_adaptive_norm_update.py +127 -0
- adv_lib-0.2.2/adv_lib/attacks/sigma_zero.py +119 -0
- adv_lib-0.2.2/adv_lib/attacks/stochastic_sparse_attacks.py +237 -0
- adv_lib-0.2.2/adv_lib/attacks/structured_adversarial_attack.py +289 -0
- adv_lib-0.2.2/adv_lib/attacks/trust_region.py +153 -0
- adv_lib-0.2.2/adv_lib/distances/__init__.py +0 -0
- adv_lib-0.2.2/adv_lib/distances/color_difference.py +212 -0
- adv_lib-0.2.2/adv_lib/distances/lp_norms.py +18 -0
- adv_lib-0.2.2/adv_lib/distances/lpips.py +99 -0
- adv_lib-0.2.2/adv_lib/distances/structural_similarity.py +147 -0
- adv_lib-0.2.2/adv_lib/utils/__init__.py +1 -0
- adv_lib-0.2.2/adv_lib/utils/attack_utils.py +226 -0
- adv_lib-0.2.2/adv_lib/utils/color_conversions.py +71 -0
- adv_lib-0.2.2/adv_lib/utils/image_selection.py +27 -0
- adv_lib-0.2.2/adv_lib/utils/lagrangian_penalties/__init__.py +1 -0
- adv_lib-0.2.2/adv_lib/utils/lagrangian_penalties/all_penalties.py +67 -0
- adv_lib-0.2.2/adv_lib/utils/lagrangian_penalties/penalty_functions.py +79 -0
- adv_lib-0.2.2/adv_lib/utils/lagrangian_penalties/scripts/plot_penalties.py +42 -0
- adv_lib-0.2.2/adv_lib/utils/lagrangian_penalties/scripts/plot_univariates.py +32 -0
- adv_lib-0.2.2/adv_lib/utils/lagrangian_penalties/univariate_functions.py +299 -0
- adv_lib-0.2.2/adv_lib/utils/losses.py +29 -0
- adv_lib-0.2.2/adv_lib/utils/projections.py +100 -0
- adv_lib-0.2.2/adv_lib/utils/utils.py +58 -0
- adv_lib-0.2.2/adv_lib/utils/visdom_logger.py +109 -0
- adv_lib-0.2.2/adv_lib.egg-info/PKG-INFO +170 -0
- adv_lib-0.2.2/adv_lib.egg-info/SOURCES.txt +55 -0
- adv_lib-0.2.2/adv_lib.egg-info/dependency_links.txt +1 -0
- adv_lib-0.2.2/adv_lib.egg-info/requires.txt +8 -0
- adv_lib-0.2.2/adv_lib.egg-info/top_level.txt +1 -0
- adv_lib-0.2.2/pyproject.toml +39 -0
- adv_lib-0.2.2/setup.cfg +4 -0
adv_lib-0.2.2/LICENSE
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020, Jérôme Rony
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
10
|
+
list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
15
|
+
|
|
16
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
17
|
+
contributors may be used to endorse or promote products derived from
|
|
18
|
+
this software without specific prior written permission.
|
|
19
|
+
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
24
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
26
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
28
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
adv_lib-0.2.2/PKG-INFO
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: adv-lib
|
|
3
|
+
Version: 0.2.2
|
|
4
|
+
Summary: Library of various adversarial attacks resources in PyTorch
|
|
5
|
+
Author-email: Jerome Rony <jerome.rony@gmail.com>
|
|
6
|
+
License: BSD 3-Clause License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2020, Jérôme Rony
|
|
9
|
+
All rights reserved.
|
|
10
|
+
|
|
11
|
+
Redistribution and use in source and binary forms, with or without
|
|
12
|
+
modification, are permitted provided that the following conditions are met:
|
|
13
|
+
|
|
14
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
15
|
+
list of conditions and the following disclaimer.
|
|
16
|
+
|
|
17
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
18
|
+
this list of conditions and the following disclaimer in the documentation
|
|
19
|
+
and/or other materials provided with the distribution.
|
|
20
|
+
|
|
21
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
22
|
+
contributors may be used to endorse or promote products derived from
|
|
23
|
+
this software without specific prior written permission.
|
|
24
|
+
|
|
25
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
26
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
27
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
28
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
29
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
30
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
31
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
32
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
33
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
34
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
35
|
+
|
|
36
|
+
Project-URL: Repository, https://github.com/jeromerony/adversarial-library.git
|
|
37
|
+
Classifier: Programming Language :: Python :: 3
|
|
38
|
+
Classifier: Development Status :: 3 - Alpha
|
|
39
|
+
Classifier: Intended Audience :: Developers
|
|
40
|
+
Classifier: Intended Audience :: Science/Research
|
|
41
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
42
|
+
Requires-Python: >=3.8
|
|
43
|
+
Description-Content-Type: text/markdown
|
|
44
|
+
License-File: LICENSE
|
|
45
|
+
Requires-Dist: torch>=1.8.0
|
|
46
|
+
Requires-Dist: torchvision>=0.9.0
|
|
47
|
+
Requires-Dist: tqdm>=4.48.0
|
|
48
|
+
Requires-Dist: visdom>=0.1.8
|
|
49
|
+
Provides-Extra: test
|
|
50
|
+
Requires-Dist: scikit-image; extra == "test"
|
|
51
|
+
Requires-Dist: pytest; extra == "test"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
[](https://zenodo.org/badge/latestdoi/315504148)
|
|
55
|
+
|
|
56
|
+
# Adversarial Library
|
|
57
|
+
|
|
58
|
+
This library contains various resources related to adversarial attacks implemented in PyTorch. It is aimed towards researchers looking for implementations of state-of-the-art attacks.
|
|
59
|
+
|
|
60
|
+
The code was written to maximize efficiency (_e.g._ by preferring low level functions from PyTorch) while retaining simplicity (_e.g._ by avoiding abstractions). As a consequence, most of the library, and especially the attacks, is implemented using **pure functions** (whenever possible).
|
|
61
|
+
|
|
62
|
+
While focused on attacks, this library also provides several utilities related to adversarial attacks: distances (SSIM, CIEDE2000, LPIPS), visdom callback, projections, losses and helper functions. Most notably the function `run_attack` from `utils/attack_utils.py` performs an attack on a model given the inputs and labels, with fixed batch size, and reports complexity related metrics (run-time and forward/backward propagations).
|
|
63
|
+
|
|
64
|
+
### Dependencies
|
|
65
|
+
|
|
66
|
+
The goal of this library is to be up-to-date with newer versions of PyTorch so the dependencies are expected to be updated regularly (possibly resulting in breaking changes).
|
|
67
|
+
|
|
68
|
+
- pytorch>=1.8.0
|
|
69
|
+
- torchvision>=0.9.0
|
|
70
|
+
- tqdm>=4.48.0
|
|
71
|
+
- visdom>=0.1.8
|
|
72
|
+
|
|
73
|
+
### Installation
|
|
74
|
+
|
|
75
|
+
You can either install using:
|
|
76
|
+
|
|
77
|
+
```pip install git+https://github.com/jeromerony/adversarial-library```
|
|
78
|
+
|
|
79
|
+
Or you can clone the repo and run:
|
|
80
|
+
|
|
81
|
+
```python setup.py install```
|
|
82
|
+
|
|
83
|
+
Alternatively, you can install (after cloning) the library in editable mode:
|
|
84
|
+
|
|
85
|
+
```pip install -e .```
|
|
86
|
+
|
|
87
|
+
### Usage
|
|
88
|
+
Attacks are implemented as functions, so they can be called directly by providing the model, samples and labels (possibly with optional arguments):
|
|
89
|
+
```python
|
|
90
|
+
from adv_lib.attacks import ddn
|
|
91
|
+
adv_samples = ddn(model=model, inputs=inputs, labels=labels, steps=300)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Classification attacks all expect the following arguments:
|
|
95
|
+
- `model`: the model that produces logits (pre-softmax activations) with inputs in $[0, 1]$
|
|
96
|
+
- `inputs`: the samples to attack in $[0, 1]$
|
|
97
|
+
- `labels`: either the ground-truth labels for the samples or the targets
|
|
98
|
+
- `targeted`: flag indicated if the attack should be targeted or not -- defaults to `False`
|
|
99
|
+
|
|
100
|
+
Additionally, many attacks have an optional `callback` argument which accepts an `adv_lib.utils.visdom_logger.VisdomLogger` to plot data to a visdom server for monitoring purposes.
|
|
101
|
+
|
|
102
|
+
For a more detailed example on how to use this library, you can look at this repo: https://github.com/jeromerony/augmented_lagrangian_adversarial_attacks
|
|
103
|
+
|
|
104
|
+
## Contents
|
|
105
|
+
|
|
106
|
+
### Attacks
|
|
107
|
+
|
|
108
|
+
#### Classification
|
|
109
|
+
|
|
110
|
+
Currently the following classification attacks are implemented in the `adv_lib.attacks` module:
|
|
111
|
+
|
|
112
|
+
| Name | Knowledge | Type | Distance(s) | ArXiv Link |
|
|
113
|
+
|-----------------------------------------------------------------------------------------|-----------|---------|-----------------------------------------------------------|------------------------------------------------------------------------------------------------------|
|
|
114
|
+
| Carlini and Wagner (C&W) | White-box | Minimal | $\ell_2$, $\ell_\infty$ | [1608.04644](https://arxiv.org/abs/1608.04644) |
|
|
115
|
+
| Projected Gradient Descent (PGD) | White-box | Budget | $\ell_\infty$ | [1706.06083](https://arxiv.org/abs/1706.06083) |
|
|
116
|
+
| Structured Adversarial Attack (StrAttack) | White-box | Minimal | $\ell_2$ + group-sparsity | [1808.01664](https://arxiv.org/abs/1808.01664) |
|
|
117
|
+
| **Decoupled Direction and Norm (DDN)** | White-box | Minimal | $\ell_2$ | [1811.09600](https://arxiv.org/abs/1811.09600) |
|
|
118
|
+
| Trust Region (TR) | White-box | Minimal | $\ell_2$, $\ell_\infty$ | [1812.06371](https://arxiv.org/abs/1812.06371) |
|
|
119
|
+
| Fast Adaptive Boundary (FAB) | White-box | Minimal | $\ell_1$, $\ell_2$, $\ell_\infty$ | [1907.02044](https://arxiv.org/abs/1907.02044) |
|
|
120
|
+
| Perceptual Color distance Alternating Loss (PerC-AL) | White-box | Minimal | CIEDE2000 | [1911.02466](https://arxiv.org/abs/1911.02466) |
|
|
121
|
+
| Auto-PGD (APGD) | White-box | Budget | $\ell_1$, $\ell_2$, $\ell_\infty$ | [2003.01690](https://arxiv.org/abs/2003.01690) <br /> [2103.01208](https://arxiv.org/abs/2103.01208) |
|
|
122
|
+
| **Augmented Lagrangian Method for Adversarial (ALMA)** | White-box | Minimal | $\ell_1$, $\ell_2$, SSIM, CIEDE2000, LPIPS, ... | [2011.11857](https://arxiv.org/abs/2011.11857) |
|
|
123
|
+
| Folded Gaussian Attack (FGA)<br /> Voting Folded Gaussian Attack (VFGA) | White-box | Minimal | $\ell_0$ | [2011.12423](https://arxiv.org/abs/2011.12423) |
|
|
124
|
+
| Fast Minimum-Norm (FMN) | White-box | Minimal | $\ell_0$, $\ell_1$, $\ell_2$, $\ell_\infty$ | [2102.12827](https://arxiv.org/abs/2102.12827) |
|
|
125
|
+
| Primal-Dual Gradient Descent (PDGD)<br /> Primal-Dual Proximal Gradient Descent (PDPGD) | White-box | Minimal | $\ell_2$<br />$\ell_0$, $\ell_1$, $\ell_2$, $\ell_\infty$ | [2106.01538](https://arxiv.org/abs/2106.01538) |
|
|
126
|
+
| σ-zero | White-box | Minimal | $\ell_0$ | [2402.01879](https://arxiv.org/abs/2402.01879) |
|
|
127
|
+
|
|
128
|
+
**Bold** means that this repository contains the official implementation.
|
|
129
|
+
|
|
130
|
+
_Type_ refers to the goal of the attack:
|
|
131
|
+
- _Minimal_ attacks aim to find the smallest adversarial perturbation w.r.t. a given distance;
|
|
132
|
+
- _Budget_ attacks aim to find an adversarial perturbation within a distance budget (and often to maximize a loss as well).
|
|
133
|
+
|
|
134
|
+
#### Segmentation
|
|
135
|
+
|
|
136
|
+
The library now includes segmentation attacks in the `adv_lib.attacks.segmentation` module. These require the following arguments:
|
|
137
|
+
- `model`: the model that produces logits (pre-softmax activations) with inputs in $[0, 1]$
|
|
138
|
+
- `inputs`: the images to attack in $[0, 1]$. Shape: $b\times c\times h\times w$ with $b$ the batch size, $c$ the number of color channels and $h$ and $w$ the height and width of the images.
|
|
139
|
+
- `labels`: either the ground-truth labels for the samples or the targets. Shape: $b\times h\times w$.
|
|
140
|
+
- `masks`: binary mask indicating which pixels to attack, to account for unlabeled pixels (e.g. void in Pascal VOC). Shape: $b\times h\times w$
|
|
141
|
+
- `targeted`: flag indicated if the attack should be targeted or not -- defaults to `False`
|
|
142
|
+
- `adv_threshold`: fraction of the pixels to consider an attack successful -- defaults to `0.99`
|
|
143
|
+
|
|
144
|
+
The following segmentation attacks are implemented:
|
|
145
|
+
|
|
146
|
+
| Name | Knowledge | Type | Distance(s) | ArXiv Link |
|
|
147
|
+
|-------------------------------------------------------------------------------------------|-----------|---------|-----------------------------------------------------------|------------------------------------------------|
|
|
148
|
+
| Dense Adversary Generation (DAG) | White-box | Minimal | $\ell_2$, $\ell_\infty$ | [1703.08603](https://arxiv.org/abs/1703.08603) |
|
|
149
|
+
| Adaptive Segmentation Mask Attack (ASMA) | White-box | Minimal | $\ell_2$ | [1907.13124](https://arxiv.org/abs/1907.13124) |
|
|
150
|
+
| _Primal-Dual Gradient Descent (PDGD)<br /> Primal-Dual Proximal Gradient Descent (PDPGD)_ | White-box | Minimal | $\ell_2$<br />$\ell_0$, $\ell_1$, $\ell_2$, $\ell_\infty$ | [2106.01538](https://arxiv.org/abs/2106.01538) |
|
|
151
|
+
| **ALMA prox** | White-box | Minimal | $\ell_\infty$ | [2206.07179](https://arxiv.org/abs/2206.07179) |
|
|
152
|
+
|
|
153
|
+
_Italic_ indicates that the attack is unofficially adapted from the classification variant.
|
|
154
|
+
|
|
155
|
+
### Distances
|
|
156
|
+
|
|
157
|
+
The following distances are available in the utils `adv_lib.distances` module:
|
|
158
|
+
- Lp-norms
|
|
159
|
+
- SSIM https://ece.uwaterloo.ca/~z70wang/research/ssim/
|
|
160
|
+
- MS-SSIM https://ece.uwaterloo.ca/~z70wang/publications/msssim.html
|
|
161
|
+
- CIEDE2000 color difference http://www2.ece.rochester.edu/~gsharma/ciede2000/ciede2000noteCRNA.pdf
|
|
162
|
+
- LPIPS https://arxiv.org/abs/1801.03924
|
|
163
|
+
|
|
164
|
+
## Contributions
|
|
165
|
+
|
|
166
|
+
Suggestions and contributions are welcome :)
|
|
167
|
+
|
|
168
|
+
## Citation
|
|
169
|
+
|
|
170
|
+
If this library has been useful for your research, you can cite it using the "Cite this repository" button in the "About" section.
|
adv_lib-0.2.2/README.md
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
|
|
2
|
+
[](https://zenodo.org/badge/latestdoi/315504148)
|
|
3
|
+
|
|
4
|
+
# Adversarial Library
|
|
5
|
+
|
|
6
|
+
This library contains various resources related to adversarial attacks implemented in PyTorch. It is aimed towards researchers looking for implementations of state-of-the-art attacks.
|
|
7
|
+
|
|
8
|
+
The code was written to maximize efficiency (_e.g._ by preferring low level functions from PyTorch) while retaining simplicity (_e.g._ by avoiding abstractions). As a consequence, most of the library, and especially the attacks, is implemented using **pure functions** (whenever possible).
|
|
9
|
+
|
|
10
|
+
While focused on attacks, this library also provides several utilities related to adversarial attacks: distances (SSIM, CIEDE2000, LPIPS), visdom callback, projections, losses and helper functions. Most notably the function `run_attack` from `utils/attack_utils.py` performs an attack on a model given the inputs and labels, with fixed batch size, and reports complexity related metrics (run-time and forward/backward propagations).
|
|
11
|
+
|
|
12
|
+
### Dependencies
|
|
13
|
+
|
|
14
|
+
The goal of this library is to be up-to-date with newer versions of PyTorch so the dependencies are expected to be updated regularly (possibly resulting in breaking changes).
|
|
15
|
+
|
|
16
|
+
- pytorch>=1.8.0
|
|
17
|
+
- torchvision>=0.9.0
|
|
18
|
+
- tqdm>=4.48.0
|
|
19
|
+
- visdom>=0.1.8
|
|
20
|
+
|
|
21
|
+
### Installation
|
|
22
|
+
|
|
23
|
+
You can either install using:
|
|
24
|
+
|
|
25
|
+
```pip install git+https://github.com/jeromerony/adversarial-library```
|
|
26
|
+
|
|
27
|
+
Or you can clone the repo and run:
|
|
28
|
+
|
|
29
|
+
```python setup.py install```
|
|
30
|
+
|
|
31
|
+
Alternatively, you can install (after cloning) the library in editable mode:
|
|
32
|
+
|
|
33
|
+
```pip install -e .```
|
|
34
|
+
|
|
35
|
+
### Usage
|
|
36
|
+
Attacks are implemented as functions, so they can be called directly by providing the model, samples and labels (possibly with optional arguments):
|
|
37
|
+
```python
|
|
38
|
+
from adv_lib.attacks import ddn
|
|
39
|
+
adv_samples = ddn(model=model, inputs=inputs, labels=labels, steps=300)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Classification attacks all expect the following arguments:
|
|
43
|
+
- `model`: the model that produces logits (pre-softmax activations) with inputs in $[0, 1]$
|
|
44
|
+
- `inputs`: the samples to attack in $[0, 1]$
|
|
45
|
+
- `labels`: either the ground-truth labels for the samples or the targets
|
|
46
|
+
- `targeted`: flag indicated if the attack should be targeted or not -- defaults to `False`
|
|
47
|
+
|
|
48
|
+
Additionally, many attacks have an optional `callback` argument which accepts an `adv_lib.utils.visdom_logger.VisdomLogger` to plot data to a visdom server for monitoring purposes.
|
|
49
|
+
|
|
50
|
+
For a more detailed example on how to use this library, you can look at this repo: https://github.com/jeromerony/augmented_lagrangian_adversarial_attacks
|
|
51
|
+
|
|
52
|
+
## Contents
|
|
53
|
+
|
|
54
|
+
### Attacks
|
|
55
|
+
|
|
56
|
+
#### Classification
|
|
57
|
+
|
|
58
|
+
Currently the following classification attacks are implemented in the `adv_lib.attacks` module:
|
|
59
|
+
|
|
60
|
+
| Name | Knowledge | Type | Distance(s) | ArXiv Link |
|
|
61
|
+
|-----------------------------------------------------------------------------------------|-----------|---------|-----------------------------------------------------------|------------------------------------------------------------------------------------------------------|
|
|
62
|
+
| Carlini and Wagner (C&W) | White-box | Minimal | $\ell_2$, $\ell_\infty$ | [1608.04644](https://arxiv.org/abs/1608.04644) |
|
|
63
|
+
| Projected Gradient Descent (PGD) | White-box | Budget | $\ell_\infty$ | [1706.06083](https://arxiv.org/abs/1706.06083) |
|
|
64
|
+
| Structured Adversarial Attack (StrAttack) | White-box | Minimal | $\ell_2$ + group-sparsity | [1808.01664](https://arxiv.org/abs/1808.01664) |
|
|
65
|
+
| **Decoupled Direction and Norm (DDN)** | White-box | Minimal | $\ell_2$ | [1811.09600](https://arxiv.org/abs/1811.09600) |
|
|
66
|
+
| Trust Region (TR) | White-box | Minimal | $\ell_2$, $\ell_\infty$ | [1812.06371](https://arxiv.org/abs/1812.06371) |
|
|
67
|
+
| Fast Adaptive Boundary (FAB) | White-box | Minimal | $\ell_1$, $\ell_2$, $\ell_\infty$ | [1907.02044](https://arxiv.org/abs/1907.02044) |
|
|
68
|
+
| Perceptual Color distance Alternating Loss (PerC-AL) | White-box | Minimal | CIEDE2000 | [1911.02466](https://arxiv.org/abs/1911.02466) |
|
|
69
|
+
| Auto-PGD (APGD) | White-box | Budget | $\ell_1$, $\ell_2$, $\ell_\infty$ | [2003.01690](https://arxiv.org/abs/2003.01690) <br /> [2103.01208](https://arxiv.org/abs/2103.01208) |
|
|
70
|
+
| **Augmented Lagrangian Method for Adversarial (ALMA)** | White-box | Minimal | $\ell_1$, $\ell_2$, SSIM, CIEDE2000, LPIPS, ... | [2011.11857](https://arxiv.org/abs/2011.11857) |
|
|
71
|
+
| Folded Gaussian Attack (FGA)<br /> Voting Folded Gaussian Attack (VFGA) | White-box | Minimal | $\ell_0$ | [2011.12423](https://arxiv.org/abs/2011.12423) |
|
|
72
|
+
| Fast Minimum-Norm (FMN) | White-box | Minimal | $\ell_0$, $\ell_1$, $\ell_2$, $\ell_\infty$ | [2102.12827](https://arxiv.org/abs/2102.12827) |
|
|
73
|
+
| Primal-Dual Gradient Descent (PDGD)<br /> Primal-Dual Proximal Gradient Descent (PDPGD) | White-box | Minimal | $\ell_2$<br />$\ell_0$, $\ell_1$, $\ell_2$, $\ell_\infty$ | [2106.01538](https://arxiv.org/abs/2106.01538) |
|
|
74
|
+
| σ-zero | White-box | Minimal | $\ell_0$ | [2402.01879](https://arxiv.org/abs/2402.01879) |
|
|
75
|
+
|
|
76
|
+
**Bold** means that this repository contains the official implementation.
|
|
77
|
+
|
|
78
|
+
_Type_ refers to the goal of the attack:
|
|
79
|
+
- _Minimal_ attacks aim to find the smallest adversarial perturbation w.r.t. a given distance;
|
|
80
|
+
- _Budget_ attacks aim to find an adversarial perturbation within a distance budget (and often to maximize a loss as well).
|
|
81
|
+
|
|
82
|
+
#### Segmentation
|
|
83
|
+
|
|
84
|
+
The library now includes segmentation attacks in the `adv_lib.attacks.segmentation` module. These require the following arguments:
|
|
85
|
+
- `model`: the model that produces logits (pre-softmax activations) with inputs in $[0, 1]$
|
|
86
|
+
- `inputs`: the images to attack in $[0, 1]$. Shape: $b\times c\times h\times w$ with $b$ the batch size, $c$ the number of color channels and $h$ and $w$ the height and width of the images.
|
|
87
|
+
- `labels`: either the ground-truth labels for the samples or the targets. Shape: $b\times h\times w$.
|
|
88
|
+
- `masks`: binary mask indicating which pixels to attack, to account for unlabeled pixels (e.g. void in Pascal VOC). Shape: $b\times h\times w$
|
|
89
|
+
- `targeted`: flag indicated if the attack should be targeted or not -- defaults to `False`
|
|
90
|
+
- `adv_threshold`: fraction of the pixels to consider an attack successful -- defaults to `0.99`
|
|
91
|
+
|
|
92
|
+
The following segmentation attacks are implemented:
|
|
93
|
+
|
|
94
|
+
| Name | Knowledge | Type | Distance(s) | ArXiv Link |
|
|
95
|
+
|-------------------------------------------------------------------------------------------|-----------|---------|-----------------------------------------------------------|------------------------------------------------|
|
|
96
|
+
| Dense Adversary Generation (DAG) | White-box | Minimal | $\ell_2$, $\ell_\infty$ | [1703.08603](https://arxiv.org/abs/1703.08603) |
|
|
97
|
+
| Adaptive Segmentation Mask Attack (ASMA) | White-box | Minimal | $\ell_2$ | [1907.13124](https://arxiv.org/abs/1907.13124) |
|
|
98
|
+
| _Primal-Dual Gradient Descent (PDGD)<br /> Primal-Dual Proximal Gradient Descent (PDPGD)_ | White-box | Minimal | $\ell_2$<br />$\ell_0$, $\ell_1$, $\ell_2$, $\ell_\infty$ | [2106.01538](https://arxiv.org/abs/2106.01538) |
|
|
99
|
+
| **ALMA prox** | White-box | Minimal | $\ell_\infty$ | [2206.07179](https://arxiv.org/abs/2206.07179) |
|
|
100
|
+
|
|
101
|
+
_Italic_ indicates that the attack is unofficially adapted from the classification variant.
|
|
102
|
+
|
|
103
|
+
### Distances
|
|
104
|
+
|
|
105
|
+
The following distances are available in the utils `adv_lib.distances` module:
|
|
106
|
+
- Lp-norms
|
|
107
|
+
- SSIM https://ece.uwaterloo.ca/~z70wang/research/ssim/
|
|
108
|
+
- MS-SSIM https://ece.uwaterloo.ca/~z70wang/publications/msssim.html
|
|
109
|
+
- CIEDE2000 color difference http://www2.ece.rochester.edu/~gsharma/ciede2000/ciede2000noteCRNA.pdf
|
|
110
|
+
- LPIPS https://arxiv.org/abs/1801.03924
|
|
111
|
+
|
|
112
|
+
## Contributions
|
|
113
|
+
|
|
114
|
+
Suggestions and contributions are welcome :)
|
|
115
|
+
|
|
116
|
+
## Citation
|
|
117
|
+
|
|
118
|
+
If this library has been useful for your research, you can cite it using the "Cite this repository" button in the "About" section.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.2.2"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from .augmented_lagrangian import alma
|
|
2
|
+
from .auto_pgd import apgd, apgd_targeted
|
|
3
|
+
from .carlini_wagner import carlini_wagner_l2, carlini_wagner_linf
|
|
4
|
+
from .decoupled_direction_norm import ddn
|
|
5
|
+
from .fast_adaptive_boundary import fab
|
|
6
|
+
from .fast_minimum_norm import fmn
|
|
7
|
+
from .perceptual_color_attacks import perc_al
|
|
8
|
+
from .primal_dual_gradient_descent import pdgd, pdpgd
|
|
9
|
+
from .projected_gradient_descent import pgd_linf
|
|
10
|
+
from .sigma_zero import sigma_zero
|
|
11
|
+
from .stochastic_sparse_attacks import fga, vfga
|
|
12
|
+
from .structured_adversarial_attack import str_attack
|
|
13
|
+
from .trust_region import tr
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
from functools import partial
|
|
2
|
+
from typing import Callable, Optional
|
|
3
|
+
|
|
4
|
+
import torch
|
|
5
|
+
from torch import Tensor, nn
|
|
6
|
+
from torch.autograd import grad
|
|
7
|
+
|
|
8
|
+
from adv_lib.distances.color_difference import ciede2000_loss
|
|
9
|
+
from adv_lib.distances.lp_norms import l1_distances, l2_distances
|
|
10
|
+
from adv_lib.distances.lpips import LPIPS
|
|
11
|
+
from adv_lib.distances.structural_similarity import ms_ssim_loss, ssim_loss
|
|
12
|
+
from adv_lib.utils.lagrangian_penalties import all_penalties
|
|
13
|
+
from adv_lib.utils.losses import difference_of_logits_ratio
|
|
14
|
+
from adv_lib.utils.visdom_logger import VisdomLogger
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def init_lr_finder(inputs: Tensor, grad: Tensor, distance_function: Callable, target_distance: float) -> Tensor:
|
|
18
|
+
"""
|
|
19
|
+
Performs a line search and a binary search to find the learning rate η for each sample such that:
|
|
20
|
+
distance_function(inputs - η * grad) = target_distance.
|
|
21
|
+
|
|
22
|
+
Parameters
|
|
23
|
+
----------
|
|
24
|
+
inputs : Tensor
|
|
25
|
+
Reference to compute the distance from.
|
|
26
|
+
grad : Tensor
|
|
27
|
+
Direction to step in.
|
|
28
|
+
distance_function : Callable
|
|
29
|
+
target_distance : float
|
|
30
|
+
Target distance that inputs - η * grad should reach.
|
|
31
|
+
|
|
32
|
+
Returns
|
|
33
|
+
-------
|
|
34
|
+
η : Tensor
|
|
35
|
+
Learning rate for each sample.
|
|
36
|
+
|
|
37
|
+
"""
|
|
38
|
+
batch_size = len(inputs)
|
|
39
|
+
batch_view = lambda tensor: tensor.view(batch_size, *[1] * (inputs.ndim - 1))
|
|
40
|
+
lr = torch.ones(batch_size, device=inputs.device)
|
|
41
|
+
lower = torch.zeros_like(lr)
|
|
42
|
+
|
|
43
|
+
found_upper = distance_function((inputs - grad).clamp_(min=0, max=1)) > target_distance
|
|
44
|
+
while (~found_upper).any():
|
|
45
|
+
lower = torch.where(found_upper, lower, lr)
|
|
46
|
+
lr = torch.where(found_upper, lr, lr * 2)
|
|
47
|
+
found_upper = distance_function((inputs - batch_view(lr) * grad).clamp_(min=0, max=1)) > target_distance
|
|
48
|
+
|
|
49
|
+
for i in range(20):
|
|
50
|
+
new_lr = (lower + lr) / 2
|
|
51
|
+
larger = distance_function((inputs - batch_view(new_lr) * grad).clamp_(min=0, max=1)) > target_distance
|
|
52
|
+
lower, lr = torch.where(larger, lower, new_lr), torch.where(larger, new_lr, lr)
|
|
53
|
+
|
|
54
|
+
return (lr + lower) / 2
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
_distances = {
|
|
58
|
+
'ssim': ssim_loss,
|
|
59
|
+
'msssim': ms_ssim_loss,
|
|
60
|
+
'ciede2000': partial(ciede2000_loss, ε=1e-12),
|
|
61
|
+
'lpips': LPIPS,
|
|
62
|
+
'l2': l2_distances,
|
|
63
|
+
'l1': l1_distances,
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def alma(model: nn.Module,
|
|
68
|
+
inputs: Tensor,
|
|
69
|
+
labels: Tensor,
|
|
70
|
+
penalty: Callable = all_penalties['P2'],
|
|
71
|
+
targeted: bool = False,
|
|
72
|
+
num_steps: int = 1000,
|
|
73
|
+
lr_init: float = 0.1,
|
|
74
|
+
lr_reduction: float = 0.01,
|
|
75
|
+
distance: str = 'l2',
|
|
76
|
+
init_lr_distance: Optional[float] = None,
|
|
77
|
+
μ_init: float = 1,
|
|
78
|
+
ρ_init: float = 1,
|
|
79
|
+
check_steps: int = 10,
|
|
80
|
+
τ: float = 0.95,
|
|
81
|
+
γ: float = 1.2,
|
|
82
|
+
α: float = 0.9,
|
|
83
|
+
α_rms: Optional[float] = None,
|
|
84
|
+
momentum: Optional[float] = None,
|
|
85
|
+
logit_tolerance: float = 1e-4,
|
|
86
|
+
levels: Optional[int] = None,
|
|
87
|
+
callback: Optional[VisdomLogger] = None) -> Tensor:
|
|
88
|
+
"""
|
|
89
|
+
Augmented Lagrangian Method for Adversarial (ALMA) attack from https://arxiv.org/abs/2011.11857.
|
|
90
|
+
|
|
91
|
+
Parameters
|
|
92
|
+
----------
|
|
93
|
+
model : nn.Module
|
|
94
|
+
Model to attack.
|
|
95
|
+
inputs : Tensor
|
|
96
|
+
Inputs to attack. Should be in [0, 1].
|
|
97
|
+
labels : Tensor
|
|
98
|
+
Labels corresponding to the inputs if untargeted, else target labels.
|
|
99
|
+
penalty : Callable
|
|
100
|
+
Penalty-Lagrangian function to use. A good default choice is P2 (see the original article).
|
|
101
|
+
targeted : bool
|
|
102
|
+
Whether to perform a targeted attack or not.
|
|
103
|
+
num_steps : int
|
|
104
|
+
Number of optimization steps. Corresponds to the number of forward and backward propagations.
|
|
105
|
+
lr_init : float
|
|
106
|
+
Initial learning rate.
|
|
107
|
+
lr_reduction : float
|
|
108
|
+
Reduction factor for the learning rate. The final learning rate is lr_init * lr_reduction
|
|
109
|
+
distance : str
|
|
110
|
+
Distance to use.
|
|
111
|
+
init_lr_distance : float
|
|
112
|
+
If a float is given, the initial learning rate will be calculated such that the first step results in an
|
|
113
|
+
increase of init_lr_distance of the distance to minimize. This corresponds to ε in the original article.
|
|
114
|
+
μ_init : float
|
|
115
|
+
Initial value of the penalty multiplier.
|
|
116
|
+
ρ_init : float
|
|
117
|
+
Initial value of the penalty parameter.
|
|
118
|
+
check_steps : int
|
|
119
|
+
Number of steps between checks for the improvement of the constraint. This corresponds to M in the original
|
|
120
|
+
article.
|
|
121
|
+
τ : float
|
|
122
|
+
Constraint improvement rate.
|
|
123
|
+
γ : float
|
|
124
|
+
Penalty parameter increase rate.
|
|
125
|
+
α : float
|
|
126
|
+
Weight for the exponential moving average.
|
|
127
|
+
α_rms : float
|
|
128
|
+
Smoothing constant for RMSProp. If none is provided, defaults to α.
|
|
129
|
+
momentum : float
|
|
130
|
+
Momentum for the RMSProp. If none is provided, defaults to α.
|
|
131
|
+
logit_tolerance : float
|
|
132
|
+
Small quantity added to the difference of logits to avoid solutions where the difference of logits is 0, which
|
|
133
|
+
can results in inconsistent class prediction (using argmax) on GPU. This can also be used as a confidence
|
|
134
|
+
parameter κ as in https://arxiv.org/abs/1608.04644, however, a confidence parameter on logits is not robust to
|
|
135
|
+
scaling of the logits.
|
|
136
|
+
levels : int
|
|
137
|
+
Number of levels for quantization. The attack will perform quantization only if the number of levels is
|
|
138
|
+
provided.
|
|
139
|
+
callback : VisdomLogger
|
|
140
|
+
Callback to visualize the progress of the algorithm.
|
|
141
|
+
|
|
142
|
+
Returns
|
|
143
|
+
-------
|
|
144
|
+
best_adv : Tensor
|
|
145
|
+
Perturbed inputs (inputs + perturbation) that are adversarial and have smallest distance with the original
|
|
146
|
+
inputs.
|
|
147
|
+
|
|
148
|
+
"""
|
|
149
|
+
device = inputs.device
|
|
150
|
+
batch_size = len(inputs)
|
|
151
|
+
batch_view = lambda tensor: tensor.view(batch_size, *[1] * (inputs.ndim - 1))
|
|
152
|
+
multiplier = -1 if targeted else 1
|
|
153
|
+
|
|
154
|
+
# Setup variables
|
|
155
|
+
δ = torch.zeros_like(inputs, requires_grad=True)
|
|
156
|
+
square_avg = torch.ones_like(inputs)
|
|
157
|
+
momentum_buffer = torch.zeros_like(inputs)
|
|
158
|
+
lr = torch.full((batch_size,), lr_init, device=device, dtype=torch.float)
|
|
159
|
+
α_rms, momentum = α if α_rms is None else α_rms, α if momentum is None else momentum
|
|
160
|
+
|
|
161
|
+
# Init rho and mu
|
|
162
|
+
μ = torch.full((batch_size,), μ_init, device=device, dtype=torch.float)
|
|
163
|
+
ρ = torch.full((batch_size,), ρ_init, device=device, dtype=torch.float)
|
|
164
|
+
|
|
165
|
+
# Init similarity metric
|
|
166
|
+
if distance in ['lpips']:
|
|
167
|
+
dist_func = _distances[distance](target=inputs)
|
|
168
|
+
else:
|
|
169
|
+
dist_func = partial(_distances[distance], inputs)
|
|
170
|
+
|
|
171
|
+
# Init trackers
|
|
172
|
+
best_dist = torch.full((batch_size,), float('inf'), device=device)
|
|
173
|
+
best_adv = inputs.clone()
|
|
174
|
+
adv_found = torch.zeros_like(best_dist, dtype=torch.bool)
|
|
175
|
+
step_found = torch.full_like(best_dist, num_steps + 1)
|
|
176
|
+
|
|
177
|
+
for i in range(num_steps):
|
|
178
|
+
|
|
179
|
+
adv_inputs = inputs + δ
|
|
180
|
+
logits = model(adv_inputs)
|
|
181
|
+
dist = dist_func(adv_inputs)
|
|
182
|
+
|
|
183
|
+
if i == 0:
|
|
184
|
+
labels_infhot = torch.zeros_like(logits).scatter_(1, labels.unsqueeze(1), float('inf'))
|
|
185
|
+
dlr_func = partial(difference_of_logits_ratio, labels=labels, labels_infhot=labels_infhot,
|
|
186
|
+
targeted=targeted, ε=logit_tolerance)
|
|
187
|
+
|
|
188
|
+
dlr = multiplier * dlr_func(logits)
|
|
189
|
+
|
|
190
|
+
if i == 0:
|
|
191
|
+
prev_dlr = dlr.detach()
|
|
192
|
+
elif (i + 1) % check_steps == 0:
|
|
193
|
+
improved_dlr = (dlr.detach() < τ * prev_dlr)
|
|
194
|
+
ρ = torch.where(~(adv_found | improved_dlr), γ * ρ, ρ)
|
|
195
|
+
prev_dlr = dlr.detach()
|
|
196
|
+
|
|
197
|
+
if i:
|
|
198
|
+
new_μ = grad(penalty(dlr, ρ, μ).sum(), dlr, only_inputs=True)[0]
|
|
199
|
+
μ.lerp_(new_μ, weight=1 - α).clamp_(min=1e-6, max=1e12)
|
|
200
|
+
|
|
201
|
+
is_adv = dlr < 0
|
|
202
|
+
is_smaller = dist < best_dist
|
|
203
|
+
is_both = is_adv & is_smaller
|
|
204
|
+
step_found.masked_fill_((~adv_found) & is_adv, i)
|
|
205
|
+
adv_found.logical_or_(is_adv)
|
|
206
|
+
best_dist = torch.where(is_both, dist.detach(), best_dist)
|
|
207
|
+
best_adv = torch.where(batch_view(is_both), adv_inputs.detach(), best_adv)
|
|
208
|
+
|
|
209
|
+
if i == 0:
|
|
210
|
+
loss = penalty(dlr, ρ, μ)
|
|
211
|
+
else:
|
|
212
|
+
loss = dist + penalty(dlr, ρ, μ)
|
|
213
|
+
δ_grad = grad(loss.sum(), δ, only_inputs=True)[0]
|
|
214
|
+
|
|
215
|
+
grad_norm = δ_grad.flatten(1).norm(p=2, dim=1)
|
|
216
|
+
if init_lr_distance is not None and i == 0:
|
|
217
|
+
randn_grad = torch.randn_like(δ_grad).renorm(dim=0, p=2, maxnorm=1)
|
|
218
|
+
δ_grad = torch.where(batch_view(grad_norm <= 1e-6), randn_grad, δ_grad)
|
|
219
|
+
lr = init_lr_finder(inputs, δ_grad, dist_func, target_distance=init_lr_distance)
|
|
220
|
+
|
|
221
|
+
exp_decay = lr_reduction ** ((i - step_found).clamp_(min=0) / (num_steps - step_found))
|
|
222
|
+
step_lr = lr * exp_decay
|
|
223
|
+
square_avg.mul_(α_rms).addcmul_(δ_grad, δ_grad, value=1 - α_rms)
|
|
224
|
+
momentum_buffer.mul_(momentum).addcdiv_(δ_grad, square_avg.sqrt().add_(1e-8))
|
|
225
|
+
δ.data.addcmul_(momentum_buffer, batch_view(step_lr), value=-1)
|
|
226
|
+
|
|
227
|
+
δ.data.add_(inputs).clamp_(min=0, max=1)
|
|
228
|
+
if levels is not None:
|
|
229
|
+
δ.data.mul_(levels - 1).round_().div_(levels - 1)
|
|
230
|
+
δ.data.sub_(inputs)
|
|
231
|
+
|
|
232
|
+
if callback:
|
|
233
|
+
cb_best_dist = best_dist.masked_select(adv_found).mean()
|
|
234
|
+
callback.accumulate_line([distance, 'dlr'], i, [dist.mean(), dlr.mean()])
|
|
235
|
+
callback.accumulate_line(['μ_c', 'ρ_c'], i, [μ.mean(), ρ.mean()])
|
|
236
|
+
callback.accumulate_line('grad_norm', i, grad_norm.mean())
|
|
237
|
+
callback.accumulate_line(['best_{}'.format(distance), 'success', 'lr'], i,
|
|
238
|
+
[cb_best_dist, adv_found.float().mean(), step_lr.mean()])
|
|
239
|
+
|
|
240
|
+
if (i + 1) % (num_steps // 20) == 0 or (i + 1) == num_steps:
|
|
241
|
+
callback.update_lines()
|
|
242
|
+
|
|
243
|
+
return best_adv
|