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 n has a feature row xn and a target yn, and its loss is
ℓn(w,b)=21(xn⋅w+b−yn)2Let gn be the gradient of ℓn with respect to both parameters, and let ∥gn∥ be its L2 norm taken over all D + 1 entries together, the D weight entries and the bias entry. With C equal to max_norm, each gradient is clipped to
gˉn=max(1,∥gn∥/C)gnand the result is the mean of gˉn over the N examples. Here x has shape (N, D) with rows xn 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∥ before clipping.
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]}
jax.vmap(jax.grad(loss), in_axes=(None, 0, 0)) gives one gradient per example.
jnp.linalg.norm(g, axis=-1) or jnp.sqrt(jnp.sum(g ** 2, axis=...)) gives each example's norm.
factor[:, None] broadcasts an (N,) scale against (N, D) gradients.
Accepts: object
Accepts: array
Accepts: array
Accepts: number
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 n has a feature row xn and a target yn, and its loss is
ℓn(w,b)=21(xn⋅w+b−yn)2Let gn be the gradient of ℓn with respect to both parameters, and let ∥gn∥ be its L2 norm taken over all D + 1 entries together, the D weight entries and the bias entry. With C equal to max_norm, each gradient is clipped to
gˉn=max(1,∥gn∥/C)gnand the result is the mean of gˉn over the N examples. Here x has shape (N, D) with rows xn 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∥ before clipping.
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]}
jax.vmap(jax.grad(loss), in_axes=(None, 0, 0)) gives one gradient per example.
jnp.linalg.norm(g, axis=-1) or jnp.sqrt(jnp.sum(g ** 2, axis=...)) gives each example's norm.
factor[:, None] broadcasts an (N,) scale against (N, D) gradients.
Accepts: object
Accepts: array
Accepts: array
Accepts: number