Skip to main content
Open In Colab

The gradient of a neuron is proportional to its input

Start with a single neuron. It forms a weighted sum of its inputs and passes it through a sigmoid: z=iwixi+b,a=σ(z)=11+ez.z = \sum_i w_i x_i + b, \qquad a = \sigma(z) = \frac{1}{1+e^{-z}}. The partial derivative of the output with respect to a weight is awi=σ(z)xi=a(1a)xi.\frac{\partial a}{\partial w_i} = \sigma'(z)\, x_i = a(1-a)\, x_i . For any scalar loss LL on top, the chain rule gives Lwi=Laσ(z)δ  xi=δxi.\frac{\partial L}{\partial w_i} = \underbrace{\frac{\partial L}{\partial a}\,\sigma'(z)}_{\delta}\; x_i = \delta\, x_i . Two things to read off. The gradient of weight wiw_i is the input xix_i scaled by a single number δ\delta shared across all weights, so the gradient vector points along the input. And δ\delta carries σ(z)=a(1a)\sigma'(z) = a(1-a), which collapses toward zero when z|z| is large: a saturated neuron has a small gradient no matter how large the input is.
Output from cell 3

Extending to a fully connected ReLU layer

A fully connected layer applies z=Wx+bz = Wx + b and then a ReLU, a=ReLU(z)a = \mathrm{ReLU}(z). ReLU has derivative 1[z>0]\mathbb{1}[z>0], so ajWjk=1[zj>0]xk,ajbj=1[zj>0].\frac{\partial a_j}{\partial W_{jk}} = \mathbb{1}[z_j>0]\, x_k, \qquad \frac{\partial a_j}{\partial b_j} = \mathbb{1}[z_j>0]. With an upstream gradient g=L/ag = \partial L/\partial a and the gate m=1[z>0]m = \mathbb{1}[z>0], write δ=gm\delta = g \odot m. Then LW=δx(an outer product),Lb=δ.\frac{\partial L}{\partial W} = \delta\, x^\top \quad(\text{an outer product}), \qquad \frac{\partial L}{\partial b} = \delta . Every row of L/W\partial L/\partial W is the input vector xx scaled by one entry of δ\delta, so again the weight gradient points along the input. Keep an eye on the bias gradient, L/b=δ\partial L/\partial b = \delta: there is no factor of xx in it. That asymmetry returns later.
Output from cell 5

Controlling the input distribution with batch normalization

Because each layer’s weight gradient is the input scaled by δ\delta, the scale of the inputs feeding a layer sets the scale of its gradients. Batch normalization standardizes those values per feature across a mini-batch, x^=xμbatchσbatch2+ϵ,x~=γx^+β,\hat{x} = \frac{x - \mu_{\text{batch}}}{\sqrt{\sigma^2_{\text{batch}} + \epsilon}}, \qquad \tilde{x} = \gamma \hat{x} + \beta, with learnable scale γ\gamma and shift β\beta. This is the cheap, per-feature, differentiable relative of whitening: whitening removes all correlations by working with the full covariance matrix, while batch normalization only fixes the per-feature mean and variance (the diagonal). Place batch normalization before the ReLU. If the pre-activation is approximately Gaussian, then x~N(β,γ2)\tilde{x} \sim \mathcal{N}(\beta, \gamma^2) and ReLU(x~)\mathrm{ReLU}(\tilde{x}) is a rectified Gaussian: a spike of zeros plus the positive tail. The fraction of dead units is P(x~0)=Φ ⁣(βγ),P(\tilde{x} \le 0) = \Phi\!\left(-\frac{\beta}{\gamma}\right), so β/γ\beta/\gamma sets how much of the distribution the ReLU clips to zero.
Output from cell 7

Training and inference

