1) Why this trade-off matters
When you harden a model (adversarial training, preprocessing, certified methods), you rarely get “free robustness.” In practice, you almost always manage a trade-off between:
Clean accuracy (performance on normal inputs)
Robustness under attack (how well the model holds up to adversarial perturbations)
Attack Success Rate (ASR) (how often an attacker wins)
Understanding this trade-off is essential because:
a model that is “accurate” but collapses under attack is unsafe
a model that is robust but too inaccurate may be unusable
teams need a measurable way to choose acceptable operating points
2) Attack Success Rate (ASR): definition and variants
A) Untargeted ASR
Attack succeeds if the model’s prediction becomes wrong.
Interpretation: higher ASR = attacker is more successful (worse for defender).
B) Targeted ASR
Attack succeeds if the model predicts a specific target class t.
Targeted ASR is usually lower than untargeted ASR because it’s a harder goal.
C) Conditional ASR (recommended)
Compute ASR only on samples that the model got right on clean data:
Why it’s better: it avoids inflating ASR due to samples the model was already failing on.
3) The accuracy–robustness trade-off (what’s really happening)
A) Clean accuracy vs robust accuracy
- Clean accuracy: AcccleanAcc
- Robust accuracy under attack
- a: Acc a/robusta(ϵ)
A common trade-off:
- Improving robustness often reduces clean accuracy slightly
- Increasing ε usually decreases robust accuracy for any model
Robustness gap:
B) Why the trade-off occurs (intuition)
Many standard models learn “sharp” boundaries that maximize clean accuracy but are brittle. Robust training encourages smoother boundaries, which can reduce overfitting to fine-grained cues and sometimes lower clean accuracy.
This is why robust models may:
- be less confident
- rely on more stable features
- sacrifice some peak performance for stability under perturbation
4) How to visualize and report the trade-off
A) Robustness curve (recommended)
Compute robust accuracy (or ASR) across multiple ε values.
Example ε grid:
- ε ∈ {0.0, 0.05, 0.10, 0.20, 0.30}
Report:
- RobustAcc(ε)
- ASR(ε)
This lets you compare two models even if one is “better” only at certain ε.
B) Pareto view (clean acc vs robust acc)
A model is “Pareto better” if it improves robustness without hurting clean accuracy (rare, but possible with better architectures or training).
5) ELMS-ready decision rules (practical interpretation)
When comparing two models:
- If both have similar clean accuracy, prefer higher robust accuracy / lower ASR under the strongest attack you care about.
- If robust accuracy improves but clean accuracy drops, decide if the drop is acceptable for your domain:
- safety-critical: accept more clean drop for robustness
- consumer UX: stricter clean accuracy requirement
- If robustness improves only for FGSM but not PGD, suspect:
- weak evaluation
- gradient masking illusion
- Always report the attack configuration (ε, steps, restarts).
6) Code: compute ASR + clean/robust accuracy and show trade-offs (TF2 + CleverHans)
Assumes you have:
model(logits output)x_test,y_test_ohone-hot labels
import numpy as np
import tensorflow as tf
from cleverhans.tf2.attacks.fast_gradient_method import fast_gradient_method
from cleverhans.tf2.attacks.projected_gradient_descent import projected_gradient_descent
def predict_labels(model, x):
logits = model(x, training=False)
return tf.argmax(logits, axis=1)
def compute_asr_and_acc(model, x, y_onehot, x_adv):
y_true = tf.argmax(y_onehot, axis=1)
y_pred_clean = predict_labels(model, x)
y_pred_adv = predict_labels(model, x_adv)
clean_acc = float(tf.reduce_mean(tf.cast(tf.equal(y_pred_clean, y_true), tf.float32)))
adv_acc = float(tf.reduce_mean(tf.cast(tf.equal(y_pred_adv, y_true), tf.float32)))
# Untargeted ASR over all samples
asr = 1.0 - adv_acc
# Conditional ASR: only on clean-correct samples
mask = tf.equal(y_pred_clean, y_true)
if int(tf.reduce_sum(tf.cast(mask, tf.int32))) > 0:
y_true_cc = tf.boolean_mask(y_true, mask)
y_adv_cc = tf.boolean_mask(y_pred_adv, mask)
cond_asr = float(tf.reduce_mean(tf.cast(tf.not_equal(y_adv_cc, y_true_cc), tf.float32)))
else:
cond_asr = 0.0
return {"clean_acc": clean_acc, "adv_acc": adv_acc, "asr": asr, "cond_asr": cond_asr}
def evaluate_tradeoff_over_eps(model, x, y_onehot, eps_list, attack="pgd",
pgd_eps_iter=0.03, pgd_steps=20):
rows = []
for eps in eps_list:
if attack.lower() == "fgsm":
x_adv = fast_gradient_method(model_fn=model, x=x, eps=eps, norm=np.inf)
else:
x_adv = projected_gradient_descent(model_fn=model, x=x,
eps=eps, eps_iter=pgd_eps_iter, nb_iter=pgd_steps,
norm=np.inf, targeted=False)
metrics = compute_asr_and_acc(model, x, y_onehot, x_adv)
metrics.update({"eps": eps, "attack": attack})
rows.append(metrics)
return rows
# Example:
# eps_grid = [0.0, 0.05, 0.1, 0.2, 0.3]
# pgd_results = evaluate_tradeoff_over_eps(model, x_test, y_test_oh, eps_grid, attack="pgd", pgd_eps_iter=0.03, pgd_steps=20)
# for r in pgd_results:
# print(r)
7) Reporting template (copy/paste into ELMS submission)
Threat model: L∞, ε ∈ {…}, attack = PGD-20, step size = …
Model A (baseline):
- Clean Acc = __
- Robust Acc (ε=0.3) = __
- ASR (ε=0.3) = __
- Conditional ASR (ε=0.3) = __
Model B (robust/defended):
- Clean Acc = __
- Robust Acc (ε=0.3) = __
- ASR (ε=0.3) = __
- Conditional ASR (ε=0.3) = __
Interpretation (6–8 sentences):
- describe robustness improvement vs clean loss
- justify whether trade-off is acceptable for the target application
- mention any signs of weak evaluation (FGSM-only, gradient masking, etc.)






Comments are closed.