The rule is short: for one sample, the clipped objective has zero gradient only when r has already moved past the clip edge in the direction the advantage asks for.
| The objective is L = min(r·A, clip(r, 1−ε, 1+ε)·A), with r = π_θ(a | s) / π_θ_old(a | s). |
Why: the min always picks the more pessimistic term. The clipped term is constant outside [1−ε, 1+ε].
| So ε sets where the flat part starts, and the sign of A sets which side is flat. | A | only sets how steep the sloped part is. |
| The policy gradient goes through r: ∇_θ L = (∂L/∂r) · r · ∇_θ log π_θ(a | s). At the start of each update, r = 1 for every sample, so the first step is the plain policy gradient. The clip only takes effect in later epochs and minibatches, after r has drifted. |
I built a page to play with this: index.html. Open it with
open index.html # macOS; Linux: xdg-open index.html
It has sliders for ε, A, and r. It plots L(r) with both terms and shades the zero-gradient region, plots ∂L/∂r under it, and adds a map of the whole (r, A) plane. The “Try this” cards animate the key cases. You can also set a starting state in the URL, e.g. index.html?A=-1&r=1.6 (the “wrong way” case).