Skip to content

Commit

Permalink
Fix style checks
Browse files Browse the repository at this point in the history
Signed-off-by: Beat Buesser <beat.buesser@ibm.com>
  • Loading branch information
beat-buesser committed Jun 15, 2024
1 parent 7e589ee commit 8bbb29e
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 86 deletions.
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-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
10 changes: 8 additions & 2 deletions art/attacks/evasion/overload/box_iou.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# pylint: disable=C0103,C0114
# GNU AFFERO GENERAL PUBLIC LICENSE
# Version 3, 19 November 2007
#
Expand Down Expand Up @@ -660,8 +661,14 @@
# For more information on this, and how to apply and follow the GNU AGPL, see
# <https://www.gnu.org/licenses/>.

from typing import TYPE_CHECKING

def box_iou(box1: "torch.tensor", box2: "torch.tensor", eps: float = 1e-7) -> "torch.tensor":
if TYPE_CHECKING:
# pylint: disable=C0412
import torch


def box_iou(box1: "torch.Tensor", box2: "torch.Tensor", eps: float = 1e-7) -> "torch.Tensor":
"""
=== NOTE ===
This function is copied from YOLOv5 repository (yolov5/utils/metrics.py)
Expand All @@ -684,4 +691,3 @@ def box_iou(box1: "torch.tensor", box2: "torch.tensor", eps: float = 1e-7) -> "t

# IoU = inter / (area1 + area2 - inter)
return inter / ((a2 - a1).prod(2) + (b2 - b1).prod(2) - inter + eps)

54 changes: 27 additions & 27 deletions art/attacks/evasion/overload/overload.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,11 @@ def generate(self, x: np.ndarray, y: Optional[np.ndarray] = None, **kwargs) -> n

return x_adv

def _generate_batch(self, x_batch: np.ndarray, y_batch: Optional[np.ndarray] = None) -> np.ndarray:
def _generate_batch(self, x_batch: np.ndarray) -> np.ndarray:
"""
Run the attack on a batch of images.
:param x_batch: A batch of original examples.
:param y_batch: Not Used.
:return: A batch of adversarial examples.
"""

Expand Down Expand Up @@ -144,7 +143,7 @@ def _attack(self, x_adv: "torch.Tensor", x: "torch.Tensor") -> "torch.Tensor":
x_adv.requires_grad_(False)
return x_adv

def _loss(self, x: "torch.tensor") -> Tuple["torch.tensor", "torch.tensor"]:
def _loss(self, x: "torch.Tensor") -> Tuple["torch.Tensor", "torch.Tensor"]:
"""
Compute the weight of each pixel and the overload loss for a given image.
Expand All @@ -155,13 +154,13 @@ def _loss(self, x: "torch.tensor") -> Tuple["torch.tensor", "torch.tensor"]:
import torch

adv_logits = self.estimator.model.model(x)
if type(adv_logits) is tuple:
if isinstance(adv_logits, tuple):
adv_logits = adv_logits[0]

Check warning on line 158 in art/attacks/evasion/overload/overload.py

View check run for this annotation

Codecov / codecov/patch

art/attacks/evasion/overload/overload.py#L158

Added line #L158 was not covered by tests

THRESHOLD = self.estimator.model.conf
threshold = self.estimator.model.conf
conf = adv_logits[..., 4]
prob = adv_logits[..., 5:]
prob = torch.where(conf[:, :, None] * prob > THRESHOLD, torch.ones_like(prob), prob)
prob = torch.where(conf[:, :, None] * prob > threshold, torch.ones_like(prob), prob)
prob = torch.sum(prob, dim=2)
conf = conf * prob

Expand All @@ -174,19 +173,19 @@ def _loss(self, x: "torch.tensor") -> Tuple["torch.tensor", "torch.tensor"]:
stride_x = x.shape[-2] // self.num_grid
stride_y = x.shape[-1] // self.num_grid
grid_box = torch.zeros((0, 4), device=x.device)
for ii in range(self.num_grid):
for jj in range(self.num_grid):
x1 = ii * stride_x
y1 = jj * stride_y
x2 = min(x1 + stride_x, x.shape[-2])
y2 = min(y1 + stride_y, x.shape[-1])
bb = torch.as_tensor([x1, y1, x2, y2], device=x.device)[None, :]
grid_box = torch.cat([grid_box, bb], dim=0)

