list初始化_深度学习权重初始化常用方法

深度学习的参数分为超参(hyper parameters)和普通参数。超参是模型开始训练前,人工指定的参数,比如网络层数、每层的神经元数、学习速率以及正则项系数等。神经网络的权重初始化(weight initialization)对模型的收敛速度和性能有着至关重要的影响。神经网络的学习是对权重参数W的不停迭代更新,以期达到较好的性能,随着网络层数的增多,在BP(back propagation)过程中,极易出现梯度消失或者爆炸。一个好的权重初始化虽然不能完全解决梯度消失或爆炸的问题,但是对于处理这两个问题是有很大帮助的,并且十分有利于模型性能和收敛速度。

把W初始化为0

在线性回归、logistics回归的时候,把参数初始化为0,模型也能很好的工作。但是在神经网络中,把W初始化为0是不可以的,因为神经网络单点激活的过程可抽象为Y= H(W*X)+ b,当W=0时 公式变为 Y = H(0) + b,每一层神经元学到的东西都是一样的(输出是一样的),而且在bp的时候,每一层内的神经元也是相同的,因为他们的gradient相同。

对W随机初始化

常用的是随机初始化,即W随机初始化。随机初始化的代码如下:

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):
        parameters['W' + str(l)] = np.random.randn(layers_dims[l], layers_dims[l - 1])*0.01
        parameters['b' + str(l)] = np.zeros((layers_dims[l], 1))
    return parameters
————————————————
版权声明:本文为CSDN博主「天泽28」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u012328159/article/details/80025785

乘0.01是因为要把W随机初始化到一个相对较小的值,Y=H(W*X)+b,例如H为sigmoid激活函数,X很大,W也相对较大会导致输出的值是1或0,会导致一系列的问题。随机初始化后,cost function随着迭代次数的变化示意图为:

c5fe60f4366c0b87bcfe7b9107dbc3d1.png

能够看出,cost function的变化比较正常的。但是随机初始化也有缺点,np.random.randn()其实是一个均值为0,方差为1的高斯分布采样。当神经元的层数增多时,会发现月往后面层的激活函数(activation function)例如使用tanh的输出值几乎都接近0。激活函数输出值接近于0会导致梯度非常接近于0,会导致梯度消失。

import numpy as np
import matplotlib.pyplot as plt

def initialize_parameters(layer_dims):
    """
    :param layer_dims: list,每一层单元的个数(维度)
    :return:dictionary,存储参数w1,w2,...,wL,b1,...,bL
    """
    np.random.seed(3)
    L = len(layer_dims)#the number of layers in the network
    parameters = {}
    for l in range(1,L):
        parameters["W" + str(l)] = np.random.randn(layer_dims[l],layer_dims[l-1])*0.01
        parameters["b" + str(l)] = np.zeros((layer_dims[l],1))
    return parameters

def forward_propagation():
    data = np.random.randn(1000, 100000)
    # layer_sizes = [100 - 10 * i for i in range(0,5)]
    layer_sizes = [1000,800,500,300,200,100,10]
    num_layers = len(layer_sizes)
    parameters = initialize_parameters(layer_sizes)
    A = data
    for l in range(1,num_layers):
        A_pre = A
        W = parameters["W" + str(l)]
        b = parameters["b" + str(l)]
        z = np.dot(W,A_pre) + b #计算z = wx + b
        A = np.tanh(z)
        #画图
        plt.subplot(2,3,l)
        plt.hist(A.flatten(),facecolor='g')
        plt.xlim([-1,1])
        plt.yticks([])
    plt.show()
————————————————
版权声明:本文为CSDN博主「天泽28」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u012328159/article/details/80025785

结果如下图所示:

8ec72a4430a9d7c4f47d915b7c561b64.png

W值使用xavier初始化

xavier initialization是Glorot等人为了解决随机初始化的问题提出来的另一种初始化方法,思想就是尽可能的让输入和输出服从相同的分布,即保持输入和输出的方差一致。即将随机初始化的值乘以缩放因子:

,初始化代码为:
np.random.randn(layers_dims[l], layers_dims[l - 1]) * np.sqrt(1. / layers_dims[l - 1])

1、caffer下的xavier实现

