深度学习入门笔记(七):深层神经网络

专栏——深度学习入门笔记

声明

1)该文章整理自网上的大牛和机器学习专家无私奉献的资料,具体引用的资料请看参考文献。
2)本文仅供学术交流,非商用。所以每一部分具体的参考资料并没有详细对应。如果某部分不小心侵犯了大家的利益,还望海涵,并联系博主删除。
3)博主才疏学浅,文中如有不当之处,请各位指出,共同进步,谢谢。
4)此属于第一版本,若有错误,还需继续修正与增删。还望大家多多指点。大家都共享一点点,一起为祖国科研的推进添砖加瓦。

深度学习入门笔记(七):深层神经网络

1、深层神经网络

目前为止,学习了只有一个单独隐藏层的神经网络(深度学习入门笔记(六):浅层神经网络)的正向传播和反向传播,还有逻辑回归(深度学习入门笔记(二):神经网络基础),并且还学到了向量化(深度学习入门笔记(四):向量化),这在随机初始化权重(深度学习入门笔记(六):浅层神经网络)时是很重要。

这一次所要做的是把这些理念集合起来,就可以组建并执行一个术语你自己的 深度神经网络,有没有一种乐高积木的感觉呢?

简单复习下前面的内容:

逻辑回归,下图左边。一个隐藏层的神经网络,下图右边。
在这里插入图片描述
神经网络层数的定义方式:从左到右,由隐藏层开始,定义为第一层,比如上边右图, x 1 {x}_{1} x 2 {x}_{2} x 3 {x}_{3} 这一层右边的隐藏层是第一层,所以浅层神经网络是两层网络。

由此类推,下图左边是两个隐藏层的三层神经网络,右边是五个隐藏层的六层神经网络。(这个层数叫法是存在不同的结论的,最简单且不出错的方法是说隐藏层的层数,比如左边的是两个隐藏层,右边的是五个隐藏层)
在这里插入图片描述
所以,严格意义上来说,逻辑回归也是一个一层的神经网络,而上边右图一个深得多的模型,是一个六层的神经网络。我们所说的浅层神经网络和深层神经网络中的浅与深,仅仅是指一种程度,也就是相对而言的。

小结一下: 严格的说,有一个隐藏层的神经网络,就是一个两层神经网络。记住算神经网络的层数时,不算输入层,只算隐藏层和输出层。

2、前向传播和反向传播

深度神经网络的每一层都有 前向传播 步骤以及一个相反的 反向传播 步骤,那么这两个步骤是如何实现的呢?

先说前向传播 l l 表示层数,网络的输入 a [ l 1 ] {a}^{[l-1]} ,网络的输出是 a [ l ] {a}^{[l]} ,网络的缓存为 z [ l ] {z}^{[l]} ;从实现的角度来说可以缓存下 w [ l ] {w}^{[l]} b [ l ] {b}^{[l]} ,这样更容易在不同的环节中调用函数。

所以前向传播的步骤可以写成:

(1) z [ l ] = W [ l ] a [ l 1 ] + b [ l ] {z}^{[l]}={W}^{[l]}\cdot{a}^{[l-1]}+{b}^{[l]}

(2) a [ l ] = g [ l ] ( z [ l ] ) {{a}^{[l]}}={{g}^{[l]}}\left( {{z}^{[l]}}\right)

向量化(深度学习入门笔记(四):向量化)整个过程之后,可以写成:

(1) z [ l ] = W [ l ] A [ l 1 ] + b [ l ] {z}^{[l]}={W}^{[l]}\cdot {A}^{[l-1]}+{b}^{[l]}

(2) A [ l ] = g [ l ] ( Z [ l ] ) {A}^{[l]}={g}^{[l]}({Z}^{[l]})

前向传播需要喂入 A [ 0 ] {A}^{[0]} 也就是 X X ,即输入特征,来进行初始化,初始化的是第一层的输入值。 a [ 0 ] {a}^{[0]} 对应于一个训练样本中的输入特征,而 A [ 0 ] {{A}^{[0]}} 对应于一整个训练样本中的输入特征,所以这就是这条链的第一个前向函数的输入,重复这个步骤就可以从左到右计算前向传播。

