Skip to content

Commit

Permalink
Update GH actions and dependencies (bethgelab#715)
Browse files Browse the repository at this point in the history
* Update requirements

* Update requirements for tests

* Update type annotations to latest mypy version

* Reformat with black

* Bump python version
  • Loading branch information
zimmerrol authored and lcy committed Oct 27, 2023
1 parent 7ae1ace commit 196b993
Show file tree
Hide file tree
Showing 21 changed files with 81 additions and 69 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- name: Set up Python 3.8
uses: actions/setup-python@v1
with:
python-version: 3.8
python-version: 3.9
- name: Install package
run: |
pip install -e .
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: '3.8'
python-version: '3.9'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
strategy:
max-parallel: 20
matrix:
python-version: ['3.8', '3.9']
python-version: ['3.9', '3.10']
backend: ["none", "pytorch", "tensorflow", "jax", "numpy"]

steps:
Expand Down
14 changes: 10 additions & 4 deletions foolbox/attacks/additive_noise.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from ..devutils import flatten
from ..devutils import atleast_kd

from ..distances import l2, linf
from ..distances import l2, linf, Distance

from .base import FixedEpsilonAttack
from .base import Criterion
Expand Down Expand Up @@ -56,7 +56,9 @@ def get_epsilons(


class L2Mixin:
distance = l2
@property
def distance(self) -> Distance:
return l2

def get_epsilons(
self, x: ep.Tensor, p: ep.Tensor, epsilon: float, min_: float, max_: float
Expand All @@ -66,7 +68,9 @@ def get_epsilons(


class L2ClippingAwareMixin:
distance = l2
@property
def distance(self) -> Distance:
return l2

def get_epsilons(
self, x: ep.Tensor, p: ep.Tensor, epsilon: float, min_: float, max_: float
Expand All @@ -77,7 +81,9 @@ def get_epsilons(


class LinfMixin:
distance = linf
@property
def distance(self) -> Distance:
return linf

def get_epsilons(
self, x: ep.Tensor, p: ep.Tensor, epsilon: float, min_: float, max_: float
Expand Down
4 changes: 2 additions & 2 deletions foolbox/attacks/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ def __call__(
...

@final # noqa: F811
def __call__( # type: ignore
def __call__(
self,
model: Model,
inputs: T,
Expand Down Expand Up @@ -381,7 +381,7 @@ def __call__(
...

@final # noqa: F811
def __call__( # type: ignore
def __call__(
self,
model: Model,
inputs: T,
Expand Down
2 changes: 1 addition & 1 deletion foolbox/attacks/boundary_attack.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ def clear(self, dims: ep.Tensor) -> None:
self.tensor = dims # pragma: no cover
dims = dims.numpy()
assert dims.shape == (self.N,)
assert dims.dtype == np.bool
assert dims.dtype == np.bool_
self.data[:, dims] = np.nan

def mean(self) -> ep.Tensor:
Expand Down
6 changes: 4 additions & 2 deletions foolbox/attacks/brendel_bethge.py
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ def logits_diff_and_grads(x) -> Tuple[Any, Any]:
x = starting_points
lrs = self.lr * np.ones(N)
lr_reduction_interval = max(1, int(self.steps / self.lr_num_decay))
converged = np.zeros(N, dtype=np.bool)
converged = np.zeros(N, dtype=np.bool_)
rate_normalization = np.prod(x.shape) * (max_ - min_)
original_shape = x.shape
_best_advs = best_advs.numpy()
Expand Down Expand Up @@ -569,7 +569,9 @@ def logits_diff_and_grads(x) -> Tuple[Any, Any]:
# add step to current perturbation
x = (x + ep.astensor(deltas)).reshape(original_shape)

tb.probability("converged", converged, step)
tb.probability(
"converged", ep.from_numpy(x, converged.astype(np.bool_)), step
)
tb.histogram("norms", source_norms, step)
tb.histogram("candidates/distances", distances, step)

Expand Down
2 changes: 1 addition & 1 deletion foolbox/attacks/carlini_wagner.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ def loss_fun(
# after each tenth of the overall steps, check progress
if not (loss <= 0.9999 * loss_at_previous_check):
break # stop Adam if there has been no progress
loss_at_previous_check = loss
loss_at_previous_check = loss.item()

found_advs_iter = is_adversarial(perturbed, logits)
found_advs = np.logical_or(found_advs, found_advs_iter.numpy())
Expand Down
6 changes: 3 additions & 3 deletions foolbox/attacks/dataset_attack.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,10 @@ def run(
if found.all():
break

indices = np.array([pool[i] for pool in index_pools])
indices_np = np.array([pool[i] for pool in index_pools])

xp = self.inputs[indices]
yp = self.outputs[indices]
xp = self.inputs[indices_np]
yp = self.outputs[indices_np]
is_adv = criterion(xp, yp)

new_found = ep.logical_and(is_adv, found.logical_not())
Expand Down
4 changes: 2 additions & 2 deletions foolbox/attacks/gen_attack.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ def apply_noise(
def choice(
self, a: int, size: Union[int, ep.TensorType], replace: bool, p: ep.TensorType
) -> Any:
p = p.numpy()
x = np.random.choice(a, size, replace, p)
p_np: np.ndarray = p.numpy()
x = np.random.choice(a, size, replace, p_np) # type: ignore
return x

def run(
Expand Down
14 changes: 7 additions & 7 deletions foolbox/attacks/gen_attack_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ def rclip(rows: np.ndarray) -> np.ndarray:
wc = np.expand_dims((cols - col_lo) * (row_hi - rows), -1)
wd = np.expand_dims((cols - col_lo) * (rows - row_lo), -1)

return wa * Ia + wb * Ib + wc * Ic + wd * Id # type: ignore
return wa * Ia + wb * Ib + wc * Ic + wd * Id

nrows, ncols = img.shape[-3:-1]
deltas = (0.5 / resize_rates[0], 0.5 / resize_rates[1])

rows = np.linspace(deltas[0], nrows - deltas[0], np.int32(resize_rates[0] * nrows))
cols = np.linspace(deltas[1], ncols - deltas[1], np.int32(resize_rates[1] * ncols))
rows = np.linspace(deltas[0], nrows - deltas[0], int(resize_rates[0] * nrows))
cols = np.linspace(deltas[1], ncols - deltas[1], int(resize_rates[1] * ncols))
rows_grid, cols_grid = np.meshgrid(rows - 0.5, cols - 0.5, indexing="ij")

img_resize_vec = interpolate_bilinear(img, rows_grid.flatten(), cols_grid.flatten())
Expand All @@ -63,7 +63,7 @@ def rescale_numpy(x: ep.NumPyTensor, target_shape: List[int]) -> ep.NumPyTensor:

resize_rates = (target_shape[1] / x.shape[1], target_shape[2] / x.shape[2])

def interpolate_bilinear( # type: ignore
def interpolate_bilinear(
im: np.ndarray, rows: np.ndarray, cols: np.ndarray
) -> np.ndarray:
# based on http://stackoverflow.com/a/12729229
Expand All @@ -72,10 +72,10 @@ def interpolate_bilinear( # type: ignore
row_lo = np.floor(rows).astype(int)
row_hi = row_lo + 1

def cclip(cols: np.ndarray) -> np.ndarray: # type: ignore
def cclip(cols: np.ndarray) -> np.ndarray:
return np.clip(cols, 0, ncols - 1)

def rclip(rows: np.ndarray) -> np.ndarray: # type: ignore
def rclip(rows: np.ndarray) -> np.ndarray:
return np.clip(rows, 0, nrows - 1)

nrows, ncols = im.shape[-3:-1]
Expand All @@ -90,7 +90,7 @@ def rclip(rows: np.ndarray) -> np.ndarray: # type: ignore
wc = np.expand_dims((cols - col_lo) * (row_hi - rows), -1)
wd = np.expand_dims((cols - col_lo) * (rows - row_lo), -1)

return wa * Ia + wb * Ib + wc * Ic + wd * Id
return wa * Ia + wb * Ib + wc * Ic + wd * Id # type: ignore

nrows, ncols = img.shape[-3:-1]
deltas = (0.5 / resize_rates[0], 0.5 / resize_rates[1])
Expand Down
2 changes: 1 addition & 1 deletion foolbox/attacks/gradient_descent_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def run(
classes = criterion_.labels
elif hasattr(criterion_, "target_classes"):
gradient_step_sign = -1.0
classes = criterion_.target_classes # type: ignore
classes = criterion_.target_classes
else:
raise ValueError("unsupported criterion")

Expand Down
6 changes: 3 additions & 3 deletions foolbox/attacks/hop_skip_jump.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ def _binary_search(
perturbed: ep.Tensor,
) -> ep.Tensor:
# Choose upper thresholds in binary search based on constraint.
d = np.prod(perturbed.shape[1:])
d = int(np.prod(perturbed.shape[1:]))
if self.constraint == "linf":
highs = linf(originals, perturbed)

Expand All @@ -337,7 +337,7 @@ def _binary_search(
thresholds = highs * self.gamma / (d * d)
else:
highs = ep.ones(perturbed, len(perturbed))
thresholds = self.gamma / (d * math.sqrt(d))
thresholds = highs * self.gamma / (d * math.sqrt(d))

lows = ep.zeros_like(highs)

Expand Down Expand Up @@ -371,7 +371,7 @@ def select_delta(
if step == 0:
result = 0.1 * ep.ones_like(distances)
else:
d = np.prod(originals.shape[1:])
d = int(np.prod(originals.shape[1:]))

if self.constraint == "linf":
theta = self.gamma / (d * d)
Expand Down
18 changes: 11 additions & 7 deletions foolbox/attacks/pointwise.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,13 @@ def run(
i = 0
while i < max([len(it) for it in untouched_indices]):
# mask all samples that still have pixels to manipulate left
relevant_mask = [len(it) > i for it in untouched_indices]
relevant_mask = np.array(relevant_mask, dtype=bool)
relevant_mask_index = np.flatnonzero(relevant_mask)
relevant_mask_lst = [len(it) > i for it in untouched_indices]
relevant_mask: np.ndarray[Any, np.dtype[np.bool_]] = np.array(
relevant_mask_lst, dtype=bool
)
relevant_mask_index: np.ndarray[
Any, np.dtype[np.int_]
] = np.flatnonzero(relevant_mask)

# for each image get the index of the next pixel we try out
relevant_indices = [it[i] for it in untouched_indices if len(it) > i]
Expand Down Expand Up @@ -160,8 +164,8 @@ def run(
i = 0
while i < max([len(it) for it in untouched_indices]):
# mask all samples that still have pixels to manipulate left
relevant_mask = [len(it) > i for it in untouched_indices]
relevant_mask = np.array(relevant_mask, dtype=bool)
relevant_mask_lst = [len(it) > i for it in untouched_indices]
relevant_mask = np.array(relevant_mask_lst, dtype=bool)
relevant_mask_index = np.flatnonzero(relevant_mask)

# for each image get the index of the next pixel we try out
Expand Down Expand Up @@ -227,8 +231,8 @@ def run(
def _binary_search(
self,
x_adv_flat: ep.Tensor,
mask: Union[ep.Tensor, List[bool]],
mask_indices: ep.Tensor,
mask: Union[ep.Tensor, List[bool], np.ndarray[Any, np.dtype[np.bool_]]],
mask_indices: Union[ep.Tensor, np.ndarray[Any, np.dtype[np.int_]]],
indices: Union[ep.Tensor, List[int]],
adv_values: ep.Tensor,
non_adv_values: ep.Tensor,
Expand Down
8 changes: 4 additions & 4 deletions foolbox/attacks/spatial_attack_transformations.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ def transform_pt(

# to pt
x = x_e.raw
theta = torch.tensor(theta, device=x.device)
theta_t = torch.tensor(theta, device=x.device)

assert len(x.shape) == 4
assert theta.shape[1:] == (2, 3)
assert theta_t.shape[1:] == (2, 3)

(
bs,
Expand All @@ -64,8 +64,8 @@ def create_meshgrid(x: torch.Tensor) -> torch.Tensor:
return grid

meshgrid = create_meshgrid(x)
theta = theta[:, None, None, :, :].repeat(1, n_x, n_y, 1, 1)
new_coords = torch.matmul(theta, meshgrid)
theta_t = theta_t[:, None, None, :, :].repeat(1, n_x, n_y, 1, 1)
new_coords = torch.matmul(theta_t, meshgrid)
new_coords = new_coords.squeeze_(-1)

# align_corners=True to match tf implementation
Expand Down
16 changes: 8 additions & 8 deletions foolbox/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,19 @@ def images(
"expected data_format to be 'channels_first' or 'channels_last'"
)
assert channels_first != channels_last
x = x.numpy()
x_np = x.numpy()
if channels_first:
x = np.transpose(x, axes=(0, 2, 3, 1))
x_np = np.transpose(x_np, axes=(0, 2, 3, 1))
min_, max_ = bounds
x = (x - min_) / (max_ - min_)
x_np = (x_np - min_) / (max_ - min_)

if nrows is None and ncols is None:
nrows = 1
if ncols is None:
assert nrows is not None
ncols = (len(x) + nrows - 1) // nrows
ncols = (len(x_np) + nrows - 1) // nrows
elif nrows is None:
nrows = (len(x) + ncols - 1) // ncols
nrows = (len(x_np) + ncols - 1) // ncols
if figsize is None:
figsize = (ncols * scale, nrows * scale)
fig, axes = plt.subplots(
Expand All @@ -69,7 +69,7 @@ def images(
ax.axis("off")
i = row * ncols + col
if i < len(x):
if x.shape[-1] == 1:
ax.imshow(x[i][:, :, 0])
if x_np.shape[-1] == 1:
ax.imshow(x_np[i][:, :, 0])
else:
ax.imshow(x[i])
ax.imshow(x_np[i])
12 changes: 6 additions & 6 deletions foolbox/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ def samples(
) -> Any:
if hasattr(fmodel, "data_format"):
if data_format is None:
data_format = fmodel.data_format # type: ignore
elif data_format != fmodel.data_format: # type: ignore
data_format = fmodel.data_format
elif data_format != fmodel.data_format:
raise ValueError(
f"data_format ({data_format}) does not match model.data_format ({fmodel.data_format})" # type: ignore
f"data_format ({data_format}) does not match model.data_format ({fmodel.data_format})"
)
elif data_format is None:
raise ValueError(
Expand All @@ -50,9 +50,9 @@ def samples(
bounds=bounds,
)

if hasattr(fmodel, "dummy") and fmodel.dummy is not None: # type: ignore
images = ep.from_numpy(fmodel.dummy, images).raw # type: ignore
labels = ep.from_numpy(fmodel.dummy, labels).raw # type: ignore
if hasattr(fmodel, "dummy") and fmodel.dummy is not None:
images = ep.from_numpy(fmodel.dummy, images).raw
labels = ep.from_numpy(fmodel.dummy, labels).raw
else:
warnings.warn(f"unknown model type {type(fmodel)}, returning NumPy arrays")

Expand Down
8 changes: 4 additions & 4 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
flake8==4.0.1
flake8==6.1.0
black==22.3.0
pytest==7.1.1
pytest==7.4.3
pytest-cov==3.0.0
coverage==6.3.2
codecov==2.1.12
codecov==2.1.13
coveralls==3.3.1
mypy==0.942
mypy==1.6.1
pre-commit==2.17.0
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ max-complexity = 18
select = B,C,E,F,W,T4,B9

[mypy]
python_version = 3.8
python_version = 3.9
warn_unused_ignores = True
warn_unused_configs = True
warn_return_any = True
Expand Down
Loading

0 comments on commit 196b993

Please sign in to comment.