在我们真正开始训练网络之前,我们必须要知道如何去初始化神经网络的参数。
Training your neural network requires specifying an initial value of the weights.
A well chosen initialization method will help learning.
我们先来看看三种不同的参数初始化方式:
[He initialization is named for the first author of He et al., 2015. If you have heard of "Xavier initialization", this is similar except Xavier initialization uses a scaling factor for the weights W[l]W[l] of sqrt(1./layers_dims[l-1])
where He initialization would use sqrt(2./layers_dims[l-1])
. ]
三种初始化方式的代码如下:
def initialize_parameters_zeros(layers_dims):
"""
Arguments:
layer_dims -- python array (list) containing the size of each layer.
Returns:
parameters -- python dictionary containing your parameters "W1", "b1", ..., "WL", "bL":
W1 -- weight matrix of shape (layers_dims[1], layers_dims[0])
b1 -- bias vector of shape (layers_dims[1], 1)
...
WL -- weight matrix of shape (layers_dims[L], layers_dims[L-1])
bL -- bias vector of shape (layers_dims[L], 1)
"""
parameters = {}
L = len(layers_dims) # number of layers in the network
for l in range(1, L):
### START CODE HERE ### (≈ 2 lines of code)
parameters['W' + str(l)] = np.zeros((layers_dims[l], layers_dims[l-1]))
parameters['b' + str(l)] = 0
### END CODE HERE ###
return parameters
def initialize_parameters_random(layers_dims):
"""
Arguments:
layer_dims -- python array (list) containing the size of each layer.
Returns:
parameters -- python dictionary containing your parameters "W1", "b1", ..., "WL", "bL":
W1 -- weight matrix of shape (layers_dims[1], layers_dims[0])
b1 -- bias vector of shape (layers_dims[1], 1)
...
WL -- weight matrix of shape (layers_dims[L], layers_dims[L-1])
bL -- bias vector of shape (layers_dims[L], 1)
"""
np.random.seed(3) # This seed makes sure your "random" numbers will be the as ours
parameters = {}
L = len(layers_dims) # integer representing the number of layers
for l in range(1, L):
### START CODE HERE ### (≈ 2 lines of code)
parameters['W' + str(l)] = np.random.randn(layers_dims[l], layers_dims[l-1]) * 10
parameters['b' + str(l)] = np.zeros((layers_dims[l],1))
### END CODE HERE ###
return parameters
def initialize_parameters_he(layers_dims):
"""
Arguments:
layer_dims -- python array (list) containing the size of each layer.
Returns:
parameters -- python dictionary containing your parameters "W1", "b1", ..., "WL", "bL":
W1 -- weight matrix of shape (layers_dims[1], layers_dims[0])
b1 -- bias vector of shape (layers_dims[1], 1)
...
WL -- weight matrix of shape (layers_dims[L], layers_dims[L-1])
bL -- bias vector of shape (layers_dims[L], 1)
"""
np.random.seed(3)
parameters = {}
L = len(layers_dims) - 1 # integer representing the number of layers
for l in range(1, L + 1):
### START CODE HERE ### (≈ 2 lines of code)
parameters['W' + str(l)] = np.random.randn(layers_dims[l], layers_dims[l-1]) * np.sqrt(2/layers_dims[l-1])
parameters['b' + str(l)] = np.zeros((layers_dims[l],1))
### END CODE HERE ###
return parameters
用三种初始化方式对同一个数据集进行分类,发现 "He initialize" 的准确率最高
这是为什么呢?
第一种初始化方式,也就是全部参数初始化为零的方式, 没有打破神经网络的对称性, 而且可以发现,输入层与隐藏层之间的参数更新都是一样的,所以更新之后的参数都是相同的; 此外, cost几乎没有下降更别说收敛,训练结束后在测试集上进行预测,预测结果也几乎全部都是同一类.
[神经网络的对称性 : 对称的权重其实限制了网络模型变化的可能性,从而也限制了网络的能力. 所有权重相同的问题称为对称权重(Symmetric ways),随机初始化解决的就是如何打破这种对称性]
第二种初始化方式, 随机化初始参数,由于初始参数过大,导致了cost难以收敛,故分类准确率也很低.
总结一下这个例子:
1.初始化为小的随机数
既然不能都初始化为0,那么很自然的我们会想到将权重初始化为非常接近0的小数(正如我们上面所讨论的不能等于0)。将权重初始化为很小的数字是一个普遍的打破网络对称性的解决办法。
这个想法是,神经元在一开始都是随机的、独一无二的,所以它们会计算出不同的更新,并将自己整合到整个网络的各个部分。一个权重矩阵的实现可能看起来像W=0.01∗np.random.randn(D,H)W=0.01∗np.random.randn(D,H),其中randn是从均值为0的单位标准高斯分布进行取样。通过这个公式(函数),每个神经元的权重向量初始化为一个从多维高斯分布取样的随机向量,所以神经元在输入空间中指向随机的方向(so the neurons point in random direction in the input space.应该是指输入空间对于随机方向有影响)。其实也可以从均匀分布中来随机选取小数,但是在实际操作中看起来似乎对最后的表现并没有太大的影响。
警告:并不是数字越小就会表现的越好。比如,如果一个神经网络层的权重非常小,那么在反向传播算法就会计算出很小的梯度(因为梯度gradient是与权重成正比的)。在网络不断的反向传播过程中将极大地减少“梯度信号”,并可能成为深层网络的一个需要注意的问题。
2.批量标准化
loffe和Ioffe最近开发的一项技术,称为“Batch Normalization”,在训练开始的时候,通过显式地迫使网络上的激活函数让整个网络上采用高斯分布来初始化神经网络,从而缓解了许多头痛的问题。(A recently developed technique by Ioffe and Szegedy called Batch Normalization alleviates a lot of headaches with properly initializing neural networks by explicitly forcing the activations throughout a network to take on a unit gaussian distribution at the beginning of the training.)。通过核心观察证明这是可能的,因为标准化是一个简单的可微分的操作(The core observation is that this is possible because normalization is a simple differentiable operation.)。在实际操作中,运用这项技术相当于在全连接层(或者卷积层,我们很快将会看到)后面嵌入BatchNorm层,并嵌在非线性(层)前。这里我们不会展开来讲解这项技术,因为它已经在上面那提供链接的论文中详细的介绍了,但是请注意,在神经网络中使用批量标准化已经成为一种非常常见的做法。在实践中,使用批量标准化的网络对糟糕的初始化更加健壮。还要需要提到的是,批量标准化可以解释为在网络的每一层进行预处理,但它以可微分的方式整合到网络中。
references:
https://arxiv.org/abs/1502.01852
http://www.cnblogs.com/marsggbo/p/7462682.html