感慨一下,人工智能这个名字挺有意思,这段时间也不知咋回事,朋友圈里都是学人工智能的,什么python,tf.......还有不少大神在互联网上开讲,也是赚了一笔,现在看来,真是百花齐放,一派繁荣的景象啊,有好有坏,大多数也只是人工的智能,就好像今天要讲的训练和调参,千万不要觉得随随便便就能够获得一个好的结果,若是你没有丰富的经验、大量的实验,等于空谈。固然你彻底能够借鉴别人的经验,甚至是借用别人的成果,可是绝大多数实际的情形,咱们只能是在借鉴的基础上作本身的工做。这篇博客是我以前写的,现在放在博客里,记录下来,勉励同志们共同窗习。python
博客中已经省略了公式,图表引用网上资源,在此表示感谢!网络
近年来,深度学习做为机器学习中比较火的一种方法出如今咱们面前,可是和非深度学习的机器学习相比(我将深度学习归于机器学习的领域内),还存在着几点很大的不一样,具体来讲,有如下几点:框架
综上所述,其实咱们已经认识到了深度学习的本质,其实很简单,就是数据和模型,二者之间相辅相成,相互促进。认识到了深度学习的本质和与通常意义上的机器学习的区别,你才能明白调参和训练的技巧和建议对于深度学习而言是多么的重要,绝不夸张的说,直接影响到咱们刚刚谈到的模型的泛化能力,并且是根本缘由。机器学习
从咱们准备数据集到训练到理想的模型的过程顺序,咱们把其分红以下几个部分分别叙述。函数
(1) Normalization。能够这样认为,归一化主要在干这样一件事:把数据从一个通常的分布,变成0均值、单位方差的分布,为何这么干呢?缘由是这么作更容易收敛,这种方法在Caffe框架中广泛使用(mean value或者mean binaryproto 文件)。Batch Normalization(BN)是一个升级版本,做者主要考虑当使用了饱和的激活函数时,例如sigmoid函数变成0均值、单位方差则会出如今该函数中间近似线性的那一段,这是很是糟糕的,中间线性的部分的拟合能力最差,所以下降了模型的表达capacity,因此BN应运而生,实验代表,其效果sigmoid函数比Relu函数要好。性能
(2) PCA。研究如何以最少的信息丢失将众多原有的变量信息浓缩到少数几个维度上,即所谓的主成分。首先计算出协方差矩阵,而后求出协方差矩阵的特征向量,并用其对原特征进行线性变换,实现降维。学习
(3) Whitening。去除特征向量中各个特征之间的相关性,同时保证每一个特征的方差一致。 设特征向量 X = (X1,X2,X3),对于向量 X,能够计算出相应的协方差矩阵(根据已有数据集来估计)。咱们但愿协方差矩阵是一个对角矩阵,由于这意味着 X 的每一个元素之间都是互不关联的,可是咱们的数据并不具有这样的性质。为了解耦数据,咱们须要对原始特征向量执行一个变换,从而使得变换后的向量 Y 的各个特征之间相关性为0。设 Σ 是 X 的协方差矩阵,有:ΣΦ=ΦΛ, 那么 Λ 中的每一个元素都是协方差矩阵的特征值,Φ 的每一个列向量是相应的特征向量。若是对特征向量作变换:Y = XΦ = X(Φ1,Φ2,Φ3),此时根据向量 Y 计算出来的协方差矩阵是一个对角矩阵。对角矩阵 Λ 的特征值就是 Y 的每一个元素的方差,能够所有相同,也可能不相同,若是对变换后的特征向量的某些维度进行缩放,使得 Λ 的每一个元素都相等,那么整个过程就是 whitening。大数据
3. Initialization(初始化)。当前两步完成以后,能够考虑模型参数的初始化方式了。此处举出实例,Caffe中的参数初始化方式有7种方法,分别为:constant、gaussian、positive_unitball、uniform、xavier、msra和bilinear。用的较多的是xavier用在权重初始化上,constant用在偏置初始化上。人工智能
4. Activation Functions(激活函数)。深度学习之因此具备丰富的表达能力,很是关键的一点是激活函数,这就至关于一系列叠加在一块儿的非线性处理单元,能够想象出这一系列叠加的非线性处理单元原则上能够逼近任意函数(这指的是从输入到输出效果)。几种经常使用的激活函数:sigmoid、tanh和Relu,可是咱们又介绍过以前普遍使用的sigmoid和tanh等饱和激活函数,使用它们在很深网络模型中的训练效果每每很很差,由于存在梯度消失的问题,例以下图中是一个sigmoid函数的例子,因为神经网络在反向传播时,须要乘以激活函数的一阶导数,这样逐层往前传,可想0.930=0.042,这就产生了两个极端,出现了以下图所示的梯度消失区,一旦梯度都已经很小了,还怎么学习?咱们在Caffe中经常使用Relu函数有效地避免这一问题。spa
图1 sigmoid函数
5. During training(训练过程当中)。在训练过程当中,要掌握学习率的变化策略,通常而言Caffe定义学习率在超参数配置文件中(solver.prototxt),并选择了学习速率的衰减策略(学习速率都是开始的时候大,而后以后变小,如何变,怎么变,咱们将其称为策略,因此在论文中通常都会谈到这一问题),更为重要的是,能够在网络层定义中指定lr_mult选择某一层的学习率,该技巧也可为以后的调参作准备。另一点很是重要的是fine-tune,微调的用处一般状况下就是你选择了一个较为深的model,也就是较为复杂的model,你并不须要把全部的layers都从新训练,而只是训练了其中的some layers,此时咱们彻底能够站在巨人的肩膀上(利用预训练模型的weights初始化),能够省去不少工做,更为重要的是,加上合适的调参还会提升模型的泛化能力(由于预训练的模型每每还未收敛)。具体来讲,存在如下几种情形:
|
很是类似的数据集 |
很是不一样的数据集 |
很是少的数据 |
在顶层调一层线性分类器 |
尝试在不一样的层训练线性分类器 |
很是多的数据 |
可微调一些层 |
微调更多的层 |
注意微调的时候,在Caffe中操做须要改变微调的那些层的名字(同时根据本身的须要改变layer参数,例如图片的通道、全链接层输出的类别数目等)。
6. Regularizations(正则化)。正则化也称为Weight-decay(限制权值)。正则化应该讲是一种避免over-fitting的有效方法,这里咱们插入一段对over-fitting的分析,就个人认识而言,从事机器学习的工程师们常常会遇到不少问题,不少bug,可是能够这样说over-fitting是全部工程师都必须面对的一个问题,其具备很强的通用性,这是因为方法自己所决定的。既然你们都会遇到这个问题,又该如何解决呢?回头看,咱们说过深度学习的本质就是数据和模型,那解决过拟合的根本途径也必须从这两个方向出发,那什么是过拟合呢?形象一点说就是你认为你的model在训练集上已经表现很好了,但是当你把它使用在验证集上的时候,效果则不好,进一步说就是数据集太少或者模型太复杂,二者显然不匹配。如今咱们开始从这两个方向分析,解决方法两个:增长数据集和减少模型的复杂度(限制网络的capacity)。此处正则化就是从减少模型的复杂度出发的一项技术,其本质就是控制模型学习的特征数目,使其最小化,从而防止在训练过程当中引入训练集的抽样偏差,正则化包括L2正则化和L1正则化。
7. Dropout。Dropout是指在深度学习网络的训练过程当中,对于神经网络单元,按照必定的几率将其暂时从网络中丢弃,以下图所示。对于随机梯度降低来讲,因为是随机丢弃,所以每个mini-batch都在训练不一样的网络(对于一个有N个节点的神经网络,采用dropout后,能够认为其是2n个模型的集合),同时每一个网络只见过一个训练数据(每次都是随机的新网络),从而将这些多个模型组合起来,以每一个模型的平均输出做为结果,caffe中也定义了Dropout层。
图2 Dropout示例
8. Insights from Figures。若是说经过上面的方法,你都作了,仍是存在问题,那就须要仔细的检查了,检查的方法有不少,其中最为形象生动的,也就是这里要说的就是画图,从图中进行推断。咱们知道Caffe也给咱们提供了不少画图的tools(称其为可视化),这对写论文、科研分析仍是挺好的。言归正传,下面从网上找到几张图片,这些图片均可以从log中经过tools画出,让咱们来看一看。
图3表示的是不一样学习率下的loss变化曲线,很明显图中的四条曲线随着迭代次数的增长表现出不一样的性能,黄色的曲线随着迭代次数的增长,loss先减小然后剧烈增长,每每引起loss等于Nan,这是因为选择的学习率太大的缘故(ps:本人亲测,有几回我在修改一些模型时,开始的loss就很大,而后选择了较大的学习率,一会儿就Nan了);蓝色的曲线随着迭代次数的增长,loss的减小速率很慢很慢,并且设置的最大迭代次数已经很大,但网络并无收敛,这说明选择的学习率过小了;绿色的曲线随着迭代次数的增长,loss的很快减小,而且网络收敛在一个loss较高的地方居高不下,这说明选择的学习率有点大了,已达到局部最优,可观察在网络loss不降时下降学习率;红色的曲线随着迭代的次数的增长,loss缓慢降低,曲线相对平滑,最终收敛在loss很低的水平上,说明选择的学习率较好。固然图中是理想的曲线,只能说明变化趋势,实际状况下曲线是有波动的,有些毛刺感(ps:大量的实践证实能够接受的就是局部最优和全局最优了,也就是红色和绿色曲线表明的过程,固然大多数同志们遇到的都是局部最优,此时咱们考虑在局部最优的基础上减少学习率继续训练,二者的区别就是局部最优会保持在一个较高的loss上,固然怎么衡量loss高低没有标准,因此局部最优不表明训练结果就差,局部最优的结果也能够媲美全局最优,由于咱们根本不知道全局最优在哪一个地方)。
图3 学习率与loss的关系曲线
图4表示的是不一样迭代次数的loss变化曲线,从图中能够看到随着迭代次数的增长,loss的变化趋势是减少的,注意图中标注出的“宽度”,若是曲线的宽度太大了,则说明有可能你选择的batch过小了,而其实batch的选择在深度学习中也不是随便来的,太大了很差,过小了也很差,太大了会有显存溢出的错误,过小了有可能某个label很难被学到,这每每致使模型不收敛,或者出现loss为Nan等错误。这个时候能够用accum_batch_size来解决因为硬件不足不能选择较大batch的问题。
图4 迭代次数与loss的关系曲线
图5是模型在训练集和验证集上的精度曲线。红色曲线表示的是模型在训练集上的分类精度,能够看到,还不错,随着迭代次数增长,分类的精度也在增长,而且有收敛的趋势;绿色曲线表示的是模型在验证集上的分类精度,能够看出,与训练集的精度相比,差距很大,说明模型over-fitting了,应该运用上面说到过的解决方法解决。若是图中二者之间没什么大的差距并且精度都很低,应该增长模型的capacity,提高性能。
图5 模型在训练集和验证集上的精度曲线