for xi in range(x.shape[0]):
xyhw = adv_logits[xi, :, :4]
prob = torch.max(adv_logits[xi, :, 5:], dim=1).values
box_idx = adv_logits[xi, :, 4] * prob > THRESHOLD
for i_i in range(self.num_grid):
for j_j in range(self.num_grid):
x_1 = i_i * stride_x
y_1 = j_j * stride_y
x_2 = min(x_1 + stride_x, x.shape[-2])
y_2 = min(y_1 + stride_y, x.shape[-1])
b_b = torch.as_tensor([x_1, y_1, x_2, y_2], device=x.device)[None, :]
grid_box = torch.cat([grid_box, b_b], dim=0)

for x_i in range(x.shape[0]):
xyhw = adv_logits[x_i, :, :4]
prob = torch.max(adv_logits[x_i, :, 5:], dim=1).values
box_idx = adv_logits[x_i, :, 4] * prob > threshold
xyhw = xyhw[box_idx]
c_xyxy = self.xywh2xyxy(xyhw)
scores = box_iou(grid_box, c_xyxy)
Expand All @@ -197,20 +196,21 @@ def _loss(self, x: "torch.tensor") -> Tuple["torch.tensor", "torch.tensor"]:
# Increase the weight of the grid with fewer objects
idx_min = torch.argmin(scores)
grid_min = grid_box[idx_min]
x1, y1, x2, y2 = grid_min.int()
pixel_weight[xi, :, y1:y2, x1:x2] = pixel_weight[xi, :, y1:y2, x1:x2] * 2
pixel_weight = pixel_weight / torch.max(pixel_weight[xi, :]) / 255.0
x_1, y_1, x_2, y_2 = grid_min.int()
pixel_weight[x_i, :, y_1:y_2, x_1:x_2] = pixel_weight[x_i, :, y_1:y_2, x_1:x_2] * 2
pixel_weight = pixel_weight / torch.max(pixel_weight[x_i, :]) / 255.0

return ind_loss, pixel_weight

def xywh2xyxy(self, xywh: "torch.tensor") -> "torch.tensor":
@staticmethod
def xywh2xyxy(xywh: "torch.Tensor") -> "torch.Tensor":
"""
Convert the representation from xywh format yo xyxy format.
: param xyhw: A n by 4 boxes store the information in xyhw format
where [x ,y, w h] is [center_x, center_y, width, height]
: return: The n by 4 boxex in xyxy format
where [x1, y1, x2, y2] is [top_left_x, top_left_y, bottom_right_x, bottom_right_y]
:param xyhw: A n by 4 boxes store the information in xyhw format
where [x ,y, w h] is [center_x, center_y, width, height]
:return: The n by 4 boxes in xyxy format
where [x1, y1, x2, y2] is [top_left_x, top_left_y, bottom_right_x, bottom_right_y]
"""
xyxy = xywh.clone()
xyxy[:, 0] = xywh[:, 0] - xywh[:, 2] / 2
Expand Down
2 changes: 2 additions & 0 deletions requirements_test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ pytest-mock~=3.14.0
pytest-cov~=4.1.0
requests~=2.31.0
ultralytics==8.0.217
ipython==8.25.0

# ART
-e .

Expand Down
73 changes: 18 additions & 55 deletions tests/attacks/evasion/test_overload_attack.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,25 @@

logger = logging.getLogger(__name__)


@pytest.mark.only_with_platform("pytorch")
def test_generate(art_warning):
try:
import torch
model = torch.hub.load('ultralytics/yolov5:v7.0', model='yolov5s')
py_model = PyTorchYolo(model=model,
input_shape=(3, 640, 640),
channels_first=True)

