4.8. Numerical Stability and Initialization¶ Open the notebook in SageMaker Studio Lab
Thus far, every model that we have implemented required that we initialize its parameters according to some pre-specified distribution. Until now, we took the initialization scheme for granted, glossing over the details of how these choices are made. You might have even gotten the impression that these choices are not especially important. To the contrary, the choice of initialization scheme plays a significant role in neural network learning, and it can be crucial for maintaining numerical stability. Moreover, these choices can be tied up in interesting ways with the choice of the nonlinear activation function. Which function we choose and how we initialize parameters can determine how quickly our optimization algorithm converges. Poor choices here can cause us to encounter exploding or vanishing gradients while training. In this section, we delve into these topics with greater detail and discuss some useful heuristics that you will find useful throughout your career in deep learning.
4.8.1. Vanishing and Exploding Gradients¶
Consider a deep network with
If all the hidden variables and the input are vectors, we can write the
gradient of
In other words, this gradient is the product of
The risks posed by unstable gradients go beyond numerical representation. Gradients of unpredictable magnitude also threaten the stability of our optimization algorithms. We may be facing parameter updates that are either (i) excessively large, destroying our model (the exploding gradient problem); or (ii) excessively small (the vanishing gradient problem), rendering learning impossible as parameters hardly move on each update.
4.8.1.1. Vanishing Gradients¶
One frequent culprit causing the vanishing gradient problem is the
choice of the activation function
[19:57:04] src/base.cc:49: GPU context requested, but no GPUs found.
As you can see, the sigmoid’s gradient vanishes both when its inputs are large and when they are small. Moreover, when backpropagating through many layers, unless we are in the Goldilocks zone, where the inputs to many of the sigmoids are close to zero, the gradients of the overall product may vanish. When our network boasts many layers, unless we are careful, the gradient will likely be cut off at some layer. Indeed, this problem used to plague deep network training. Consequently, ReLUs, which are more stable (but less neurally plausible), have emerged as the default choice for practitioners.
4.8.1.2. Exploding Gradients¶
The opposite problem, when gradients explode, can be similarly vexing.
To illustrate this a bit better, we draw 100 Gaussian random matrices
and multiply them with some initial matrix. For the scale that we picked
(the choice of the variance
a single matrix [[ 2.2122064 1.1630787 0.7740038 0.4838046 ]
[ 1.0434403 0.29956347 1.1839255 0.15302546]
[ 1.8917114 -1.1688148 -1.2347414 1.5580711 ]
[-1.771029 -0.5459446 -0.45138445 -2.3556297 ]]
after multiplying 100 matrices [[ 3.4459747e+23 -7.8040759e+23 5.9973355e+23 4.5230040e+23]
[ 2.5275059e+23 -5.7240258e+23 4.3988419e+23 3.3174704e+23]
[ 1.3731275e+24 -3.1097129e+24 2.3897754e+24 1.8022945e+24]
[-4.4951091e+23 1.0180045e+24 -7.8232368e+23 -5.9000419e+23]]
a single matrix
tensor([[ 0.5930, -0.9607, 0.3428, -1.4570],
[-0.9675, 1.7427, -0.5067, -1.2196],
[-1.1508, 0.8833, -0.4733, 0.4984],
[-0.7384, 0.5001, 0.1382, -0.3808]])
after multiplying 100 matrices
tensor([[-3.3673e+24, 1.3732e+25, -6.4221e+24, -1.5688e+25],
[-3.1811e+27, 1.2973e+28, -6.0671e+27, -1.4821e+28],
[-1.0542e+27, 4.2992e+27, -2.0106e+27, -4.9116e+27],
[-1.4229e+27, 5.8027e+27, -2.7138e+27, -6.6294e+27]])
a single matrix
tf.Tensor(
[[ 1.2806058 -0.56058913 1.3834499 1.6276002 ]
[-1.5746655 -0.5485347 -0.10410738 -1.4066125 ]
[ 0.32219663 0.39856827 0.8961904 -1.2755852 ]
[-1.1672167 0.590858 -0.2693691 -0.46184957]], shape=(4, 4), dtype=float32)
after multiplying 100 matrices
[[-2.47881294e+24 -1.02315644e+24 -3.65571291e+24 2.11338294e+24]
[-7.21467653e+21 -2.97793460e+21 -1.06400874e+22 6.15107942e+21]
[ 7.32929898e+24 3.02524643e+24 1.08091303e+25 -6.24880343e+24]
[-7.86093463e+21 -3.24468478e+21 -1.15931785e+22 6.70206556e+21]]
4.8.1.3. Breaking the Symmetry¶
Another problem in neural network design is the symmetry inherent in
their parametrization. Assume that we have a simple MLP with one hidden
layer and two units. In this case, we could permute the weights
This is more than just a theoretical nuisance. Consider the
aforementioned one-hidden-layer MLP with two hidden units. For
illustration, suppose that the output layer transforms the two hidden
units into only one output unit. Imagine what would happen if we
initialized all of the parameters of the hidden layer as
4.8.2. Parameter Initialization¶
One way of addressing—or at least mitigating—the issues raised above is through careful initialization. Additional care during optimization and suitable regularization can further enhance stability.
4.8.2.1. Default Initialization¶
In the previous sections, e.g., in Section 3.3, we used a normal distribution to initialize the values of our weights. If we do not specify the initialization method, the framework will use a default random initialization method, which often works well in practice for moderate problem sizes.
4.8.2.2. Xavier Initialization¶
Let us look at the scale distribution of an output (e.g., a hidden
variable)
The weights
One way to keep the variance fixed is to set
This is the reasoning underlying the now-standard and practically
beneficial Xavier initialization, named after the first author of its
creators (). Typically, the Xavier
initialization samples weights from a Gaussian distribution with zero
mean and variance
Though the assumption for nonexistence of nonlinearities in the above mathematical reasoning can be easily violated in neural networks, the Xavier initialization method turns out to work well in practice.
4.8.2.3. Beyond¶
The reasoning above barely scratches the surface of modern approaches to parameter initialization. A deep learning framework often implements over a dozen different heuristics. Moreover, parameter initialization continues to be a hot area of fundamental research in deep learning. Among these are heuristics specialized for tied (shared) parameters, super-resolution, sequence models, and other situations. For instance, Xiao et al. demonstrated the possibility of training 10000-layer neural networks without architectural tricks by using a carefully-designed initialization method ().
If the topic interests you we suggest a deep dive into this module’s offerings, reading the papers that proposed and analyzed each heuristic, and then exploring the latest publications on the topic. Perhaps you will stumble across or even invent a clever idea and contribute an implementation to deep learning frameworks.
4.8.3. Summary¶
Vanishing and exploding gradients are common issues in deep networks. Great care in parameter initialization is required to ensure that gradients and parameters remain well controlled.
Initialization heuristics are needed to ensure that the initial gradients are neither too large nor too small.
ReLU activation functions mitigate the vanishing gradient problem. This can accelerate convergence.
Random initialization is key to ensure that symmetry is broken before optimization.
Xavier initialization suggests that, for each layer, variance of any output is not affected by the number of inputs, and variance of any gradient is not affected by the number of outputs.
4.8.4. Exercises¶
Can you design other cases where a neural network might exhibit symmetry requiring breaking besides the permutation symmetry in an MLP’s layers?
Can we initialize all weight parameters in linear regression or in softmax regression to the same value?
Look up analytic bounds on the eigenvalues of the product of two matrices. What does this tell you about ensuring that gradients are well conditioned?
If we know that some terms diverge, can we fix this after the fact? Look at the paper on layerwise adaptive rate scaling for inspiration ().