神经网络与深度学习四:建立多层的深层神经网络

1深层神经网络

到目前为止你应该见过单隐层神经网络中的前向传播和后向传播以及logistic回归,并且学习了向量化和为什么随机初始化比较重要。如果你完成了之前的作业我们也已经亲自实现过一些理念,所以到现在你应该已经看到过大多数的实现神经网络的概念,这周我们将会学习如何把这些理念组合起来,从而实现你自己的深度神经网络模型

什么是深度神经网络,你已经学过logistic回归并且见过单隐层神经网络了,这里有一个双隐层以及一个五隐层的神经网络的例子

image-20220501170550349

我们说logistic回归是一个浅层模型,而五隐层的神经网络是一个更深的模型。要记住当我们计算神经网络有几层的时候,我们不能把输入层放进去只算上隐层的数量和输出层 ,前几年在人工智能或机器学习社区中大家发觉有些函数只有非常深层的神经网络能够学习而浅一些的模型通常无法学习。虽然处理任何具体问题的时候都会很难预先准确的判断需要多深的神经网络,所以先试试看logistic回归是非常合理的做法,试一下单层然后两层,然后把隐层的数量当成另一个可以自由选择大小的超参数,然后在保留交叉验证数据上评估,或者用你自己的开发集评估

下面看看一下符号说明

image-20220501173830858

n l n^{l} nl来表示节点的数量或l层上单元数量,用 a l a^{l} al表示l层中的激活函数。

image-20220501174210836

a l a^{l} al是激活函数g(z^{[l]}),输入特征x也是第0层的激活函数, x = a [ 0 ] x=a^{[0]} x=a[0],最后一层的激活函数 a [ l ] = y ^ a^{[l]}=\hat{y} a[l]=y^,就是说 a [ l ] a^{[l]} a[l]等于预测输出

2前向和反向传播

现在你了解了构成深度神经网络的基本模块,比如每一层都有的前向传播步骤以及一个相对的反向传播步骤,现在我们来看看如何实现这些步骤

image-20220507145744101

cache缓存一下 w [ l ] 和 b [ l ] w^{[l]}和b^{[l]} w[l]b[l],这样更容易地在不同地练习中调用函数

前向传播地计算方法是

image-20220507170034360

重复这个步骤就能从左到右计算前向传播,下面我们讲一下反向传播的步骤

image-20220507171122155

小结一下,用x作为输入,第一层你可能会有一个修正线性单元激活函数,然后第二层可能会用另一个修正线性单元激活函数,到第三层可能是sigmoid函数,如果你想做二分分类输出值是 y ^ \hat{y} y^,用 y ^ \hat{y} y^你可以计算出损失这样你就可以开始向后迭代,接下来你就可以反向传播求导

image-20220508093310494

cache会把 z [ i ] z^{[i]} z[i]传递过来,然后反向传播回传 d a [ i ] da^{[i]} da[i]

image-20220508094113357

好了现在讲完了一个三层网络前向和反向传播,现在就只剩下一点细节没有讲就是前向递归我们会用输入数据x初始化那么反向递归呢?当你用logistic回归做二分类的时候 d a [ l ] da^{[l]} da[l] 如下图

image-20220508094805008

这个 d a [ l ] da^{[l]} da[l]的式子用在最后一层上,如果你想要向量化这个实现过程那你需要初始化反向递归 d A l dA^{l} dAl的式子

image-20220508095236103

这就是实现向量化版本的方式换句话说就是初始化一个向量化反向传播的方法。目前为止你已经看过了前向和反向传播的一些基石,如果你现在去尝试实现这些式子你会得到一个正确实现的前向和反向传播来得到你所需要算的导数,你可能在吐槽这也太多公式了吧,可能蒙了,都没搞懂这都是咋回事,要是你这么觉得 我给你个建议就是当你开始这周的编程作业时你需要亲自实现这一切那时候就会学的更加扎实。虽然我必须要说到现在我在实现一个算法的时候有时候我也会惊讶怎么莫名其妙就成功了,那是因为机器学习里的复杂性是来源于数据本身而不是一行行的代码,所以有时候你会感觉你实现了几行代码 但是不太确定它具体做了什么但是奇迹般地实现了那是其实不是因为真正神奇的东西不是你写的程序,通常情况下你的代码不会很长,虽然也不会太简单但是不会需要写一万行或者十万行代码,但有时当你喂入超多数据之后,就算我已经搞机器学习这么长时间了有时候也还是在算法管用的时候惊讶一下下,因为实际上你的算法的复杂性来源于数据而不是你写的代码,因为你不需要写个几千行的代码,all right,这节课就讲了怎么实现深度神经网络,重申一下,这些知识点会在做完编程作业后得到巩固。之后我们会讨论超参数和参数,其实当你训练深度神经网络时能够好好的安排超参数会帮助你提高开发网络的效率。

