1) Why input transformations are used as defenses

Most adversarial attacks (especially on images) rely on adding small, high-frequency perturbations that humans barely notice but models pick up. Input transformations try to break or weaken those perturbations before the model sees them.

Think of input transformations as a security filter placed in front of the model:

Input → Transformation/Filter → Model → Output

They are commonly used when:

  • retraining is expensive (you can’t do adversarial training immediately)

  • you want a quick robustness uplift

  • you want defense-in-depth (layered security)

2) How transformations work (the intuition)

Most transformations work by one (or more) of these mechanisms:

  1. Remove high-frequency noise
    (e.g., smoothing, denoising, compression)

  2. Disrupt precise perturbation alignment
    (e.g., random resizing/padding/cropping)

  3. Reduce sensitivity to tiny pixel changes
    (e.g., bit-depth reduction, quantization)

  4. Add stochasticity so attacker cannot perfectly optimize
    (e.g., randomized transformations with expectation-over-transforms evaluation)

3) Common input transformations (what to teach + when to use)

A) Smoothing / Denoising

Goal: reduce small pixel-level noise.

Typical techniques

  • Gaussian blur

  • Median filter

  • Bilateral filter (preserves edges better than Gaussian)

Best for

  • attacks dominated by high-frequency noise

  • basic evasion attacks like FGSM

Risk

  • can reduce clean accuracy (removes useful details too)

B) JPEG compression

Goal: discard high-frequency components through compression.

Why it helps
JPEG compression quantizes frequency components—many adversarial perturbations get weakened in the process.

Best for

  • image pipelines where compression is acceptable (web, mobile)

Risk

  • too much compression harms clean performance

  • adaptive attackers can train through compression (EOT) if they know the defense

C) Resizing + padding / random crop

Goal: perturbation crafted for exact pixel grid may fail when geometry changes.

Best for

  • models where small geometric changes don’t break semantics

Risk

  • cropping can remove important features (especially on small objects)

D) Bit-depth reduction / quantization

Goal: reduce precision so tiny perturbations “snap” to the same value.

Example

  • 8-bit → 4-bit input representation

Best for

  • lightweight defenses in constrained environments

Risk

  • may reduce accuracy if model needs subtle signals

E) Random noise injection

Goal: add stochasticity that degrades adversarial perturbations.

Best for

  • combined with robust training or smoothing approaches

Risk

  • can lower clean accuracy; may require calibration

4) The critical warning (ELMS must include this)

Input transformations can create “illusory robustness”

Some transformations make gradients harder to compute, so simple gradient-based attacks fail, but the model is not truly robust.

How to avoid being fooled

  • evaluate with stronger attacks (PGD)

  • evaluate with adaptive methods like EOT (Expectation Over Transformations) if the defense is randomized

  • test transfer attacks (attack a surrogate, test on your model)

5) Implementation lab (TensorFlow 2): transformations + robustness evaluation

Below is a practical workflow:

  1. Train a CNN on MNIST

  2. Generate adversarial examples (FGSM/PGD)

  3. Evaluate model with and without transformations

This example uses TensorFlow ops only (so it runs anywhere TF runs).

5.1 Train a simple model

import tensorflow as tf
import numpy as np

(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
x_train = (x_train.astype("float32")/255.0)[..., None]
x_test = (x_test.astype("float32")/255.0)[..., None]
y_train_oh = tf.one_hot(y_train, 10)
y_test_oh = tf.one_hot(y_test, 10)

model = tf.keras.Sequential([
tf.keras.layers.Conv2D(32, 3, activation="relu", input_shape=(28,28,1)),
tf.keras.layers.MaxPool2D(),
tf.keras.layers.Conv2D(64, 3, activation="relu"),
tf.keras.layers.MaxPool2D(),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation="relu"),
tf.keras.layers.Dense(10) # logits
])

loss_fn = tf.keras.losses.CategoricalCrossentropy(from_logits=True)
model.compile(optimizer=tf.keras.optimizers.Adam(1e-3),
loss=loss_fn,
metrics=[tf.keras.metrics.CategoricalAccuracy(name="acc")])

model.fit(x_train, y_train_oh, epochs=2, batch_size=128, validation_split=0.1)
print("Clean accuracy:", model.evaluate(x_test, y_test_oh, verbose=0)[1])

5.2 Generate adversarial examples (CleverHans FGSM + PGD)

from cleverhans.tf2.attacks.fast_gradient_method import fast_gradient_method
from cleverhans.tf2.attacks.projected_gradient_descent import projected_gradient_descent

# FGSM
x_adv_fgsm = fast_gradient_method(model_fn=model, x=x_test, eps=0.2, norm=np.inf)

