Batch normalization forward and backward

ImplementHard45 min15 checks

batch-normnormalizationgradientsbackpropagation

Problem

Batch normalization normalizes each feature over the examples of a mini-batch. Then it scales and shifts each feature with two learned vectors. In training, it uses the statistics of the batch and updates running averages. In inference, it uses only the running averages. You write the forward pass for both modes and the backward pass for training mode.

Task

Write two functions.

  1. batchnorm_forward(x, gamma, beta, running_mean, running_var, momentum=0.1, eps=1e-5, training=True) returns (out, cache, new_running_mean, new_running_var).
  2. batchnorm_backward(grad_output, cache) returns (dx, dgamma, dbeta).

In training mode, compute for each feature column j over the batch of N rows:

\mu_j = \frac{1}{N} \sum_i x_{ij}, \quad \sigma^2_j = \frac{1}{N} \sum_i (x_{ij} - \mu_j)^2
\hat{x}_{ij} = \frac{x_{ij} - \mu_j}{\sqrt{\sigma^2_j + \epsilon}}, \quad \text{out}_{ij} = \gamma_j \hat{x}_{ij} + \beta_j

The variance is the biased variance. It divides by N, not by N - 1. The running statistics also use this biased variance:

\text{new mean} = (1 - m) \cdot \text{running mean} + m \cdot \mu, \quad \text{new var} = (1 - m) \cdot \text{running var} + m \cdot \sigma^2

Here m is momentum.

In inference mode (training=False), use running_mean and running_var in place of \mu and \sigma^2. Return copies of the running statistics without a change. The cache in inference mode can be None.

batchnorm_backward gets the gradient of the loss with respect to out and the cache from a training mode call. It returns the gradients of the loss with respect to x, gamma and beta. The gradient dx must include the effect of x on \mu and on \sigma^2.

The cache is your own choice. The checks pass the cache from your forward pass to your backward pass and do not read it.

Input and output

NameTypeShapeMeaning
xfloat array(N, D)the batch, one row for each example, one column for each feature
gammafloat array(D,)the scale of each feature
betafloat array(D,)the shift of each feature
running_meanfloat array(D,)the running mean before this call
running_varfloat array(D,)the running variance before this call
momentumfloatthe weight of the batch statistics, from 0 to 1
epsfloatthe small number added to the variance inside the square root
trainingboolTrue for training mode, False for inference mode
grad_outputfloat array(N, D)the gradient of the loss with respect to out
  • batchnorm_forward returns a tuple (out, cache, new_running_mean, new_running_var). out has shape (N, D). The two running arrays have shape (D,).
  • batchnorm_backward returns a tuple (dx, dgamma, dbeta) with shapes (N, D), (D,) and (D,).

Constraints

  • 1 <= N <= 64 and 1 <= D <= 32.
  • A column can be constant. Its variance is then 0.
  • Do not change any input array. Return new arrays for the running statistics.
  • Use numpy only.

Examples

pythonx = np.array([[1.0, 2.0], [3.0, 6.0], [5.0, 10.0]])
gamma = np.array([1.0, 0.5])
beta = np.array([0.0, 1.0])
out, cache, mean, var = batchnorm_forward(x, gamma, beta, np.zeros(2), np.ones(2))
dx, dgamma, dbeta = batchnorm_backward(np.array([[1.0, 0.0], [0.0, 1.0], [1.0, 1.0]]), cache)
textout
[[-1.22474258  0.38762785]
 [ 0.          1.        ]
 [ 1.22474258  1.61237215]]
mean
[0.3 0.6]
var
[1.16666667 1.96666667]
dx
[[ 0.20412376 -0.02551558]
 [-0.40824753  0.05103101]
 [ 0.20412376 -0.02551543]]
dgamma
[0.        1.2247443]
dbeta
[2. 2.]
pythonout, cache, mean, var = batchnorm_forward(np.array([[2.0, 4.0]]), gamma, beta, np.array([0.3, 0.6]), np.array([1.16666667, 1.96666667]), training=False)
textout
[[1.57388742 2.21222277]]
cache
None

Hints

4 hints

    Solution and notes

    Locked

    Pass every check with Submit to open the reference solution and the notes.

    Run it on your computer

    Clone the repository, install numpy and run the same checks in a terminal:

    python3 scripts/practice/run.py batch-norm my_answer.py
    python3 scripts/practice/run.py batch-norm my_answer.py --examples

    Start my_answer.py from starter.py.

    Your code

    Python loads on the first run

    Your code is saved in this browser as you type. On a phone you can read and edit the code, but the checks are easier to use on a desktop.

    Keyboard shortcuts
    Ctrl Enter
    Run the examples
    Ctrl Shift Enter
    Submit
    Tab / Shift Tab
    Indent or outdent the lines
    Esc then Tab
    Move the focus out of the editor
    Alt H
    Show the next hint

    On a Mac, use Cmd in place of Ctrl.

    Select Run to check the examples, or Submit to run every check.