3 深层网络中的前向传播

在这节你会看到如何在深度网络中灵活应用正向和反向传播,跟以前一样我们先看看对其中一个训练样本x该怎么应用正向传播,之后我们会讨论向量化的版本也就是当你想要对整个训练集来应用正向传播的时候。

image-20220508193926031

第一层的计算如上,下面几层的计算都是类似的

image-20220508194809972

x也就是 a [ 0 ] a^{[0]} a[0],然后这些等式基本上就看起来一致了,基本规律就是

image-20220508195241181

以上就是所有正向传播的公式了,那么我们已经过了一遍针对一个训练样本的过程,接下来看看怎么用向量化的方法训练整个训练集,公式其实都差不多

image-20220508195624602

X = A [ 0 ] X=A^{[0]} X=A[0]这些其实只是把训练样本写成列向量堆叠在一起

image-20220508200020103

我们要做的只是在把所有的z或者a向量堆叠起来,把它们写成列向量堆叠起来构成矩阵Z

image-20220508200244949

把上面规律中的a,z改成A,Z

image-20220508200459869

现在你回顾一下向量化的全过程,其实就是一个for循环,for 循环i从1到4,然后你去计算第一层的激活函数接着第二 三 四 层,我知道当实现你的网络时通常是不想用显式for循环的,但这个情况下除了显示for循环并没有更好的办法,所以当我们实现正向传播的时候用for循环也是可以的,它可以计算第一层的激活函数然后按顺序计算第二 三 四 层,应该没有人能用除了for循环以外更好的方法,那么深度神经网络就讲的差不多了,还有如何在这些网络中使用正向传播,如果其中的过程你觉得很眼熟,那是因为这些步骤其实非常类似于单隐层的神经网络的步骤,只不过是多重复几遍。事实上我们在实现深度神经网络的过程中想增加得到没有bug的程序的概率 其中一个方法需要非常仔细和系统化地去思考矩阵的维数,我在自己debug的时候通常会拿出一张纸一边很仔细的过一遍我在操作的矩阵的维数。下一节会详细解释具体怎么做

4 核对矩阵的维数

当实现深度网络的时候 其中一个我常用的检查代码是否有错的方法是拿出一张纸然后过一遍算法中矩阵的维数,下面我会给大家展示具体怎么做,希望也能帮助大家更容易地实现自己地深度网络

我们现在先忽略掉偏置项b只关注参数w

image-20220508204744466

到目前为止我们只看到过只有一个输出单元的神经网络,在之后的课程里我们也许会学有多个输出单元的神经网络,最后回到输入层 n [ 0 ] = 2 = n x n^{[0]}=2=n_x n[0]=2=nx,然后我们来看看z,w和x的维度。z是第一个隐层的激活函数向量,所以在的维度是(3×1)也就是一个三维的向量 ,接着来看输入特征x,x在这里有2个输入特征所以x的维度是2×1

image-20220508205611728

而我们需要 W [ 1 ] W^{[1]} W[1]这个矩阵能够实现这样的结果,也就是当我们用 W [ 1 ] W^{[1]} W[1]乘以一个( n [ 0 ] n^{[0]} n[0],1)向量时我们会得到一个( n [ 1 ] n^{[1]} n[1],1)的向量。所以你有一个三维的向量它等于某个矩阵乘以一个二维向量,根据矩阵乘法法则会得到一个3×2的矩阵,稍微概括一下就是( n [ 1 ] n^{[1]} n[1], n [ 0 ] n^{[0]} n[0])

image-20220508210254634

然后我们就可以退出其他层的w

image-20220508210601596

