深度学习中神经网络的几种权重初始化方法
       在深度学习中,神经网络的权重初始化方法对(weight initialization)对模型的收敛速度和性能有着至关重要的影响。说白了,神经网络其实就是对权重参数w的不停迭代更新,以期达到较好的性能。在深度神经网络中,随着层数的增多,我们在梯度下降的过程中,极易出现梯度消失或者梯度爆炸。因此,对权重w的初始化则显得至关重要,一个好的权重初始化虽然不能完全解决梯度消失和梯度爆炸的问题,但是对于处理这两个问题是有很大的帮助的,并且十分有利于模型性能和收敛速度。在这篇博客中,我们主要讨论四种权重初始化方法:

把w初始化为0
对w随机初始化
Xavier initialization
He initialization
1.把w初始化为0 
我们在线性回归,logistics回归的时候,基本上都是把参数初始化为0,我们的模型也能够很好的工作。然后在神经网络中,把w初始化为0是不可以的。这是因为如果把w初始化0,那么每一层的神经元学到的东西都是一样的(输出是一样的),而且在bp的时候,每一层内的神经元也是相同的,因为他们的gradient相同。下面用一段代码来演示,当把w初始化为0:

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 = {}
    np.random.seed(3)
    L = len(layers_dims)  # number of layers in the network
    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

我们可以看看cost function是如何变化的:

能够看到代价函数降到0.64(迭代1000次)后,再迭代已经不起什么作用了。

2.对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

乘0.01是因为要把W随机初始化到一个相对较小的值,因为如果X很大的话,W又相对较大,会导致Z非常大,这样如果激活函数是sigmoid,就会导致sigmoid的输出值1或者0,然后会导致一系列问题(比如cost function计算的时候,log里是0,这样会有点麻烦)。随机初始化后,cost function随着迭代次数的变化示意图为:

能够看出,cost function的变化是比较正常的。但是随机初始化也有缺点,np.random.randn()其实是一个均值为0,方差为1的高斯分布中采样。当神经网络的层数增多时,会发现越往后面的层的激活函数(使用tanH)的输出值几乎都接近于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()

还记得我们在上一篇博客一步步手写神经网络中关于bp部分导数的推导吗?激活函数输出值接近于0会导致梯度非常接近于0,因此会导致梯度消失。 
3.Xavier initialization 
Xavier initialization是 Glorot 等人为了解决随机初始化的问题提出来的另一种初始化方法,他们的思想倒也简单,就是尽可能的让输入和输出服从相同的分布,这样就能够避免后面层的激活函数的输出值趋向于0。他们的初始化方法为:

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

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

能够看出,深层的激活函数输出值还是非常漂亮的服从标准高斯分布。虽然Xavier initialization能够很好的 tanH 激活函数,但是对于目前神经网络中最常用的ReLU激活函数,还是无能能力,请看下图:

当达到5,6层后几乎又开始趋向于0,更深层的话很明显又会趋向于0。 
4.He initialization 
为了解决上面的问题,我们的何恺明大神(关于恺明大神的轶事有兴趣的可以八卦下,哈哈哈,蛮有意思的)提出了一种针对ReLU的初始化方法,一般称作 He initialization。初始化方式为:
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(2 / layers_dims[l - 1])
        parameters['b' + str(l)] = np.zeros((layers_dims[l], 1))
    return parameters

来看看经过He initialization后,当隐藏层使用ReLU时,激活函数的输出值的分布情况:

效果是比Xavier initialization好很多。现在神经网络中,隐藏层常使用ReLU,权重初始化常用He initialization这种方法。

关于深度学习中神经网络的几种初始化方法的对比就介绍这么多,现在深度学习中常用的隐藏层激活函数是ReLU,因此常用的初始化方法就是 He initialization。

以上所有代码都放到github上了,感兴趣的可以看一波:compare_initialization.

参考文献 
1. Xavier Glorot et al., Understanding the Difficult of Training Deep Feedforward Neural Networks 
2. Kaiming He et al., Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classfication 
3. Andrew ng coursera 《deep learning》课 
4. 夏飞 《聊一聊深度学习的weight initialization》
————————————————
版权声明:本文为CSDN博主「天泽28」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u012328159/article/details/80025785

