Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check & update GH actions #715

Merged
merged 13 commits into from
Oct 27, 2023
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
Loading