做这种运算的时候一般要检查的公式是在实现第l层中矩阵的维数

image-20220508210931500

希望这两个式子能帮助检查你的矩阵W的维数已经你的向量b的维数,当然了如果你在实现反向传播的话那么dw的维度应该和W的维度相同,然后db会和b的维度一样。我们还需要注意检查 z [ l ] z^{[l]} z[l] a [ l ] a^{[l]} a[l]的维度,因为 a [ l ] a^{[l]} a[l]=g( a [ l ] a^{[l]} a[l]),所以z和a的维度应该是相同的

按照惯例我们接下来看看向量化的实现过程,这样就可以同时作用于多个样本,即便实现过程已经向量化了w,b dw,db的维度应该始终是一样的,但是Z,A以及X的维度会在向量化后发生变化。所以之前的情况

image-20220508212103737

现在一切向量化之后

image-20220508212305433

所以

image-20220508212610980

​ 我希望刚刚举的例子能帮助大家搞清楚需要用代码实现的各个矩阵的维度,如果你想做深度神经网络的反向传播,在你写代码的时候一定要确认所有的矩阵维数是前后一致的,这会大大的帮助你排除一些bug的来源。

那么我们之前已经看过一些如何在深度神经网络里实现正向传播的算法了,机智的你一定会好奇为什么深度神经网络这么好用,为什么它们就是比浅层一些的模型好用

5 为什么使用深层表示

我们都知道深度神经网络能解决好多问题,其实并不需要很大的神经网络但是得有深度,得有比较多的隐藏层,这是为什么呢?我们一起来看几个例子来帮助理解为什么深度神经网络会很好用。首先深度网络究竟在计算什么,如果你在建一个人脸识别或是人脸检测系统深度网络所做的事就是当你输入一张脸部的照片,然后你可以把深度神经网络的第一层当成一个特征检测器或边缘探测器,第一层隐层大约有20个隐藏单元,隐藏单元就是图里的这些小方块,一个小方块就是一个隐层单元

你可以先把神经网络的第一层看作图然后去找这张图片的各个边缘我们可以把图片里组成边缘的像素们放在一起看,然后它可以把探测到的边缘组成面部的不同部分

image-20220509154942163

比如说可能有一个神经元会去找眼睛的部分,还有别的在找鼻子的部分,然后把这许多的边缘结合在一起就可以开始探测人脸的不同部分,然后在把这些部分放在一起,比如眼睛,下巴,鼻子等就可以识别或是探测不同的人脸了。

image-20220509160027916

你可以直觉上把这种神经网络的前几层当作简单的探测函数,比如边缘之后把它们和后几层结合在一起那么总体上就能学习更多复杂的函数。还有一个技术性的细节需要理解的是边缘探测器其实相对来说都是针对照片中非常小块的面积,而面部探测器就会针对大一些的区域,但是主要的概念是一般你会从一些较小的细节入手,比如边缘,然后在一步步到更大更复杂的区域比如一只眼睛或是一个鼻子,再把眼睛鼻子组装到一起组成更复杂的部分。这种从简单到复杂的金字塔状表示方法也可以应用在图像或人脸识别以外的其他数据上

比如你想要建一个语音识别系统的时候,需要解决的就是如何可视化语音,比如你输入一个音频片段,那么神经网络的第一层可能就会试着去探测比较低层次的音频波形的一些特征,比如音调是变高了还是变低了分辨白噪声啦,呲呲呲的声音或者音调可以选择这些相对程度比较低的波形特征,然后把这些波形组合在一起就能去探测声音的基本单元,在语言学中有个概念叫音位,比如cat c的发音k就是一个音位a的发音也是一个音位还有t,有了基本的声音单元以后组合起来你就能识别音频当中的单词,单词再组合起来就能识别词组,再到完整的句子

image-20220509162912426

所以深度神经网络的这许多隐层中较早的前几层能学习一些低层次的简单特征,等到后几层就能把简单的特征组合起来去探测更加复杂的东西比如你录在音频里的单词 词组或者是句子然后就能运行语音识别了

