Skip to content

Commit

Permalink
Merge pull request #2448 from Trusted-AI/dev_1.18.0
Browse files Browse the repository at this point in the history
Update to ART 1.18.0
  • Loading branch information
beat-buesser committed Jun 16, 2024
2 parents 02f8290 + 263715d commit 5e830d6
Show file tree
Hide file tree
Showing 37 changed files with 2,723 additions and 2,106 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/ci-huggingface.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ jobs:
include:
- name: Huggingface 4.30
framework: huggingface
python: 3.9
torch: 1.13.1+cpu
torchvision: 0.14.1+cpu
torchaudio: 0.13.1
python: '3.10'
torch: 2.2.1
torchvision: 0.17.1+cpu
torchaudio: 2.2.1
transformers: 4.30.2

name: ${{ matrix.name }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-lingvo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ jobs:
sudo apt-get update
sudo apt-get -y -q install ffmpeg libavcodec-extra
python -m pip install --upgrade pip setuptools wheel
pip install -q -r <(sed '/^scipy/d;/^matplotlib/d;/^pandas/d;/^statsmodels/d;/^numba/d;/^jax/d;/^h5py/d;/^Pillow/d;/^pytest/d;/^pytest-mock/d;/^torch/d;/^torchaudio/d;/^torchvision/d;/^xgboost/d;/^requests/d;/^tensorflow/d;/^keras/d;/^kornia/d;/^librosa/d;/^tqdm/d;/^timm/d;/^catboost/d;/^scikit-learn/d;/^GPy/d;/^lief/d' requirements_test.txt)
pip install -q -r <(sed '/^scipy/d;/^matplotlib/d;/^pandas/d;/^statsmodels/d;/^numba/d;/^jax/d;/^h5py/d;/^Pillow/d;/^pytest/d;/^pytest-mock/d;/^torch/d;/^torchaudio/d;/^torchvision/d;/^xgboost/d;/^requests/d;/^tensorflow/d;/^keras/d;/^kornia/d;/^librosa/d;/^tqdm/d;/^timm/d;/^catboost/d;/^scikit-learn/d;/^GPy/d;/^lief/d;/^ultralytics/d;/^ipython/d' requirements_test.txt)
pip install scipy==1.5.4
pip install matplotlib==3.3.4
pip install pandas==1.1.5
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-mxnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
sudo apt-get update
sudo apt-get -y -q install ffmpeg libavcodec-extra
python -m pip install --upgrade pip setuptools wheel
pip3 install -q -r requirements_test.txt
pip install -q -r <(sed '/^ultralytics/d;/^ipython/d' requirements_test.txt)
pip list
- name: Run ${{ matrix.name }} ${{ matrix.module }} Tests
run: ./run_tests.sh ${{ matrix.framework }} ${{ matrix.module }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-tensorflow-v1.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
sudo apt-get update
sudo apt-get -y -q install ffmpeg libavcodec-extra
python -m pip install --upgrade pip setuptools wheel
pip install -q -r <(sed '/^pandas/d;/^scipy/d;/^matplotlib/d;/^xgboost/d;/^tensorflow/d;/^keras/d;/^jax/d;/^torch/d;/^Pillow/d;/^h5py/d;/^kornia/d;/^scikit-learn/d;/^pytest-mock/d;/^GPy/d;/^lief/d;/^statsmodels/d' requirements_test.txt)
pip install -q -r <(sed '/^pandas/d;/^scipy/d;/^matplotlib/d;/^xgboost/d;/^tensorflow/d;/^keras/d;/^jax/d;/^torch/d;/^Pillow/d;/^h5py/d;/^kornia/d;/^scikit-learn/d;/^pytest-mock/d;/^GPy/d;/^lief/d;/^statsmodels/d;/^ultralytics/d;/^ipython/d' requirements_test.txt)
pip install pandas==1.3.5
pip install scipy==1.7.2
pip install matplotlib==3.5.3
Expand Down
1 change: 1 addition & 0 deletions art/attacks/evasion/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
from art.attacks.evasion.lowprofool import LowProFool
from art.attacks.evasion.momentum_iterative_method import MomentumIterativeMethod
from art.attacks.evasion.newtonfool import NewtonFool
from art.attacks.evasion.overload.overload import OverloadPyTorch
from art.attacks.evasion.pe_malware_attack import MalwareGDTensorFlow
from art.attacks.evasion.pixel_threshold import PixelAttack
from art.attacks.evasion.projected_gradient_descent.projected_gradient_descent import ProjectedGradientDescent
Expand Down
71 changes: 39 additions & 32 deletions art/attacks/evasion/fast_gradient.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def __init__(
Create a :class:`.FastGradientMethod` instance.
:param estimator: A trained classifier.
:param norm: The norm of the adversarial perturbation. Possible values: "inf", np.inf, 1 or 2.
:param norm: The norm of the adversarial perturbation. Possible values: "inf", `np.inf` or a real `p >= 1`.
:param eps: Attack step size (input variation).
:param eps_step: Step size of input variation for minimal perturbation computation.
:param targeted: Indicates whether the attack is targeted (True) or untargeted (False)
Expand Down Expand Up @@ -288,16 +288,18 @@ def generate(self, x: np.ndarray, y: Optional[np.ndarray] = None, **kwargs) -> n

logger.info(
"Success rate of FGM attack: %.2f%%",
rate_best
if rate_best is not None
else 100
* compute_success(
self.estimator, # type: ignore
x,
y_array,
adv_x_best,
self.targeted,
batch_size=self.batch_size,
(
rate_best
if rate_best is not None
else 100
* compute_success(
self.estimator, # type: ignore
x,
y_array,
adv_x_best,
self.targeted,
batch_size=self.batch_size,
)
),
)

Expand Down Expand Up @@ -334,8 +336,9 @@ def generate(self, x: np.ndarray, y: Optional[np.ndarray] = None, **kwargs) -> n

def _check_params(self) -> None:

if self.norm not in [1, 2, np.inf, "inf"]:
raise ValueError('Norm order must be either 1, 2, `np.inf` or "inf".')
norm: float = np.inf if self.norm == "inf" else float(self.norm)
if norm < 1:
raise ValueError('Norm order must be either "inf", `np.inf` or a real `p >= 1`.')

if not (
isinstance(self.eps, (int, float))
Expand Down Expand Up @@ -391,9 +394,6 @@ def _compute_perturbation(
decay: Optional[float] = None,
momentum: Optional[np.ndarray] = None,
) -> np.ndarray:
# Pick a small scalar to avoid division by 0
tol = 10e-8

# Get gradient wrt loss; invert it if attack is targeted
grad = self.estimator.loss_gradient(x, y) * (1 - 2 * int(self.targeted))

Expand Down Expand Up @@ -426,32 +426,39 @@ def _compute_perturbation(

# Apply norm bound
def _apply_norm(norm, grad, object_type=False):
"""Returns an x maximizing <grad, x> subject to ||x||_norm<=1."""
if (grad.dtype != object and np.isinf(grad).any()) or np.isnan( # pragma: no cover
grad.astype(np.float32)
).any():
logger.info("The loss gradient array contains at least one positive or negative infinity.")

grad_2d = grad.reshape(1 if object_type else len(grad), -1)
if norm in [np.inf, "inf"]:
grad = np.sign(grad)
grad_2d = np.ones_like(grad_2d)
elif norm == 1:
if not object_type:
ind = tuple(range(1, len(x.shape)))
else:
ind = None
grad = grad / (np.sum(np.abs(grad), axis=ind, keepdims=True) + tol)
elif norm == 2:
if not object_type:
ind = tuple(range(1, len(x.shape)))
else:
ind = None
grad = grad / (np.sqrt(np.sum(np.square(grad), axis=ind, keepdims=True)) + tol)
i_max = np.argmax(np.abs(grad_2d), axis=1)
grad_2d = np.zeros_like(grad_2d)
grad_2d[range(len(grad_2d)), i_max] = 1
elif norm > 1:
conjugate = norm / (norm - 1)
q_norm = np.linalg.norm(grad_2d, ord=conjugate, axis=1, keepdims=True)
grad_2d = (np.abs(grad_2d) / np.where(q_norm, q_norm, np.inf)) ** (conjugate - 1)
grad = grad_2d.reshape(grad.shape) * np.sign(grad)
return grad

# Add momentum
# Compute gradient momentum
if decay is not None and momentum is not None:
grad = _apply_norm(norm=1, grad=grad)
grad = decay * momentum + grad
momentum += grad
if x.dtype == object:
raise NotImplementedError("Momentum Iterative Method not yet implemented for object type input.")
# Update momentum in-place (important).
# The L1 normalization for accumulation is an arbitrary choice of the paper.
grad_2d = grad.reshape(len(grad), -1)
norm1 = np.linalg.norm(grad_2d, ord=1, axis=1, keepdims=True)
normalized_grad = (grad_2d / np.where(norm1, norm1, np.inf)).reshape(grad.shape)
momentum *= decay
momentum += normalized_grad
# Use the momentum to compute the perturbation, instead of the gradient
grad = momentum

if x.dtype == object:
for i_sample in range(x.shape[0]):
Expand Down
Empty file.
Loading

0 comments on commit 5e830d6

Please sign in to comment.