再讲反向传播,具体的原理和推导可以看这个博客——深度学习100问之深入理解Back Propagation(反向传播),输入为 d a [ l ] {{da}^{[l]}} ,输出为 d a [ l 1 ] {{da}^{[l-1]}} d w [ l ] {{dw}^{[l]}} , d b [ l ] {{db}^{[l]}}

所以反向传播的步骤可以写成:

(1) d z [ l ] = d a [ l ] g [ l ] ( z [ l ] ) d{{z}^{[l]}}=d{{a}^{[l]}}*{{g}^{[l]}}'( {{z}^{[l]}})

(2) d w [ l ] = d z [ l ] a [ l 1 ]   d{{w}^{[l]}}=d{{z}^{[l]}}\cdot{{a}^{[l-1]}}~

(3) d b [ l ] = d z [ l ]    d{{b}^{[l]}}=d{{z}^{[l]}}~~

(4) d a [ l 1 ] = w [ l ] T d z [ l ] d{{a}^{[l-1]}}={{w}^{\left[ l \right]T}}\cdot {{dz}^{[l]}}

(5) d z [ l ] = w [ l + 1 ] T d z [ l + 1 ]   g [ l ] ( z [ l ] )   d{{z}^{[l]}}={{w}^{[l+1]T}}d{{z}^{[l+1]}}\cdot \text{ }{{g}^{[l]}}'( {{z}^{[l]}})~

式子(5)由式子(4)带入式子(1)得到,前四个式子就可实现反向传播。

向量化实现过程可以写成:

(6) d Z [ l ] = d A [ l ] g [ l ] ( Z [ l ] )    d{{Z}^{[l]}}=d{{A}^{[l]}}*{{g}^{\left[ l \right]}}'\left({{Z}^{[l]}} \right)~~

(7) d W [ l ] = 1 m d Z [ l ] A [ l 1 ] T d{{W}^{[l]}}=\frac{1}{m}\text{}d{{Z}^{[l]}}\cdot {{A}^{\left[ l-1 \right]T}}

(8) d b [ l ] = 1 m   n p . s u m ( d z [ l ] , a x i s = 1 , k e e p d i m s = T r u e ) d{{b}^{[l]}}=\frac{1}{m}\text{ }np.sum(d{{z}^{[l]}},axis=1,keepdims=True)

(9) d A [ l 1 ] = W [ l ] T d Z [ l ] d{{A}^{[l-1]}}={{W}^{\left[ l \right]T}}\cdot d{{Z}^{[l]}}

小结一下:

吴恩达老师手稿如下,举一个简单的三层(两层隐藏层)神经网络。

在这里插入图片描述

  • 前向传播:第一层可能有一个 ReLU 激活函数,第二层为另一个 ReLU 激活函数,第三层(输出层)可能是 sigmoid 函数(如果做二分类的话),输出值为 y ^ \hat y ,用来和 y y 计算损失 L L
  • 反向传播:向后迭代,进行反向传播求导来求 d w [ 3 ] {{dw}^{[3]}} d b [ 3 ] {{db}^{[3]}} d w [ 2 ] {{dw}^{[2]}} d b [ 2 ] {{db}^{[2]}} d w [ 1 ] {{dw}^{[1]}} d b [ 1 ] {{db}^{[1]}} 。在计算的时候,缓存会把 z [ 1 ] {{z}^{[1]}} z [ 2 ] {{z}^{[2]}} z [ 3 ] {{z}^{[3]}} 传递过来,然后回传 d a [ 2 ] {{da}^{[2]}} d a [ 1 ] {{da}^{[1]}} d a [ 0 ] {{da}^{[0]}}
  • 前向递归:用输入数据 x x 来初始化,那么反向递归(使用 Logistic 回归做二分类),对 A [ l ] {{A}^{[l]}} 求导。

3、核对矩阵的维数

当实现深度神经网络的时候,其中一个最常用的也是最好用的检查代码是否有错的方法,就是拿出一张纸过一遍算法中矩阵的维数。或者有一个笨方法就是,一直运行,一直 d e b u g debug ,不过这样太低效了。