我们所计算的之前几层也就是相对简单的输入函数,比如图像单元的边缘啥的,到网络的深层时,你实际上就能做很多复杂的事情比如探测面部,探测单词句子等。有些人喜欢把深度神经网络和人类大脑做类比,这些神经科学家觉得人的大脑也是先探测简单的东西,这种深度学习和人类大脑的比较有时候比较危险但是不可否认的是对我们大脑的运行机制的认识很有价值,有可能大脑先是从简单的东西比如边缘着手再组成一个完整的复杂物体。这些简单到复杂的过程同样也是其他一些深度学习的灵感来源

另外一个关于神经网络为什么有效的理论来源于电路理论,它和你能用电路元件计算哪些函数有着分不开的联系

通常情况下可以使用相对较小但是很深的网络来计算,小在这里的意思是隐层隐层单元的数量相对较小,但是如果你用浅一些的神经网络计算相同的函数也就是我们不能使用很多隐层层时,你会需要成指数增长的单元数量才能达到相同的计算结果。

假设你想要对输入特征计算异或,假设你有n个特征

image-20220509165312425

如果你被迫只能用单隐层,那么隐层单元成指数增长。我希望这能让你有点概念意识到有很多数学函数用深层网络计算比浅层网络要容易的多

除了这些原因,实话说我认为深度学习这个名字挺唬人的,这些概念以前都统称为有很多隐层的神经网络,但是深度学习听起来多高大上啊,太深奥了,对吧,这个词传出去以后,这是神经网络的重新包装或者是多隐层神经网络的重新包装激发了大众的想象力。抛开这些重新包装的概念不谈,深度神经网络确实效果不错,有时候人们还是会钻牛角尖非要用很多的隐层,但是当我开始解决一个新问题时我通常会从logistic回归开始再试试一到两个隐层,把隐层数量当作超参数去调试,这样去找比较合适的深度,但是近几年有一些人会趋向于使用非常深的神经网络,比如可能有几十层,某些问题中有时只有这种网络是最佳模型,这就是我想讲的为什么深度学习效果拔群的直觉解释。

6 搭建深层神经网络块

之前你已经看到过正向反向传播的基础组成部分了,它们也是深度神经网络的重要组成部分,现在我们用它们建一个深度神经网络

image-20220509175952349

注意在正向传播的计算时用cache存一下Z的值,反向传播的时候会用到。总结一下

image-20220509180718660

然后如果实现了这两个函数,然后神经网络的计算过程会是这样的

image-20220509181655898

目前为止你就计算出了所有需要的导数。神经网络的一步训练包括了从 a [ 0 ] a^{[0]} a[0]开始也就是x然后经过一系列正向传播计算得到 y ^ \hat{y} y^,然后再用输出值计算 d a [ l ] da^{[l]} da[l],再实现反向传播,现在你就有所有的导数项了,w也会在每一层被更新为w=w-dw,b也一样,反向传播就都计算完毕我们有所有的导数值

image-20220509182303736

那么这就是神经网络的一个梯度下降循环,补充一个细节,概念上会非常有帮助,那就是把正向函数计算出的Z值保存下来,cache是把w,b传给反向函数的一中非常方便的方法,正向传播时cache了w,b,z,可以将参数复制到你在计算反向传播的时所需要的地方,这就是是实现过程的细节。

现在你们见过实现深度神经网络的基本元件在每一层中有一个正向传播步骤以及对应的反向传播步骤,以及把信息从一步传递到另一步的cache

7 参数vs超参数

想要你的神经网络起到很好的效果你还需要规划好你的参数以及超参数,那么什么是超参数呢

image-20220509183656275

比如学习率,echo迭代次数,隐层的个数或是隐藏单元数,你选择的激活函数。这些都需要你来设置,这些参数实际控制了最后参数w和b的值,所以它们被称为超参数

所以当你着手于训练自己的深度神经网络时你会发现超参数的选择有很多可能性所以你得尝试不同的值,今天的深度学习应用领域还是很经验性的过程,通常你有一个想法,比如你可能大致知道一个最好的学习率值,可能说 α = 0.01 \alpha=0.01 α=0.01最好我会想先试试看,然后你可以实际试一下,训练一下看看效果如何,然后基于尝试的结果你会发现你觉得学习率设定再提高到0.05可能会比较好,如果你不确定什么值是最好的你大可以先试试一个学习率 α \alpha α再看看损失函数的值有没有下降,然后你可以试一试大一些的值,然后发现损失函数的值增加并发散了

