TorchLean API

NN.Examples.BugZoo.NormalizationState

BugZoo: normalization state and BatchNorm contracts #

BatchNorm is a small formula with a surprisingly large bug surface. Cross-backend testing work found real library bugs around normalization formulas and backend conventions, including epsilon placement in BatchNorm. Model-generation testing also found BatchNormalization failures involving wrong moving statistics and NaN-producing outputs.

References:

TorchLean addresses this class in two layers:

noncomputable def NN.Examples.BugZoo.NormalizationState.wrongEpsilonOutsideSqrt (x mean variance gamma beta epsilon : ) :

The buggy BatchNorm pattern reported by cross-backend testing is easy to state: putting epsilon outside the square root changes the formula from

$$ \frac{x-\mu}{\sqrt{\sigma^2+\varepsilon}} $$

to

$$ \frac{x-\mu}{\sqrt{\sigma^2}+\varepsilon}. $$

The separating example below uses zero variance and epsilon four.

Instances For
    noncomputable def NN.Examples.BugZoo.NormalizationState.correctEpsilonInsideSqrt (x mean variance gamma beta epsilon : ) :

    The intended scalar BatchNorm expression. This mirrors the public TorchLean normalization spec: epsilon is added to the variance before the square root.

    Instances For

      At variance zero and epsilon four, the misplaced epsilon divides by four instead of two.

      Spec-level BatchNorm uses epsilon inside the variance term.

      There is one extra implementation detail worth making explicit: sqrtSpec is total, so it computes $\sqrt{\max(\mathrm{variance}+\varepsilon,0)}$. On the usual BatchNorm path, variance is nonnegative and epsilon is positive, so this is the same mathematical formula as $\sqrt{\mathrm{variance}+\varepsilon}$.

      Running statistics are part of the BatchNorm inference contract.

      The exact running mean and variance are arguments to the spec, so a reviewer can identify which state the result uses. Their shape does not establish that they are current or came from the intended training run; that provenance remains a separate obligation.

      • mean : TorchLean.Tensor [channels]

        Inference-time running mean, usually learned/updated during training.

      • variance : TorchLean.Tensor [channels]

        Inference-time running variance, clamped by the spec before normalization.

      Instances For
        noncomputable def NN.Examples.BugZoo.NormalizationState.batchNormEvalWithStats {channels : } {sSpatial : Spec.Shape} (x : TorchLean.Tensor (sSpatial.prependDim channels)) (stats : RunningStats channels) (gamma beta : TorchLean.Tensor [channels]) (epsilon : := TorchLean.normalizationEpsilon) :
        TorchLean.Tensor (sSpatial.prependDim channels)

        Evaluation-time BatchNorm with state packaged as an explicit value.

        Instances For
          theorem NN.Examples.BugZoo.NormalizationState.batchNormEvalWithStats_unfolds {channels : } {sSpatial : Spec.Shape} (x : TorchLean.Tensor (sSpatial.prependDim channels)) (stats : RunningStats channels) (gamma beta : TorchLean.Tensor [channels]) (epsilon : := TorchLean.normalizationEpsilon) :
          batchNormEvalWithStats x stats gamma beta epsilon = Spec.batchNormInference x stats.mean stats.variance gamma beta epsilon

          The packaged-state wrapper is exactly the public inference-time BatchNorm spec.

          theorem NN.Examples.BugZoo.NormalizationState.batchNormEvalWithStats_affine {channels : } {sSpatial : Spec.Shape} (stats : RunningStats channels) (gamma beta : TorchLean.Tensor [channels]) (epsilon : := TorchLean.normalizationEpsilon) :
          ∃ (scale : TorchLean.Tensor (sSpatial.prependDim channels)) (bias : TorchLean.Tensor (sSpatial.prependDim channels)), ∀ (x : TorchLean.Tensor (sSpatial.prependDim channels)), batchNormEvalWithStats x stats gamma beta epsilon = (x.mulSpec scale).addSpec bias

          Fixed BatchNorm running statistics determine one scale and bias that work for every input.

          The witnesses depend only on the running statistics, affine parameters, and epsilon. This is the uniform affine representation needed when folding inference-time normalization into another layer.

          theorem NN.Examples.BugZoo.NormalizationState.batchNormEvalWithStats_is_affine {channels : } {sSpatial : Spec.Shape} (x : TorchLean.Tensor (sSpatial.prependDim channels)) (stats : RunningStats channels) (gamma beta : TorchLean.Tensor [channels]) (epsilon : := TorchLean.normalizationEpsilon) :
          ∃ (scale : TorchLean.Tensor (sSpatial.prependDim channels)) (bias : TorchLean.Tensor (sSpatial.prependDim channels)), batchNormEvalWithStats x stats gamma beta epsilon = (x.mulSpec scale).addSpec bias

          Specialize the shared affine representation to one input.