向量化前,变量的维度如下:

  • w w 的维度是(下一层的维数,前一层的维数),即 w [ l ] {{w}^{[l]}} :( n [ l ] {{n}^{[l]}} , n [ l 1 ] {{n}^{[l-1]}} );

  • b b 的维度是(下一层的维数,1),即 b [ l ] {{b}^{[l]}} :( n [ l ] , 1 ) {{n}^{[l]}},1)

  • z z a a 的维度是(下一层的维数,1),即 z [ l ] {{z}^{[l]}} , a [ l ] {{a}^{[l]}} : ( n [ l ] , 1 ) ({{n}^{[l]}},1)

  • d w [ l ] {{dw}^{[l]}} w [ l ] {{w}^{[l]}} 维度相同;

  • d b [ l ] {{db}^{[l]}} b [ l ] {{b}^{[l]}} 维度相同;

w w b b 向量化维度不变,但 z z , a a 以及 x x 的维度会向量化后发生变化。
在这里插入图片描述

向量化后:

  • Z [ l ] {Z}^{[l]} 可以看成由每一个单独的 z [ l ] {z}^{[l]} 叠加而得到, Z [ l ] = ( z [ l ] [ 1 ] z [ l ] [ 2 ] z [ l ] [ 3 ] z [ l ] [ m ] ) {Z}^{[l]}=({{z}^{[l][1]}},{{z}^{[l][2]}},{{z}^{[l][3]}},…,{{z}^{[l][m]}}) m m 为训练集大小,所以 Z [ l ] {Z}^{[l]} 的维度不再是 ( n [ l ] , 1 ) ({{n}^{[l]}},1) ,而是 ( n [ l ] , m ) ({{n}^{[l]}},m)

  • A [ l ] {A}^{[l]} Z [ l ] {Z}^{[l]} 一样,维度变成 ( n [ l ] , m ) ({n}^{[l]},m) ,其中 A [ 0 ] = X = ( n [ l ] , m ) {A}^{[0]} = X =({n}^{[l]},m)
    在这里插入图片描述
    到这里,一个深层神经网络就设计完成了,理论知识也大概讲述完毕了。

4、参数VS超参数

想要你的深度神经网络起很好的效果,维度的准确性是最基本的东西,代码不出错也是必须的一步,除了这些以外,还需要规划好参数以及超参数。

  • 什么是超参数?

定义:在机器学习的上下文中,超参数是在开始学习过程之前设置值的参数,而不是通过训练得到的参数数据。通常情况下,需要对超参数进行优化,给学习机选择一组最优超参数,以提高学习的性能和效果。

  • 超参数和参数的区别是什么?

参数是从数据中自动估计的,而超参数是手动设置的。

  • 超参数是如何影响神经网络的?

超参数,实际上控制了最后的参数 W W b b 的值,影响了模型。

  • 超参数有哪些呢?

比如算法中的 learning rate(学习率)、iterations(梯度下降法循环的数量)、 L L (隐藏层数目)、 n [ l ] {{n}^{[l]}} (隐藏层单元数目)、choice of activation function(激活函数的选择)等等,这些都需要你来设置。

输了一些比较熟悉的超参数,你可能有点感觉了,但是实际上深度学习有很多不同的超参数,之后也会介绍一些其他的超参数,如 momentum(动量)、mini batch size(批大小)、regularization parameters(正则化参数)等等。

  • 如何寻找超参数的最优值?
    在这里插入图片描述

其实这个过程和人类的思维过程类似,为什么这么说呢?人类在大脑风暴的过程中,是先有 Idea,然后 Realize,最后 Experiment。不过深度学习中,是 Idea—Code—Experiment—Idea 这个大循环,Realize 是用 Code 替换的,再尝试各种不同的参数,实现模型并观察是否成功,然后再迭代。

深度学习的应用领域,是个很经验性的过程:通常有个想法(Idea),比如你可能大致知道一个别人用的最好的学习率值,可能说 a = 0.0001 1 0 4 a=0.0001(10^{-4}) 效果最好,我在做图像处理实验的时候,真的发现这个学习率很不错,建议你也可以尝试一下。

那么我会想说,先试试看,然后可以实际更改一下,再训练一下,最后看看效果如何。

基于这个尝试的结果,你会发现,学习率设定再提高到 0.0005 5 1 0 4 0.0005(5*10^{-4}) 可能会比较好。

但是你又不确定什么值是最好的,这个时候大可以先试试你猜想的新学习率 a a 到底怎么样,更改参数重新实验,再看看损失函数 J J 的值有没有下降?

