几分钟理解卷积神经网络(二):神经网络的训练

浏览: 1810

作者:YJango
链接:https://www.zhihu.com/question/22553761/answer/126474394
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

三、神经网络的训练

知道了神经网络的学习过程就是学习控制着空间变换方式(物质组成方式)的权重矩阵后,接下来的问题就是如何学习每一层的权重矩阵W。

如何训练:

既然我们希望网络的输出尽可能的接近真正想要预测的值。那么就可以通过比较当前网络的预测值和我们真正想要的目标值,再根据两者的差异情况来更新每一层的权重矩阵(比如,如果网络的预测值高了,就调整权重让它预测低一些,不断调整,直到能够预测出目标值)。因此就需要先定义“如何比较预测值和目标值的差异”,这便是损失函数或目标函数(loss function or objective function),用于衡量预测值和目标值的差异的方程。loss function的输出值(loss)越高表示差异性越大。那神经网络的训练就变成了尽可能的缩小loss的过程。 

所用的方法是梯度下降(Gradient descent):通过使loss值向当前点对应梯度的反方向不断移动,来降低loss。一次移动多少是由学习速率(learning rate)来控制的。

梯度下降的问题:

然而使用梯度下降训练神经网络拥有两个主要难题。

1、局部极小值

梯度下降寻找的是loss function的局部极小值,而我们想要全局最小值。如下图所示,我们希望loss值可以降低到右侧深蓝色的最低点,但loss有可能“卡”在左侧的局部极小值中。

image.png

