TensorTonic
Study Plans
Study Plan
Per-Example Gradient Clipping
JAX
Medium

Compute per-example gradients of a linear model, clip each one to a maximum norm and average the clipped gradients, as one step of DP-SGD does before it adds noise.

The model has a weight vector w and a scalar bias b, stored in the dict params under the keys w and b. Example nnn has a feature row xnx_nxn​ and a target yny_nyn​, and its loss is

ℓn(w,b)=12(xn⋅w+b−yn)2\ell_n(w, b) = \tfrac{1}{2}\big(x_n \cdot w + b - y_n\big)^2ℓn​(w,b)=21​(xn​⋅w+b−yn​)2

Let gng_ngn​ be the gradient of ℓn\ell_nℓn​ with respect to both parameters, and let ∥gn∥\lVert g_n \rVert∥gn​∥ be its L2 norm taken over all D + 1 entries together, the D weight entries and the bias entry. With CCC equal to max_norm, each gradient is clipped to

gˉn=gnmax⁡(1,∥gn∥/C)\bar g_n = \frac{g_n}{\max\big(1, \lVert g_n \rVert / C\big)}gˉ​n​=max(1,∥gn​∥/C)gn​​

and the result is the mean of gˉn\bar g_ngˉ​n​ over the N examples. Here x has shape (N, D) with rows xnx_nxn​ and y has shape (N,).

Return a dict with two keys. The value under grads is a dict with keys w and b holding the mean clipped gradient, w as a float32 JAX array of shape (D,) and b as a float32 JAX array of shape (). The value under norms is a float32 JAX array of shape (N,) holding ∥gn∥\lVert g_n \rVert∥gn​∥ before clipping.

Examples

Input: params = {"w":[1.0,-1.0],"b":0.0}, x = [[1.0,0.0],[2.0,2.0],[0.0,3.0]], y = [0.0,1.0,1.0], max_norm = 1.0

Output: {"grads":{"w":[0.01348,-0.53845],"b":0.019182},"norms":[1.414214,3.0,12.649111]}

Explanation: The first example has error 1 and gradient ([1, 0], 1) with norm 1.414214, so it is scaled down to length 1. The other two examples have norms 3 and 12.649111 and are scaled down too, and the three clipped gradients are then averaged.

Input: params = {"w":[0.5],"b":0.5}, x = [[1.0],[-1.0],[2.0],[0.0]], y = [1.5,0.5,1.0,0.0], max_norm = 10.0

Output: {"grads":{"w":[0.25],"b":0.0},"norms":[0.707107,0.707107,1.118034,0.5]}

Input: params = {"w":[2.0,1.0],"b":-1.0}, x = [[1.0,1.0],[0.5,-1.0]], y = [2.0,-4.0], max_norm = 2.0

Output: {"grads":{"w":[0.333333,-0.666667],"b":0.666667},"norms":[0.0,4.5]}

Hint 1

jax.vmap(jax.grad(loss), in_axes=(None, 0, 0)) gives one gradient per example.

Hint 2

jnp.linalg.norm(g, axis=-1) or jnp.sqrt(jnp.sum(g ** 2, axis=...)) gives each example's norm.

Hint 3

factor[:, None] broadcasts an (N,) scale against (N, D) gradients.

Requirements

  • Write the loss for a single example and get the per-example gradients by applying jax.vmap to jax.grad of it, mapping over the rows of x and y while sharing params. Solutions that do not call both transforms are rejected.
  • An example whose gradient is exactly zero must contribute zero without producing NaN.
  • Leave the params dict unchanged.

Constraints

  • params holds w, a float32 JAX array of shape (D,), and b, a float32 JAX array of shape ().
  • x is a float32 JAX array of shape (N, D) with N between 1 and 8 and D between 1 and 4.
  • y is a float32 JAX array of shape (N,).
  • max_norm is a positive Python float between 0.1 and 100.
Try Similar Problems
Hessian-Vector ProductMediumStraight-Through Estimator with Custom VJPMediumValue and Grad of a LossEasyPad and Mask to Bucket LengthMediumTraced Learning Rate ScheduleMediumExponential Moving Average with ScanMediumSpectral Norm by Power IterationMediumBatched Attention with vmapMediumPairwise Distances with Nested vmapMediumGlobal Norm Gradient ClippingMediumAdamW from ScratchMediumMixed Precision with Loss ScalingMedium

Accepts: object

Accepts: array

Accepts: array

Accepts: number

