zoukankan      html  css  js  c++  java
  • deeplearning.ai 改善深层神经网络 week3 超参数调试、Batch Normalization和程序框架

    这一周的主体是调参。

    1. 超参数:No. 1最重要,No. 2其次,No. 3其次次。

      No. 1学习率α:最重要的参数。在log取值空间随机采样。例如取值范围是[0.001, 1],r = -4*np.random.rand(), α = 10r

      No. 2 Momentum β:0.9是个不错的选择。在1-β的log取值空间随机采样。例如取值范围[0.9, 0.999],则1-β的取值空间[0.001, 0.1]。

      No. 2 各个隐含层的神经元数量:可以在线性取值空间随机采样。

      No. 2 mini-batch的大小:

      No. 3 神经网络层数:可以在线性取值空间随机采样。

      No. 3 Learning rate decay:

      Adam算法中的 β1、β1、ε:从来不调,用默认值,0.9、0.999、10-8.

      调试超参数的时候,不要在参数的取值范围均匀采样(网格),而要随机采样。

      从粗到细收缩参数的取值范围。

      同一个神经网络用在不同的领域,最优的超参数是很可能不同的;即使在同一个领域,随着时间的推移,数据的变化,最优的超参数也会发生变化。所以要时不时重新调参,看能不能找到更好地。

      两大类调参流派:1)对于数据量很大(比如计算机视觉、广告),计算资源不够,一次只能负担起试验一个模型或一小批模型,维护一条loss function,逐渐改良模型,努力让loss function越来越小。2)并行试验多种模型,同时看好多条loss function,直接选最好的那个。NG戏称第一类是熊猫型,每次只生一个(或几个)小孩,悉心照料;第二类则是鱼子(caviar)类,每次生一大堆,也不管不问,就看最后谁长得好。如果有足够的计算资源并行计算模型,那一定选第二类。否则,则选第一类。

    2. Batch normalization:

      基本想法是,既然把输入归一化可以加速优化,那么可以把中间层对下一层的输出也归一化。NG说这里可以选择是归一化未激活的z[l],也可以归一化激活后的a[l],他建议默认选择是z[l]。

      具体算法:

      对于神经网络中的某一层,z[l](i), ..., z[l](m),这里是对每个特征在所有样本上的分布。

        μ = 1/m*(∑z(i)),#省略了第l层的[l]标记。

        σ2 = 1/m*(∑(z(i)-μ)2),

        znorm(i) = (z(i) - μ)/sqrt(σ2+ε)

        ztilde(i) = γznorm(i) + β,#这里γ和β是神经网络可以学习的参数,这相当于给它自由度,并不像对输入数据一样强制要求均值为0方差为1。

      

      例如对于某个网络可能会是这样的前向传播:

                                    w[1], b[1]                β[1], γ[1]                                                                    w[2], b[2]                β[2], γ[2]

                               x ---------------> z[1]  ---------------> ztilt[1] ---------------> a[1] = g[1](ztilt[1]) ---------------> z[2] ---------------> ztilt[2] ---------------> a[2] --------------->...

      此时的参数包括 w[1], b[1], w[2], b[2],...,w[l], b[l],β[1], γ[1], β[2], γ[2],...,β[l], γ[l]。注意这里的β和优化中的β(例如Momentum)是完全不同的参数,不要搞混。

      由于z[l] = w[l]*a[l-1] + b[l],紧跟着做归一化时,b[l]是被减去了,所以实际可以把公式简化为z[l] = w[l]*a[l-1] 。然后计算znorm[l],接着计算ztilde[l][l]znorm[l] + β[l]。此时β[l]体现了之前b[l]的作用。所以实际的参数包括w[1], w[2],...,w[l], β[1], γ[1], β[2], γ[2],...,β[l], γ[l]。另外,z[l]的维度是(n[l], 1),β[l]和γ[l]的维度也都是(n[l], 1)。n[l]是第l层的神经元数量。

      当和mini-batch结合的时候,则是对每个mini-batch前向计算的时候,在z[l]和a[l]之间插入针对当前mini-batch数据的归一化层。

      总结算法:

      遍历所有mini-batch

        计算当前mini-batch的前向传播

          在每一层,用batch normalization计算出ztilt[l]

        计算反向传播,得到 dw[l], dβ[l], dγ[l]

        更新参数,可以用标准梯度下降、Momentum、RMSprop、Adam等算法。

      

      为什么在中间层做batch normalization有效呢?1)第一个很浅显的原因是和输入层特征归一化一样,各个维度近似分布更利于优化。2)第二个原因是它使得后面的层对于前面层的变化更鲁棒。为了更好地解释这个原因,我们先设想一个算法在数据集A上训练,然后在B上测试,A和B的分布相差约大,越不利于算法泛化。Covariate shift描述的就是这种数据分布发生变化的现象。对于深度学习来说,各个层神经元是处理前面的网络传过来的数据,如果前面网络的参数发生变化(比如因为优化迭代),则传入这一层的数据也会发生变化,这就产生了covaraite shift。Batch normalization就缓解了这个问题,它把不同分布的数据归一化成比较稳定的分布,限制了前面网络产生的数据的shift。或者说它减小了不同层之间的关联,使得每一层网络可以自己学习。这有助于加速整个网络的学习。3)第三个原因是batch normalization有轻微的正则化效果,在归一化的作用下每个mini-batch被它的均值和方差缩放,由于均值、方差只是小部分数据算出来是有噪音的,所以类似dropout(每个神经元有一定概率被删掉),它在每个隐藏层的输出上加了噪音,这迫使后面的层不过分依赖任何一个隐藏单元。但是由于噪音小,所以并不是巨大的正则化效果,可以把batch normalization和dropout一起用。NG强调batch normalizatoin只是有轻微正则化效果,但是还是不要把它当做正则化手段。

      训练阶段是用mini-batch训练权重,而在测试阶段,需要根据训练集来估算测试样本的均值μ和方差σ2,一般采用的方法是对mini-batch算出的均值、方差做指数加权平均。

    3. Softmax回归:logistic回归的一般形式,从识别两个分类推广到多个分类。

      对于多分类的应用,神经网络的最后一层(第L层)是Softmax层,z[L] = w[L]a[L-1] + b[L],中间变量t = exp(z[L]),这是对z[L]的每个元素进行exp操作,如果是四分类的问题,则z[L]的形状是(4, 1),t也是(4, 1)。激活函数 a[L] = exp(z[L])/(∑ti),ti是t的第i个元素,a[L]的形状也是(4, 1),a[L]的第i个元素ai[L] = ti/∑ti。ai[L]的可以看成是每个类的概率。

      Softmax和Logistic回归都是对特征空间的线性划分。

      Softmax名字的来源是“hard max”,hard max是把最大值设为1,其他值都抹成0,非常强硬,例如向量[0.842, 0.042, 0.002, 0.114]T经过hard max操作就变成[1, 0, 0, 0]T

           单个训练样本的损失函数L(y_hat, y) = -∑(yj*logy_hatj)。想要损失函数尽可能小,就要使正确类别的概率尽可能大。

           整个训练集的损失J(w[1], b[1], ...) = 1/m*∑(L(y_hat(i), y(i)))。

           反向传播的计算,dz[L] = y_hat - y。

      

    4. 市面上的深度学习框架:

      用户只需要定义网络架构以及前向传播,框架自己会搞定反向传播。

      NG选框架的标准:1)容易编程;2)运行速度快,尤其是针对大数据;3)是否真的开放,不仅仅开源,而且要有很好的维护。

      TensorFlow上写深度学习程序一般包含几个步骤:

        1) Create Tensors (variables) that are not yet executed/evaluated.

        2) Write operations between those Tensors.

        3) Initialize your Tensors.

        4) Create a Session.

        5) Run the Session. This will run the operations you'd write above.

    import numpy as np
    import tensorflow as tf
    
    coefficients = np.array([[1.], [-10.], [25.]]) #传给x的数据。
    
    w = tf.Variable(0, dtype=tf.float32) #希望被优化的参数。
    x = tf.placeholder(tf.float32, [3, 1]) #告诉TensorFlow稍后会为x提供数据,这种方式便于把训练数据加入损失方程。
    # cost = tf.add(tf.add(w**2, tf.multiply(-10., w)), 25) #这是第一个例子。
    # cost = w**2 - 10*w + 25 # 由于TensorFlow重载了运算发,所以可以直接这样写。
    cost = x[0][0]w**2 + x[1][0]*w+x[2][0] #第二个例子加入了样本x。 
    train = tf.train.GradientDescentOptimizer(0.01).minimize(cost) #使用梯度下降法最小化cost,这里0.01是学习率。
    
    init = tf.global_variables_initializer()
    session = tf.Session() # with命令在python中更方便防止内循环出现错误,这一句也可以写成 with tf.Session() as session:
    session.run(init)
    print(session.run(w)) #还没有运行优化,w现在是0.
    
    session.run(train, feed_dict={x:coefficients}) #运行一步梯度下降,把coefficients喂给x。如果在做mini-batch梯度下降,每次迭代可以喂不同的mini-batch
    print(session.run(w)) #一步梯度下降之后,w现在是0.1
    
    for i in range(1000):
        session.run(train, feed_dict={x:coefficients})
    print(session.run(w)) # 运行1000次梯度下降之后,w现在是4.99999
    

      

  • 相关阅读:
    IOS开发-UIDynamic(物理仿真)简单使用
    IOS开发---视频录制
    利用阿里云服务器免费体验word press博客、个人网站
    Next Cloud通过修改数据库表,达到替换文件而不改变分享的链接地址的效果,以及自定义分享链接地址
    非华为笔记本如何实现多屏协同和一碰互传以及一些问题的解决方法
    如何申请XShell和XFtp的免费家庭学生版本
    PicGo配合Typora怎么配置Chevereto图床,PicGo的Chevereto图床配置
    Ubuntu无法正常引导,进不去Ubuntu,安装Ubuntu20和Window10双系统后,
    搭建自己的Chevereto免费图床—写博客更加得心应手了!
    如何搭建自己的本地服务器,Web服务器
  • 原文地址:https://www.cnblogs.com/zonghaochen/p/7802419.html
Copyright © 2011-2022 走看看