image-20220509212633837

然后可能试试其他的数看结果是否下降的很快或者收敛在更高的位置,你可能尝试不同的 α \alpha α并观察损失函数J的变化,试试一组值,损失函数可能变成这样

image-20220509213307715

这个 α \alpha α会加快学习的过程并且收敛在更低的损失函数值上我就用这个 α \alpha α值了,还有很多的超参数,然而当你开始开发新的应用时预先很难确切知道究竟超参数的最优值应该是什么,所以通常你必须尝试很多不同的值并走这个循环(idea->code->experiment)试试各种参数,试试看5个隐层实施模型并观察是否成功,然后再迭代。应用深度学习领域一个很大程度基于经验的过程凭经验的过程,通俗来说就是试 试 试直到你找到合适的数值另一个近来深度学习的影响是它用于解决很多问题,从计算机视觉到语音识别到自然语言处理到很多结构化的数据应用,比如网络广告或是网页搜索或产品推荐等等,我所看到过的就有其中一个领域的研究员尝试了不同的设置,有时候这种设置超参数的直觉可以推广,但有时又不会,所以我经常建议人们 特别是刚开始应用于新问题的人们去试一定范围的值看看结果如何,然后下一节课我们会用更系统的方式尝试各种超参数取值,然后其次 甚至是你已经用了很久的模型可能你在做网络广告应用,在你开发途中很有可能学习率的最优数值或者其他超参数的最优数值是会变的,所以即使你每天都在用当前最优 的参数调试你的系统你还是会发现最优值过一年就会变化,因为电脑的基础设施CPU或GPU 可能会变化很大,所以有一条经验规律可能每几个月就会变 如果你需要解决的问题需要很多年时间,只要经常试试不同的超参数,勤于检验结果看看有没有更好的超参数数值,相信你慢慢会得到设定超参数的直觉知道你的问题最好用什么数值。

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

8 这和大脑有什么关系

那么深度学习和大脑有什么关联性吗?这句话可能有剧透的嫌疑但是我觉得关联不大,我们来看看为什么人们做这样的类比,为什么说深度学习和人类大脑相关,当你实现一个神经网络时,这是你在做的东西

image-20220509221421107

你会做正反向传播,其实很难表述这些公式具体做了什么就是在做这些复杂函数的梯度下降法,到底具体在做什么而这样的类比其实过度简化了我们的大脑具体在做什么,但因为这种形式很简洁也让普通人更愿意公开讨论也方便新闻媒体报道并且吸引大众眼球,但这个类比还是很粗略的

image-20220509222034928

左侧是logistics回归,右侧是一个生物神经元,右侧这个神经元 能接受来自其他神经元的电信号比如x1,x2,x3等其中有一个简单的临界计算值,如果这个神经元突然激发了它会让电脉冲沿着这条长长的轴突传到另一个神经元,所以这是一个过度简化的对比,把一个神经网络的逻辑单元和右边的生物单元对比,但是迄今为止其实连神经科学家们都很难解释究竟一个神经元能做什么,一个小小的神经元其实是极其复杂的,它 的一些功能可能真的是类似logistics回归的运算,但单个神经元到底在做什么目前还没有人可以能够真正解释大脑中的神经元是怎么学习的,至今这仍是一个谜,到底大脑是用类似反向传播或者梯度下降的算法或者人类大脑的学习过程用的是完全不同的原理。所以虽然深度学习的确是一个很好的工具能学到各种很灵活很复杂的函数来学习x->y的映射,在监督学习中学习从x到y的映射,但这种和人类大脑的类比在这个领域的早期或许值得一提但现在这种类比已经逐渐过时了,我自己也在尽量少用这种说法,这就是神经网络和大脑的关系。我相信在计算机视觉或其他的学科都曾受到人类大脑启发还有深度学习其他领域也曾受人类 大脑启发,但是个人来讲我用这个人类大脑类比的次数逐渐减少了。

现在你知道怎么实现深度网络里梯度下降的正反向传播了,助你做编程练习的时候好运

猜你喜欢

转载自blog.csdn.net/m0_52118763/article/details/124850452