1) What is CleverHans?

CleverHans is a Python library built to generate adversarial examples and evaluate model robustness—especially for deep learning models. It became popular because it provides clean, research-aligned implementations of core adversarial attacks (e.g., FGSM, PGD) and helps standardize how teams test robustness.

Where it fits in the workflow:

  • Red-team / testing: “Can my model be fooled under a realistic threat model?”

  • Defense iteration: “If I add adversarial training or preprocessing, does robustness actually improve?”

  • Benchmarking: Comparing robustness across models, datasets, and training strategies.

2) Why CleverHans is important in adversarial ML

CleverHans is valuable because it helps you operationalize three things:

A) Reproducible attacks

You don’t want a “homebrew” attack that accidentally underestimates risk. CleverHans gives you known baselines.

B) Threat-model aware evaluation

It’s easy to claim robustness by testing weak attacks. CleverHans makes it straightforward to run stronger iterative attacks (e.g., PGD) and report parameters.

C) Defense validation

Defenses often “look good” under one attack but collapse under another. CleverHans supports a more honest attack suite mindset.

3) Core concepts you should know before using it

Evasion attacks (inference-time)

You keep the model fixed, and you perturb the input xxx slightly to get x′x'x′ such that:

  • Humans see “the same” input

  • Model prediction flips (or confidence changes drastically)

Norm bounds

Most attacks constrain perturbations by a norm (common in images):

  • L∞ bound: every pixel changes by at most ε

  • L2 bound: overall perturbation energy is bounded

White-box vs black-box

CleverHans is mostly used for white-box testing (attacker can compute gradients). That’s still crucial because white-box testing is the “worst-case” sanity check.

4) Setup: Install CleverHans

pip install cleverhans

Note: CleverHans is most commonly used with TensorFlow 2.x APIs. (If you’re using PyTorch-heavy workflows, ART/Foolbox are often used too, but CleverHans still helps conceptually and sometimes practically depending on version.)

5) Minimal, high-quality example (TensorFlow 2): FGSM + PGD evaluation

This example shows:

  1. Train a simple CNN on MNIST

  2. Attack it with FGSM and PGD

  3. Compare clean accuracy vs adversarial accuracy

5.1 Train a baseline model

import tensorflow as tf
import numpy as np

# 1) Data
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
x_train = (x_train.astype("float32") / 255.0)[..., None] # (N, 28, 28, 1)
x_test = (x_test.astype("float32") / 255.0)[..., None]

y_train_oh = tf.one_hot(y_train, depth=10)
y_test_oh = tf.one_hot(y_test, depth=10)

# 2) Model
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)

clean_eval = model.evaluate(x_test, y_test_oh, verbose=0)
print("Clean test accuracy:", clean_eval[1])

5.2 Generate adversarial examples using CleverHans

FGSM (Fast Gradient Sign Method)

from cleverhans.tf2.attacks.fast_gradient_method import fast_gradient_method

eps = 0.2 # L-infinity bound
x_adv_fgsm = fast_gradient_method(model_fn=model, x=x_test, eps=eps, norm=np.inf)

adv_eval_fgsm = model.evaluate(x_adv_fgsm, y_test_oh, verbose=0)
print(f"FGSM (eps={eps}) accuracy:", adv_eval_fgsm[1])

PGD (Projected Gradient Descent)

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)

adv_eval_pgd = model.evaluate(x_adv_pgd, y_test_oh, verbose=0)
print(f"PGD (eps={eps}, steps={nb_iter}) accuracy:", adv_eval_pgd[1])

Interpretation guideline (what learners should notice):

  • Clean accuracy might be high (e.g., >98% on MNIST)

  • FGSM drops accuracy noticeably

  • PGD usually drops it much more, because it’s a stronger iterative attack

6) Using CleverHans for Adversarial Training (defense)

Adversarial training is the most practical baseline defense: train on a mix of clean and adversarial samples so the model learns a smoother, more robust decision boundary.

6.1 Simple FGSM-based adversarial training loop (TensorFlow 2)

@tf.function
def train_step(x, y, eps=0.2):
# Generate FGSM examples on-the-fly
x_adv = fast_gradient_method(model_fn=model, x=x, eps=eps, norm=np.inf)

with tf.GradientTape() as tape:
# Mix clean + adversarial in one batch (simple strategy)
x_mix = tf.concat([x, x_adv], axis=0)
y_mix = tf.concat([y, y], axis=0)

logits = model(x_mix, training=True)
loss = loss_fn(y_mix, logits)

grads = tape.gradient(loss, model.trainable_variables)
model.optimizer.apply_gradients(zip(grads, model.trainable_variables))
return loss

# Build a dataset pipeline
train_ds = tf.data.Dataset.from_tensor_slices((x_train, y_train_oh)).shuffle(10000).batch(128)

# Run a few adversarial-training epochs
for epoch in range(2):
losses = []
for xb, yb in train_ds:
l = train_step(xb, yb, eps=0.2)
losses.append(float(l))
print(f"Adv-training epoch {epoch+1} | loss={np.mean(losses):.4f}")

# Re-evaluate
clean_eval2 = model.evaluate(x_test, y_test_oh, verbose=0)
print("Clean accuracy after adv training:", clean_eval2[1])

x_adv_pgd2 = projected_gradient_descent(model_fn=model, x=x_test, eps=0.3, eps_iter=0.03, nb_iter=20,
norm=np.inf, targeted=False)
adv_eval_pgd2 = model.evaluate(x_adv_pgd2, y_test_oh, verbose=0)
print("PGD accuracy after adv training:", adv_eval_pgd2[1])

What learners typically observe:

  • Robust accuracy under PGD often improves

  • Clean accuracy might dip slightly (robustness–accuracy trade-off)

7) Common mistakes (and how to teach learners to avoid them)

Mistake 1: “It’s robust because FGSM didn’t work”

FGSM is often too weak. Always test at least one iterative attack like PGD.

Mistake 2: Not reporting attack parameters

Robustness is meaningless without:

  • ε (budget)

  • step size

  • number of steps

  • norm type

Mistake 3: Gradient masking illusions

Some defenses break gradients; attacks fail without real robustness. Validate using:

  • stronger attacks

  • transfer-style checks (attack a surrogate and test on target)

  • sanity checks (does robust accuracy collapse under adaptive settings?)

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