caffe中,网络参数初始化通过从一个0均值和特定方差的分布(一般为正态分布或均匀分布)中获得:

,

2、Glorot & Bengio vaxier实现

在 Glorot & Bengio’s 的文章(Understanding the difficulty of training deep feedforward neural networks)中,推荐的却是如下形式:

3、简单推导

n个成分构成的输入向量X,经过一个随机矩阵为W的线性神经元,得到输出

已知

是独立同分布的,且均值方差已知,此时求输出y的方差。

推导如下,由独立变量积的方差计算公式(Product of independent variables)可知,

又已对输入向量去均值,输入和权值矩阵均值均为 0,则:

所以进一步有:

因此为使得,输出 yy 与输入 xx 具有相同的均值和方差,权值矩阵的方差则要求:

这里的 nn 指的是输入样本的维数,这即是 caffe 中关于 xavier 的实现。

Glorot & Bengio’s 论文中,在基础上,还需考虑反向传播时的情形,反向传播是正向传播的逆过程,此时的输入是前向传播的输出,则有:

综合以下两点要求,则可得到满足以上两点要求的权值矩阵的方差为:

初始化方法为:

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)  # integer representing the number of layers
    for l in range(1, L):
        parameters['W' + str(l)] = np.random.randn(layers_dims[l], layers_dims[l - 1]) * np.sqrt(1 / layers_dims[l - 1])
        parameters['b' + str(l)] = np.zeros((layers_dims[l], 1))
    return parameters
————————————————
版权声明:本文为CSDN博主「天泽28」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u012328159/article/details/80025785

来看下xavier initialization后每层的激活函数输出值的分布:

8efe69ceec0aa93517ebe5354c27af78.png

能够看出,深层的激活函数输出值服从标准高斯分布。但是xavier initialization对于目前常用的ReLU激活函数,还是无能为力,请看下图:

95d8d2a834abbf2473f8d70b6354962d.png

当达到5、6层后几乎又开始趋向于0,更深层更趋向于0.

W值使用he initialization初始化

He初始化可以解决上面在ReLU激活函数是Xavier效果不好的问题。其思想是:在ReLU网络中,假定每一层有一半的神经元被激活,另一半为0,要保持方差不变,只需要在Xavier的基础上再除以2。即缩放因子变为:

,初始化代码为:
np.random.randn(layers_dims[l], layers_dims[l - 1]) * np.sqrt(2. / layers_dims[l - 1])

其分布如下图,可见效果很好。

e52256550b48842d0b0942f617bfba4b.png

He初始化在ReLU的输出概率分布

51678d95a21368d6e0b531971a45a2c1.png

Batch Normalization Layer

合理的参数初始化是为了避免梯度消失,有效的反向传播,需要进入激活函数的数值有一个合理的分布,以便于反向传播是计算梯度。其思想是在线性变化和非线性激活函数之间,将数值做一次高斯归一化和线性变化。

ffb9a131fec2aa184d4d89d28ddbff2f.png

Batch Normalization中所有的操作都是平滑可导,因此可以有效的学习到参数

。需要注意的是,训练时的
是由当前batch计算得出,而测试时
使用时保存的均值。

如图表示使用随机初始化的参数,ReLU作为激活函数,未使用Batch Normalization时,每层激活函数的输出分布:

1ecb1c3c6d2ff98561caf171493b9da8.png

下图为使用Batch Normalization时,每层激活函数的输出分布:

e52256550b48842d0b0942f617bfba4b.png

可见,使用batch Normalization 非常有效。

#参考资料

  1. Glorot X, Bengio Y. Understanding the difficulty of training deep feedforward neural networks[C]//Proceedings of the Thirteenth International Conference on Artificial Intelligence and Statistics. 2010: 249-256.
  2. He K, Zhang X, Ren S, et al. Delving deep into rectifiers: Surpassing human-level performance on imagenet classification[C]//Proceedings of the IEEE international conference on computer vision. 2015: 1026-1034.
  3. Ioffe S, Szegedy C. Batch normalization: accelerating deep network training by reducing internal covariate shift (2015)[J]. arXiv preprint arXiv:1502.03167, 1735-1780.
  4. Coursera, deep-neural-network
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值