1) Why generating adversarial examples matters
Adversarial training is only as good as the adversarial examples you generate during training. If you generate weak or unrealistic adversarial samples, you may end up with a model that appears robust but fails under stronger attacks.
Adversarial example generation is used for:
- Robustness evaluation (How vulnerable is the model right now?)
- Robust training (Improve resistance by training on adversarial samples)
- Red-team simulation (Model behavior under attack conditions)
2) Key terms (quick primer)
- Clean input: xxx (e.g., original image)
- Label: yyy (true class)
- Model parameters: θ\thetaθ
- Loss function: J(θ,x,y)J(\theta, x, y)J(θ,x,y)
- Adversarial input: xadvx_{adv}xadv
- Perturbation budget: ϵ\epsilonϵ (how much input can change)
- Norm constraint: often L∞L_\inftyL∞ or L2L_2L2
Typical goal (untargeted attack):

3) Threat models and constraints (what you must define)
Before generating adversarial examples, always define:
- Attacker knowledge
- White-box (has gradients)
- Black-box (queries only)
- Perturbation constraint
- L∞L_\inftyL∞: maximum per-pixel change ≤ ε
- L2L_2L2: total perturbation energy bounded
- Attack objective
- Untargeted: “make it wrong”
- Targeted: “force it to predict class T”
- Data domain
- Images: continuous, easy to perturb
- Text: discrete, more complex (token-level changes)
- Tabular: feature constraints matter (must stay realistic)
This lesson focuses on image-domain adversarial examples (most standard for adversarial training).
4) Core techniques for generating adversarial examples
A) FGSM (Fast Gradient Sign Method) — 1-step, fast baseline
Idea: Move the input in the direction that increases loss most rapidly.

When used:
quick robustness check
cheap adversarial training variant
as a baseline comparison (but often too weak alone)
Pros
fast, easy to compute
useful as a sanity test
Cons
weaker than iterative attacks
robust models can resist FGSM but still fail to PGD
B) BIM (Basic Iterative Method) — iterative FGSM
Idea: Apply FGSM multiple times with a small step size α\alphaα, projecting back into the ε-ball each step.
When used:

- stronger training adversary than FGSM
- common stepping stone to PGD
C) PGD (Projected Gradient Descent) — gold standard for training
Idea: Like BIM, but usually starts from a random point inside the ε-ball and iteratively climbs loss.
Why PGD is central: PGD is widely treated as a strong first-order adversary. PGD-based adversarial training is a standard baseline for robust ML.
Pros
- strong, widely accepted for evaluation/training
- reveals “real” vulnerabilities better than FGSM
Cons
- expensive (many steps)
- still not “complete” (certified robustness is different)
D) Targeted attacks (targeted FGSM/PGD)
Idea: Instead of maximizing loss for the true class, you minimize loss toward a chosen target class ytargety_{target}ytarget.
Targeted FGSM (conceptually):

Use cases
red-team “forced mislabel” scenarios
testing worst-case misclassification outcomes
E) Optimization-based attacks (C&W, etc.) — strong but heavier
These solve an explicit optimization problem to find small perturbations that reliably fool the model. They’re often used for evaluation, less often for training due to computational cost.
5) Hands-on: Generate adversarial examples with code (TensorFlow 2 + CleverHans)
Below is a clean lab-style snippet that:
trains a CNN on MNIST
generates FGSM + PGD adversarial examples
compares accuracy
5.1 Train a simple model
import tensorflow as tf
import numpy as np
# Load MNIST
(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)
# Simple CNN
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 test accuracy:", model.evaluate(x_test, y_test_oh, verbose=0)[1])
5.2 FGSM adversarial examples (CleverHans)
from cleverhans.tf2.attacks.fast_gradient_method import fast_gradient_method
eps = 0.2
x_adv_fgsm = fast_gradient_method(model_fn=model, x=x_test, eps=eps, norm=np.inf)
print(f"FGSM accuracy (eps={eps}):", model.evaluate(x_adv_fgsm, y_test_oh, verbose=0)[1])
5.3 PGD adversarial examples (CleverHans)
from cleverhans.tf2.attacks.projected_gradient_descent import projected_gradient_descent
eps = 0.3
eps_iter = 0.03
nb_iter = 20
x_adv_pgd = projected_gradient_descent(
model_fn=model,
x=x_test,
eps=eps,
eps_iter=eps_iter,
nb_iter=nb_iter,
norm=np.inf,
targeted=False
)
print(f"PGD accuracy (eps={eps}, steps={nb_iter}):", model.evaluate(x_adv_pgd, y_test_oh, verbose=0)[1])
What you should observe: PGD typically reduces accuracy much more than FGSM, because it’s iterative and stronger.


Comments are closed.