RealCorrectness #
Real-valued autograd correctness layer (proof-only).
This file does not talk about calculus (HasFDerivAt) yet. Instead it proves the standard
reverse-mode / forward-mode adjointness law (aka VJP/JVP duality) for a core set of ops:
$$ \left\langle \operatorname{JVP}(x,dx),\delta\right\rangle =\left\langle dx,\operatorname{VJP}(x,\delta)\right\rangle. $$
where $\langle\cdot,\cdot\rangle$ is the tensor dot product (sum of elementwise products).
This law is preserved by Spec.OpSpec.compose: composing local JVPs and VJPs preserves their
adjointness. Analytic reverse-mode correctness also requires a proof that each local JVP
differentiates its forward map at the relevant point. With those derivative facts and their domain
hypotheses, the chain rule identifies the composed JVP with the derivative of the composed forward
map, and adjointness identifies the composed VJP with its adjoint. The separate HasFDerivAt proofs
provide this extra evidence for the operations and domains they cover.
Why this file exists (and why there is a second “algebraic” file) #
We keep two correctness developments:
NN/Proofs/Autograd/Core/RealCorrectness.lean(this file) specializes toℝand is the home for rules whose definitions/proofs genuinely depend on real-analytic structure (e.g. smooth activations andexp/log-style ops).NN/Proofs/Autograd/Core/SemiringCorrectness.leanis backend-generic over a typeαwith[CommSemiring α]. It is meant to instantiate to exact backends likeℚ, so it avoids assuming division, order, or transcendental functions unless an op explicitly requires them.
Keeping them separate prevents importing analysis-heavy assumptions into the semiring-generic proofs and keeps compilation dependencies smaller.
Technical difference #
- This file uses the
Spec.dot/Tensortheory fromNN/Proofs/Tensor/Basic.lean(specialized toℝ). - The semiring-generic file uses
TensorAlgebra.dotfromNN/Proofs/Tensor/Algebra.leanand keeps all statements polymorphic inαwith[CommSemiring α].
Runtime note #
- The runtime engine in
NN.Runtime.Autograd.Engineremains generic overαand works whenever the needed ops exist. Relating a concrete backend to these $\mathbb R$-proofs may require a separate semantic model (e.g. mapping toℝwith rounding error bounds for NeuralFloat).
PyTorch correspondence / citations #
- PyTorch AD background and conventions (VJP in reverse-mode): https://pytorch.org/docs/stable/autograd.html
- Custom VJP rules are analogous to implementing
torch.autograd.Function: https://pytorch.org/docs/stable/autograd.html#torch.autograd.Function
References (background):
- Baydin et al., “Automatic Differentiation in Machine Learning: a Survey”, JMLR 2018
(originally circulated as
arXiv:1502.05767). - Griewank & Walther, Evaluating Derivatives (2nd ed.), SIAM 2008 (reverse-mode AD foundations).
VJP/JVP adjointness for a unary op σ → τ.
Instances For
An OpSpec together with a matching JVP and a proof of VJP/JVP adjointness.
This is the “proved-correct local op” interface needed to build a sound reverse-mode tape.
- op : Spec.OpSpec ℝ σ τ
The underlying real-valued op (forward map and VJP).
- jvp : TorchLean.Tensor ℝ σ → TorchLean.Tensor ℝ σ → TorchLean.Tensor ℝ τ
The forward-mode derivative:
jvp x dxis the directional derivative ofop.forwardatxalongdx. Adjointness of
jvpandop.backwardunder the tensor dot product.
Instances For
Composition preserves VJP/JVP correctness (reverse-mode chain rule).
Informally: if $f$ and $g$ each satisfy the adjointness law, then $g\circ f$ does as well, with the composed JVP and the composed VJP.
Instances For
A reusable adjointness identity #
Most elementwise ops have JVP of the form $dx\odot f'(x)$ and VJP of the form $f'(x)\odot\delta$. The following lemma is the “commute elementwise factors under dot” fact that makes those proofs one-liners.
Correctness of ReLU’s backward rule.
PyTorch analogue: torch.nn.functional.relu / torch.relu with its standard VJP.
Instances For
Correctness of sigmoid’s backward rule.
PyTorch analogue: torch.sigmoid.
Instances For
Correctness of tanh’s backward rule.
PyTorch analogue: torch.tanh.
Instances For
Correctness of softplus’s backward rule.
PyTorch analogue: torch.nn.functional.softplus.
Instances For
Correctness of SiLU’s backward rule.
PyTorch analogue: torch.nn.functional.silu, equivalently $x\,\operatorname{sigmoid}(x)$.
Instances For
Correctness of tanh-approximate GELU's VJP/JVP adjointness rule.
This proves the linear-algebraic part of the gelu backward rule used by Transformer-style
feed-forward blocks: multiplying the upstream cotangent by the local derivative mask is adjoint to
multiplying the tangent by the same mask. The scalar calculus theorem for the full tanh
approximation is separated because it depends on a longer chain-rule proof through
tanh, sqrt, and the cubic inner polynomial.
PyTorch analogue: torch.nn.functional.gelu(..., approximate="tanh").
Instances For
Correctness of safeLog’s backward rule (a log with an $\varepsilon$ safeguard).
PyTorch analogue: typically implemented as torch.log(torch.clamp(x, min=ε)) (or similar).
Instances For
Correctness of a smooth absolute value’s backward rule (a differentiable approximation to |x|).
PyTorch analogue: a custom smooth abs implemented via $\sqrt{x^2+\varepsilon^2}$ or similar.
Instances For
Correctness of exp’s backward rule.
PyTorch analogue: torch.exp.
Instances For
Correctness of square's backward rule.
PyTorch analogue: torch.square; the local derivative is $2x$.
Instances For
Correctness of ELU's VJP/JVP adjointness rule.
This is the algebraic half of the argument: once a local derivative mask is chosen, the VJP
$\operatorname{elu}'(x)\odot\delta$ is adjoint to the JVP
$dx\odot\operatorname{elu}'(x)$. The analytic differentiability theorem lives in
Proofs.elu_deriv_correct, which correctly excludes the kink at 0 for arbitrary alpha.
PyTorch analogue: torch.nn.functional.elu.
Instances For
Correctness of sinh's backward rule.
PyTorch analogue: torch.sinh; the local derivative is cosh.
Instances For
Correctness of cosh's backward rule.
PyTorch analogue: torch.cosh; the local derivative is sinh.
Instances For
Correctness of log's backward rule.
PyTorch analogue: torch.log.
Instances For
Correctness of a linear layer’s backward rule (matrix–vector multiply).
PyTorch analogue: torch.nn.functional.linear restricted to the weight-only map.
Instances For
Correctness of sum (reduce-all) backward rule.
Informally, $\frac{d}{dx}\sum x=1$, so the VJP replicates the upstream scalar gradient into every entry.
PyTorch analogue: torch.sum (over all elements).