TorchLean API

NN.Proofs.Autograd.Tape.Ops.Norm.LayerNormAdjoint

LayerNorm JVP and VJP adjointness #

Spec.layerNormJvp is the forward-mode rule and Spec.layerNormBackward the reverse-mode rule shipped with Spec.layerNorm. This file proves that they are adjoint: pairing an input and parameter tangent with the JVP gives the same scalar as pairing the upstream gradient with the three backward outputs. LayerNormFDeriv identifies this JVP with the derivative of the actual specification for positive epsilon, then uses this pairing to prove that the backward rule is the adjoint derivative. The pairing itself is algebraic and allows any real epsilon.

The proof is entrywise. Both spec functions are unfolded to explicit matrix forms (rfl), every entry is rewritten as a real expression, and the per-row identity row_adjoint finishes with ring.

Entry lemmas #

Entries of a pointwise vector product.

Explicit matrix forms #

@[reducible, inline]

Row broadcast of a length-m vector to an m × n matrix.

Instances For

    1 / std, as computed by the spec.

    Instances For

      Spec.layerNormJvp with its axis, broadcast, and cast evidence spelled out.

      Instances For
        theorem Proofs.Autograd.LayerNorm.layerNormJvp_eq_mat {m n : } (hm : 0 < m) (hn : 0 < n) (x tangent : TorchLean.Tensor [m, n]) (gamma dgamma beta dbeta : TorchLean.Tensor [n]) (ε : ) :
        Spec.layerNormJvp hm hn x tangent gamma dgamma beta dbeta ε = layerNormJvpMat x tangent gamma dgamma dbeta ε

        Spec.layerNormJvp is layerNormJvpMat by unfolding.

        theorem Proofs.Autograd.LayerNorm.layerNormBackward_eq_mat {m n : } (hm : 0 < m) (hn : 0 < n) (x : TorchLean.Tensor [m, n]) (gamma : TorchLean.Tensor [n]) (grad : TorchLean.Tensor [m, n]) (ε : ) :
        Spec.layerNormBackward hm hn x gamma grad ε = layerNormBackwardMat x gamma grad ε

        Spec.layerNormBackward is layerNormBackwardMat by unfolding.

        The per-row identity #

        theorem Proofs.Autograd.LayerNorm.row_adjoint {n : } (t g xh γ : Fin n) (s : ) :
        j : Fin n, (s * (t j - (∑ k : Fin n, t k) / n - xh j * ((∑ k : Fin n, t k * xh k) / n)) * γ j + xh j * j + j) * g j = j : Fin n, t j * (s * (g j * γ j - (∑ k : Fin n, g k * γ k) / n - xh j * ((∑ k : Fin n, g k * γ k * xh k) / n))) + j : Fin n, j * (g j * xh j) + j : Fin n, j * g j

        Scalar adjointness of the LayerNorm rules on one row: s is the inverse standard deviation, xh the normalized row, γ the per-column scale.

        Adjointness #

        theorem Proofs.Autograd.LayerNorm.get2_layerNormJvpMat {m n : } (x tangent : TorchLean.Tensor [m, n]) (gamma dgamma dbeta : TorchLean.Tensor [n]) (h1 : Spec.Shape.NonemptyAxis 1 (Spec.Shape.dim m (Spec.Shape.dim n Spec.Shape.scalar))) (ε : ) (i : Fin m) (j : Fin n) :
        Spec.get2 (layerNormJvpMat x tangent gamma dgamma dbeta h1 ε) i j = (lnInvStd x h1 ε).getScalar i * (Spec.get2 tangent i j - (∑ k : Fin n, Spec.get2 tangent i k) / n - Spec.get2 (Norm.lnCentered x h1) i j * (lnInvStd x h1 ε).getScalar i * ((∑ k : Fin n, Spec.get2 tangent i k * (Spec.get2 (Norm.lnCentered x h1) i k * (lnInvStd x h1 ε).getScalar i)) / n)) * gamma.getScalar j + Spec.get2 (Norm.lnCentered x h1) i j * (lnInvStd x h1 ε).getScalar i * dgamma.getScalar j + dbeta.getScalar j

        Entries of the JVP output.

        theorem Proofs.Autograd.LayerNorm.get2_inputGradient {m n : } (x : TorchLean.Tensor [m, n]) (gamma : TorchLean.Tensor [n]) (grad : TorchLean.Tensor [m, n]) (h1 : Spec.Shape.NonemptyAxis 1 (Spec.Shape.dim m (Spec.Shape.dim n Spec.Shape.scalar))) (h0 : Spec.Shape.NonemptyAxis 0 (Spec.Shape.dim m (Spec.Shape.dim n Spec.Shape.scalar))) (ε : ) (i : Fin m) (j : Fin n) :
        Spec.get2 (layerNormBackwardMat x gamma grad h1 h0 ε).inputGradient i j = (lnInvStd x h1 ε).getScalar i * (Spec.get2 grad i j * gamma.getScalar j - (∑ k : Fin n, Spec.get2 grad i k * gamma.getScalar k) / n - Spec.get2 (Norm.lnCentered x h1) i j / (Norm.lnStd x h1 ε).getScalar i * ((∑ k : Fin n, Spec.get2 grad i k * gamma.getScalar k * (Spec.get2 (Norm.lnCentered x h1) i k / (Norm.lnStd x h1 ε).getScalar i)) / n))

        Entries of the backward input gradient.

        1 / std times centered is centered / std.

        theorem Proofs.Autograd.LayerNorm.layerNormJvp_layerNormBackward_adjoint {m n : } (hm : 0 < m) (hn : 0 < n) (x tangent gradOutput : TorchLean.Tensor [m, n]) (gamma dgamma beta dbeta : TorchLean.Tensor [n]) (ε : ) :
        Spec.dot (Spec.layerNormJvp hm hn x tangent gamma dgamma beta dbeta ε) gradOutput = Spec.dot tangent (Spec.layerNormBackward hm hn x gamma gradOutput ε).inputGradient + Spec.dot dgamma (Spec.layerNormBackward hm hn x gamma gradOutput ε).scaleGradient + Spec.dot dbeta (Spec.layerNormBackward hm hn x gamma gradOutput ε).biasGradient

        The LayerNorm reverse rule is adjoint to its forward differential.

        Pairing the input tangent and both parameter tangents with Spec.layerNormJvp gives the same scalar as pairing the upstream gradient with the three outputs of Spec.layerNormBackward.