深度学习中神经网络的几种权重初始化方法相关推荐

  1. 收藏 | 深度学习中神经网络的可视化解释!

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自:计算机视觉联盟 第一个卷积神经网络是Alexander ...

  2. 深度学习中的单阶段小目标检测方法综述

    随着深度学习的不断发展,目标检测技术逐步从基于传统的手工检测方法向基于深度神经网络的检测方法转变.在众多基于深度学习的目标检测方法中,基于深度学习的单阶段目标检测方法因其网络结构较简单.运行速度较快以 ...

  3. 深度学习中常见的10种激活函数(Activation Function)总结

    目录 一:简介 二:为什么要用激活函数 三:激活函数的分类 四:常见的几种激活函数 4.1.Sigmoid函数 4.2.Tanh函数 4.3.ReLU函数 4.4.Leaky Relu函数 4.5.P ...

  4. 权重初始化方法及适用情况

    1. Gaussian 从具有固定均值(例如0)和固定2的标准差(例如0.01)的搞死分布中随机抽取权重,这是最常用的. 一般使用截断高斯. 2. Xavier 这种方法是但的缩放均值或者搞死分布进行 ...

  5. 卷积有多少种?一文读懂深度学习中的各种卷积

    点击上方"视学算法",选择"星标"公众号 精选作品,第一时间送达 本文选自towardsdatascience 作者:Kunlun Bai 公众号机器之心整理 ...

  6. 干货|卷积有多少种?一文读懂深度学习中的各种卷积

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 我们都知道卷积的重要性,但你知道深度学习领域的卷积究竟是什么,又有 ...

  7. 万字长文带你看尽深度学习中的12种卷积网络

    转自 | AI科技评论 作者 | Kunlun Bai 深度学习中的各种卷积网络大家知多少?对于那些听说过却又对它们没有特别清晰的认识的小伙伴们,Kunlun Bai 这篇文章非常值得一读.Kunlu ...

  8. 深度学习中的两种不确定性:偶然不确定性和认知不确定性(Aleatoric Uncertainty Epistemic Uncertainty)

    转载:https://zhuanlan.zhihu.com/p/56986840 注: 本文中,概念.公式与实验均基于 Alex Kendall & Yarin Gal的论文:https:// ...

  9. 一文读懂深度学习中的各种卷积

    来源|机器之心 我们都知道卷积的重要性,但你知道深度学习领域的卷积究竟是什么,又有多少种类吗?研究学者 Kunlun Bai 发布了一篇介绍深度学习的卷积文章,用浅显易懂的方式介绍了深度学习领域的各种 ...

  10. 深度学习中GPU和显存分析

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 转自:机器学习AI算法工程 深度学习最吃机器,耗资源,在本文,我将 ...

最新文章

  1. FTP与TFTP的区别
  2. Linux 学习记录 四(Bash 和 Shell scirpt).
  3. Win10如何远程连接Windows Server 2008,以及提示“您的凭证不工作”问题解决
  4. 创业——不可忽视的创业计划书!!!
  5. bitcoin 在ubuntu上的安装指南
  6. helm3安装mysql_Helm3(kubernetes包管理工具)安装使用踩坑指南
  7. 程序员如何理解Gmail“撤销发送”功能
  8. java编译生成哪些文件_java编译后生成什么文件?生成的文件包括什么?
  9. SQL Server实用经验与技巧大汇集 [转]
  10. 仿照vue实现简易的MVVM框架(二)
  11. Safetype Config使用
  12. 全国市级城市拼音-中文对照表(json格式)
  13. Smartdrv在安装操作系统中的作用
  14. MTCNN优化和另类用法
  15. 设计模式——备份模式
  16. 畅想X9BYOD式的生活
  17. 电脑彻底删除的文件如何恢复?
  18. 知其然不知其所以然 系列
  19. ## GEE Landsat8 Collection2 level2 数据集 计算LST地表温度
  20. yolov5训练自己的数据集,OpenCV DNN推理

热门文章

  1. 解决阿里云Workbench登录失败
  2. PBI Report Builder 报表设计与可视化
  3. python表情换头_教你用Python制作表情包,实现换脸技术!
  4. 【机器学习】异常检测算法之(KNN)-K Nearest Neighbors
  5. windows/vs如何获取程序内存使用量和时间花费
  6. 操作系统-程序执行时间分析
  7. 一元多项式的相加和相减操作(链表)
  8. python 去除水印_cv2 去除图片水印
  9. SOHUDBA/SOHU-DBProxy: 搜狐公司强大的数据库中间件
  10. Android 拨号盘按键音修改为钢琴音效果实现