数据科学个人笔记:神经网络(矩阵化+正则化)

继续吴恩达老师的深度学习课程笔记

 

一、算法实现中的矩阵化方法

到此,我们已经讲完了构建并训练出一个神经网络的流程和其中的计算细节。但仅仅是知道这些还不够,要想编写代码去实现这样一个过程,我们需要将上述的计算过程矩阵化。

什么是矩阵化呢?就是说,原来我们一个样本一个样本地把x放进神经网络中,然后一个样本一个样本地计算出y*的值。但这样太慢了。我们可以使用一种技巧,如下所述:

1.我们设第i个样本的x为xi,由于x是有对个特征的,原本的xi长成这样:xi=【x1i,x2i.。。。xni】,n是样本的特征数。

2.在原本的神经网络计算过程中,我们把这个xi中的x1放在输入端的第一个节点上,x2放在第二个上,以此类推,则根据第六节中的算法流程,就可以计算出最后的y*。

3.而现在,我们每次输入神经网络的是一个矩阵,他长成下面这个样子:

【(x11,x12,x13。。。);。。。;(xn1,xn2,xn3.。。。)】

4.这个矩阵是什么意思呢?其实很简单,第一列中的第一个元素代表第一个样本的第一个特征,第二个元素代表第一个样本的而个特诊,以此类推,也就是说,第一列代表了第一个样本的n个特征,第二列代表第二个样本的n个特征,以此类推。也就是说,第一行代表了i个样本各自的第一个特征,以此类推。

5.我们将这个矩阵输入神经网络中,其实就相当于是,同时将i个样本全部输入到神经网络中同时进行计算,那么显然地,计算出的结果就是Y=【y*1,y*2.。。。y*i】。

6.那么这么一个大矩阵怎么才能在神经网络中进行计算呢?其实也很简单,只要大家学过矩阵乘法和矩阵加法就绝对ok了。下面我们来看一下详细的流程:

7.将矩阵的第一行(也就是所有样本的第一个特征)放在输入端的第一个节点上,第二行(也就是所有样本的第二个特征)放在输入端的第二个节点上,以此类推。

8.我们说过,神经网络中每一层中的所有节点的输出量,都要被组合在一起,输入到下一层的第一节点中,再重复输入到下一层的第二个节点中,以此类推。也就是说,下一层中每一个节点的输入量,都是我现在这一层中所有输出量纵向组合的矩阵。

9.而现在我们输入端的每一个节点输出的都是一个行向量,纵向组合在一起就是如下矩阵

10.下一层中的每一个节点,都要输入这整个矩阵进去计算,算出一个输出量。如果我们设下一层中第i个节点中的参数们长成如下样子:【wi1,wi2.。。。win,bi】,n是每个节点中的w数量,必须和样本的特征数量相同,因为函数是y=w1x1+。。。Wnxn+b,所以w和特征是一一对应的。

11.首先我们看下,我们输入端输出的整个矩阵,放入第一个节点中,则该节点中的参数将对矩阵中的每一个样本(也就是每一列分别进行如下操作)

y=w1x1+w2x2+w3x3+。。。+w(n)x(n)+b

Z=g(y)

很眼熟吧,和上面单个x的输入是完全一样的,只不过当时的x只有一列,现在有i列,那么我们只要按照矩阵乘法的习惯,写成如下矩阵乘法公式:

其实以上公式计算出的结果,就相当于同时对i列(i个样本)进行了以上操作,并将计算所得z值按照每样本所在列的排列方式排成了一行而已。

由此,第一个节点输出的量就是【z1,z2,z3.。。。】

以此类推,在第二个节点中发生的事情和第一个节点是完全一样的,只不过可能第二个节点中的参数w们和b跟第一个节点当中是不同的。同样的,输入端输出的大矩阵被左乘了一个行向量,如下公式:

并没有什么区别。

以此类推,若当前层有5个节点,则在每层中,上一层的输出矩阵被左乘上了一个行向量,由此得到了一个行向量,并输出。

那么,我们可以让我们的大矩阵同时乘以每各节点的行向量,并同时输出p个行向量吗?可以的,用以下矩阵乘法:

上式中左边的大矩阵,其中第一行代表第一个节点中的参数们,第二行代表第二个节点中的参数们,以此类推。计算所得的结果,即为每个节点计算并输出的行向量,按照每个节点所在行的位置纵向排列成一个矩阵的结果。

则第一个隐藏层输出的结果为矩阵

其中,第一行第一个元素代表第一个样本的特征们在被第一个节点的参数们和激活函数计算后得到的输出量,第一行第二个元素代表第二个样本被第一个节点的参数们和激活函数计算后的到的输出量,以此类推。简而言之,这个矩阵中第i行第j列个元素,代表第i个节点对第j个样本计算所得到的输出量。

然后,本层的输出矩阵又被下一层所组成的大矩阵左乘一次,又可以计算出一个大的输出矩阵。这样一层层往下推,就能在最后一层输出端计算输出我们之前提到过的Y=【y*】

这里要注意的一点是,每一层的参数矩阵(公式中左边的矩阵),其行数等于改层节点数,列数等于该层每个节点中的w的数量,也等于上一层的节点数。右边的输入矩阵,其行数等于上一层的节点数,列数等于我们的样本数量。等式右边的输出矩阵,其行数等于该层的节点数,列数等于我们的样本数量。

本节内容,最好结合矩阵乘法的定义自己理解一遍,会更有助于之后的学习。

 

二、矩阵化后的参数调整(梯度下降法)

