nula-cifar10-robust-v0 / augmentations.py
MamaPearl's picture
Update augmentations.py
290c8f1 verified
Raw
History Blame Contribute Delete
2.65 kB
import torch as pt
import torch.nn.functional as F
import numbers
def resize_down_up(x, scale=0.5, mode="bilinear"):
# shrinks image then blows it back up to see what info was lost
if isinstance(scale, pt.Tensor):
scale = scale.item()
_val_invars(x, scale=scale, mode=mode, type="resize")
B, C, H, W = x.shape
h_new, w_new = max(1, int(H * scale)), max(1, int(W * scale))
kwargs = {}
if mode in {"bilinear", "bicubic"}:
kwargs["align_corners"] = False
x_down = F.interpolate(x, size=(h_new, w_new), mode=mode, **kwargs)
return F.interpolate(x_down, size=(H,W), mode=mode, **kwargs)
def decimate(x, factor=2):
# decimation: keep every factor-th pixel, then upsample back up.
_val_invars(x, factor=factor, type="decimate")
B, C, H, W = x.shape
x_dec = x[:, :, ::factor, ::factor]
return F.interpolate(x_dec, size=(H,W), mode="nearest")
def blur_decimate(x, blur):
B, C, H, W = x.shape
x_down = blur(x)
return F.interpolate(x_down, size=(H,W), mode="bilinear", align_corners=False)
def checkerboard_alias_attack(x, epsilon=0.5):
# injects high-frequency noise that mimics sampling artifacts
_val_invars(x, epsilon=epsilon, type="attack")
B, C, H, W = x.shape
device = x.device
dtype = x.dtype
rows = pt.arange(H, device=device).view(H,1)
cols = pt.arange(W, device=device).view(1,W)
checker = ((rows + cols) % 2).float() * 2.0 - 1.0 # values in {-1, +1}
checker = checker.view( 1, 1, H, W).expand(B, C, H, W).to(dtype)
x_adv = (x + epsilon * checker).clamp(-1.0, 1.0)
return x_adv
def _val_invars(x, **kwargs):
# validate invariants
if x.ndim != 4:
raise ValueError(f"x needs shape (B,C,H,W), got {x.shape}")
op_type = kwargs.get("type")
if op_type == "resize":
scale = kwargs.get("scale")
if not isinstance(scale, numbers.Real):
raise ValueError(f"scale must be a real number, got {scale}")
if scale <= 0.0 or scale >= 1.0:
raise ValueError(f"scale must be in (0,1), got {scale}")
mode = kwargs.get("mode")
valid_modes = {"bilinear", "bicubic", "nearest", "area"}
if mode not in valid_modes:
raise ValueError(f"mode must be one of {valid_modes}, got {mode}")
elif op_type == "decimate":
factor = kwargs.get("factor")
if factor < 2:
raise ValueError(f"decimation factor must be >=2, got {factor}")
elif op_type == "attack":
epsilon = kwargs.get("epsilon")
if not (0.0 < epsilon < 1.0):
raise ValueError(f"epsilon must be (0,1), got {epsilon}")