1.代价函数
神经网络在分类问题中的应用:
两种分类问题:
第一种是二元分类;这里的y只能是0或1,在这种情况下,我们会有且仅有一个输出单元。K:输出层的单元数目。
第二种是多类别分类问题:即会有K个不同的类,有K个输出单元,假设输出K维向量。
接下来为神经网络单元定义代价函数:
这时我们有K个输出单元,神经网络现在输出了R^K的向量:
这个看起来复杂很多的代价函数背后的思想还是一样的,我们希望通过代价函数来观察算法预测的结果与真实情况的误差有多大,唯一不同的是,对于每一行特征,我们都会给出K个预测,基本上我们可以利用循环,对每一行特征都预测K个不同结果,然后在利用循环在K个预测中选择可能性最高的一个,将其与 y 中的实际数据进行比较。
正则化的那一项只是排除了每一层θ0后,每一层的θ矩阵的和。最里层的循环 j 循环所有的行(由s_l +1 层的激活单元数决定),循环i则循环所有的列,由该层(s_l层)的激活单元数所决定。即:hθ(x)与真实值之间的距离为每个样本-每个类输出的加和,对参数进行regularization的bias项处理所有参数的平方和。
2.反向传播算法
如何让代价函数最小化?反向传播算法!
之前我们在计算神经网络预测结果的时候我们采用了一种正向传播方法,我们从第一层开始正向一层一层进行计算,直到最后一层的hθ(x)。
现在,为了计算代价函数的偏导数:
我们需要采用一种反向传播算法,也就是首先计算最后一层的误差,然后再一层一层反向求出各层的误差,直到倒数第二层。 以一个例子来说明反向传播算法。
前向传播算法:
重要的是清楚地知道上面式子中上下标的含义:
如果我们考虑正则化处理,并且我们的训练集是一个特征矩阵而非向量。在上面的特殊情况中,我们需要计算每一层的误差单元来计算代价函数的偏导数。在更为一般的情况中,我们同样需要计算每一层的误差单元,但是我们需要为整个训练集计算误差单元,此时的误差单元也是一个矩阵,我们用
来表示这个误差矩阵。第 l 层的第 i 个激活单元受到第 j 个参数影响而导致的误差。
如何实现反向传播算法来计算这些参数的偏导数?
3.反向传播算法的直观理解
在上一段视频中,我们介绍了反向传播算法,对很多人来说,当第一次看到这种算法时,第一印象通常是,这个算法需要那么多繁杂的步骤,简直是太复杂了,实在不知道这些步骤,到底应该如何合在一起使用。就好像一个黑箱,里面充满了复杂的步骤。如果你对反向传播算法也有这种感受的话,这其实是正常的,相比于线性回归算法和逻辑回归算法而言,从数学的角度上讲,反向传播算法似乎并不简洁,对于反向传播这种算法,其实我已经使用了很多年了,但即便如此,即使是现在,我也经常感觉自己对反向传播算法的理解并不是十分深入,对于反向传播算法究竟是如何执行的,并没有一个很直观的理解。做过编程练习的同学应该可以感受到这些练习或多或少能帮助你,将这些复杂的步骤梳理了一遍,巩固了反向传播算法具体是如何实现的,这样你才能自己掌握这种算法。
在这段视频中,我想更加深入地讨论一下反向传播算法的这些复杂的步骤,并且希望给你一个更加全面直观的感受,理解这些步骤究竟是在做什么,也希望通过这段视频,你能理解,它至少还是一个合理的算法。但可能你即使看了这段视频,你还是觉得反向传播依然很复杂,依然像一个黑箱,太多复杂的步骤,依然感到有点神奇,这也是没关系的。即使是我接触反向传播这么多年了,有时候仍然觉得这是一个难以理解的算法,但还是希望这段视频能有些许帮助,为了更好地理解反向传播算法,我们再来仔细研究一下前向传播的原理:
前向传播算法:
反向传播算法做的是:
看了几个讲解反向传播的博客,我现在的理解就是,反向传播就是将神经细胞的输出误差反向传播到输入端,通过梯度下降来更新神经细胞输入端的权重。即首先用正向传播方法计算出每一层的激活单元,利用训练集的结果与神经网络预测的结果求出最后一层的误差,然后利用该误差运用反向传播法计算出直至第二层的所有误差。求出误差值以后,通过偏导数和链式法则将误差值转换为权重矩阵。
4.实现注意:展开参数
在上一段视频中,我们谈到了怎样使用反向传播算法计算代价函数的导数。在这段视频中,我想快速地向你介绍一个细节的实现过程,怎样把你的参数从矩阵展开成向量,以便我们在高级最优化步骤中的使用需要。
5.梯度检验
当我们对一个较为复杂的模型(例如神经网络)使用梯度下降算法时,可能会存在一些不容易察觉的错误,意味着,虽然代价看上去在不断减小,但最终的结果可能并不是最优解。
为了避免这样的问题,我们采取一种叫做梯度的数值检验(Numerical Gradient Checking)方法。这种方法的思想是通过估计梯度值来检验我们计算的导数值是否真的是我们要求的。
从数值上去估算代价函数J关于任何参数的偏导数:
在神经网络中使用这种方法时,使用了for循环,来完成对神经网络中代价函数的所有参数的偏导数的计算,然后与反向传播中得到的梯度进行比较,以验证反向传播的实现是正确的。
总结:如何实现梯度检验以及为什么要关掉梯度检验:
梯度检验代码是一个计算量非常大的,也是非常慢的计算导数的程序,相对地,我们之前讲的反向传播算法是一个高性能的计算导数的方法,所以一旦你通过梯度检验反向传播的算法是正确的,就应该关掉梯度检验。
重申一下:在运行算法之前,比如多次迭代的梯度下降,或是多次迭代,或训练分类器的高级优化算法,先禁用你的梯度检验代码。具体地,如果你在每次梯度下降迭代或者在每次代价函数的内循环里,都进行一次梯度检验,程序就会变得非常慢,因为梯度检验代码相比于反向传播算法要慢很多。
6.随机初始化
当你执行一个算法,例如梯度下降法或者高级优化算法时,我们需要为变量θ选取一些初始值。
高级优化算法默认你会给它一个初始值,在梯度下降法中,初始化完毕后,一步一步通过梯度下降来最小化代价函数J,那么应该如何对θ设初始值呢?有一种想法是将θ值全部设为0。
但是对于神经网络,不需要这么做:
这就意味着这个神经网络计算不出什么有趣的函数!所有的隐藏单元都在计算相同的特征,所有的隐藏单元都以相同的函数作为输出,这是一种高度冗余现象,最后的逻辑回归单元只能得到一个特征。为了避免这种情况的发生,要使用随机初始化的思想!
总而言之,为了训练神经网络,应首先要将权重随机初始化为一个接近0的,范围在-ξ到ξ之间的数,然后进行反向传播,再进行梯度检验,最后使用梯度下降或者其他高级优化算法来最小化代价函数J,这个关于参数θ的函数。
这是一种打破对称性的操作!
7.综合起来
神经网络相互之间有怎么样的联系?以及神经网络学习算法的总体实现过程?
训练神经网络时,我们要做的第一件事就是选择一种网络架构(神经元之间的连接模式),输入单元,输出单元,隐藏层!怎么做出选择呢?
首先我们已经定义了输入单元的数量,一旦你确定了特征集x,输入单元的数量就等于特征x^(i)的维度,输入单元个数就确定下来了。
如果你正在进行多类别分类,那么输出层的数目将会由你分类问题中所要区分的类别个数确定,记得把y重新写成向量的形式。
隐藏层常见的是选择一层,即单隐藏层(较为合理的默认结构)。或者如果你使用不止一个隐藏层的话,同样也有一个合理的默认选项,那就是每一个隐藏层通常都应有相同的单元数。通常情况下,隐藏单元越多越好,不过如果有大量的隐藏单元,计算量一般会比较大。并且每个隐藏层所包含的单元数量还应该和输入x的维度相匹配,即和特征的数目匹配。隐藏单元的数目可以和输入特征的数量相同或者是它的二倍或者三四倍。
小结一下使用神经网络时的步骤:
网络结构:第一件要做的事是选择网络结构,即决定选择多少层以及决定每层分别有多少个单元。
第一层的单元数即我们训练集的特征数量。
最后一层的单元数是我们训练集的结果的类的数量。
如果隐藏层数大于1,确保每个隐藏层的单元个数相同,通常情况下隐藏层单元的个数越多越好。
我们真正要决定的是隐藏层的层数和每个中间层的单元数。
训练神经网络:
参数的随机初始化
利用正向传播方法计算所有的hθ(x)
编写计算代价函数 J 的代码
利用反向传播方法计算所有偏导数
利用数值检验方法检验这些偏导数
使用优化算法来最小化代价函数
对于神经网络,J(θ)是一个非凸函数,因此理论上可能停留在局部最小值的位置,实际上,梯度下降法和其他一些高级优化算法理论上都可能收敛于局部最小值,但一般来讲,在实际操作中,这些都不是大问题,尽管我们不能保证一定能得到全局最优值,但一般而言,算法运行的还是不错的,通常能够得到一个很小的局部最小值,尽管这可能不是全局最优值。
神经网络的梯度下降法和之前的线性回归梯度下降法其实原理差不多!
原理:试图找到某个最优的参数值使得神经网络的输出值与训练集观测到的y^(i)的实际值尽可能地接近。
不懂!没关系!如果你实现了反向传播算法,你一定会发现这的确是一个很强大的学习算法,如果你执行以下这个算法,执行反向传播,执行其中的优化算法,你一定会发现,反向传播算法能够让更复杂、强大、非线性的函数模型跟你的数据很好地拟合。
8.自主驾驶
在这段视频中,我想向你介绍一个具有历史意义的神经网络学习的重要例子。那就是使用神经网络来实现自动驾驶,也就是说使汽车通过学习来自己驾驶。接下来我将演示的这段视频是我从 Dean Pomerleau那里拿到的,他是我的同事,任职于美国东海岸的卡耐基梅隆大学。在这部分视频中,你就会明白可视化技术到底是什么?在看这段视频之前,我会告诉你可视化技术是什么。
在下面也就是左下方,就是汽车所看到的前方的路况图像。
在图中你依稀能看出一条道路,朝左延伸了一点,又向右了一点,然后上面的这幅图,你可以看到一条水平的菜单栏显示的是驾驶操作人选择的方向。就是这里的这条白亮的区段显示的就是人类驾驶者选择的方向。比如:最左边的区段,对应的操作就是向左急转,而最右端则对应向右急转的操作。因此,稍微靠左的区段,也就是中心稍微向左一点的位置,则表示在这一点上人类驾驶者的操作是慢慢的向左拐。
这幅图的第二部分对应的就是学习算法选出的行驶方向。并且,类似的,这一条白亮的区段显示的就是神经网络在这里选择的行驶方向,是稍微的左转,并且实际上在神经网络开始学习之前,你会看到网络的输出是一条灰色的区段,就像这样的一条灰色区段覆盖着整个区域这些均称的灰色区域,显示出神经网络已经随机初始化了,并且初始化时,我们并不知道汽车如何行驶,或者说我们并不知道所选行驶方向。只有在学习算法运行了足够长的时间之后,才会有这条白色的区段出现在整条灰色区域之中。显示出一个具体的行驶方向这就表示神经网络算法,在这时候已经选出了一个明确的行驶方向,不像刚开始的时候,输出一段模糊的浅灰色区域,而是输出一条白亮的区段,表示已经选出了明确的行驶方向。
ALVINN (Autonomous Land Vehicle In a Neural Network)是一个基于神经网络的智能系统,通过观察人类的驾驶来学习驾驶,ALVINN能够控制NavLab,装在一辆改装版军用悍马,这辆悍马装载了传感器、计算机和驱动器用来进行自动驾驶的导航试验。实现ALVINN功能的第一步,是对它进行训练,也就是训练一个人驾驶汽车。
然后让ALVINN观看,ALVINN每两秒将前方的路况图生成一张数字化图片,并且记录驾驶者的驾驶方向,得到的训练集图片被压缩为30x32像素,并且作为输入提供给ALVINN的三层神经网络,通过使用反向传播学习算法,ALVINN会训练得到一个与人类驾驶员操纵方向基本相近的结果。一开始,我们的网络选择出的方向是随机的,大约经过两分钟的训练后,我们的神经网络便能够准确地模拟人类驾驶者的驾驶方向,对其他道路类型,也重复进行这个训练过程,当网络被训练完成后,操作者就可按下运行按钮,车辆便开始行驶了。
每秒钟ALVINN生成12次数字化图片,并且将图像传送给神经网络进行训练,多个神经网络同时工作,每一个网络都生成一个行驶方向,以及一个预测自信度的参数,预测自信度最高的那个神经网络得到的行驶方向。比如这里,在这条单行道上训练出的网络将被最终用于控制车辆方向,车辆前方突然出现了一个交叉十字路口,当车辆到达这个十字路口时,我们单行道网络对应的自信度骤减,当它穿过这个十字路口时,前方的双车道将进入其视线,双车道网络的自信度便开始上升,当它的自信度上升时,双车道的网络,将被选择来控制行驶方向,车辆将被安全地引导进入双车道路。
这就是基于神经网络的自动驾驶技术。当然,我们还有很多更加先进的试验来实现自动驾驶技术。在美国,欧洲等一些国家和地区,他们提供了一些比这个方法更加稳定的驾驶控制技术。但我认为,使用这样一个简单的基于反向传播的神经网络,训练出如此强大的自动驾驶汽车,的确是一次令人惊讶的成就。