model = torch.hub.load("ultralytics/yolov5:v7.0", model="yolov5s")
py_model = PyTorchYolo(model=model, input_shape=(3, 640, 640), channels_first=True)
# Download a sample image
import requests
from io import BytesIO
from PIL import Image

TARGET = 'https://ultralytics.com/images/zidane.jpg'
response = requests.get(TARGET)
target = "https://ultralytics.com/images/zidane.jpg"
response = requests.get(target)
org_img = np.asarray(Image.open(BytesIO(response.content)).resize((640, 640)))
x = np.stack([org_img.transpose((2, 0, 1))], axis=0).astype(np.float32)

attack = OverloadPyTorch(py_model,
eps = 16.0 / 255.0,
max_iter = 10,
num_grid = 10,
batch_size = 1)
attack = OverloadPyTorch(py_model, eps=16.0 / 255.0, max_iter=10, num_grid=10, batch_size=1)

x_adv = attack.generate(x / 255.0)
assert x.shape == x_adv.shape
Expand All @@ -67,59 +63,26 @@ def test_generate(art_warning):
def test_check_params(art_warning):
try:
import torch
model = torch.hub.load('ultralytics/yolov5:v7.0', model='yolov5s')
py_model = PyTorchYolo(model=model,
input_shape=(3, 640, 640),
channels_first=True)

model = torch.hub.load("ultralytics/yolov5:v7.0", model="yolov5s")
py_model = PyTorchYolo(model=model, input_shape=(3, 640, 640), channels_first=True)

with pytest.raises(ValueError):
_ = OverloadPyTorch(estimator=py_model,
eps=-1.0,
max_iter=5,
num_grid=10,
batch_size=1)
_ = OverloadPyTorch(estimator=py_model, eps=-1.0, max_iter=5, num_grid=10, batch_size=1)
with pytest.raises(ValueError):
_ = OverloadPyTorch(estimator=py_model,
eps=2.0,
max_iter=5,
num_grid=10,
batch_size=1)
_ = OverloadPyTorch(estimator=py_model, eps=2.0, max_iter=5, num_grid=10, batch_size=1)
with pytest.raises(TypeError):
_ = OverloadPyTorch(estimator=py_model,
eps=8 / 255.0,
max_iter=1.0,
num_grid=10,
batch_size=1)
_ = OverloadPyTorch(estimator=py_model, eps=8 / 255.0, max_iter=1.0, num_grid=10, batch_size=1)
with pytest.raises(ValueError):
_ = OverloadPyTorch(estimator=py_model,
eps=8 / 255.0,
max_iter=0,
num_grid=10,
batch_size=1)
_ = OverloadPyTorch(estimator=py_model, eps=8 / 255.0, max_iter=0, num_grid=10, batch_size=1)
with pytest.raises(TypeError):
_ = OverloadPyTorch(estimator=py_model,
eps=8 / 255.0,
max_iter=5,
num_grid=1.0,
batch_size=1)
_ = OverloadPyTorch(estimator=py_model, eps=8 / 255.0, max_iter=5, num_grid=1.0, batch_size=1)
with pytest.raises(ValueError):
_ = OverloadPyTorch(estimator=py_model,
eps=8 / 255.0,
max_iter=5,
num_grid=0,
batch_size=1)
_ = OverloadPyTorch(estimator=py_model, eps=8 / 255.0, max_iter=5, num_grid=0, batch_size=1)
with pytest.raises(TypeError):
_ = OverloadPyTorch(estimator=py_model,
eps=8 / 255.0,
max_iter=5,
num_grid=10,
batch_size=1.0)
_ = OverloadPyTorch(estimator=py_model, eps=8 / 255.0, max_iter=5, num_grid=10, batch_size=1.0)
with pytest.raises(ValueError):
_ = OverloadPyTorch(estimator=py_model,
eps=8 / 255.0,
max_iter=5,
num_grid=0,
batch_size=0)
_ = OverloadPyTorch(estimator=py_model, eps=8 / 255.0, max_iter=5, num_grid=0, batch_size=0)

except ARTTestException as e:
art_warning(e)

0 comments on commit 8bbb29e

Please sign in to comment.