接上节,在我们将所有样本的所有特征输入神经网络中以后,计算出了一组y*。结合样本真实的y值,我们就可以列出公式L=(sum((y-y*)^2)),并能计算出当前L的值。但是L实际上代表着我们当前使用的这组参数构成的神经网络对y的预测水平偏差有多大,这个偏差越大,说明我们的预测能力越差,所以我们当然希望这个L越小越好。在此,我们给L取个名字叫损失函数。

之前我们已经提过,要使L更小,就要调整影响L的变量们,也就是各个w和b,怎么调整呢?之前也提过了,梯度下降法,每次我们输入我们的样本,并输出一组y*以后,我们使网络中每个节点的每个参数w和b们做如下计算:w=w-a*dL/dw,b=b-a*dL/db。实际上,我们可以把这个过程也矩阵化,就成了如下公式:

这样计算完以后,我们再把所有样本代入这组新的参数组成的神经网络中,计算出一组y*,并计算出L,我们就会发现,L变小了。

重复更新参数,输入样本,输出y*,计算L,更新参数。。。这个过程一直重复,L就会越来越小,到L的值小于我们设定的某个阈值,我们就认为此时我们的神经网络预测偏差足够小了,预测能力足够强了,停止训练过程。或者,我们的训练次数达到了我们设置的最大训练次数了,我们也就不再训练了,停止训练过程。

 

三、超参数

基于第八节用简洁的公式形式呈现出来的构建和训练神经网络的流程,我们就可以很方便地用python写一段代码实现这个模型、并使用该模型对未知y值的数据进行分类了。但是,我们还有一些问题需要解决,因为我们在训练一个神经网络之前,我们需要先初始化一个神经网络。通俗点来说,我们得先画一个有四层的神经网络,确定每层的节点数,确定梯度下降时的步数a,以及确定我们的训练最大迭代次数是多少次。以上这些要确定的量,我们称为神经网络的超参数。总结一下神经网络的超参数有下面这些:

1.层数2.各层节点数3.激活函数类型4.最大迭代次数/迭代阈值5.迭代步长a

那么,参数w和b可以训练,这些超参数怎么确定呢?(待补充)

 

四、训练集、验证集和测试集

通常我们拿到一堆同时知道x和y的数据,我们会将它们分成三部分:训练集、验证集和测试集。在小数据时代,比例通常是8:1:1,但在大数据时代,验证集和测试集的数量只要能达到测试要求就可以了,没有比例上的要求。

那么,分完这三类数据集后分别用它们来干嘛呢?

1.训练集:用来训练算法,之前我们谈到被不断输入神经网络来调整w和b的都是训练集的数据。

2.验证集:选择一组超参数构建神经网络并用训练集完训练完以后,导入验证集的x进去,计算输出的y*和y之间的偏差,偏差太大不能接受,就重新选取超参数构建网络进行训练。也就是,验证集是用来训练超参数的,只不过这里的训练是手工完成的,通过人为地不断尝试各种参数构建的模型,来试出一个对于验证集的偏差最小的。不过现在也有一些根据验证集搜索超参数的算法,这里暂时不做讨论。

3.测试集:参数和超参数都训练好了,我们的神经网络模型就算是设计完成了。赶紧用测试集最终测试一下,评价一下它的表现吧。通常来说,即使在测试集上表现不好,我们也不会再根据测试集再去调整超参数了,不如测试集就又变成验证集了。

 

五、神经网络的过拟合现象和正则化方法

所谓过拟合,就是神经网络在使用数据进行训练的过程中,把一些由随机误差产生的噪音数据也拟合进了我们的模型当中,这就会导致我们的神经网络在训练集中表现很好,而在测试集中表现却很差。解决这个问题的方法有以下几种():

1.在损失函数中添加正则化项:

我们知道,在训练神经网络的过程中,我们的目标是让损失函数越小越好。由此,如果我们将原来的损失函数L=(sum((y-y*)^2))改成L=(sum((y-y*)^2))+sum(w^2),那么为我们在最小化神经网络的输出与真实y值之间误差的同时,也在最小化各个参数的平方和,这种方式可以限制参数的取值范围,使神经网络可选取的参数可能性变少,从而降低模型过拟合的可能性。

2.使用随机失活(Dropout):

使用这种方法的时候,我们首先设置一个失活的概率p%,在前向传播时,当一堆输入值要进入下一层时,对下一层的节点随机的去掉p%,只用剩下的节点进行这次的前向传播,那些别去掉的节点对应的输出值就是0。其他的计算过程全都不变,然后到最后整个网络训练完毕后,使用网络时每一层的输出量要除以(1-p)%再输入下一层。

3.增加训练集数量。

4.数据增强:

原理同第三条,但是处理方式是将已有数据进行一些转换,是它变成不一样的数据,这样也能够增加数据的数量。比如,在小猫的图像识别任务中,将现有的小猫图片进行旋转。

5.提前结束训练(不做介绍)。

6.给参数设置球型限制域(第1种)。

 

六、输入值的归一化

1.输入神经网络的输入值有不同维度,每个维度如果数值差距很大的话,会严重影响神将网络的训练过程中,所以要对输入的x每个维度x1、x2、x3.。。。进行归一化。方法有(1)最大最小法(x-min)/(max-min)(2)z-score (x-均值)/标准差

2.另外,最好将输入量的特征预先进行降维处理和打乱顺序。

3.同样的,我们也会希望网络中每一层的输如值都能先进行归一化再输入其中,但我们在操作过程中会对激活函数前的z而不是激活函数后的a进行归一化,此处我们使用以下方程即可:z*=a【(z-均值)/sqrt(方差-ep)】+b,其中ep是我们需要去设置的超参数(一个非常小的数以防分母为零),则圆括号操作后的变量符合N(0,1)分布,整个等式操作后的变量符合N(b,a^2)。

你可能感兴趣的:(数据科学个人笔记:神经网络(矩阵化+正则化))