This page is the "muscle memory" companion to Adversarial examples and robustness . There we derived the Fast Gradient Sign Method and PGD. Here we run them by hand on tiny numbers so you can watch every gear turn — including the weird corners: zero gradients, gradients that vanish, the exact moment clipping bites, and a full targeted attack.
Intuition Read this first
Every attack in this chapter is one idea repeated: look at the gradient of the loss with respect to the input, and step the input in whatever direction makes the loss go up (or down, if you have a target class in mind). A gradient is just a list of numbers — one per input pixel — telling you "if you nudge this pixel up a tiny bit, the loss changes by this much." We will work entirely with 2-pixel and 3-pixel "images" so you can see all the numbers at once.
Before we do anything, the symbols we will lean on constantly:
Definition The workhorses
∇ x L (read "grad-x of L") is the gradient of the loss with respect to the input : a vector with one entry per input coordinate. Entry i is ∂ L / ∂ x i — "how fast the loss rises as I raise pixel i ." A positive entry means raising that pixel raises loss (good for an attacker who wants a wrong answer); a negative entry means raising that pixel lowers loss.
L ( θ , x , y ) is the loss written out in full: θ is the model's weights (the trained numbers inside the network — fixed during an attack; we never change them here), x is the input we do change, and y is the label. When we attack we differentiate only with respect to x , holding θ frozen — that is exactly what the little "x " under ∇ x means.
sign ( v ) takes a number and returns + 1 if it is positive, − 1 if negative, and 0 if it is exactly zero. Applied to a vector, it acts entry-by-entry. This is the whole trick of FGSM: throw away the magnitude of each gradient entry, keep only its direction , then step by the fixed budget ϵ in that direction.
L ∞ norm and the "budget" ϵ
Write a perturbation as δ = ( δ 1 , δ 2 , … ) — the amount added to each pixel. Its ==L ∞ norm== is the single largest absolute move over all pixels:
∥ δ ∥ ∞ = max i ∣ δ i ∣.
So "∥ δ ∥ ∞ ≤ ϵ " reads: no pixel may move by more than ϵ . Picture the set of legal moves as a tiny square box of half-width ϵ centred on the clean input — every corner and edge is allowed, but nothing outside. The budget ϵ is that half-width.
clip operator (used by PGD)
clip ( z , lo , hi ) squashes a number back into the interval [ lo , hi ] :
clip ( z , lo , hi ) = max ( lo , min ( z , hi ) ) .
In words: if z is above the ceiling hi , return hi ; if below the floor lo , return lo ; otherwise leave z alone. Applied to a vector, it acts pixel-by-pixel. PGD uses it to drag a step that wandered out of the ϵ -box back onto the nearest legal value.
Recall Where is
L ∞ -optimality proven?
The claim "under ∥ δ ∥ ∞ ≤ ϵ the best move is ϵ sign ( ∇ x L ) " is derived in the parent note (FGSM derivation, Steps 1–3). Quick reminder of why : we want to maximize the dot product δ ⊤ ∇ x L = ∑ i δ i g i . Each term δ i g i is biggest when δ i has the same sign as g i and is as large as allowed, namely ± ϵ . Hence δ i = ϵ sign ( g i ) maximizes every term at once.
Every worked example below is tagged with the cell(s) it covers. If a cell has no example, you have found a gap — there are none.
Cell
What makes it tricky
Covered by
A. All-positive gradient
plain FGSM, every sign = + 1
Ex 1
B. Mixed signs
some pixels pushed up, some down
Ex 2
C. Zero gradient entry
sign ( 0 ) = 0 : that pixel does not move
Ex 3
D. Zero-vector gradient (degenerate)
attack does nothing — a local flat/optimum
Ex 3
E. Targeted attack (minus sign)
drive toward a chosen class t
Ex 4
F. PGD with no clipping
steps stay inside the ball, projection is idle
Ex 5
G. PGD where projection bites
a step leaves the ϵ -ball, clip pulls it back
Ex 6
H. Pixel-range clipping (valid image)
0 ≤ x i ≤ 1 also clips
Ex 6
I. High-dimensional accumulation
why ϵ d blows up
Ex 7
J. Real-world word problem
ϵ = 8/255 in RGB units
Ex 8
K. Exam twist
L 2 optimal step = sign step
Ex 9
Worked example Ex 1 — Cell A (all-positive gradient)
A model has a 2-pixel input x = ( 0.40 , 0.60 ) . Its loss gradient at x is ∇ x L = ( 0.9 , 0.2 ) . Budget ϵ = 0.1 , L ∞ . Compute the FGSM adversarial input.
Forecast: both gradient entries are positive, so both pixels get pushed up by the full ϵ . Guess the answer before reading on.
Take the sign of the gradient. sign ( 0.9 , 0.2 ) = ( + 1 , + 1 ) .
Why this step? FGSM keeps only direction, not size. A gradient of 0.9 and one of 0.2 both say "raise this pixel," so both become + 1 . The magnitudes 0.9 vs 0.2 are deliberately thrown away — that is what makes the step fast and keeps every pixel exactly at the budget edge.
Scale by ϵ to get the perturbation. δ = ϵ ⋅ ( + 1 , + 1 ) = ( 0.1 , 0.1 ) .
Why this step? We want the biggest loss increase allowed. Under L ∞ (max any pixel may move is ϵ ), stepping every pixel the full ϵ in its gradient's direction is optimal — see the reminder box above.
Add to the input. x adv = x + δ = ( 0.40 + 0.1 , 0.60 + 0.1 ) = ( 0.50 , 0.70 ) .
Why this step? An adversarial example is by definition the clean input plus the perturbation (x ′ = x + δ ); adding δ is how the chosen move actually lands on the new input.
Verify: ∥ δ ∥ ∞ = max ( 0.1 , 0.1 ) = 0.1 = ϵ ✓ (budget hit exactly, not exceeded). Linearized loss increase = δ ⊤ ∇ x L = 0.1 ( 0.9 ) + 0.1 ( 0.2 ) = 0.11 > 0 ✓ (loss went up, attack succeeds in the linear model).
Figure s01 (sketch it yourself): on axes "pixel 1" and "pixel 2", a teal square box of half-width 0.1 is centred on the clean point x = ( 0.40 , 0.60 ) . A plum arrow from x points up-and-right along the gradient ( 0.9 , 0.2 ) . FGSM lands on the orange top-right corner ( 0.50 , 0.70 ) — the corner of the box most aligned with that arrow.
Worked example Ex 2 — Cell B (mixed signs)
Same input x = ( 0.40 , 0.60 ) , ϵ = 0.1 , but now the gradient is ∇ x L = ( 0.9 , − 0.3 ) .
Forecast: pixel 1's gradient is positive (push up), pixel 2's is negative (push down ). The corner chosen will be a different corner than Ex 1.
Sign. sign ( 0.9 , − 0.3 ) = ( + 1 , − 1 ) .
Why this step? A negative gradient entry means raising that pixel lowers the loss — the attacker wants loss higher , so it moves that pixel the other way: down.
Perturbation. δ = 0.1 ⋅ ( + 1 , − 1 ) = ( 0.1 , − 0.1 ) .
Why this step? Same rule as Ex 1: scale the sign vector by the budget ϵ so each pixel moves the maximum allowed amount in its chosen direction — up on pixel 1, down on pixel 2.
Add. x adv = x + δ = ( 0.40 + 0.1 , 0.60 − 0.1 ) = ( 0.50 , 0.50 ) .
Why this step? The adversarial input is clean-input-plus-perturbation; here the negative second component pulls pixel 2 down to 0.50 .
Verify: ∥ δ ∥ ∞ = 0.1 = ϵ ✓. Linear loss change = 0.1 ( 0.9 ) + ( − 0.1 ) ( − 0.3 ) = 0.09 + 0.03 = 0.12 > 0 ✓ — notice both terms are positive: choosing the sign correctly makes even the down-move help the attacker.
Figure s02 (sketch it yourself): the same teal box on x = ( 0.40 , 0.60 ) , but now the plum gradient arrow points down-and-right (sign ( + , − ) ), so FGSM snaps to the orange bottom-right corner ( 0.50 , 0.50 ) — a different corner than Ex 1.
Common mistake The classic sign-flip error
Beginners write δ = ϵ ⋅ ∇ x L (using the gradient itself, not its sign). That would give δ = ( 0.09 , − 0.03 ) — pixel 2 barely moves. The L ∞ -optimal move uses every pixel to the full budget, so the sign is essential. Using the raw gradient is the L 2 direction, not L ∞ (see Ex 9).
Worked example Ex 3 — Cells C & D (a zero entry, and the all-zero gradient)
Part (i), Cell C. x = ( 0.5 , 0.5 , 0.5 ) , ϵ = 0.1 , gradient ∇ x L = ( 0.7 , 0 , − 0.4 ) .
Part (ii), Cell D. Same x , but gradient = ( 0 , 0 , 0 ) .
Forecast: in (i), pixel 2 has gradient exactly 0 — sign ( 0 ) = 0 , so it does not move. In (ii), nothing moves; the attack is powerless.
Part (i):
Sign. sign ( 0.7 , 0 , − 0.4 ) = ( + 1 , 0 , − 1 ) .
Why this step? sign ( 0 ) = 0 by definition. Geometrically, a zero gradient entry means the loss is momentarily flat along that pixel — nudging it up or down changes nothing to first order, so the optimal L ∞ move leaves it put.
Perturbation. δ = 0.1 ⋅ ( + 1 , 0 , − 1 ) = ( 0.1 , 0 , − 0.1 ) .
Why this step? Scaling by ϵ moves the two live pixels to the budget edge; the middle entry is 0.1 ⋅ 0 = 0 , so that pixel stays frozen — the zero sign carries straight through.
Add. x adv = x + δ = ( 0.5 + 0.1 , 0.5 + 0 , 0.5 − 0.1 ) = ( 0.6 , 0.5 , 0.4 ) .
Why this step? Clean-input-plus-perturbation again; the untouched middle pixel confirms a zero-gradient coordinate is simply left alone.
Verify (i): ∥ δ ∥ ∞ = 0.1 ✓. Linear change = 0.1 ( 0.7 ) + 0 + ( − 0.1 ) ( − 0.4 ) = 0.07 + 0.04 = 0.11 > 0 ✓. Middle pixel unchanged ✓.
Part (ii):
sign ( 0 , 0 , 0 ) = ( 0 , 0 , 0 ) , so δ = 0 and x adv = x .
Why? An all-zero input gradient is a critical point of the loss with respect to x — a flat spot. FGSM has no downhill (or uphill) to grab. In practice this is rare and often means you are at a genuine minimum of the input loss, or the gradient underflowed; either way, single-step FGSM fails here and you would need a random restart (a trick PGD uses).
Verify (ii): ∥ δ ∥ ∞ = 0 = (no change) , loss change = 0 ✓ — the honest, disappointing answer.
Worked example Ex 4 — Cell E (targeted, subtract the sign)
Untargeted FGSM asks "make any wrong answer." Targeted FGSM asks "make it say class t ." We minimize the loss toward t , so we step in the negative sign direction: x adv = x − ϵ sign ( ∇ x L ( θ , x , t )) . (Recall from the workhorses box: θ is the frozen model weights, and ∇ x L ( θ , x , t ) is just "the input-gradient of the loss, but scored against the target label t instead of the true label.")
x = ( 0.30 , 0.80 ) , ϵ = 0.05 . The gradient of the loss for the target class t is ∇ x L ( θ , x , t ) = ( 0.6 , − 0.5 ) .
Forecast: because we subtract, positive gradient entries get pushed down and negative ones up — the mirror image of untargeted.
Sign of the target-loss gradient. sign ( 0.6 , − 0.5 ) = ( + 1 , − 1 ) .
Why this step? Same "keep direction, drop magnitude" rule; it tells us which way each pixel would raise the target loss.
Subtract ϵ ⋅ sign. δ = − 0.05 ⋅ ( + 1 , − 1 ) = ( − 0.05 , + 0.05 ) .
Why this step? To make the model predict t , we want its loss for t to be small — so we descend, i.e. move opposite the gradient. The minus sign encodes "descend on target loss" instead of "ascend on true loss."
Add. x adv = x + δ = ( 0.30 − 0.05 , 0.80 + 0.05 ) = ( 0.25 , 0.85 ) .
Why this step? Clean-input-plus-perturbation; the flipped signs (down on pixel 1, up on pixel 2) are exactly the mirror of what an untargeted attack on the same gradient would do.
Verify: ∥ δ ∥ ∞ = 0.05 = ϵ ✓. Change in target loss (linearized) = δ ⊤ ∇ x L ( θ , x , t ) = ( − 0.05 ) ( 0.6 ) + ( 0.05 ) ( − 0.5 ) = − 0.03 − 0.025 = − 0.055 < 0 ✓ — target loss dropped , so class t becomes more likely. Exactly what we wanted.
FGSM takes one big leap of size ϵ . Projected Gradient Descent (PGD) instead takes several small steps, re-reading the gradient after each one, and "projects" (clips) back into the budget whenever a step wanders out. This finds stronger attacks because the loss surface bends, and one linear leap can overshoot or miss.
Definition The PGD update, spelled out
Let t = 0 , 1 , 2 , … , T − 1 index the iterations, so x ( t ) is the input after t steps, starting from x ( 0 ) = x (the clean input). The ==step size α == is how far each small step moves per pixel; we always pick α < ϵ so no single step can jump the whole budget — this lets the attack creep and correct course. The update is
x ( t + 1 ) = clip ( x ( t ) + α sign ( ∇ x L ( θ , x ( t ) , y ) ) , x − ϵ , x + ϵ ) .
Read it inside-out: (1) at the current point x ( t ) take an FGSM-style step of size α ; (2) clip each pixel back into [ x − ϵ , x + ϵ ] — the ϵ -box around the original x , not around x ( t ) . That second clip is the "projection": it guarantees the running perturbation never exceeds the budget, no matter how many steps we take.
Worked example Ex 5 — Cell F (PGD, projection never triggers)
One pixel for clarity. x = 0.50 , ϵ = 0.10 , α = 0.03 , run T = 3 steps (t = 0 , 1 , 2 ), gradient sign is + 1 every step. The legal window is [ x − ϵ , x + ϵ ] = [ 0.40 , 0.60 ] .
Forecast: each step adds α = 0.03 . After 3 steps that is + 0.09 , still under the ϵ = 0.10 cap — so clipping never does anything and we end at 0.59 .
Step t = 0 → 1 . x ( 1 ) = clip ( 0.50 + 0.03 , 0.40 , 0.60 ) = clip ( 0.53 , 0.40 , 0.60 ) = 0.53 .
Why this step? 0.53 is between the allowed bounds [ 0.40 , 0.60 ] , so clip returns it unchanged (recall: clip only acts when a value pokes outside the interval).
Step t = 1 → 2 . x ( 2 ) = clip ( 0.53 + 0.03 , 0.40 , 0.60 ) = clip ( 0.56 , 0.40 , 0.60 ) = 0.56 .
Why this step? We re-take a small step of size α = 0.03 from the current point — PGD always steps from where it currently is, not from the original x . 0.56 is still inside the window, so no clipping.
Step t = 2 → 3 . x ( 3 ) = clip ( 0.56 + 0.03 , 0.40 , 0.60 ) = clip ( 0.59 , 0.40 , 0.60 ) = 0.59 .
Why this step? Third small step for the same reason; 0.59 < 0.60 , so still legal. Three small steps beat one big FGSM leap because each recomputes the gradient (here fixed for simplicity).
Verify: ∣ x ( 3 ) − x ∣ = ∣0.59 − 0.50∣ = 0.09 ≤ ϵ = 0.10 ✓. Projection idle in all 3 steps ✓ (each pre-clip value was already legal).
Worked example Ex 6 — Cells G & H (projection
and pixel-range clip both bite)
Same setup but push harder: x = 0.95 , ϵ = 0.10 , α = 0.06 , gradient sign + 1 , and the pixel must stay a valid intensity 0 ≤ x ≤ 1 . Run T = 3 steps.
Two constraints apply each step: the ϵ -ball [ x − ϵ , x + ϵ ] = [ 0.85 , 1.05 ] and the valid-pixel range [ 0 , 1 ] . Order does not matter — applying two clips in a row is the same as clipping once to the intersection of the intervals, because clipping to [ 0 , 1 ] then to [ 0.85 , 1.05 ] (or vice-versa) both land you in the overlap [ max ( 0 , 0.85 ) , min ( 1.05 , 1.00 )] = [ 0.85 , 1.00 ] . So we simply clip to that combined window [ 0.85 , 1.00 ] each step.
Forecast: naive steps would climb 0.95 → 1.01 → 1.07 … , but 1.00 is the ceiling — clipping pins us at 1.00 from step 1 onward.
Step t = 0 → 1 . raw = 0.95 + 0.06 = 1.01 . Clip to [ 0.85 , 1.00 ] : min ( 1.01 , 1.00 ) = 1.00 . So x ( 1 ) = 1.00 .
Why this step? 1.01 exceeds the pixel ceiling 1.00 , so the image-validity clip (Cell H) fires. Note it is 1.00 , not 1.05 : the tighter of the two upper bounds (min ( 1.05 , 1.00 ) = 1.00 ) wins — this is exactly why the intersection is what matters.
Step t = 1 → 2 . raw = 1.00 + 0.06 = 1.06 . Clip to [ 0.85 , 1.00 ] : 1.00 . Unchanged.
Why this step? PGD steps again from the current 1.00 ; the raw 1.06 is over both ceilings, so it is dragged back to 1.00 .
Step t = 2 → 3 . raw = 1.00 + 0.06 = 1.06 → clip → 1.00 . Still 1.00 .
Why this step? Once pinned at a saturated boundary, further same-direction steps stay pinned — extra iterations buy nothing here.
Verify: final x ( 3 ) = 1.00 . Both constraints satisfied: ∣1.00 − 0.95∣ = 0.05 ≤ ϵ ✓ and 0 ≤ 1.00 ≤ 1 ✓. Lesson: a pixel already near the boundary of valid values has less room than ϵ suggests — real attacks account for this.
Figure s03 (sketch it yourself): PGD step number on the x-axis (0 , 1 , 2 , 3 ), pixel value on the y-axis. A plum dashed line traces the pre-clip "raw" values climbing past 1.00 (0.95 → 1.01 → 1.06 → 1.06 ); a solid ink line shows the post-clip values flattening onto the orange ceiling at 1.00 from step 1 on. A dotted teal line marks the looser ϵ -ceiling x + ϵ = 1.05 that never gets to bind because the pixel ceiling 1.00 is tighter.
Worked example Ex 7 — Cell I (the
ϵ d blow-up)
Suppose every one of d pixels has the same gradient sign, and we move each by the full ϵ (FGSM). Compare d = 4 and d = 150 , 528 (a 224 × 224 × 3 image). Take a per-pixel gradient magnitude of g = 1 so numbers stay clean, and ϵ = 0.01 .
Forecast: the loss increase adds up over all pixels, so it grows with d even though each pixel barely moves.
Per-pixel contribution. Each pixel contributes δ i ⋅ g i = ϵ ⋅ 1 = 0.01 to the linearized loss change δ ⊤ ∇ x L = ∑ i δ i g i .
Why this step? With all signs aligned, no cancellation happens — every term is positive and equal.
Sum over d pixels. Total loss change = d ⋅ ϵ = d ⋅ 0.01 .
Why this step? d equal terms of 0.01 add straight up; the dot product is just a sum, so more dimensions means more terms piling on.
d = 4 : change = 0.04 (small).
d = 150528 : change = 1505.28 (enormous).
The "per-dimension-imperceptible" version. If instead we shrink each move to ϵ / d (so the whole L 2 size stays fixed at ϵ ), the total is ∑ i d ϵ ⋅ 1 = d ϵ . For ϵ = 0.01 , d = 150528 : 150528 ≈ 388.0 , times 0.01 ≈ 3.88 .
Why this step? This is the headline of the parent note: even with a fixed, tiny total budget, the achievable loss change scales as d — the curse of dimensionality, turned into a weapon.
Verify: d ϵ at d = 4 is 0.04 ✓; at d = 150528 is 1505.28 ✓. 150528 ϵ ≈ 3.88 ✓ (vs a mere 0.02 for d = 4 ).
Worked example Ex 8 — Cell J (the
8/255 budget in real RGB units)
An RGB pixel channel is an integer 0 –255 . A standard robustness benchmark uses ϵ = 8/255 on inputs normalized to [ 0 , 1 ] . A particular channel reads 200/255 and its loss-gradient sign there is + 1 . What is the attacked value, in both [ 0 , 1 ] and 0 –255 units?
Forecast: 8/255 ≈ 0.0314 , so the value climbs by about 3% — visually invisible.
Convert the budget to [ 0 , 1 ] units. ϵ = 8/255 ≈ 0.03137 .
Why this step? The input lives on the normalized [ 0 , 1 ] scale, so the budget must be expressed on that same scale before we add anything.
Apply the FGSM step (one pixel). normalized value = 200/255 + 0.03137 = 0.7843 + 0.0314 = 0.8157 .
Why this step? Sign + 1 means push up by the full budget; add ϵ to the current normalized value.
Convert back to 0 –255 units. 0.8157 × 255 = 208 , i.e. 208/255 . So the channel goes 200 → 208 — a change of exactly 8 levels.
Why this step? Multiplying a normalized value by 255 returns the integer intensity; confirming the move is exactly 8 levels shows the budget does what it advertises.
Verify: in [ 0 , 1 ] units the answer is 208/255 ≈ 0.8157 ; in 0 –255 units it is 208 . Check: 200/255 + 8/255 = 208/255 ✓ exactly; ∥ δ ∥ ∞ = 8/255 ≈ 0.0314 = ϵ ✓. A shift of 8 out of 255 is below human perception, yet enough to flip a classifier — that is why this budget is the field's default.
Worked example Ex 9 — Cell K (
L 2 optimum is NOT the sign)
Recall the ==L 2 norm== is the ordinary Euclidean length ∥ δ ∥ 2 = ∑ i δ i 2 ; bounding it by ϵ carves out a ball (circle in 2-D) of radius ϵ , not a square box. Under this L 2 budget, what is the loss-maximizing δ ? Use gradient ∇ x L = ( 3 , 4 ) and ϵ = 1 .
Forecast: for L ∞ we used the sign . For L 2 the optimal move points exactly along the gradient , scaled to length ϵ — a different vector. Guess whether the two answers match.
State the optimum for L 2 . Maximizing δ ⊤ ∇ x L with ∥ δ ∥ 2 ≤ ϵ is solved (Cauchy–Schwarz) by aligning δ with ∇ x L : δ = ϵ ∥ ∇ x L ∥ 2 ∇ x L .
Why this step? Cauchy–Schwarz says δ ⊤ g ≤ ∥ δ ∥ 2 ∥ g ∥ 2 , with equality only when δ is parallel to g . So keep the magnitude ratios of the gradient — the opposite of FGSM which discards them.
Compute the norm. ∥ ( 3 , 4 ) ∥ 2 = 9 + 16 = 25 = 5 .
Why this step? We need the gradient's length to rescale it to exactly ϵ ; dividing by its own length makes a unit vector.
Plug in. δ = 1 ⋅ 5 ( 3 , 4 ) = ( 0.6 , 0.8 ) .
Why this step? Multiplying the unit gradient by ϵ = 1 gives the longest legal move along the gradient direction — the L 2 -optimal perturbation.
Compare to the L ∞ /sign answer. sign ( 3 , 4 ) = ( 1 , 1 ) ; scaling that to L 2 length 1 gives ( 0.707 , 0.707 ) — a different direction . The two balls give genuinely different attacks.
Why this step? It makes the exam point concrete: the shape of the budget (box vs ball) decides the optimal move, so you cannot blindly reuse the sign rule.
Verify: ∥ ( 0.6 , 0.8 ) ∥ 2 = 0.36 + 0.64 = 1 = 1 = ϵ ✓. Loss change = ( 0.6 ) ( 3 ) + ( 0.8 ) ( 4 ) = 1.8 + 3.2 = 5.0 = ∥ ∇ x L ∥ 2 ⋅ ϵ ✓ (equals the Cauchy–Schwarz bound, so it is truly optimal). Sign-based ( 0.707 , 0.707 ) would give 0.707 ( 3 ) + 0.707 ( 4 ) = 4.95 < 5.0 — strictly worse under L 2 , confirming the norm choice changes the answer.
Figure s04 (sketch it yourself): axes "delta 1" and "delta 2". Draw a teal L 2 circle of radius 1 and a plum dashed L ∞ square of half-width 1 . An ink arrow points along the gradient ( 3 , 4 ) . The orange L 2 -optimal dot sits on the circle at ( 0.6 , 0.8 ) (on the gradient line); the plum "sign, rescaled" dot sits at ( 0.707 , 0.707 ) — clearly not on the gradient line, showing the two attacks differ.
Recall Self-test
FGSM under L ∞ uses which function of the gradient? ::: sign — direction only, magnitude discarded.
sign ( 0 ) equals? ::: 0 — that pixel does not move.
What does ∥ δ ∥ ∞ measure? ::: The largest single-pixel move, max i ∣ δ i ∣ .
What does clip ( z , lo , hi ) do? ::: Returns max ( lo , min ( z , hi )) — squashes z into [ lo , hi ] .
Targeted FGSM uses plus or minus ϵ sign ? ::: Minus — we descend the target-class loss.
In PGD, what does the step size α satisfy and why? ::: α < ϵ , so no single step can jump the whole budget; the attack creeps and corrects course.
In PGD, what does the clip/projection step guarantee? ::: The perturbation stays within the ϵ -ball around the original x (and often within valid pixel range).
Under an L 2 budget, the optimal δ points along what? ::: The gradient ∇ x L itself, scaled to length ϵ (not its sign).
Why does high d help the attacker? ::: Aligned per-pixel nudges accumulate; loss change grows like ϵ d under a fixed L 2 budget.
Mnemonic One line to remember it all
"Sign for the square box, gradient for the ball; clip to stay inside; minus if you have a target in mind."
See also: Gradient descent optimization (the same ∇ x L machinery, but PGD ascends the input not the weights), Neural network training , Out-of-distribution detection , Interpretability and explainability , and the framing in AI Safety fundamentals and Reward hacking .