为什么要初始化权重
训练神经网络需要指定权重的初始值,而一个好的初始化方法将有助于网络学习。
好的初始化可以加快梯度下降、模型收敛;减小梯度下降收敛过程中训练和泛化出现误差的几率;
在一个多层的神经网络的正向传播和反向传播中,可知经常会出现连乘的计算,假设激活函数为线性函数,则 y=WnWn−1⋅⋅⋅W2W1x ,当权重 W 小于 1 时,由于连乘可知结果很容易出现指数级减小;当权重 W 大于 1 时,由于连乘可知结果很容易出现指数级爆炸式增长;
梯度消失和梯度爆炸问题都是因为网络太深,网络权值更新不稳定造成的,本质上是因为梯度反向传播中的连乘效应。
通过选择好的初始化权重一般可以有效减小这种问题的出现。
初始化权重方法
零初始化(不推荐)
通常,将所有权重初始化为零会导致网络无法打破对称性。
当所有初始值相同时,例如将每个权重初始化为0,然后进行反向传播时,所有权重将具有相同的梯度,因此也将具有相同的更新。这就是所谓的对称性。这意味着所有节点都将学习相同的东西,而我们不希望这样做,因为我们希望网络学习不同种类的功能。
若权重通过随机初始化实现的,此后梯度将有所不同,并且每个节点将变得与其他节点更加不同,从而可以进行多种特征提取。这就是所谓的破坏对称性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 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) for l in range(1, L): parameters['W' + str(l)] = np.zeros((layers_dims[l], layers_dims[l - 1])) parameters['b' + str(l)] = np.zeros((layers_dims[l], 1))
return parameters
|
随机初始化(不推荐)
随机分布选择不当会导致网络优化陷入困境。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| 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) parameters = {} L = len(layers_dims)
for l in range(1, L): 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))
return parameters
|
Xavier初始化
早期的参数初始化普遍是将数据和参数normalize为高斯分布(均值0,方差1),但随着神经网络深度的增加,这个方法并不能解决梯度消失的问题。
Xavier初始化的作者,Xavier Glorot,发现:激活值的方差是逐层递减的,这导致反向传播中的梯度也逐层递减。要解决梯度消失,就要避免激活值方差的衰减,即每一层输出的方差应该尽量相等。
Xavier初始化的基本思想是,若对于一层网络的 输出和输出可以保持正态分布且方差相近,这样就可以避免输出趋向于0,从而避免梯度消失情况。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| def initialize_parameters_Xavier(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)
for l in range(1, L): 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))
return parameters
|
He初始化
Xavier 在 tanh 中表现的很好,但在 Relu 激活函数中表现的很差,He是针对于Relu的初始化方法。
He 初始化和 xavier 一样都是为了防止梯度弥散而使用的初始化方式。He初始化的出现是因为xavier 存在一个不成立的假设, xavier 在推导中假设激活函数都是线性的,而在深度学习中常用的ReLu 等都是非线性的激活函数。
He 初始化本质上是高斯分布初始化,与上述高斯分布初始化有所不同,其是个满足均值为 0,方差为 2/n 的高斯分布。
由于ReLU 函数让一半的Z值(负值)变为零,实际上移除了大约一半的方差。所以我们需要加倍权重的方差以补偿这一点。补偿的方法,只需要对 Xavier 初始化进行一项微小的调整——将权重的方差乘以2。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| 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)
for l in range(1, L): 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))
return parameters
|
1511.06422.pdf (arxiv.org)
1702.08591.pdf (arxiv.org)
啃一啃神经网络——权重初始化 - 知乎 (zhihu.com)
(47条消息) 深度学习之参数初始化(二)——Kaiming初始化_凯明初始化公式_Vic时代的博客-CSDN博客
深度学习——Xavier初始化方法_shuzfan-DevPress官方社区 (csdn.net)
Deep Learning基础–参数优化方法 - 蓝鲸王子 - 博客园 (cnblogs.com)