You must run your code first.
Per-Example Gradient Clipping

Per-Example Gradient Clipping

JAX
Medium

Compute per-example gradients of a linear model, clip each one to a maximum norm and average the clipped gradients, as one step of DP-SGD does before it adds noise.

The model has a weight vector w and a scalar bias b, stored in the dict params under the keys w and b. Example nnn has a feature row xnx_nxn​ and a target yny_nyn​, and its loss is

ℓn(w,b)=12(xn⋅w+b−yn)2\ell_n(w, b) = \tfrac{1}{2}\big(x_n \cdot w + b - y_n\big)^2ℓn​(w,b)=21​(xn​⋅w+b−yn​)2

Let gng_ngn​ be the gradient of ℓn\ell_nℓn​ with respect to both parameters, and let ∥gn∥\lVert g_n \rVert∥gn​∥ be its L2 norm taken over all D + 1 entries together, the D weight entries and the bias entry. With CCC equal to max_norm, each gradient is clipped to

gˉn=gnmax⁡(1,∥gn∥/C)\bar g_n = \frac{g_n}{\max\big(1, \lVert g_n \rVert / C\big)}gˉ​n​=max(1,∥gn​∥/C)gn​​

and the result is the mean of gˉn\bar g_ngˉ​n​ over the N examples. Here x has shape (N, D) with rows xnx_nxn​ and y has shape (N,).

Return a dict with two keys. The value under grads is a dict with keys w and b holding the mean clipped gradient, w as a float32 JAX array of shape (D,) and b as a float32 JAX array of shape (). The value under norms is a float32 JAX array of shape (N,) holding ∥gn∥\lVert g_n \rVert∥gn​∥ before clipping.

Examples

Input: params = {"w":[1.0,-1.0],"b":0.0}, x = [[1.0,0.0],[2.0,2.0],[0.0,3.0]], y = [0.0,1.0,1.0], max_norm = 1.0

Output: {"grads":{"w":[0.01348,-0.53845],"b":0.019182},"norms":[1.414214,3.0,12.649111]}

Explanation: The first example has error 1 and gradient ([1, 0], 1) with norm 1.414214, so it is scaled down to length 1. The other two examples have norms 3 and 12.649111 and are scaled down too, and the three clipped gradients are then averaged.

Input: params = {"w":[0.5],"b":0.5}, x = [[1.0],[-1.0],[2.0],[0.0]], y = [1.5,0.5,1.0,0.0], max_norm = 10.0

Output: {"grads":{"w":[0.25],"b":0.0},"norms":[0.707107,0.707107,1.118034,0.5]}

Input: params = {"w":[2.0,1.0],"b":-1.0}, x = [[1.0,1.0],[0.5,-1.0]], y = [2.0,-4.0], max_norm = 2.0

Output: {"grads":{"w":[0.333333,-0.666667],"b":0.666667},"norms":[0.0,4.5]}

Hint 1

jax.vmap(jax.grad(loss), in_axes=(None, 0, 0)) gives one gradient per example.

Hint 2

jnp.linalg.norm(g, axis=-1) or jnp.sqrt(jnp.sum(g ** 2, axis=...)) gives each example's norm.

Hint 3

factor[:, None] broadcasts an (N,) scale against (N, D) gradients.

Requirements

  • Write the loss for a single example and get the per-example gradients by applying jax.vmap to jax.grad of it, mapping over the rows of x and y while sharing params. Solutions that do not call both transforms are rejected.
  • An example whose gradient is exactly zero must contribute zero without producing NaN.
  • Leave the params dict unchanged.

Constraints

  • params holds w, a float32 JAX array of shape (D,), and b, a float32 JAX array of shape ().
  • x is a float32 JAX array of shape (N, D) with N between 1 and 8 and D between 1 and 4.
  • y is a float32 JAX array of shape (N,).
  • max_norm is a positive Python float between 0.1 and 100.
Try Similar Problems
Hessian-Vector ProductMediumStraight-Through Estimator with Custom VJPMediumValue and Grad of a LossEasyPad and Mask to Bucket LengthMediumTraced Learning Rate ScheduleMediumExponential Moving Average with ScanMediumSpectral Norm by Power IterationMediumBatched Attention with vmapMediumPairwise Distances with Nested vmapMediumGlobal Norm Gradient ClippingMediumAdamW from ScratchMediumMixed Precision with Loss ScalingMedium

Accepts: object

Accepts: array

Accepts: array

Accepts: number

You must run your code first.