试图解决“卡在局部极小值”问题的方法分两大类:

  • 调节步伐:调节学习速率,使每一次的更新“步伐”不同。常用方法有:

  • 随机梯度下降(Stochastic Gradient Descent (SGD):每次只更新一个样本所计算的梯度

  • 小批量梯度下降(Mini-batch gradient descent):每次更新若干样本所计算的梯度的平均值

  • 动量(Momentum):不仅仅考虑当前样本所计算的梯度;Nesterov动量(Nesterov Momentum):Momentum的改进

  • Adagrad、RMSProp、Adadelta、Adam:这些方法都是训练过程中依照规则降低学习速率,部分也综合动量

  • 优化起点:合理初始化权重(weights initialization)、预训练网络(pre-train),使网络获得一个较好的“起始点”,如最右侧的起始点就比最左侧的起始点要好。常用方法有:高斯分布初始权重(Gaussian distribution)、均匀分布初始权重(Uniform distribution)、Glorot 初始权重、He初始权、稀疏矩阵初始权重(sparse matrix)

2、梯度的计算

机器学习所处理的数据都是高维数据,该如何快速计算梯度、而不是以年来计算。 其次如何更新隐藏层的权重? 

解决方法是:计算图:反向传播算法

这里的解释留给非常棒的Computational Graphs: Backpropagation(http://colah.github.io/posts/2015-08-Backprop/

需要知道的是,反向传播算法是求梯度的一种方法。如同快速傅里叶变换(FFT)的贡献。 而计算图的概念又使梯度的计算更加合理方便。


基本流程图:

下面就结合图简单浏览一下训练和识别过程,并描述各个部分的作用。要结合图解阅读以下内容。但手机显示的图过小,最好用电脑打开

image.png

  • 收集训练集(train data):也就是同时有input以及对应label的数据。每个数据叫做训练样本(sample)。label也叫target,也是机器学习中最贵的部分。上图表示的是我的数据库。假设input本别是x的维度是39,label的维度是48。

  • 设计网络结构(architecture):确定层数、每一隐藏层的节点数和激活函数,以及输出层的激活函数和损失函数。上图用的是两层隐藏层(最后一层是输出层)。隐藏层所用激活函数a( )是ReLu,输出层的激活函数是线性linear(也可看成是没有激活函数)。隐藏层都是1000节点。损失函数L( )是用于比较距离MSE:mean((output - target)^2)。MSE越小表示预测效果越好。训练过程就是不断减小MSE的过程。到此所有数据的维度都已确定:

  • 训练数据:

  • image.png

    • 数据预处理(preprocessing):将所有样本的input和label处理成能够使用神经网络的数据,label的值域符合激活函数的值域。并简单优化数据以便让训练易于收敛。比如中心化(mean subtraction)、归一化(normlization)、主成分分析(PCA)、白化(whitening)。假设上图的input和output全都经过了中心化和归一化。

    • 权重初始化(weights initialization)在训练前不能为空,要初始化才能够计算loss从而来降低。初始化决定了loss在loss function中从哪个点开始作为起点训练网络。上图用均匀分布初始权重(Uniform distribution)。


    • 训练网络(training):训练过程就是用训练数据的input经过网络计算出output,再和label计算出loss,再计算出gradients来更新weights的过程。

      • 正向传递:计算当前网络的预测值


      • 计算loss:


      • 计算梯度:从loss开始反向传播计算每个参数(parameters)对应的梯度(gradients)。这里用Stochastic Gradient Descent (SGD) 来计算梯度,即每次更新所计算的梯度都是从一个样本计算出来的。传统的方法Gradient Descent是正向传递所有样本来计算梯度。SGD的方法来计算梯度的话,loss function的形状如下图所示会有变化,这样在更新中就有可能“跳出”局部最小值。

      • image.png

        • 更新权重:这里用最简单的方法来更新,即所有参数都 

        • 预测新值:训练过所有样本后,打乱样本顺序再次训练若干次。训练完毕后,当再来新的数据input,就可以利用训练的网络来预测了。这时的output就是效果很好的预测值了。下图是一张实际值预测值的三组对比图。输出数据是48维,这里只取1个维度来画图。蓝色的是实际值,绿色的是实际值。最上方的是训练数据的对比图,而下方的两行是神经网络模型从未见过的数据预测对比图。(不过这里用的是RNN,主要是为了让大家感受一下效果)

        image.png

      • 注:此部分内容不是这篇文章的重点,但为了理解深层神经网络,需要明白最基本的训练过程。 若能理解训练过程是通过梯度下降尽可能缩小loss的过程即可。 若有理解障碍,可以用python实践一下从零开始训练一个神经网络(http://www.wildml.com/2015/09/implementing-a-neural-network-from-scratch/),体会整个训练过程。若有时间则可以再体会一下计算图自动求梯度的方便利用TensorFlow。

        结合Tensorflow playground理解5种空间操作物质组成视角

        打开网页后,总体来说,蓝色代表正值,黄色代表负值。拿分类任务来分析。

        • 数据:在二维平面内,若干点被标记成了两种颜色。黄色,蓝色,表示想要区分的两类。你可以把平面内的任意点标记成任意颜色。网页给你提供了4种规律。神经网络会根据你给的数据训练,再分类相同规律的点。

        image.png

      • 输入:在二维平面内,你想给网络多少关于“点”的信息。从颜色就可以看出来,左边是负,右边是正,表示此点的横坐标值。同理,表示此点的纵坐标值。是关于横坐标值的“抛物线”信息。你也可以给更多关于这个点的信息。给的越多,越容易被分开。

      • image.png

      • 连接线:表示权重,蓝色表示用神经元的原始输出,黄色表示用负输出。深浅表示权重的绝对值大小。鼠标放在线上可以看到具体值。也可以更改。在(1)中,当把输出的一个权重改为-1时,的形状直接倒置了。不过还需要考虑激活函数。(1)中用的是linear。在(2)中,当换成sigmoid时,你会发现没有黄色区域了。因为sigmoid的值域是(0,1)

      • image.png

      • (2)输出:黄色背景颜色都被归为黄点类,蓝色背景颜色都被归为蓝点类。深浅表示可能性的强弱。

        image.png

      • 上图中所有在黄色背景颜色的点都会被分类为“黄点“,同理,蓝色区域被分成蓝点。在上面的分类分布图中你可以看到每一层通过上一层信息的组合所形成的。权重(那些连接线)控制了“如何组合”。神经网络的学习也就是从数据中学习那些权重。Tensorflow playground所表现出来的现象就是“在我文章里所写的“物质组成思想”,这也是为什么我把Tensorflow playground(http://playground.tensorflow.org)放在了那一部分。

        不过你要是把Tensorflow的个名字拆开来看的话,是tensor(张量)的flow(流动)。Tensorflow playground的作者想要阐述的侧重点是“张量如何流动”的。

        5种空间变换的理解:Tensorflow playground下没有体现5种空间变换的理解。需要打开这个网站尝试:ConvNetJS demo: Classify toy 2D data(http://cs.stanford.edu/people/karpathy/convnetjs//demo/classify2d.html

        image.png

      • 左侧是原始输入空间下的分类图,右侧是转换后的高维空间下的扭曲图。

      • image.png

      • 最终的扭曲效果是所有绿点都被扭曲到了一侧,而所有红点都被扭曲到了另一侧。这样就可以线性分割(用超平面(这里是一个平面)在中间分开两类)

        四、“深层”的思考:真的只有这些原因吗?

        文章的最后稍微提一下深层神经网络。深层神经网络就是拥有更多层数的神经网络。

        按照上文在理解视角中所述的观点,可以想出下面两条理由关于为什么更深的网络会更加容易识别,增加容纳变异体(variation)(红苹果、绿苹果)的能力、鲁棒性(robust)。

        数学视角:变异体(variation)很多的分类的任务需要高度非线性的分割曲线。不断的利用那5种空间变换操作将原始输入空间像“捏橡皮泥一样”在高维空间下捏成更为线性可分/稀疏的形状。  物理视角:通过对“抽象概念”的判断来识别物体,而非细节。比如对“飞机”的判断,即便人类自己也无法用语言或者若干条规则来解释自己如何判断一个飞机。因为人脑中真正判断的不是是否“有机翼”、“能飞行”等细节现象,而是一个抽象概念。层数越深,这种概念就越抽象,所能涵盖的变异体就越多,就可以容纳战斗机,客机等很多种不同种类的飞机。

        往期回顾

        几分钟理解卷积神经网络(一):空间变换

        机器学习中的数学知识(二):微积分

        机器学习中的数学知识(一):线性代数

        手把手教你搭建谷歌TensorFlow深度学习开发环境!

        零基础学爬虫(一):不用编程抓取B站弹幕信息

        零基础学爬虫(二):几分钟完成你的第一个爬虫程序!

        零基础学爬虫(三):抓取网页的多个元素

        零基础学爬虫(四):不规则分页的抓取和反爬虫应对方法

        情人节这天,这对90后新婚夫妻做的事情震惊了所有人!

        【创客】手把手教你DIY四轴无人飞行器(建议收藏!)



推荐 0
本文由 李亮辰 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

0 个评论

要回复文章请先登录注册