简介
前面,针对图片训练了简单的逻辑分类器,现在,我们会将该分类器转变为深度网络
只需要几行代码就能搞定,所以一定要确保十分理解之前的内容。
在第二部分,将简单地介绍如何完全通过优化器计算任意函数的斜率
第三部分,将学习一个重要的概念 即规则化,通过规则化我们能够训练更加庞大的模型
参数的数量
目前训练的简单模型看起来不错,但是功能却有限,不妨思考个问题,该模型世界上有多少个训练参数?
提醒下 每个输入值都是28*28的图片 输出值是10个类
矩阵W 取整个28*28像素的图像作为输入,输出大小是10 所以矩阵的另一个维度是10
偏置向量是1*10,所以参数的总数目是
Total number of parameters
= size of W + size of b
= 28x28x10 + 10
= 7850
线性模型的局限性
这是一般情况,如果你有N个输入值 K个输出值 则可以使用(N+1)K个参数,不能再多了
问题是 实际上你可能需要使用多得多的参数。
而且该算式是线性的。这意味着你使用该模型,能够表示的算式关系是有限的
例如 如果两个输入值的算式关系是相加,则你的模型可以通过矩阵相乘来很好的表示这一关系
但是 如果两个输入值的算式关系是相乘,则无法使用线性模型有效地表示这一关系
但是线性运算本身还是很有用的,大的矩阵相乘正是图形处理器的设计宗旨
图形处理器相对来说成本低廉而且速度非常快
从数学角度来讲 线性运算非常稳定,我们可以通过数学公式来演示,
输入值得小小变化绝对不会使输出值出现非常大的波动
其中的导数也很理想,线性函数的导数是常量,在数学上没有什么比常量更加稳定的了
我们希望将参数保持在大的线性函数里面,但是又希望整个模型是非线性的
我们不能仅仅通过线性函数将输入值不断地相乘,因为这就等同于一个大的线性函数
因此现在介绍的是非线性函数
ReLUs 网络
现在介绍偷懒的工程师最喜欢使用的非线性函数 修正线性单元(the rectified linear units)简称ReLU
ReLU 绝对是你能够想到的最简单的非线性函数,如果x大于0则是线性函数,如果x小于等于0 输出就保持为0
ReLU 的导数也很理想the derivative of the segment to the left would be zero, as the value remains constant (x=0), and to the right would be a constant (=1) since it grows linearly (y=x).
因为我们是偷懒工程师,所以我们需要运用能够派的上用场的工具,
也就是逻辑分类器 只需要稍加修改 就能变成非线性函数
我们将用最简便的方法构建新的函数 我们将直接在公式中间插入一个ReLU
而不是将单个矩阵因子当做分类器。现在我们获得了两个矩阵
一个将输入值传递到ReLU中,一个将ReLU与分类器相连。我们已经解决了两个问题
通过在中间插入ReLU函数现在已经变成非线性函数
我们现在已经找到可以调节公式的新切入点,这里的H对应的是分类器中ReLU的个数
我们可以根据需要将H调的非常大。这就已经构建了第一个神经网络
你可能想问,神经元在哪里呀?
过去 提到神经网络 我能记起的都是由树突和轴突组成的图表 还有激发函数、大脑、神经科学,这些都在哪里?
不提神经元
是的,我们可以用神经网络来比喻大脑,这样很直观,甚至可能是正确的,但是其中涉及到的知识太复杂了
而且有时候可能会让你走偏了,所以在本课程中,不会介绍神经网络。
我们不需要成为巫师或科学家,如果你是个偷懒的工程师,拥有一个大的图形处理器
并且只想机器学习的效果能更好,则构建神经网络自然是最合理的选择。
但是,我们需要好好地讲讲数学原理了
两层神经网络
注意:以上描述的是一个“两层”神经网络
1、第一层是由一组X的权重和偏差组成并通过ReLU函数激活。
这一层的输出会提供给下一层,但是在神经网络的外部不可见,一次被称为隐藏层
2、第二层有隐藏层的权重和偏差组成,隐藏层的输入即为第一层的输出,然后由
Softmax函数来生成概率
链式法则
为何要通过将简单的运算公式,例如相乘,相加还有ReLU,相互叠加在一起构建一个网络
原因很简单,因为这在数学上是非常简单的,简单到深度学习框架能够帮你实现
关键的数学点是链式法则(chain rule)
如果你有两个组合函数,将一个函数的结果运用到另一个函数中,则利用链式法则
你可以求出这个组合函数的导数,只需要求出各部分的导数并计算他们的乘积
作用太强大了,只要你知道如何写出大哥函数的导数,就有一个简单的图形方法将他们结合到一起
并计算出整个函数的导数。从计算机科学家角度来说,这更是个好消息了
有一个编写该链式法则的非常高效的计算方法,你可以多次重复使用数据
看起来就像个简单的数据管道
反向传播
假设你的神经网络 是由一系列的简单运算构成,譬如线性变换、ReLU等等
有的变换有参数,如矩阵变换,有的则没有,如ReLU
当你把数据输入到x,它们将会经过这堆运算,然后得到预测值y
为了计算相应的偏导数 我们又画出了新的流程图来演示如何运算,数据在新图中的流动方向与之前的方向相反,
它集成了我们刚演示的链式法则来计算出梯度,这个图,可以完全自动地从你神经网络中每一个单独的运算出导出
大多数深度学习框架,都将会为我们完成这项工作
这就叫做反向传播法(back-propagation),是一个非常强大的概念
在函数是由由简单导数的函数复合而成的时候,该方法使得计算函数偏导数的过程变得非常高效
运行该模型进行预测的过程一般被称为 正向传播
而当模型反向运行以计算偏导数的时候 则被称为 逆向传播
让我们来总结一下,在使用梯度下降法时,对训练集中的每一小批数据,你先后要运行正向、逆向传播
如此,你将会求出你模型各个权重的梯度值,然后,你就可以在原始的权重上,使用求出的梯度值和学习率来更新它
你将会重复该过程一次又一次,而这 就是你的模型变得优化的全部过程。
这里不展开讲每一步运算背后具体的运算过程,因为,通常不需要担心那些问题
因为它的核心就是链式法则,不过要记住,这个流程图,特别是逆向传播中的每个区块,
相比正向传播,它们通常需要花费两倍的运算与储存空间
当你需要改变你模型尺寸,并放到内存中的时候,这将会非常重要
训练一个深度神经网络
现在,你有一个“小”神经网络,它不是很“深”仅仅只有两层
通过增大中间隐藏层的尺寸,你可以让它变的更大,更复杂
但总体上说,仅仅增大H数,并非高效的手段
你需要让他变的非常非常大,当然这也会使它很难被训练
而这正是深度学习核心思想发挥作用的地方
实际上,你可以通过增加更多层的方式,来使你的模型变得更“深”
有如下原因:
一个是参数的“效率” -- 通过让网络变深的方式,你可以通过增加较少的参数以使模型表现大为改善
另一个原因是,这会出现很多神奇的现象。更深模型,往往会呈现出层次化的结构
我们以一个图形分类器模型为例,若我们画出它每层所学到的内容
你会发现模型最底层会是一些非常简单的东西,例如线、边等
再往右看,则会有更复杂的东西出现,例如几何形状等
再往深处看,你则会看到一些更具体的内容,例如脸、物件等。该模型因此而显得十分强大
因为模型能够学习到数据中的抽象内容,而这正是你所期望的
而最终,模型也会因此而更快地完成学习过程
正则化
为什么我们不更早一点提出更为高效地深度模型呢?
这又有很多原因,但最主要的是,当你有足够的训练数据时,深度模型才会表现优异
在近年,学界才有机会接触到足够大规模的数据集
当然还有另外的原因,其中之一便是在当下我们知道,如何更好地利用正则化方法来训练很大的模型
在用数值优化训练模型的时候,你通常会遇到被成为“小裤子”(skinny jeans)的问题
也就是 很紧的裤子 看起来很棒也很合身,但它们很难被穿上
所以大部分人,都会穿上稍大一点的裤子
这与深度网络相类似
与你给出的数据非常符合的模型 ,将会很难被优化
所以在实际应用中,我们往往会尝试一个更泛化,但不是那么符合我们数据的模型,以解决过拟合的问题
第一种防止过拟合的方法,是通过观察模型在验证集的表现,并在模型开始过拟合的时候,停止训练
这种方法叫做“早停”并且它是防止你模型,对于训练集过度优化的最好方法
另一种方法是使用正则化
正则化即是,在网络上施加额外的限制,以此来间接地减少自由变量的参数数量
但同时却不增大优化的难度,在穿 紧裤子 比喻中,你可以想想弹力裤
这种裤子非常贴身,但因为它具有弹性,所以也能很好的适应其他人
在该问题中,这个“弹力裤”就是我们所说的L2正则化
它的核心思想是在罚函数中加入一个额外的一项,以削减大权重的影响
它的常用做法是在罚函数中加上权重矩阵的L2范数,乘以一个小常数得到的值
不过结果就是不可避免的引入了一个超参数要去调试
L2正则化最好的地方,莫过于它非常非常的简单,因为你仅在你的罚函数上加上了一个数值
而你神经网络的架构并未因此改变
并且你能很快地徒手算出它的导数
注意L2范数 意思是:向量里每一个数平方的和
那么请问,这些选项里,哪个是L2范数的导数?
对于该矩阵每个分量求导后,类似地,会得到与原来相同的值,因此答案是第三个
Dropout
对于正则化而言,我们有另一个重要的技巧,它近期才出现,但功能非常强大
当你刚接触到这个,你甚至会觉得这有些疯狂,他叫做,dropout丢弃法
dropout的机理是这样的,假设这一层与这一层升级网络相连
从前面一层到后面一层的值叫做激活值
在训练你神经网络的过程中对每个样列,任选所有激活值中的一半,并把他们设为0
在这个完全随机的过程中,你将选取流过神经网络的一半的数据,并直接忽略它
然后对下一组数据也进行如下随机的过程
如果你不觉得这很疯狂的话,那你可算是最先提出该方法的Jeffery Hinton的合格学生了
所以在该过程后会发生什么?
你的神经网络不能再依赖任何给定的激活值,因为它们很可能在下一秒就被忽略掉
因此,它要学习一个redundant冗余的表达式,以确保至少部分的信息被保留了
这就像是打地鼠游戏一样,万一一个激活值被删去了,但总会有另外的能起到相同作用的、未被删除的激活值
最终一切看起来并没有问题
让你的神经网络学习冗余的表达式看起来是一个低效的行为
但在实践中,它使得系统更为坚实,并能够防止过拟合
同时,它使得你的神经网络变得像是由一群神经网络的集成的
这也是改善表现的好方法
dropout是最近几年刚出现的一个 非常重要的方法
如果连这个方法都没有用的话,看来你需要使用一个更大的网络了
当你评估被使用Dropput训练的神经网络的时候
你很显然不希望这种随机性,你更加希望一些确定的东西
取而代之的,你将会分析这一对冗余模型的集群
通过取激活值的平均,你将会得到一个综合的评估,
这个Ye是所有训练时得到的Yt 的平均值,这是一个小技巧,使这个估计成立
在训练过程中,不仅对于dropout的激活值使用0代替,而今,对其他激活值放大到二倍
在这种方法下,在评估时对模型取均值时,你只需要删除丢弃值,并且合理缩放其他的值即可
所以结果是,你将得到一个被合理缩放的,激活值的均值