Type at least 2 letters. Enter opens the first result, Esc closes.

    Calculus for ML · Lesson 9 · Second-order and implicit derivatives

    The implicit function theorem and gradients through solvers

    Advanced 70 min 4 interactive figures 4 videos Colab notebook

    Before this lesson: lesson 04 (the chain rule as a product of Jacobians), lesson 05 (JVP and VJP, why reverse mode brackets the product from the loss side) and lesson 08 (matrix-free products such as HVPs). From linear algebra: lesson 03 (inverse, "solve, do not invert"), lesson 13 (conditioning) and lesson 14 (CG and GMRES). Time: about 70 minutes, plus the notebook.


    Why this matters #

    • Deep equilibrium models (DEQs) find a fixed point z∗=f(z∗,x;θ)z^* = f(z^*, x; \theta) and train with an implicit gradient, so memory does not grow with the number of solver iterations (Bai, Kolter and Koltun 2019).
    • Bilevel optimization. Hyperparameter tuning and meta-learning have an inner problem w∗(λ)=arg⁡min⁡ww^*(\lambda) = \arg\min_w (training loss) and an outer loss on validation data. The hypergradient dw∗/dλdw^*/d\lambda comes from the optimality condition of the inner problem (Lorraine, Vicol and Duvenaud 2020; implicit MAML, Rajeswaran et al. 2019).
    • Optimization layers. OptNet (Amos and Kolter 2017) differentiates the solution of a quadratic program through its optimality (KKT) conditions.
    • ML for science. A discretized steady PDE R(s,m)=0R(s, m) = 0 links a state ss (pressure, a wavefield) to parameters mm (permeability, wave speed). The adjoint method gives the gradient of a misfit with respect to millions of parameters for one extra linear solve. It is the same theorem.

    1. Predict first #

    2. The picture #

    One dimension: the slope of a curve you never solve #

    The equation x2−θ=0x^2 - \theta = 0 with x>0x > 0 defines x(θ)=θx(\theta) = \sqrt\theta. Now forget the formula θ\sqrt\theta. When θ\theta moves by dθd\theta, the solution must move by dxdx so that F(x,θ)=x2−θF(x, \theta) = x^2 - \theta stays zero. To first order, FF changes by

    dF=Fx dx+Fθ dθ,Fx=∂F∂x=2x,Fθ=∂F∂θ=−1.dF = F_x\, dx + F_\theta\, d\theta, \qquad F_x = \frac{\partial F}{\partial x} = 2x, \quad F_\theta = \frac{\partial F}{\partial \theta} = -1 .

    Set dF=0dF = 0 and solve for the ratio:

    dxdθ=−FθFx=12x.\frac{dx}{d\theta} = -\frac{F_\theta}{F_x} = \frac{1}{2x}.

    At θ=4\theta = 4, x=2x = 2, so dx/dθ=1/4dx/d\theta = 1/4. This equals ddθθ=1/(2θ)\frac{d}{d\theta}\sqrt\theta = 1/(2\sqrt\theta), but we used only FF and its partial derivatives at the solution.

    Where it fails. At θ=0\theta = 0 the solution is x=0x = 0, so Fx=0F_x = 0. There the two branches ±θ\pm\sqrt\theta meet, the tangent of the curve is vertical, and for θ<0\theta < 0 there is no real solution. Such a point is a fold. The condition Fx≠0F_x \ne 0 rules out exactly this situation.

    Interactive figure: loading…

    Drag the violet point along the curve F(x,θ)=0F(x, \theta) = 0 (horizontal axis θ\theta, vertical axis xx). The blue line has the implicit slope −Fθ/Fx-F_\theta/F_x. The orange secant joins the solutions at θ±h\theta \pm h, found by Newton's method from the current xx. They agree everywhere except near a fold, where Fx→0F_x \to 0, the tangent turns vertical and the secant has no second point. Try the S-shaped cubic: it has three solutions for some θ\theta, and each branch has its own derivative.

    The linear case in nn dimensions #

    Let F(x,θ)=Ax−BθF(x, \theta) = Ax - B\theta with an invertible A∈Rn×nA \in \R^{n\times n} and B∈Rn×pB \in \R^{n\times p}. Then x∗=A−1Bθx^* = A^{-1}B\theta and dx∗/dθ=A−1Bdx^*/d\theta = A^{-1}B. Here Fx=AF_x = A and Fθ=−BF_\theta = -B, so dx∗/dθ=−Fx−1Fθdx^*/d\theta = -F_x^{-1}F_\theta. Near a solution, a smooth nonlinear FF behaves like its linear approximation, so the same formula holds locally. That is the implicit function theorem.

    Fixed points: a feedback loop #

    Let x=f(x,θ)x = f(x, \theta), and write fx=∂f/∂x∈Rn×nf_x = \partial f/\partial x \in \R^{n\times n} and fθ=∂f/∂θ∈Rn×pf_\theta = \partial f/\partial\theta \in \R^{n\times p} at the fixed point. A change dθd\theta moves xx directly by fθ dθf_\theta\, d\theta. That move goes through ff again and moves xx by fxf_x times it, and so on:

    dx=fθ dθ+fxfθ dθ+fx2fθ dθ+⋯=(I−fx)−1fθ dθ.dx = f_\theta\, d\theta + f_x f_\theta\, d\theta + f_x^2 f_\theta\, d\theta + \cdots = (I - f_x)^{-1} f_\theta\, d\theta .

    This Neumann series converges when the spectral radius ρ(fx)\rho(f_x) (the largest ∣eigenvalue∣|\text{eigenvalue}|) is below 1. Each solver iteration adds one term. The implicit derivative is the whole sum.

    Interactive figure: loading…

    Move θ\theta and watch the cobweb. The iteration xk+1=f(xk,θ)x_{k+1} = f(x_k, \theta) walks between the curve y=f(x,θ)y = f(x, \theta) and the diagonal y=xy = x, and stops at the fixed point. The dashed curve is f(⋅,θ+0.3)f(\cdot, \theta + 0.3): its fixed point moved by about 0.3⋅fθ/(1−fx)0.3 \cdot f_\theta/(1 - f_x). The readout compares this implicit slope with the derivative of the KK-step iteration (unrolled). For f=(x2+θ)/4f = (x^2 + \theta)/4, the upper fixed point repels the iteration, but the implicit formula still gives its slope.

    Argmins: a minimizer is a root #

    If x∗(θ)x^*(\theta) minimizes a smooth function h(x,θ)h(x, \theta) over xx, then ∇xh(x∗,θ)=0\nabla_x h(x^*, \theta) = 0. So the argmin is a root of F=∇xhF = \nabla_x h, and FxF_x is the Hessian ∇xx2h\nabla^2_{xx} h. Everything above applies.

    Quick check

    The equation x2−θ=0x^2 - \theta = 0 with x>0x > 0 defines x∗(θ)x^*(\theta). Use only the partial derivatives of FF: what is dx∗/dθdx^*/d\theta at θ=9\theta = 9?

    3. Definitions and main results #

    Notation. F:Rn×Rp→RnF: \R^n \times \R^p \to \R^n (as many equations as unknowns). Fx=∂F/∂x∈Rn×nF_x = \partial F/\partial x \in \R^{n\times n} and Fθ=∂F/∂θ∈Rn×pF_\theta = \partial F/\partial\theta \in \R^{n\times p} are the partial Jacobians. Dx∗(θ)∈Rn×pDx^*(\theta) \in \R^{n\times p} is the Jacobian of the solution map θ↦x∗(θ)\theta \mapsto x^*(\theta). A map is C1C^1 if it is differentiable with continuous derivatives.

    3.1 The implicit function theorem #

    Theorem (implicit function theorem). Let FF be C1C^1 near (x0,θ0)(x_0, \theta_0), with F(x0,θ0)=0F(x_0, \theta_0) = 0 and Fx(x0,θ0)F_x(x_0, \theta_0) invertible. Then there are open sets U∋θ0U \ni \theta_0 and V∋x0V \ni x_0 and a unique map x∗:U→Vx^*: U \to V such that, for every θ∈U\theta \in U, x∗(θ)x^*(\theta) is the only solution of F(x,θ)=0F(x, \theta) = 0 in VV. The map x∗x^* is C1C^1, x∗(θ0)=x0x^*(\theta_0) = x_0, and

    Dx∗(θ)=−Fx(x∗(θ),θ)−1 Fθ(x∗(θ),θ).Dx^*(\theta) = -F_x\big(x^*(\theta), \theta\big)^{-1}\, F_\theta\big(x^*(\theta), \theta\big).

    Proof of the derivative formula (given that x∗x^* exists and is C1C^1).

    1. For every θ∈U\theta \in U, ϕ(θ):=F(x∗(θ),θ)=0\phi(\theta) := F(x^*(\theta), \theta) = 0. A function that is zero everywhere has derivative zero: Dϕ(θ)=0D\phi(\theta) = 0.
    2. ϕ\phi is the composition θ↦(x∗(θ),θ)↦F\theta \mapsto (x^*(\theta), \theta) \mapsto F. The chain rule (lesson 04) gives Dϕ=Fx Dx∗+FθD\phi = F_x\, Dx^* + F_\theta.
    3. So Fx Dx∗=−FθF_x\, Dx^* = -F_\theta.
    4. FxF_x is invertible at (x0,θ0)(x_0, \theta_0). Its determinant is continuous, so it stays nonzero on a smaller UU. Multiply on the left by Fx−1F_x^{-1}. ■\blacksquare

    Shapes: (n×n)−1(n×p)=n×p(n\times n)^{-1}(n\times p) = n\times p. The formula uses only FF at the solution. It does not care how x∗x^* was found.

    Why the solution exists and is unique (sketch)
    1. Define Ψ(x,θ)=(F(x,θ),θ)\Psi(x, \theta) = (F(x, \theta), \theta), a map from Rn×Rp\R^n\times\R^p to itself.
    2. Its Jacobian is block triangular, (FxFθ0I)\begin{pmatrix} F_x & F_\theta \\ 0 & I \end{pmatrix}, with determinant det⁡Fx≠0\det F_x \ne 0 at (x0,θ0)(x_0, \theta_0).
    3. By the inverse function theorem, Ψ\Psi has a C1C^1 inverse near Ψ(x0,θ0)=(0,θ0)\Psi(x_0, \theta_0) = (0, \theta_0).
    4. The solution is the first block of Ψ−1(0,θ)\Psi^{-1}(0, \theta). It is C1C^1 because Ψ−1\Psi^{-1} is, and it is unique near x0x_0 because Ψ\Psi is one-to-one there (Blondel and Roulet, §11.3.4). ■\blacksquare

    Fixed points. For x∗=f(x∗,θ)x^* = f(x^*, \theta), set F(x,θ)=x−f(x,θ)F(x, \theta) = x - f(x, \theta). Then Fx=I−fxF_x = I - f_x and Fθ=−fθF_\theta = -f_\theta, so

    Dx∗=(I−fx)−1fθ.Dx^* = (I - f_x)^{-1} f_\theta .

    The condition is that I−fxI - f_x is invertible, that is, 1 is not an eigenvalue of fxf_x. A contraction (∥fx∥<1\|f_x\| < 1 in some induced norm) is enough, but it is not necessary: a repelling fixed point also has a derivative (worked example (b)).

    Argmins. For x∗(θ)=arg⁡min⁡xh(x,θ)x^*(\theta) = \arg\min_x h(x, \theta) with h∈C2h \in C^2, set F=∇xhF = \nabla_x h:

    Dx∗=−(∇xx2h)−1 ∇xθ2h,Dx^* = -\big(\nabla^2_{xx} h\big)^{-1}\, \nabla^2_{x\theta} h ,

    where ∇xθ2h∈Rn×p\nabla^2_{x\theta} h \in \R^{n\times p} holds the mixed partials ∂2h/∂xi∂θj\partial^2 h/\partial x_i \partial\theta_j. It needs an invertible Hessian at x∗x^*, for example hh strongly convex in xx.

    Quick check

    A fixed point x∗=f(x∗,θ)x^* = f(x^*, \theta) in one dimension has fx=0.9f_x = 0.9 and fθ=1f_\theta = 1 at x∗x^*. What is dx∗/dθdx^*/d\theta?

    3.2 The VJP form: one adjoint solve #

    Training needs the gradient of a scalar L(θ)=ℓ(x∗(θ),θ)L(\theta) = \ell(x^*(\theta), \theta), not the n×pn\times p Jacobian. Let xˉ=∇xℓ(x∗,θ)∈Rn\bar x = \nabla_x \ell(x^*, \theta) \in \R^n be the upstream gradient, and ∂θℓ∈Rp\partial_\theta \ell \in \R^p the direct dependence of ℓ\ell on θ\theta (often zero).

    Proposition (adjoint form). Let u∈Rnu \in \R^n solve Fx⊤u=xˉF_x^\top u = \bar x. Then ∇θL=∂θℓ−Fθ⊤u\nabla_\theta L = \partial_\theta \ell - F_\theta^\top u.

    Proof.

    1. Chain rule: ∇θL=∂θℓ+(Dx∗)⊤xˉ\nabla_\theta L = \partial_\theta \ell + (Dx^*)^\top \bar x.
    2. Insert the theorem: (Dx∗)⊤xˉ=−Fθ⊤Fx−⊤xˉ(Dx^*)^\top \bar x = -F_\theta^\top F_x^{-\top} \bar x, where Fx−⊤=(Fx⊤)−1F_x^{-\top} = (F_x^\top)^{-1}.
    3. Bracket from the right, as reverse mode does (lesson 05): u=Fx−⊤xˉu = F_x^{-\top}\bar x, that is, uu solves Fx⊤u=xˉF_x^\top u = \bar x.
    4. Then (Dx∗)⊤xˉ=−Fθ⊤u(Dx^*)^\top \bar x = -F_\theta^\top u: one VJP of θ↦F(x∗,θ)\theta \mapsto F(x^*, \theta) with cotangent uu. ■\blacksquare

    Cost. Forming Dx∗Dx^* needs pp solves with FxF_x (one per column of FθF_\theta) and stores npnp numbers. The adjoint form needs one solve with Fx⊤F_x^\top and one VJP, for any pp.

    Matrix-free solves. The products v↦Fx⊤vv \mapsto F_x^\top v are VJPs of FF in xx, so a Krylov solver finds uu without forming FxF_x (linear-algebra lesson 14). Use conjugate gradient (CG) when FxF_x is symmetric positive definite. This is the case for the argmin of a strongly convex hh, where each product is an HVP of hh (lesson 08). Otherwise use GMRES or BiCGSTAB.

    Fixed points. The adjoint system is (I−fx)⊤u=xˉ(I - f_x)^\top u = \bar x, and ∇θL=∂θℓ+fθ⊤u\nabla_\theta L = \partial_\theta \ell + f_\theta^\top u. When ff is a contraction, the plain iteration

    u←xˉ+fx⊤uu \leftarrow \bar x + f_x^\top u

    converges to uu, with one VJP of ff per step. Its rate is the spectral radius of fxf_x, the same as the forward iteration, because fx⊤f_x^\top and fxf_x have the same eigenvalues.

    Interactive figure: loading…

    Move KK (the number of solver iterations) and the contraction. The chart shows three errors on a log scale: the forward error ∣xK−x∗∣|x_K - x^*| (grey), the error of the unrolled gradient (backprop through KK steps) and the error of the implicit gradient evaluated at xKx_K. Both gradients improve geometrically; the implicit one is about as accurate as the forward solve. The bars show the memory: unrolling stores KK iterates, the implicit gradient stores one point.

    3.3 Unrolled versus implicit #

    Unrolling runs xk+1=f(xk,θ)x_{k+1} = f(x_k, \theta) for KK steps and backpropagates through all of them. If the iteration starts at the fixed point (x0=x∗x_0 = x^*, so every xk=x∗x_k = x^*), the chain rule gives dxK/dθ=∑j=0K−1fxjfθdx_K/d\theta = \sum_{j=0}^{K-1} f_x^j f_\theta: the first KK terms of the Neumann series. The missing tail is fxK(I−fx)−1fθf_x^K (I - f_x)^{-1} f_\theta, so the error shrinks like ρK\rho^K, where ρ\rho is the spectral radius of fxf_x. From another start the error also decays geometrically (in worked example (b) it is proportional to KρKK\rho^K).

    Unrolled (backprop through KK steps) Implicit (theorem at x∗x^*)
    What it differentiates the KK-step algorithm, exactly the solution map θ↦x∗(θ)\theta \mapsto x^*(\theta)
    Memory all KK iterates and the intermediates of every step: grows like KK x∗x^* and one graph of ff at x∗x^*: independent of KK
    Backward cost KK VJPs of one step one linear solve (some VJPs of FF in xx) plus one VJP in θ\theta
    Error against the true Dx∗Dx^* truncation (about ρK\rho^K) plus the forward error proportional to the forward error ∥x^−x∗∥\lVert\hat x - x^*\rVert, plus the error of the adjoint solve
    Needs a differentiable solver FF differentiable at x∗x^* and FxF_x invertible; any forward solver

    Accuracy of the implicit gradient. In practice you apply the formula at an approximate solution x^\hat x. Blondel et al. (2022, Theorem 1) show: if FxF_x is well conditioned near x∗x^*, FxF_x and FθF_\theta are Lipschitz there, and FθF_\theta is bounded at x∗x^*, then the Jacobian estimate at x^\hat x has error at most C ∥x^−x∗∥C\,\|\hat x - x^*\|. So the gradient is about as accurate as the forward solve. The constant CC grows as the smallest singular value of FxF_x shrinks, that is, as FxF_x gets close to singular (linear-algebra lesson 13).

    When unrolling is the right choice. When you want the gradient of what you actually computed: a few inner steps by design (MAML-style adaptation, learned optimizers), or a solution that is not unique or not smooth.

    Quick check

    A DEQ layer reaches its fixed point in K=50K = 50 iterations. Compared with backpropagation through the 50 iterations, the implicit gradient needs memory that…

    3.4 Ridge regression: a hyperparameter gradient #

    The inner problem is h(w,λ)=12∥Xw−y∥2+λ2∥w∥2h(w, \lambda) = \frac12\|Xw - y\|^2 + \frac{\lambda}{2}\|w\|^2 with X∈RN×dX \in \R^{N\times d}, y∈RNy \in \R^N and λ>0\lambda > 0. Its optimality condition is

    F(w,λ)=X⊤(Xw−y)+λw=0.F(w, \lambda) = X^\top(Xw - y) + \lambda w = 0 .

    The partial Jacobians are Fw=X⊤X+λI=:AλF_w = X^\top X + \lambda I =: A_\lambda (symmetric positive definite) and Fλ=wF_\lambda = w (a d×1d\times1 column). The theorem gives

    dw∗dλ=−Aλ−1w∗.\frac{dw^*}{d\lambda} = -A_\lambda^{-1} w^* .

    For a validation loss V(w∗(λ))V(w^*(\lambda)) with wˉ=∇wV(w∗)\bar w = \nabla_w V(w^*), the adjoint form gives dV/dλ=−w∗⊤udV/d\lambda = -w^{*\top} u with Aλu=wˉA_\lambda u = \bar w (here Aλ⊤=AλA_\lambda^\top = A_\lambda). One solve, and no closed form of w∗(λ)w^*(\lambda) is needed, only its optimality condition.

    Corollary (the norm shrinks). ddλ12∥w∗∥2=w∗⊤dw∗dλ=−w∗⊤Aλ−1w∗<0\frac{d}{d\lambda}\frac12\|w^*\|^2 = w^{*\top}\frac{dw^*}{d\lambda} = -w^{*\top}A_\lambda^{-1}w^* < 0 whenever w∗≠0w^* \ne 0, because Aλ−1≻0A_\lambda^{-1} \succ 0 (linear-algebra lesson 07).

    Interactive figure: loading…

    Drag log⁡10λ\log_{10}\lambda with the slider. Top: the validation loss VV against log⁡10λ\log_{10}\lambda with the tangent line whose slope is the hypergradient from one linear solve. Bottom: the weights wi∗(λ)w^*_i(\lambda) and the norm ∥w∗∥\|w^*\|. Notice that ∥w∗∥\|w^*\| always falls as λ\lambda grows, but a single weight can rise. Press Hypergradient step to take gradient-descent steps on log⁡λ\log\lambda.

    Envelope theorem: when no solve is needed

    If the outer loss is the optimal value itself, v(θ)=min⁡xh(x,θ)v(\theta) = \min_x h(x, \theta), then ∇v(θ)=∂θh(x∗,θ)\nabla v(\theta) = \partial_\theta h(x^*, \theta). The implicit term (Dx∗)⊤∇xh(Dx^*)^\top \nabla_x h vanishes because ∇xh(x∗,θ)=0\nabla_x h(x^*, \theta) = 0, so no solve is needed. This is Danskin's theorem (Blondel and Roulet §11.2). It is why the gradient of a log-partition function or of a dual objective is simple.

    Answers to section 1. (1) Unrolled memory grows linearly in KK: every iterate and the intermediates of every evaluation of ff are stored. Yes: the theorem gives the exact gradient from z∗z^* alone, with one adjoint solve (I−fz)⊤u=∇ℓ(z∗)(I - f_z)^\top u = \nabla\ell(z^*) and one VJP fθ⊤uf_\theta^\top u; memory does not depend on KK. (2) Not every weight: in worked example (c), w2∗=0w_2^* = 0 at λ=1\lambda = 1 and dw2∗/dλ=+1/8dw_2^*/d\lambda = +1/8, so ∣w2∗∣|w_2^*| grows. But ∥w∗∥\|w^*\| always shrinks (the corollary).

    4. Worked example #

    (a) A 2-D root. Two unknowns x=(x1,x2)x = (x_1, x_2) and one parameter θ\theta:

    F(x,θ)=(x1+x22−θx1x2−1).F(x, \theta) = \begin{pmatrix} x_1 + x_2^2 - \theta \\ x_1 x_2 - 1 \end{pmatrix}.

    At θ=2\theta = 2, x=(1,1)x = (1, 1) is a root: F=(1+1−2,  1−1)=(0,0)F = (1 + 1 - 2,\; 1 - 1) = (0, 0).

    1. Partial Jacobians: Fx=(12x2x2x1)=(1211)F_x = \begin{pmatrix} 1 & 2x_2 \\ x_2 & x_1 \end{pmatrix} = \begin{pmatrix} 1 & 2 \\ 1 & 1 \end{pmatrix}, with det⁡Fx=1−2=−1≠0\det F_x = 1 - 2 = -1 \ne 0, so the theorem applies. Fθ=(−1,0)⊤F_\theta = (-1, 0)^\top.
    2. Fx−1=1−1(1−2−11)=(−121−1)F_x^{-1} = \frac{1}{-1}\begin{pmatrix} 1 & -2 \\ -1 & 1 \end{pmatrix} = \begin{pmatrix} -1 & 2 \\ 1 & -1 \end{pmatrix}.
    3. Dx∗=−Fx−1Fθ=Fx−1(1,0)⊤=(−1,1)⊤Dx^* = -F_x^{-1}F_\theta = F_x^{-1}(1, 0)^\top = (-1, 1)^\top.
    4. Check without the theorem: x2=1/x1x_2 = 1/x_1 gives x1+1/x12=θx_1 + 1/x_1^2 = \theta. Then dθ/dx1=1−2/x13=−1d\theta/dx_1 = 1 - 2/x_1^3 = -1 at x1=1x_1 = 1, so dx1/dθ=−1dx_1/d\theta = -1, and dx2/dθ=−x1−2 dx1/dθ=1dx_2/d\theta = -x_1^{-2}\, dx_1/d\theta = 1. ✓
    5. Prediction: at θ=2.1\theta = 2.1, x≈(1,1)+0.1 (−1,1)=(0.9,1.1)x \approx (1, 1) + 0.1\,(-1, 1) = (0.9, 1.1). The exact root is (0.9209,1.0858)(0.9209, 1.0858). The error, about 0.020.02, is second order in dθ=0.1d\theta = 0.1.
    6. Where it fails: det⁡Fx=x1−2x22\det F_x = x_1 - 2x_2^2. On the curve x2=1/x1x_2 = 1/x_1 it is zero when x13=2x_1^3 = 2, that is at x1=21/3≈1.26x_1 = 2^{1/3} \approx 1.26 and θ=3⋅2−2/3≈1.89\theta = 3 \cdot 2^{-2/3} \approx 1.89. There the branch through (1,1)(1, 1) meets a second branch (at θ=2\theta = 2 its root is x1=(1+5)/2≈1.618x_1 = (1 + \sqrt5)/2 \approx 1.618, with dx1/dθ≈+1.89dx_1/d\theta \approx +1.89). The theorem is local: each branch has its own derivative.

    (b) A fixed point and its unrolled gradient. f(x,θ)=(x2+θ)/4f(x, \theta) = (x^2 + \theta)/4 at θ=3\theta = 3. The fixed points solve x=(x2+3)/4x = (x^2 + 3)/4, that is x2−4x+3=0x^2 - 4x + 3 = 0: x∗=1x^* = 1 and x∗=3x^* = 3.

    1. At x∗=1x^* = 1: fx=x/2=1/2f_x = x/2 = 1/2 and fθ=1/4f_\theta = 1/4, so dx∗/dθ=(1/4)/(1−1/2)=1/2dx^*/d\theta = (1/4)/(1 - 1/2) = 1/2. Check: x∗(θ)=2−4−θx^*(\theta) = 2 - \sqrt{4 - \theta} has derivative 1/(24−θ)=1/21/(2\sqrt{4 - \theta}) = 1/2 at θ=3\theta = 3. ✓
    2. At x∗=3x^* = 3: fx=3/2>1f_x = 3/2 > 1, so the iteration moves away from this point. But 1−fx=−1/2≠01 - f_x = -1/2 \ne 0, and the theorem gives dx∗/dθ=(1/4)/(−1/2)=−1/2dx^*/d\theta = (1/4)/(-1/2) = -1/2 (check: 2+4−θ2 + \sqrt{4 - \theta} has derivative −1/2-1/2). The theorem needs invertibility, not a contraction.
    3. At θ=4\theta = 4 the two fixed points merge at x=2x = 2, where fx=1f_x = 1 and 1−fx=01 - f_x = 0: the theorem fails.
    4. Unrolled, started at x0=x∗=1x_0 = x^* = 1: dxK/dθ=14(1+12+⋯+12K−1)=12(1−2−K)dx_K/d\theta = \frac14\big(1 + \frac12 + \cdots + \frac{1}{2^{K-1}}\big) = \frac12(1 - 2^{-K}). Started at x0=0x_0 = 0, forward-mode differentiation of the KK-step map gives the second row:
    KK 1 2 5 10 20
    start at x∗x^* 0.25 0.375 0.484 0.49951 0.4999995
    start at 00 0.25 0.344 0.465 0.49797 0.4999961

    The implicit answer 0.50.5 costs one division. Unrolling needs about 20 steps, and 20 stored iterates, for 5–6 correct digits.

    (c) A ridge hypergradient. Three training samples, two features, λ=1\lambda = 1: X=(111001)X = \begin{pmatrix} 1 & 1 \\ 1 & 0 \\ 0 & 1 \end{pmatrix}, y=(1,2,0)y = (1, 2, 0). One validation sample xval=(0,1)x_{\text{val}} = (0, 1), yval=1y_{\text{val}} = 1, so V=12(xval⊤w∗−yval)2=12(w2∗−1)2V = \frac12(x_{\text{val}}^\top w^* - y_{\text{val}})^2 = \frac12(w_2^* - 1)^2.

    1. X⊤X=(2112)X^\top X = \begin{pmatrix} 2 & 1 \\ 1 & 2 \end{pmatrix} and X⊤y=(1+2,  1+0)=(3,1)X^\top y = (1 + 2,\; 1 + 0) = (3, 1).
    2. A1=X⊤X+I=(3113)A_1 = X^\top X + I = \begin{pmatrix} 3 & 1 \\ 1 & 3 \end{pmatrix}, with det⁡A1=8\det A_1 = 8 and A1−1=18(3−1−13)A_1^{-1} = \frac18\begin{pmatrix} 3 & -1 \\ -1 & 3 \end{pmatrix}.
    3. Optimality: A1w∗=(3,1)A_1 w^* = (3, 1) gives w∗=18(9−1,  −3+3)=(1,0)w^* = \frac18(9 - 1,\; -3 + 3) = (1, 0).
    4. dw∗/dλ=−A1−1w∗=−18(3,−1)=(−3/8,  1/8)dw^*/d\lambda = -A_1^{-1}w^* = -\frac18(3, -1) = (-3/8,\; 1/8).
    5. Forward route: wˉ=∇wV=(0,  w2∗−1)=(0,−1)\bar w = \nabla_w V = (0,\; w_2^* - 1) = (0, -1), so dV/dλ=wˉ⊤dw∗/dλ=−1/8dV/d\lambda = \bar w^\top dw^*/d\lambda = -1/8.
    6. Adjoint route: solve A1u=wˉA_1 u = \bar w: u=18(1,−3)u = \frac18(1, -3). Then dV/dλ=−w∗⊤u=−1/8dV/d\lambda = -w^{*\top}u = -1/8. ✓
    7. dV/dλ<0dV/d\lambda < 0, so increasing λ\lambda lowers the validation loss.
    8. The norm: ddλ12∥w∗∥2=w∗⊤(−3/8, 1/8)=−3/8<0\frac{d}{d\lambda}\frac12\|w^*\|^2 = w^{*\top}(-3/8,\, 1/8) = -3/8 < 0, while w2∗w_2^* grows.
    9. Check with the closed form w∗(λ)=(3λ+5,  λ−1)/((λ+1)(λ+3))w^*(\lambda) = \big(3\lambda + 5,\; \lambda - 1\big)/\big((\lambda + 1)(\lambda + 3)\big): its derivative at λ=1\lambda = 1 is (−3/8,1/8)(-3/8, 1/8). ✓

    5. In code #

    NumPy and SciPy check the numbers of section 4. The solver is a black box; the derivative comes from the equation at the solution.

    import numpy as np
    from scipy.optimize import fsolve
    
    # (a) 2-D root: implicit Jacobian vs finite differences of a black-box solver
    F = lambda x, t: [x[0] + x[1]**2 - t, x[0] * x[1] - 1]
    root = lambda t: fsolve(F, [1.0, 1.0], args=(t,), xtol=1e-13)
    x = root(2.0)
    Fx, Ft = np.array([[1, 2 * x[1]], [x[1], x[0]]]), np.array([-1.0, 0.0])
    h = 1e-5
    print(-np.linalg.solve(Fx, Ft), (root(2 + h) - root(2 - h)) / (2 * h))   # [-1. 1.] [-1. 1.]
    print(root(2.1))                                          # [0.92094247 1.08584415]
    
    # (b) fixed point x = (x^2 + t)/4 at t = 3: unrolled derivative by forward mode, from x0 = 0
    def unrolled(t, K, x=0.0, dx=0.0):
        for _ in range(K):
            x, dx = (x * x + t) / 4, (2 * x * dx + 1) / 4    # dx_{k+1} = f_x dx_k + f_t
        return dx
    print([round(unrolled(3.0, K), 7) for K in (1, 2, 5, 10, 20)])
    # [0.25, 0.34375, 0.4650059, 0.4979725, 0.4999961]   -> implicit: (1/4)/(1 - 1/2) = 0.5
    
    # (c) ridge hypergradient with one solve
    X, y = np.array([[1.0, 1.0], [1.0, 0.0], [0.0, 1.0]]), np.array([1.0, 2.0, 0.0])
    lam = 1.0
    A = X.T @ X + lam * np.eye(2)
    w = np.linalg.solve(A, X.T @ y)
    wbar = np.array([0.0, w[1] - 1.0])                        # gradient of V = (w2 - 1)^2 / 2
    u = np.linalg.solve(A, wbar)                              # adjoint solve (A is symmetric)
    print(w, -np.linalg.solve(A, w), -w @ u)                  # [1. 0.] [-0.375 0.125] -0.125
    

    In PyTorch you attach the implicit gradient to a solver with a custom backward. The forward pass runs the solver without recording a graph; the backward pass solves the adjoint equation at x∗x^*:

    import torch
    
    class FixedPoint(torch.autograd.Function):
        """x* = f(x*, theta) for f(x, theta) = (x^2 + theta) / 4, with an implicit backward."""
        @staticmethod
        def forward(ctx, theta):
            x = torch.zeros_like(theta)
            for _ in range(200):                  # any solver; no graph is recorded here
                x = (x * x + theta) / 4
            ctx.save_for_backward(x)
            return x
    
        @staticmethod
        def backward(ctx, xbar):
            (x,) = ctx.saved_tensors
            f_x, f_theta = x / 2, 0.25            # partial derivatives of f at x*
            u = xbar / (1 - f_x)                  # adjoint solve (I - f_x)^T u = xbar
            return f_theta * u                    # f_theta^T u
    
    theta = torch.tensor(3.0, dtype=torch.float64, requires_grad=True)
    x = FixedPoint.apply(theta)
    x.backward()
    print(x.item(), theta.grad.item())            # 1.0 0.5
    

    In JAX, jax.lax.custom_root and the library JAXopt (Blondel et al. 2022) do the same for roots and optimality conditions.

    6. Where it shows up #

    • Deep equilibrium models. A DEQ layer finds z∗=f(z∗,x;θ)z^* = f(z^*, x; \theta) with Broyden or Anderson iterations and trains with the implicit VJP, so memory does not grow with the number of iterations. Cheaper variants truncate the adjoint solve or set u=zˉu = \bar z ("Jacobian-free backprop"); their gradients are approximate by design (deep learning).
    • Bilevel optimization. Lorraine, Vicol and Duvenaud (2020) tune millions of hyperparameters with a truncated Neumann series of HVPs for the inverse Hessian. Implicit MAML (Rajeswaran et al. 2019) solves the adjoint system with CG on HVPs.
    • Optimization layers. OptNet differentiates the KKT conditions of a quadratic program. For a loss s+rs + r with smooth ss and non-smooth rr (an ℓ1\ell_1 penalty), the proximal-gradient fixed point x=prox⁡ηr(x−η∇s(x))x = \operatorname{prox}_{\eta r}(x - \eta\nabla s(x)) serves as the equation (optimization).
    • Matrix identities. d(X−1)=−X−1 dX X−1d(X^{-1}) = -X^{-1}\, dX\, X^{-1} (check yourself 2) and the VJP of a linear solve are the theorem applied to XY−I=0XY - I = 0 and to Ax−b=0Ax - b = 0 (linear-algebra lesson 16).
    • ML for science. For a discretized steady PDE R(s,m)=0R(s, m) = 0, the gradient of a misfit with respect to all parameters mm costs one adjoint solve with (∂R/∂s)⊤(\partial R/\partial s)^\top: for example one Helmholtz system per source and frequency in frequency-domain full-waveform inversion. An implicit time step (backward Euler for stiff terms) is a root problem, differentiated the same way. The time-continuous case is the adjoint method for ODEs, used by neural ODEs (Chen et al. 2018; ML for science).

    7. Common mistakes #

    • Differentiating an unconverged solution. The formula assumes F(x^,θ)=0F(\hat x, \theta) = 0. Check the forward residual first; the gradient error is about proportional to ∥x^−x∗∥\|\hat x - x^*\|.
    • Forgetting the transpose. The adjoint solve uses Fx⊤F_x^\top. It equals FxF_x only when FxF_x is symmetric, as for an argmin (a Hessian). For a DEQ, I−fxI - f_x is not symmetric.
    • Sign errors in the fixed-point form. With F=x−fF = x - f: Dx∗=+(I−fx)−1fθDx^* = +(I - f_x)^{-1} f_\theta and ∇θL=∂θℓ+fθ⊤u\nabla_\theta L = \partial_\theta \ell + f_\theta^\top u. If ℓ\ell depends on θ\theta directly, do not drop ∂θℓ\partial_\theta \ell.
    • Letting autograd record the solver. Then you pay unrolled memory anyway and get the unrolled gradient. Run the solver without a graph (torch.no_grad()), evaluate ff once at x∗x^* with a graph for the VJPs, and attach the implicit gradient in a custom backward.
    • Using the theorem where it does not hold. FxF_x singular or nearly singular (folds and bifurcations), non-unique minimizers (ridge with λ=0\lambda = 0 and rank-deficient XX), or FF not differentiable at x∗x^* (a ReLU kink, a constraint that becomes active).
    • The plain adjoint iteration without a contraction. u←xˉ+fx⊤uu \leftarrow \bar x + f_x^\top u does not converge when the spectral radius of fxf_x is ≥1\ge 1. Use GMRES instead.

    8. Check yourself #

    1. The circle x2+θ2=1x^2 + \theta^2 = 1 defines x(θ)x(\theta) near (x,θ)=(0.6,0.8)(x, \theta) = (0.6, 0.8). Find dx/dθdx/d\theta with the theorem. Where on the circle does it fail for xx as a function of θ\theta?
      AnswerFx=2x=1.2F_x = 2x = 1.2 and Fθ=2θ=1.6F_\theta = 2\theta = 1.6, so dx/dθ=−1.6/1.2=−4/3dx/d\theta = -1.6/1.2 = -4/3 (check: x=1−θ2x = \sqrt{1 - \theta^2} gives −θ/x=−0.8/0.6-\theta/x = -0.8/0.6). It fails at x=0x = 0, θ=±1\theta = \pm1: there Fx=0F_x = 0, the two branches ±1−θ2\pm\sqrt{1 - \theta^2} meet and the tangent is vertical.
    2. Derive d(X−1)d(X^{-1}) from the theorem.
      AnswerY=X−1Y = X^{-1} solves F(Y,X)=XY−I=0F(Y, X) = XY - I = 0. Differentiate: dX Y+X dY=0dX\,Y + X\,dY = 0, so dY=−X−1 dX X−1dY = -X^{-1}\,dX\,X^{-1}. The partial derivative in YY is the linear map dY↦X dYdY \mapsto X\,dY, which is invertible exactly when XX is.
    3. The fixed point x=0.8x+θx = 0.8x + \theta. Give dx∗/dθdx^*/d\theta, the unrolled derivative after KK steps from x0=0x_0 = 0, and the smallest KK with relative error below 1%.
      AnswerImplicit: 1/(1−0.8)=51/(1 - 0.8) = 5. Unrolled: xK=θ(1+0.8+⋯+0.8K−1)x_K = \theta(1 + 0.8 + \cdots + 0.8^{K-1}), so dxK/dθ=5(1−0.8K)dx_K/d\theta = 5(1 - 0.8^K) and the relative error is 0.8K0.8^K. 0.820≈0.01150.8^{20} \approx 0.0115 and 0.821≈0.00920.8^{21} \approx 0.0092, so K=21K = 21.
    4. x∗∈R1000x^* \in \R^{1000} and θ∈R106\theta \in \R^{10^6}. Compare forming Dx∗Dx^* with the adjoint route for ∇θℓ(x∗)\nabla_\theta \ell(x^*).
      AnswerDx∗=−Fx−1FθDx^* = -F_x^{-1}F_\theta has 10910^9 entries (8 GB in float64) and needs 10610^6 solves with FxF_x (one LU factorization, then 10610^6 pairs of triangular solves). The adjoint route needs one solve Fx⊤u=xˉF_x^\top u = \bar x and one VJP −Fθ⊤u-F_\theta^\top u, and stores nothing of size n×pn\times p.
    5. Show that ∥w∗(λ)∥\|w^*(\lambda)\| of ridge regression decreases in λ\lambda, and say why one coordinate can still grow.
      Answerddλ12∥w∗∥2=−w∗⊤Aλ−1w∗<0\frac{d}{d\lambda}\frac12\|w^*\|^2 = -w^{*\top}A_\lambda^{-1}w^* < 0 for w∗≠0w^* \ne 0, since Aλ−1≻0A_\lambda^{-1} \succ 0. The direction dw∗/dλ=−Aλ−1w∗dw^*/d\lambda = -A_\lambda^{-1}w^* has a negative inner product with w∗w^*, but the off-diagonal entries of Aλ−1A_\lambda^{-1} mix the coordinates, so a single coordinate can grow (worked example (c): dw2∗/dλ=+1/8dw_2^*/d\lambda = +1/8).
    6. The forward iteration x←f(x,θ)x \leftarrow f(x, \theta) converges with local rate 0.9 (the spectral radius of fxf_x at x∗x^*). Does the adjoint iteration u←xˉ+fx⊤uu \leftarrow \bar x + f_x^\top u converge, and how many steps does each extra correct digit cost?
      AnswerYes. Its iteration matrix fx⊤f_x^\top has the same eigenvalues as fxf_x, so the error shrinks by about 0.9 per step: ln⁡10/ln⁡(1/0.9)≈22\ln 10/\ln(1/0.9) \approx 22 steps per digit. A Krylov solver such as GMRES can need far fewer.
    Recall cardsAnswer in your head first, then reveal. Add the cards to your review deck to see them again just before you would forget.
    1. State the derivative formula of the implicit function theorem for F(x∗(θ),θ)=0F(x^*(\theta), \theta) = 0.

    2. What condition does the implicit function theorem need (besides F∈C1F \in C^1 and F(x0,θ0)=0F(x_0, \theta_0) = 0)?

    3. Derivative of a fixed point x∗=f(x∗,θ)x^* = f(x^*, \theta)?

    4. Compute dx∗/dθdx^*/d\theta for the fixed point of f(x,θ)=0.9x+θf(x, \theta) = 0.9x + \theta.

    5. How do you get ∇θL\nabla_\theta L for L=ℓ(x∗(θ))L = \ell(x^*(\theta)) without forming Dx∗Dx^*?

    6. Why does the implicit gradient need memory independent of the number of solver iterations KK?

    7. What is dw∗/dλdw^*/d\lambda for ridge regression?

    8. When is the implicit gradient inaccurate?

    9. Why can unrolling be the right choice?

    Open the review →

    9. Interview angle #

    • "How does a DEQ backpropagate with constant memory?" Implicit function theorem at z∗z^*: solve (I−fz)⊤u=zˉ(I - f_z)^\top u = \bar z with VJPs (fixed-point iteration or a Krylov method), then ∇θℓ=fθ⊤u\nabla_\theta \ell = f_\theta^\top u. Only z∗z^* is stored.
    • "How do you get the gradient of the validation loss with respect to weight decay without unrolling?" Differentiate the optimality condition: dw∗/dλ=−H−1w∗dw^*/d\lambda = -H^{-1}w^* with HH the training Hessian (for ridge, H=X⊤X+λIH = X^\top X + \lambda I), and get H−1wˉH^{-1}\bar w by CG on HVPs or a truncated Neumann series.
    • "What is the VJP of x=A−1bx = A^{-1}b?" Solve A⊤u=xˉA^\top u = \bar x; then bˉ=u\bar b = u and Aˉ=−u x⊤\bar A = -u\,x^\top.
    • "When would you unroll instead?" For the gradient of a few-step or early-stopped computation, or when the solution is not unique or not smooth.
    • "What happens at a fold?" FxF_x is singular, the derivative is infinite (vertical tangent) and two branches meet; near the fold the implicit gradient is ill-conditioned.

    10. Practice #

    The notebook for this lesson runs in Colab. Five exercises, each with a check cell and a folded solution:

    1. newton_root and implicit_jacobian for the 2-D system of worked example (a); check with finite differences.
    2. implicit_vjp: the adjoint solve with scipy.sparse.linalg.gmres and CG on a LinearOperator, for a system with 200 unknowns.
    3. fixed_point and fixed_point_vjp for a small DEQ-like layer; compare with the unrolled gradient for K=5,20,100K = 5, 20, 100.
    4. ridge_hypergradient on the diabetes data set (scikit-learn), then gradient descent on log⁡λ\log\lambda.
    5. The gradient of a softmax-regression solution with respect to its L2 weight, from the optimality condition.

    11. Watch and read #

    The one-dimensional picture of section 2: move along the curve so that F stays zero.
    Open on YouTube · the player loads from youtube-nocookie.com when you press play
    Roots, fixed points and optimality conditions as one framework, and the accuracy result of section 3.3.
    Open on YouTube · the player loads from youtube-nocookie.com when you press play
    Deep equilibrium models, fixed points and implicit backpropagation with constant memory.
    Open on YouTube · the player loads from youtube-nocookie.com when you press play
    The adjoint solve of section 3.2 for Ax=bAx = b, step by step.
    Open on YouTube · the player loads from youtube-nocookie.com when you press play