译者:本文为转载的英文文章,将逐步翻译成中文,本章内容侧重将随机梯度下降的训练方法,涉及不少数学知识,如果觉得枯燥直接看第三章,第三章给出了Python的实现代码和程序说明:http://www.cnblogs.com/pathrough/p/5855084.html
原文地址:http://neuralnetworksanddeeplearning.com/chap1.html
由于文章很长,编辑器很卡,翻译时我会分成几个篇章。上一章的地址是:http://www.cnblogs.com/pathrough/p/5297031.html
一个简单的用来分类手写数字的网络
我们已经定义了什么是神经网络,让我们回到手写识别这个话题。 我们可以将手写识别的问题分成两个小问题。第一是将一张包含多个数字的图片分成多张包含一个数字的图片。例如,我们想将图片切开
![](https://i-blog.csdnimg.cn/blog_migrate/97cf68b7cf0bc287347140cd15ef0c1f.png)
成六个独立的图片
![](https://i-blog.csdnimg.cn/blog_migrate/71f4dd1d9bf6227381cfab874d72296f.png)
我们人类很容易解决这个分割的问题,但是对于计算机这是很难的工作。一旦图片被分开了,计算机就可以对单独的图片进行分类了。例如,我们想让我们的程序能够将下面第一张图片
![](https://i-blog.csdnimg.cn/blog_migrate/636994d0cc7c9b5622a24a1a50c2d760.png)
识别为 5。
我们先不管图片切分的问题,我们集中讲解如何写一个程序来解决第二个问题,也就是如何将单个数字的图片分类。因为一旦你有了好的方法去分类单个数字的图片,那么图片切分的事情也不会很难。有很多方法来解决图片切分的问题。其中一个是用不同的方法切分图片使用单个数字的分类器来给每个切分的图片评分。如果对单个图片分类很有信心本次分割尝试就获得高分,反之获得低分。
为了识别单个数字,我们使用三层神经网络:
![](https://i-blog.csdnimg.cn/blog_migrate/2f6c2e081d2c2717d6731ebf2f63377d.png)
输入层包含输入像素的值的神经元。我们的训练数据由28X28个神经元组成。为了简单起见我在图中省略大部分输入神经元。输入的像素是灰度值,0.0表示白,1.0表示黑。从0到1黑色逐渐加深。
网络的第二次是隐藏层。 我们指定在隐藏层的神经元的数量为n,我们会用不同的值来试验n。这个例子展示了一个小的隐藏层,只有n=15个神经元。
输出层包含10个神经元。如果第一个神经元激活,例如,输出 ≈1,那么表明神经网络认为这个数字是0。如果第二个神经元激活那么表明神经网络认为输入的数字是1,以此类推。更准确一点说,我们将输出神经元从0到9编号,然后算出哪一个神经元有最高的值。如果这个神经元是,假如6号神经元,那么我们的网络会猜输入数字是6,其它输出神经元以此类推。
你可能会疑惑为什么我们使用10输出神经元。最终,网络的目的是告诉我们数字 (0,1,2,…,9) 对应输入的图片。一个看起来顺其自然的方法来做就是使用4个输出神经元,训练每个神经元带一个二进制值,依赖于神经元的输出接近0或者接近1。四个神经元足以编码答案了,因为 24=16大于10个可能的输入数字。为什么我们反而使用10神经元呢?这不是很没效率吗? 最根本的理由是凭借经验:我们可以尝试两种网络的设计方式,最终得出结论,对于特定的问题,10个输出的网络比4个输出的神经网络要好很多,但为什么?
为了明白为什么这样做,它让我们思考神经网络的第一原则。考虑一下我们使用10个输出的例子。让我们集中于第一个输出神经元,它用来决定是否输入的数字是0。它通过衡量隐藏层的线索。这些隐藏的神经元做了什么?好,假设第一个隐藏神经元的目的是检测图像是想下面的图片那样:
![](https://i-blog.csdnimg.cn/blog_migrate/22c07df7a272c75cd7911761b306018c.png)
它可以通过着重衡量输入的相连的图像像素,着轻衡量其它输入。相似的方式,让我们假设在隐藏层的第二第三和第四个参数的目的是判断图片是否长成下面图片那样:
![](https://i-blog.csdnimg.cn/blog_migrate/0d5d3a2eb0c7f0e4c6f6889c16a1a60b.png)
如你所想,这四个图像组成一个完整的0的图像,如下图:
![](https://i-blog.csdnimg.cn/blog_migrate/446caef9f526ea921355a8bcc4b42e76.png)
因此如果所有因此的神经元都激活,那么我们可以下结论说这个数字是0。当然这不是唯一的线索来判断是否是0 - 我们可以通过其它方式来判断是否是0(例如通过翻译上面的图像,或者弱化变形)。但至少可以说我们这个就是0。
如果神经网络用这种方法,我们可以给出一个合理的解释,为什么10个输出比4个输出的神经网络要好。如果我们只有四个输出,那么第一个的输出神经元会尝试决定最有意义的二进制数字是什么。这种方法不容易和上图的简单形状扯上关系。
现在,可以说这都是经验所得。没人说过三次神经网络一定和我说的那样,用隐藏神经元来检测简单的构成部分。可能一个更加聪明的学习算法会找到更加好的方法来让我们使用4个输出神经元的设计方式。
练习
- There is有一种方法来判断数字的按位表现形式,就是通过增加一个额外的层到上面的三层网络。这个额外的层从前一个层的输出转换层一个二进制的表现形式,如下图。 给新的输出层找到一系列权重和偏移量。加入第一个3层神经元第三层的输出正确(例如:旧的输出层)有一个激活值至少是 0.99,不正确的输入的激活值小于0.01
![](https://i-blog.csdnimg.cn/blog_migrate/c88e26cf9e4b5a6519f7a31ac597fdaa.png)
用梯度下降算法进行学习
现在我们设计了一个神经网络,它怎么通过学习来识别数字呢?第一件我们要做的是,我们需要一个数据集来学习,我们叫做训练数据集。我们使用 MNIST数据集,这个数据集包含几万个手写数字的扫描出来的图片,和他们对于的数值。数据集的图片像下图那样:
![](https://i-blog.csdnimg.cn/blog_migrate/71f4dd1d9bf6227381cfab874d72296f.png)
当测试网络的时候我们会用这个数据集之外的手写数字来进行。
这个数据集包含两个部分。其中 60,000个图片用来训练,由 250人来写出来的,一半人来自于政府雇员,另外一个是高中生。图片的是黑白的28X28像素。第二部分是 10,000 张图片用了测试神经网络的效果。也是 28X28黑白图片。我们用测试图片来评估神经网络数字识别的学习效果。为了测试的客观性这些测试测试图片有另外的250个人来手写的数字。
我们用x来表示训练的输入。认为每一个训练的输入x 是一个 28×28=784-纬度的向量是很便利的。 每一个变量代表单个像素的灰度值。我们会指定相应的想要的输出为 y=y(x),y是一个10维的向量。例如如果特定的训练图片,x是一个6,那么 y(x)=(0,0,0,0,0,0,1,0,0,0)T是网络的预期输出。注意T 是转换操,将行向量变成普通的列向量。
我们想要的算法是让我们找到权重和偏移量,然后对于所有训练输入x,来自于网络的输出约等于y(x)。为了量化对于我们的神经网络和理想目标的接近程度我们定义了一个消耗函数。有时候这个函数被称为 loss 或者 objective 函数。在这边书uzhong我们使用cost函数这个术语,但在其他神经网络的研究论文或文章中可能用到上面两个术语。
这里,w 表示网络的权重集合,b是所有的偏移量,n是所有输入的训练数字,a是输出向量,总和是所有训练输入x,当然输出值a依赖于x,w和b,但是为了保持符合简单,我没有明确指出这里依赖。符号∥v∥ 只是向量v的长度函数。我们把C称为量化二次 cost函数; 它因为平均方差MSE而被熟知。观察cost函数,我们看到C(w,b)是一个非负数,因为计算和的每一项都是非负数。进一步, cost C(w,b)变得很小,例如, C(w,b)≈0,精确地当y(x)约等于输出a,对于所有训练输入x。所以我们的训练算法工作的很好,如果它可以找到权重和偏移量使得C(w,b)≈0。 相反,如果C(w,b)很大证明神经网络不够符合要求 - 这可能说明大量数字输入后的结果y(x)离输出偏差很大。 训练算法的目标是最小化 cost函数 C(w,b)。换言之,我们希望找到一系列的权重和偏移量来让 cost 变得越来越小。我们会使用一个叫做梯度下降的算法。
为什么引入完全平方Cost?难题我们对图片的数字被网络正确地分类不感兴趣?比起最小化想完全平方Cost代理衡量,为什么不尝试直接最大化那个数字?问题是图片的数字的分类不是一个权重和偏移量的平滑函数的。大多数情况下,对于权重和偏移量的小变化不会导致训练图片的正确地变化。这使得计算出合适的权重和偏移量变得困难。如果我们使用一个类似完全平方Cost的平滑函数,这样会更容易找到合适的权重和偏移量。这就是为什么我们集中将军如何最小化完全平方 cost,只有这样,我们才能检验分类是否准确。
我们想要使用一个平滑的cost函数,你可能想知道为什么我们选择上面的二次函数。 难道这不是一个特设的选择?大概如果我们选择一个不同的cost函数我们会得到不同的权重和偏移量的最小化。 稍后我们会回头看一下 cost 函数,并且作些改变。然而二次 cost 函数对于理解神经网络的基本学习过程很适合,所以限制坚持讲这个。
Recapping, 我们训练神经网络的目的是找到使得二次cost函数C(w,b)得出最小值的权重和偏移量。 这是一个巧妙设置的问题,但 会使人分散注意力 - w 和b 的意思是权重和偏移量,σ函数隐藏在后台,网络架构的选择, MNIST,等等。 如果我们将注意力放在如何实现函数值的最小化,那么会更容易理解。所以现在我们忘掉cost 函数的特定形式,神经网络的连接等等。 相反,我们想象我们有一个简单的很多变量的函数,我们想计算这个函数的最小最小值。 我们准备使用一种可以用来解决这种最小化问题的叫做梯度下降的技术。然后回到特定的我们想用来最小化神经网络的函数。
好,我们假设我们尝试最小化函数C(v)。 这可能是任何一个带有多个变量的真值函数, v=v1,v2,… 注意我已经用v代替w 和b 符号,来强调这个可能是任意函数 - 我们不再在神经网络特定的上下文思考。为了最小化C(v) ,它帮助我们把C想象成只有v1,v2两个变量:
![](https://i-blog.csdnimg.cn/blog_migrate/fadadb79295606e25b6044ee69f56639.png)
我们想要做的是找到一个能够达到全局最小化的C。现在,当然, 在上图中,我们可以用肉眼看图找到最小值。但是如果是一个有很多变量复杂的函数, 通常不能用肉眼来看图找到这个函数的最小值。
攻克这个难题的一种方法是使用微积分来尝试找到最小。我们可以计算导数,然后尝试使用它们来找到函数C的极值。当C是一个或者几个变量的函数时,我们可以凭借运气来找到极值。但是当函数有更多变量时,这简直是一个梦魔。 对于神经网络来说,我们通常会有更多的变量 - 最大的神经网络肯呢个会有几千万个权重和偏移量。使用微积分来求最小值有点不切实际。
将C想象成一个有两个变量的函数,我两次提到,如果这是一个有很多变量的函数呢?请相信我,将C函数想象成只有两个变量的函数对于理解是有帮助的。图片有时候会分解,最后两段我们会将一下图形的分解。数学上的好想法通常涉及将直觉上相似的图片区分开。
微积分在这里没起到什么帮助。 幸运的是,有一个漂亮的类比来表明这个算法工作的很好。 我们开始将我们的函数想象成一个山谷。如果你斜眼扫一下下面的图,应该不会很难。我们想象一个球沿着斜坡滚下去,经验告诉我们,球最终会滚到山谷底部。大概我们可以使用这种思想作为一种方法去找到函数的最小值。我们随机选择一个开始点,球重这个点开始滚向山谷的底部。我们可以通过计算微积分导数的方式来模拟。 - 这些导数会告诉我们每一个点的斜率,在每一个点上球改往哪个方向滚动。
你可能假设,我尝试给这个滚动的球写一下牛顿运动方程。 衡量一下摩擦力和重力情况等等。事实上, 我们不准备对滚动的球进行那么严格的受力和运动分析,我们涉及一个算法类求C的最小值,不用去作那么精确的物理仿真。
为了使这个问题更加精确,让我们思考一下 当我们以Δv1速度在v1方向推动小球,在V2方向以Δv2速度推动小球会怎么样。 微积分告诉我们C函数会变成下面这样:
我们准备找到一种选择Δv1和Δv2的方式来使的ΔC为负值;例如:我们选取这些可以让球滚向山谷的值。为了算出如何使得这样的选择方法来帮助定义Δv为v的变化的向量, Δv≡(Δv1,Δv2)T,T 是顺序调换操作,将行向量变成列向量。我们也定义一个C的梯度来作为部分倒数的向量 (∂C∂v1,∂C∂v2)T。我们通过∇C来表示梯度向量∇C,例如:
在某一刻我们用Δv符号来表示变化量ΔC以及梯度∇C。当第一次看到∇C 符号,人们有时想知道符合∇是什么意思。∇是什么意思?事实上,把∇C想成一个数学对象 - 用两个符号来表示。ΔC可重写为:
这个等式帮助解释为什么∇C叫做梯度向量: ∇C 和v的变化以及C的变化有关,这就是梯度。这等我让我们兴奋的是,让我们指点怎样去选择一个Δv来让ΔC变成负值。尤其,加入我们选择
Δv=−η∇C,(10)(10)Δv=−η∇C,
总结一下,梯度下降算法工作的方式是重复地计算梯度∇C,然后向对面方向移动, 向凹地的斜坡滚下去。用图形来形容如下:
![](https://i-blog.csdnimg.cn/blog_migrate/2cda66329ef20f7cb77d4fd6b0e57503.png)
翻译不下去了,这数学。。。,去看下一章吧,有代码实现:http://www.cnblogs.com/pathrough/p/5855084.html