Batch normalization behaves differently in the two phases. During training, each mini-batch is normalized with its own mean and variance, so the statistics a sample sees depend on the other samples in the batch. During inference you want the output for a given input to be fixed, so the layer instead uses running estimates of the mean and variance, accumulated as moving averages over the training batches. The learnable scale and shift are applied in both phases.

Where this intuition breaks down

The build above is the story usually told for batch normalization. Most of it is a useful heuristic rather than a theorem. This section keeps the parts that survive scrutiny and shows, with one short experiment each, where the rest fails.

The bias gradient does not scale with the input

The weight gradient carries a factor of xx; the bias gradient, L/b=δ\partial L/\partial b = \delta, does not. Hold the ReLU gate fixed (set b=0b=0 so scaling xx by a positive constant cannot flip any sign) and scale the input. The weight gradient scales with it; the bias gradient does not.

Standardizing is not Gaussianizing

Batch normalization fixes only the first two moments. A bimodal pre-activation, standardized, has mean 0\approx 0 and variance 1\approx 1 but is still bimodal: the “clipped Gaussian” picture is a central-limit approximation that becomes accurate only as the layer fan-in grows.
Output from cell 10

Batch normalization is not whitening

Per-feature standardization leaves the off-diagonal covariance untouched. Two strongly correlated pre-activations stay correlated after batch normalization, so the per-unit clipping picture ignores how units co-activate. Removing that correlation is exactly what whitening does, at a cost batch normalization avoids.

The clipping probability is learned, not enforced

Because γ\gamma and β\beta are trainable, batch normalization does not pin the distribution to N(0,1)\mathcal{N}(0,1). The affine step can reproduce any mean and variance, which means the dead fraction Φ(β/γ)\Phi(-\beta/\gamma) is something the network learns, not something the layer imposes.

What actually controls the gradient magnitude: scale invariance

The defensible version of “batch normalization controls the gradient” needs no Gaussian assumption. Batch normalization is invariant to the scale of the weights feeding it, BN(aWx)=BN(Wx)\mathrm{BN}(aWx) = \mathrm{BN}(Wx), so the forward pass ignores the weight scale and the gradient absorbs it inversely: L(aW)=1aLW.\frac{\partial L}{\partial (aW)} = \frac{1}{a}\,\frac{\partial L}{\partial W}. Large weights therefore produce proportionally smaller gradients, which decouples the effective step size from the parameter scale.

Why batch normalization actually helps

The motivation in this build, “the gradient depends on the input, so we must control the input distribution”, is the internal covariate shift argument from the original paper. Later work (Santurkar et al., 2018) showed batch normalization does not actually reduce covariate shift: injecting noise after batch normalization, which increases the shift, still trains well. The measured effect is a smoother loss landscape, with more predictive (Lipschitz) gradients, which is what lets you raise the learning rate. The figure below shows the gradient distribution at initialization is far better behaved with batch normalization than without. Histograms of gradients at initialization for a deep layer. With batch normalization the gradients concentrate around the mean; without it the distribution has heavy tails. Gradients at initialization: concentrated with batch normalization (left), heavy-tailed without (right).

What survives

  • The weight gradient really is proportional to the input, for a single neuron and for a fully connected ReLU layer.
  • The bias gradient is not: it depends on the input only through the ReLU gate.
  • “Batch normalization before ReLU controls a clipped Gaussian” is an approximation. It fixes two moments, assumes the rest is Gaussian (true only for wide layers), and leaves correlations in place, so it is not whitening.
  • The clipping probability Φ(β/γ)\Phi(-\beta/\gamma) is learned through the affine parameters, not imposed by the layer.
  • The claim that holds without a Gaussian assumption is scale invariance, BN(aWx)=BN(Wx)\mathrm{BN}(aWx)=\mathrm{BN}(Wx) with gradients scaling as 1/a1/a. The optimization benefit is landscape smoothing, not the removal of internal covariate shift.
  • Whether batch normalization sits before or after the ReLU is an empirical choice, not a theoretical requirement.

References

PyTorch reference