如果没有的话,你可以试一试再大一些的值,如果这个时候,你发现损失函数的值不但没减少,反而增加并且发散了。恭喜你,你失败了2333。

然后可能需要试试其他的一些数,再改再看实验结果,看损失函数是否下降的很快或者收敛到在更高的位置?

你可能尝试不同的 a a 并观察损失函数 J J 这么变了,试试一组值,然后可能损失函数变成这样,这个 a a 值会加快学习过程,并且收敛在更低的损失函数值上,然后敲定,我就用这个 a a 值了。

再或者还可能你发现,固定学习率并不能满足你的要求,这个时候你需要学习率是变化的,比如学习率衰减——深度学习100问之学习率衰减

可能有的小伙伴就会说了,这也太麻烦了吧,这不是一直试试试的???这也是工作量的一部分,所以深度学习也被人吐槽说是一个经验主义学科。。。应用深度学习领域,一个很大程度基于经验的过程,凭经验的过程通俗来说,就是试直到你找到合适的数值。

只能说调参是门玄学,好与坏不是你我说了算的。

之前在知乎上看到过一个文章说可以使用算法调参,但是我还没接触过。。。论文:Hyperparameter Optimization: A Spectral Approach,有兴趣的小伙伴可以看一看,这可是顶端科学技术了。
在这里插入图片描述

5、调参

一个近来深度学习的影响是,它可以用于解决很多问题,从 计算机视觉语音识别,到 自然语言处理,到很多 结构化的数据应用,比如 网络广告 或是 网页搜索产品推荐 等等。

很多领域的研究人员,对这些领域中的一个问题进行研究,尝试了不同的参数设置,有时候这种设置超参数的直觉是可以推广的,但有时又不会。所以刚开始应用新问题的人们,去试一定范围的值看看结果如何(比如我们实验室的方向,就是近两年才开始结合深度学习作为方法论,进行问题的研究与解决)。

然后是其他情况,比如你已经用了很久的模型进行问题的解决,可能你在做网络广告应用,也可能是其他的,在开发的过程中,很有可能学习率的最优数值或是其他超参数的最优值是会变的!!!所以即使每天都在用当前最优的参数调试系统,你还是会发现,最优值过一年就会变化,这可能是很多原因导致的,其中一种可能就是因为电脑的基础设施,CPU 或是 GPU 可能会变化很大,比如你是一个 GPU,那么 GPU 的型号?(以N卡的天梯为例)

在这里插入图片描述
(图源:http://www.mydrivers.com/zhuanti/tianti/gpu/

所以之前的经验规律可能每几个月就会变,如果你的工作台一直不变,那么数据也可能会有变化,再或者你的网络结构也会有微调,等等。所以要经常试试不同的超参数,勤于检验结果,看看有没有更好的超参数数值,相信慢慢的,你会得到设定超参数的直觉,知道你的问题最好用什么数值。?

这可能的确是深度学习比较让人不满的一部分,也就是你必须尝试很多次不同可能性。但参数设定这个领域,深度学习研究还在进步中,所以可能过段时间就会有更好的方法决定超参数的值,也很有可能由于 CPUGPU、网络和数据都在变化,这样的指南可能只会在一段时间内起作用,只有不断尝试,并且尝试保留交叉检验或类似的检验方法,然后挑一个对你的问题效果比较好的数值,这种方法才是现在最好的解决办法。

近年来,受深度学习影响或者可以称之为 冲击,很多领域发生了变化,从计算机视觉到语音识别到自然语言处理到很多结构化的数据应用,比如网络广告、网页搜索、产品推荐等等;有些同一领域设置超参数的直觉可以推广,但有时又不可以,特别是那些刚开始研究新问题的人们应该去尝试一定范围内的结果如何,甚至那些用了很久的模型得学习率或是其他超参数的最优值也有可能会改变。我们能做的只有以不变应万变!!!这也是这个领域的项目经验或者经历更为重要的原因之一。

最后,记住一条经验规律:经常试试不同的超参数,勤于检查结果,看看有没有更好的超参数取值,你将会得到设定超参数的直觉。

推荐阅读

参考文章

  • 吴恩达——《神经网络和深度学习》视频课程
发布了195 篇原创文章 · 获赞 4246 · 访问量 50万+

猜你喜欢

转载自blog.csdn.net/TeFuirnever/article/details/101366168
今日推荐