# PGD (stronger)
x_adv_pgd = projected_gradient_descent(model_fn=model, x=x_test,
eps=0.3, eps_iter=0.03, nb_iter=20,
norm=np.inf, targeted=False)

print("FGSM accuracy:", model.evaluate(x_adv_fgsm, y_test_oh, verbose=0)[1])
print("PGD accuracy:", model.evaluate(x_adv_pgd, y_test_oh, verbose=0)[1])

6) Add input transformations (defense layer)

6.1 Transformation 1: Gaussian smoothing (blur)

def gaussian_blur(x, ksize=3, sigma=1.0):
# Build Gaussian kernel
ax = tf.range(-ksize//2 + 1, ksize//2 + 1, dtype=tf.float32)
xx, yy = tf.meshgrid(ax, ax)
kernel = tf.exp(-(xx**2 + yy**2) / (2.0 * sigma**2))
kernel = kernel / tf.reduce_sum(kernel)
kernel = kernel[:, :, tf.newaxis, tf.newaxis] # (k,k,1,1)
return tf.nn.depthwise_conv2d(x, kernel, strides=[1,1,1,1], padding="SAME")

6.2 Transformation 2: Random resize + pad (stochastic defense)

def random_resize_pad(x, min_size=24, max_size=28):
# Randomly resize to [min_size, max_size], then pad back to 28x28
size = tf.random.uniform([], minval=min_size, maxval=max_size+1, dtype=tf.int32)
x_resized = tf.image.resize(x, [size, size], method="bilinear")
pad_total = 28 - size
pad_top = tf.random.uniform([], 0, pad_total+1, dtype=tf.int32)
pad_bottom = pad_total - pad_top
pad_left = tf.random.uniform([], 0, pad_total+1, dtype=tf.int32)
pad_right = pad_total - pad_left
x_padded = tf.pad(x_resized, [[0,0],[pad_top,pad_bottom],[pad_left,pad_right],[0,0]])
return x_padded

7) Evaluate “transformed input” robustness

7.1 Deterministic transformation evaluation (blur)

x_test_blur = gaussian_blur(tf.constant(x_test))
x_fgsm_blur = gaussian_blur(tf.constant(x_adv_fgsm))
x_pgd_blur = gaussian_blur(tf.constant(x_adv_pgd))

print("Blur clean accuracy:", model.evaluate(x_test_blur, y_test_oh, verbose=0)[1])
print("Blur FGSM accuracy:", model.evaluate(x_fgsm_blur, y_test_oh, verbose=0)[1])
print("Blur PGD accuracy:", model.evaluate(x_pgd_blur, y_test_oh, verbose=0)[1])

7.2 Stochastic transformation evaluation (random resize+pad)

Because this is randomized, evaluate by averaging accuracy over multiple runs.

def eval_with_random_transform(x, y, runs=10):
accs = []
for _ in range(runs):
x_t = random_resize_pad(tf.constant(x))
accs.append(model.evaluate(x_t, y, verbose=0)[1])
return float(np.mean(accs)), float(np.std(accs))

clean_mean, clean_std = eval_with_random_transform(x_test, y_test_oh, runs=10)
fgsm_mean, fgsm_std = eval_with_random_transform(x_adv_fgsm, y_test_oh, runs=10)
pgd_mean, pgd_std = eval_with_random_transform(x_adv_pgd, y_test_oh, runs=10)

print(f"RandTransform clean acc: {clean_mean:.4f} ± {clean_std:.4f}")
print(f"RandTransform FGSM acc: {fgsm_mean:.4f} ± {fgsm_std:.4f}")
print(f"RandTransform PGD acc: {pgd_mean:.4f} ± {pgd_std:.4f}")

Interpretation note for learners:

  • If robustness improves against FGSM but not PGD, you may be seeing weak defense or illusory robustness.

  • Randomized defenses require EOT-style evaluation for honest robustness measurement.

8) Best practices (what to teach as “rules”)

  1. Never rely on input transformations alone for high-stakes systems.
    Use them as a layer alongside adversarial training and monitoring.

  2. Evaluate with stronger attacks than the ones you used to tune the defense.
    Example: tune with FGSM, validate with PGD-20/50.

  3. For randomized transforms, report averaged metrics and evaluate adaptively (EOT).
    Otherwise, you overestimate robustness.

  4. Measure clean accuracy impact and define acceptable degradation upfront.

Comments are closed.

{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}
FREEDOM TO LEARN • 10% OFF All Courses & Workshops • Use Code: NANOINDIA10 • ⏳ Offer Ends In: Loading... • Learn Today. Lead Tomorrow. • Explore Programs →
FREEDOM TO LEARN • 10% OFF All Courses & Workshops • Use Code: NANOINDIA10 • ⏳ Offer Ends In: Loading... • Learn Today. Lead Tomorrow. • Explore Programs →
Support