汝阳网站开发,旅游圈wordpress主题,深圳品牌策划公司推荐,电子商务网站建设 填空题积神经网络(CNN)的参数优化方法from#xff1a;http://blog.csdn.net/u010900574/article/details/51992156著名#xff1a; 本文是从 Michael Nielsen的电子书Neural Network and Deep Learning的深度学习那一章的卷积神经网络的参数优化方法的一些总结和摘录#xff0c;并…积神经网络(CNN)的参数优化方法fromhttp://blog.csdn.net/u010900574/article/details/51992156著名 本文是从 Michael Nielsen的电子书Neural Network and Deep Learning的深度学习那一章的卷积神经网络的参数优化方法的一些总结和摘录并不是我自己的结论和做实验所得到的结果。我想Michael的实验结果更有说服力一些。本书在github上有中文翻译的版本前言最近卷积神经网络(CNN)很火热它在图像分类领域的卓越表现引起了大家的广泛关注。本文总结和摘录了Michael Nielsen的那本Neural Network and Deep Learning一书中关于深度学习一章中关于提高泛化能力的一些概述和实验结果。力争用数据给大家一个关于正则化增加卷积层/全连接数弃权技术拓展训练集等参数优化方法的效果。本文并不会介绍正则化弃权(Dropout), 池化等方法的原理只会介绍它们在实验中的应用或者起到的效果更多的关于这些方法的解释请自行查询。mnist数据集介绍本文的实验是基于mnist数据集合的mnist是一个从0到9的手写数字集合共有60,000张训练图片10000张测试图片。每张图片大小是28*28大小。我们的实验就是构建一个神经网络来高精度的分类图片也就是提高泛化能力。提高泛化能力的方法一般来说提高泛化能力的方法主要有以下几个正则化增加神经网络层数使用正确的代价函数使用好的权重初始化技术人为拓展训练集弃权技术下面我们通过实验结果给这些参数优化理论一个直观的结果1. 普通的全连接神经网络的效果我们使用一个隐藏层包含100个隐藏神经元输入层是784输出层是one-hot编码的形式最后一层是Softmax层。训练过程采用对数似然代价函数60次迭代学习速率η0.1随机梯度下降的小批量数据大小为10没有正则化。在测试集上得到的结果是97.8%代码如下 import network3 from network3 import Network from network3 import ConvPoolLayer, FullyConnectedLayer, SoftmaxLayer training_data, validation_data, test_data network3.load_data_shared() mini_batch_size 10 net Network([FullyConnectedLayer(n_in784, n_out100),SoftmaxLayer(n_in100, n_out10)], mini_batch_size) net.SGD(training_data, 60, mini_batch_size, 0.1,validation_data, test_data)2.使用卷积神经网络 — 仅一个卷积层输入层是卷积层5*5的局部感受野也就是一个5*5的卷积核一共20个特征映射。最大池化层选用2*2的大小。后面是100个隐藏神经元的全连接层。结构如图所示 在这个架构中我们把卷积层和chihua层看做是学习输入训练图像中的局部感受野而后的全连接层则是一个更抽象层次的学习从整个图像整合全局信息。也是60次迭代批量数据大小是10学习率是0.1.代码如下 net Network([ConvPoolLayer(image_shape(mini_batch_size, 1, 28, 28),filter_shape(20, 1, 5, 5),poolsize(2, 2)),FullyConnectedLayer(n_in20*12*12, n_out100),SoftmaxLayer(n_in100, n_out10)], mini_batch_size) net.SGD(training_data, 60, mini_batch_size, 0.1,validation_data, test_data)经过三次运行取平均后准确率是98.78%这是相当大的改善。错误率降低了1/3。卷积神经网络开始显现威力。3.使用卷积神经网络 — 两个卷积层我们接着插入第二个卷积-混合层把它插入在之前的卷积-混合层和全连接层之间同样的5*5的局部感受野2*2的池化层。 net Network([ConvPoolLayer(image_shape(mini_batch_size, 1, 28, 28),filter_shape(20, 1, 5, 5),poolsize(2, 2)),ConvPoolLayer(image_shape(mini_batch_size, 20, 12, 12),filter_shape(40, 20, 5, 5),poolsize(2, 2)),FullyConnectedLayer(n_in40*4*4, n_out100),SoftmaxLayer(n_in100, n_out10)], mini_batch_size) net.SGD(training_data, 60, mini_batch_size, 0.1,validation_data, test_data)这一次我们拥有了99.06%的准确率。4.使用卷积神经网络 — 两个卷积层线性修正单元(ReLU)正则化上面我们使用的Sigmod激活函数现在我们换成线性修正激活函数ReLUf(z)max(0,z),我们选择60个迭代期学习速率η0.03, 使用L2正则化正则化参数λ0.1,代码如下 from network3 import ReLU net Network([ConvPoolLayer(image_shape(mini_batch_size, 1, 28, 28),filter_shape(20, 1, 5, 5),poolsize(2, 2),activation_fnReLU),ConvPoolLayer(image_shape(mini_batch_size, 20, 12, 12),filter_shape(40, 20, 5, 5),poolsize(2, 2),activation_fnReLU),FullyConnectedLayer(n_in40*4*4, n_out100, activation_fnReLU),SoftmaxLayer(n_in100, n_out10)], mini_batch_size) net.SGD(training_data, 60, mini_batch_size, 0.03,validation_data, test_data, lmbda0.1)这一次我们获得了99.23%的准确率超过了S型激活函数的99.06%. ReLU的优势是max(0,z)中z取最大极限时不会饱和不像是S函数这有助于持续学习。5.使用卷积神经网络 — 两个卷基层线性修正单元(ReLU)正则化拓展数据集拓展训练集数据的一个简单方法是将每个训练图像由一个像素来代替无论是上一个像素下一个像素或者左右的像素。其他的方法也有改变亮度改变分辨率图片旋转扭曲位移等。我们把50000幅图像人为拓展到250,000幅图像。使用第4节一样的网络因为我们是在训练5倍的数据所以减少了过拟合的风险。 expanded_training_data, _, _ network3.load_data_shared(../data/mnist_expanded.pkl.gz) net Network([ConvPoolLayer(image_shape(mini_batch_size, 1, 28, 28),filter_shape(20, 1, 5, 5),poolsize(2, 2),activation_fnReLU),ConvPoolLayer(image_shape(mini_batch_size, 20, 12, 12),filter_shape(40, 20, 5, 5),poolsize(2, 2),activation_fnReLU),FullyConnectedLayer(n_in40*4*4, n_out100, activation_fnReLU),SoftmaxLayer(n_in100, n_out10)], mini_batch_size) net.SGD(expanded_training_data, 60, mini_batch_size, 0.03,validation_data, test_data, lmbda0.1)这次的到了99.37的训练正确率。6.使用卷积神经网络 — 两个卷基层线性修正单元(ReLU)正则化拓展数据集继续插入额外的全连接层继续上面的网络我们拓展全连接层的规模300个隐藏神经元和1000个神经元的额精度分别是99.46%和99.43%.我们插入一个额外的全连接层 net Network([ConvPoolLayer(image_shape(mini_batch_size, 1, 28, 28),filter_shape(20, 1, 5, 5),poolsize(2, 2),activation_fnReLU),ConvPoolLayer(image_shape(mini_batch_size, 20, 12, 12),filter_shape(40, 20, 5, 5),poolsize(2, 2),activation_fnReLU),FullyConnectedLayer(n_in40*4*4, n_out100, activation_fnReLU),FullyConnectedLayer(n_in100, n_out100, activation_fnReLU),SoftmaxLayer(n_in100, n_out10)], mini_batch_size) net.SGD(expanded_training_data, 60, mini_batch_size, 0.03,validation_data, test_data, lmbda0.1)这次取得了99.43%的精度。拓展后的网络并没有帮助太多。7.使用卷积神经网络 — 两个卷基层线性修正单元(ReLU)拓展数据集继续插入额外的全连接层弃权技术弃权的基本思想就是在训练网络时随机的移除单独的激活值使得模型对单独的依据丢失更为强劲因此不太依赖于训练数据的特质。我们尝试应用弃权技术到最终的全连接层(不是在卷基层)。这里减少了迭代期的数量为40个全连接层使用1000个隐藏神经元因为弃权技术会丢弃一些神经元。Dropout是一种非常有效有提高泛化能力降低过拟合的方法 net Network([ConvPoolLayer(image_shape(mini_batch_size, 1, 28, 28),filter_shape(20, 1, 5, 5),poolsize(2, 2),activation_fnReLU),ConvPoolLayer(image_shape(mini_batch_size, 20, 12, 12),filter_shape(40, 20, 5, 5),poolsize(2, 2),activation_fnReLU),FullyConnectedLayer(n_in40*4*4, n_out1000, activation_fnReLU, p_dropout0.5),FullyConnectedLayer(n_in1000, n_out1000, activation_fnReLU, p_dropout0.5),SoftmaxLayer(n_in1000, n_out10, p_dropout0.5)],mini_batch_size) net.SGD(expanded_training_data, 40, mini_batch_size, 0.03,validation_data, test_data)使用弃权技术的到了99.60%的准确率。8.使用卷积神经网络 — 两个卷基层线性修正单元(ReLU)正则化拓展数据集继续插入额外的全连接层弃权技术组合网络组合网络类似于随机森林或者adaboost的集成方法创建几个神经网络让他们投票来决定最好的分类。我们训练了5个不同的神经网络每个都大到了99.60%的准去率用这5个网络来进行投票表决一个图像的分类。采用这个方法达到了99.67%的准确率。总结卷积神经网络 的一些技巧总结如下1. 使用卷积层极大地减小了全连接层中的参数的数目使学习的问题更容易2. 使用更多强有力的规范化技术(尤其是弃权和卷积)来减小过度拟合3. 使用修正线性单元而不是S型神经元来加速训练-依据经验通常是3-5倍4. 使用GPU来计算5. 利用充分大的数据集避免过拟合6. 使用正确的代价函数避免学习减速7. 使用好的权重初始化避免因为神经元饱和引起的学习减速CNN超参数优化和可视化技巧详解转自https://zhuanlan.zhihu.com/p/27905191在深度学习中有许多不同的深度网络结构包括卷积神经网络(CNN或convnet)、长短期记忆网络(LSTM)和生成对抗网络(GAN)等。在计算机视觉领域对卷积神经网络(简称为CNN)的研究和应用都取得了显著的成果。CNN网络最初的诞生收到了动物视觉神经机制的启发目前已成功用于机器视觉等领域中。技术博客Towards Data Science最近发布了一篇文章作者Suki Lau。文章讨论了在卷积神经网络中该如何调整超参数以及可视化卷积层。为什么用卷积神经网络首先我们想要计算机具有什么能力呢当我们看到一只猫跳上窗台或在沙发上睡觉时我们的潜意识会认出它是一只猫。我们希望计算机也能完成这项任务即将图像输入后找出其独有的特征最终输出该图像的类别信息。卷积神经网络可以完成这项任务。何为卷积神经网络先谈定义卷积神经网络是一种特殊的神经网络其中至少包含一个卷积层。在典型的CNN网络结构中输入一张图像经由一系列卷积层、非线性激活层、池化层和全连接层后可输出相应的类别标签。卷积神经网络的特别之处在于加入了卷积层。在经典的神经网络中整张图片会被传入网络中来训练各网络层权值。当输入为简单居中的图像时如Mnist手写数字图网络识别效果较优但是当输入变为更为复杂多变的图像时如跳上窗户的小猫此时网络识别效果不佳甚至无法辨识。加入更多隐含层学习输入图像的抽象特征可能会有所帮助但是这样会增加神经元的数目大大增加训练所需的计算资源和占用过多的内存这是不切实际的。而CNN识别目标的过程是先寻找诸如边缘、线段和曲线等相关低级特征然后使用多个卷积层来构建更多抽象的高级特征。在卷积层的学习过程中CNN网络通过共享多个卷积核(或特征检测器)的权值来学习每张图片的局部信息并用于构建抽象特征图谱。卷积核共享特性大大降低了训练网络所需的参数量。由于经过训练的检测器可以通过卷积层重复用来组合地检测图片中的抽象特征因此卷积神经网络更适用于复杂的图像识别任务。超参数调整在深度神经网络中调整超参数组合并非易事因为训练深层神经网络十分耗时且需要配置多个参数。接下来我们简单列举几个影响CNN网络的关键超参数。学习率学习率是指在优化算法中更新网络权重的幅度大小。学习率可以是恒定的、逐渐降低的、基于动量的或者是自适应的采用哪种学习率取决于所选择优化算法的类型如SGD、Adam、Adagrad、AdaDelta或RMSProp等算法。优化策略这方面的内容可参阅量子位之前编译过的“一文看懂各种神经网络优化算法从梯度下降到Adam方法”。迭代次数迭代次数是指整个训练集输入到神经网络进行训练的次数。当测试错误率和训练错误率相差较小时可认为当前的迭代次数是合适的否则需继续增大迭代次数或调整网络结构。批次大小在卷积神经网络的学习过程中小批次会表现得更好选取范围一般位于区间[16,128]内。还需要注意的是CNN网络对批次大小的调整十分敏感。激活函数激活函数具有非线性理论上可以使模型拟合出任何函数。通常情况下rectifier函数在CNN网络中的效果较好。当然可以根据实际任务选择其他类型的激活函数如Sigmoid和Tanh等等。隐含层的数目和单元数增加隐含层数目以加深网络深度会在一定程度上改善网络性能但是当测试错误率不再下降时就需要寻求其他的改良方法。增加隐含层数目也带来一个问题即提高了训练该网络的计算成本。当网络的单元数设置过少时可能会导致欠拟合而单元数设置过多时只要采取合适的正则化方式就不会产生不良影响。权重初始化在网络中通常会使用小随机数来初始化各网络层的权重以防止产生不活跃的神经元但是设置过小的随机数可能生成零梯度网络。一般来说均匀分布方法效果较好。Dropout方法作为一种常用的正则化方式加入Dropout层可以减弱深层神经网络的过拟合效应。该方法会按照所设定的概率参数在每次训练中随机地不激活一定比例的神经单元。该参数的默认值为0.5。手动调整超参数是十分费时也不切实际。接下来介绍两种搜索最优超参数的常用方法。网格搜索和随机搜索网格搜索是通过穷举法列出不同的参数组合确定性能最优的结构。随机搜索是从具有特定分布的参数空间中抽取出一定数量的候选组合。网格搜索方法也需要制定策略在初始阶段最好先确定各超参数值的大概范围。可以先尝试在较小迭代次数或较小规模的训练集上进行大步幅的网格搜索。然后在下个阶段中设置更大的迭代次数或是使用整个训练集实现小幅精确定位。虽然在许多机器学习算法中通常会使用网格搜索来确定超参数组合但是随着参数量的增大训练网络所需的计算量呈指数型增长这种方法在深层神经网络的超参数调整时效果并不是很好。有研究指出在深度神经网络的超参数调整中随机搜索方法比网格搜索的效率更高具体可参考文末中的“随机搜索在超参数优化中的应用”。当然可根据神经网络的理论经验进行超参数的手动调整在一些场景下也是可行的。可视化我们可以通过可视化各个卷积层来更好地了解CNN网络是如何学习输入图像的特征。可视化有两种直接方式分别是可视化激活程度和可视化相关权重。在网络训练过程中卷积层的激活情况通常会变得更为稀疏和具有局部特性。当不同输入图像的激活图都存在大片未激活的区域那么可能是设置了过高的学习率使得卷积核不起作用导致产生零激活图像。性能优良的神经网络通常含有多个明显而平滑的卷积器且没有任何干扰特征。若在权重中观察到相关干扰特征可能原因是网络未被充分训练或是正则化强度较低导致了过拟合效应。神经网络参数优化--基于CNN的验证转自https://ziyubiti.github.io/2016/11/20/cnnpara/当使用多层更深的隐藏层全连接网络时参数量会变得非常巨大达到数十亿量级而采用CNN结构则可以层间共享权重极大减小待训练的参数量同时可采用二维卷积保留图像的空间结构信息采用池化层进一步减少参数计算。一般来说提高泛化能力的方法主要有 正则化、增加神经网络层数、改变激活函数与代价函数、使用好的权重初始化技术、人为扩展训练集、弃权技术。下面以MNIST为例结合CNN、Pooling、Fc结构通过不同的网络结构变化给这些参数优化理论一个直观的验证结果。CNN不同网络结构性能比较可以看出1、使用L2正则化dropout技术扩展数据集等有效缓解过拟合提升了性能2、使用ReLU导数为常量可以缓解梯度下降问题并加速训练3、增加Conv/Pooling与Fc层可以改善性能。(我自己实测也是如此)Note1、网络并非越深越好单纯的Conv/Pooling/Fc结构增加到一定深度后由于过拟合性能反而下降。2、网络结构信息更重要如使用GoogleNet、ResNet等。知乎上的讨论转自https://www.zhihu.com/question/41631631训练技巧对深度学习来说是非常重要的作为一门实验性质很强的科学同样的网络结构使用不同的训练方法训练结果可能会有很大的差异。这里我总结了近一年来的炼丹心得分享给大家也欢迎大家补充指正。参数初始化。下面几种方式,随便选一个,结果基本都差不多。但是一定要做。否则可能会减慢收敛速度影响收敛结果甚至造成Nan等一系列问题。下面的n_in为网络的输入大小n_out为网络的输出大小n为n_in或(n_inn_out)*0.5uniform均匀分布初始化 w np.random.uniform(low-scale, highscale, size[n_in,n_out])Xavier初始法适用于普通激活函数(tanh,sigmoid)scale np.sqrt(3/n)He初始化适用于ReLUscale np.sqrt(6/n)normal高斯分布初始化 w np.random.randn(n_in,n_out) * stdev # stdev为高斯分布的标准差均值设为0Xavier初始法适用于普通激活函数 (tanh,sigmoid)stdev np.sqrt(n)He初始化适用于ReLUstdev np.sqrt(2/n)数据预处理方式zero-center ,这个挺常用的. X - np.mean(X, axis 0) # zero-center X / np.std(X, axis 0) # normalizePCA whitening,这个用的比较少.训练技巧要做梯度归一化,即算出来的梯度除以minibatch sizeclip c(梯度裁剪): 限制最大梯度,其实是value sqrt(w1^2w2^2….),如果value超过了阈值,就算一个衰减系系数,让value的值等于阈值: 5,10,15dropout对小数据防止过拟合有很好的效果,值一般设为0.5,小数据上dropoutsgd在我的大部分实验中效果提升都非常明显(实测sgd比adam好).因此可能的话建议一定要尝试一下。 dropout的位置比较有讲究, 对于RNN,建议放到输入-RNN与RNN-输出的位置.关于RNN如何用dropout,可以参考这篇论文:http://arxiv.org/abs/1409.2329adam,adadelta等,在小数据上,我这里实验的效果不如sgd, sgd收敛速度会慢一些但是最终收敛后的结果一般都比较好。如果使用sgd的话,可以选择从1.0或者0.1的学习率开始,隔一段时间,在验证集上检查一下,如果cost没有下降,就对学习率减半. 我看过很多论文都这么搞,我自己实验的结果也很好. 当然,也可以先用ada系列先跑,最后快收敛的时候,更换成sgd继续训练.同样也会有提升.据说adadelta一般在分类问题上效果比较好adam在生成问题上效果比较好。除了gate之类的地方,需要把输出限制成0-1之外,尽量不要用sigmoid,可以用tanh或者relu之类的激活函数.1. sigmoid函数在-4到4的区间里才有较大的梯度。之外的区间梯度接近0很容易造成梯度消失问题。2. 输入0均值sigmoid函数的输出不是0均值的。rnn的dim和embdding size,一般从128上下开始调整. batch size,一般从128左右开始调整.batch size合适最重要,并不是越大越好.word2vec初始化,在小数据上,不仅可以有效提高收敛速度,也可以可以提高结果.尽量对数据做shuffleLSTM 的forget gate的bias,用1.0或者更大的值做初始化,可以取得更好的结果,来自这篇论文:http://jmlr.org/proceedings/papers/v37/jozefowicz15.pdf, 我这里实验设成1.0,可以提高收敛速度.实际使用中,不同的任务,可能需要尝试不同的值.Batch Normalization据说可以提升效果不过我没有尝试过建议作为最后提升模型的手段参考论文Accelerating Deep Network Training by Reducing Internal Covariate Shift如果你的模型包含全连接层(MLP)并且输入和输出大小一样可以考虑将MLP替换成Highway Network,我尝试对结果有一点提升建议作为最后提升模型的手段原理很简单就是给输出加了一个gate来控制信息的流动详细介绍请参考论文: http://arxiv.org/abs/1505.00387来自张馨宇的技巧一轮加正则一轮不加正则反复进行。EnsembleEnsemble是论文刷结果的终极核武器,深度学习中一般有以下几种方式同样的参数,不同的初始化方式不同的参数,通过cross-validation,选取最好的几组同样的参数,模型训练的不同阶段即不同迭代次数的模型。不同的模型,进行线性融合. 例如RNN和传统模型.其实我发现现在深度学习越来越成熟调参工作比以前少了很多绝大多数情况自己设计的参数都不如教程和框架的默认参数好不过有一些技巧我一直都在用的(1)relubn。这套好基友组合是万精油可以满足95%的情况除非有些特殊情况会用identity比如回归问题比如resnet的shortcut支路sigmoid什么的都快从我世界里消失了(2)dropout 。分类问题用dropout 只需要最后一层softmax 前用基本就可以了能够防止过拟合可能对accuracy提高不大但是dropout 前面的那层如果是之后要使用的feature的话性能会大大提升(例如max pool进入fc实测发现加BN效果非常明显)(3)数据的shuffle 和augmentation 。这个没啥好说的aug也不是瞎加比如行人识别一般就不会加上下翻转的因为不会碰到头朝下的异型种(4)降学习率。随着网络训练的进行学习率要逐渐降下来如果你有tensorboard你有可能发现在学习率下降的一瞬间网络会有个巨大的性能提升同样的fine-tuning也要根据模型的性能设置合适的学习率比如一个训练的已经非常好的模型你上来就1e-3的学习率那之前就白训练了就是说网络性能越好学习率要越小(5)tensorboard。以前不怎么用用了之后发现太有帮助帮助你监视网络的状态来调整网络参数(6)随时存档模型要有validation 。这就跟打游戏一样存档把每个epoch和其对应的validation 结果存下来可以分析出开始overfitting的时间点方便下次加载fine-tuning(7)网络层数参数量什么的都不是大问题在性能不丢的情况下减到最小(8)batchsize通常影响没那么大塞满卡就行除了特殊的算法需要batch大一点(9)输入减不减mean归一化在有了bn之后已经不那么重要了上面那些都是大家所知道的常识也是外行人觉得深度学习一直在做的就是这些很low的东西其实网络设计(关键实测发现对于acc影响极大)上博大精深这也远超过我的水平范畴只说一些很简单的(1)卷积核的分解。从最初的5×5分解为两个3×3到后来的3×3分解为1×3和3×1再到resnet的1×13×31×1再xception的3×3 channel-wise conv1×1网络的计算量越来越小层数越来越多性能越来越好这些都是设计网络时可以借鉴的(2)不同尺寸的feature maps的concat只用一层的feature map一把梭可能不如concat好pspnet就是这种思想这个思想很常用(3)resnet的shortcut确实会很有用重点在于shortcut支路一定要是identity主路是什么conv都无所谓这是我亲耳听resnet作者所述(4)针对于metric learning对feature加个classification 的约束通常可以提高性能加快收敛补充一点adam收敛虽快但是得到的解往往没有sgdmomentum得到的解更好如果不考虑时间成本的话还是用sgd吧。再补充一个rnn trick仍然是不考虑时间成本的情况下batch size1是一个很不错的regularizer, 起码在某些task上,这也有可能是很多人无法复现alex graves实验结果的原因之一因为他总是把batch size设成1。。。没做过CNN,RNN调过连续值DNN以下经验仅限于CTR1.样本要足够随机2.样本要做归一化3.激活函数要视样本输入选择4.minibatch很重要几百到几千是比较合适的(很大数据量的情况下)5.learning rate很重要可以直接用adagrad or adadelta省去一些麻烦然后把冲量调到0.9以上6.权重初始化可用高斯分布乘上一个很小的数小白一枚在这里总结一下我在试验中观察到的现象(必然有理解错误的地方)1. Adam收敛速度的确要快一些可是结果总是不如其他优化算法如果很看重结果不在乎速度还是用其他的试试。2. Dropout的放置位置以及大小非常重要求大神能分享经验.....3. Relu并不是一定比Tanh好如果不太懂的话用的不合适可能会导致梯度消失(不知道是不是网络结构问题为什么一用relu梯度一会儿就变成Nan)4. pretrain 的 Embedding在训练中不调优泛化能力要更好一些调优的话参数会增加好多啊。另心得体会1. 深度学习真是一门实验科学很多地方解释不了为什么好为什么不好。2.如果你机器配置很不到位也没有人带你毕业设计千万别选深度学习天天愁好坑啊。最近在看 Karpathy 的 cs231n, 还没看完, 不过过程中总结了一下他提到的一些技巧:关于参数:通常情况下, 更新参数的方法默认用 Adam 效果就很好如果可以载入全部数据 (full batch updates), 可以使用 L-BFGSModel Ensembles:训练多个模型, 在测试时将结果平均起来, 大约可以得到 2% 提升.训练单个模型时, 平均不同时期的 checkpoints 的结果, 也可以有提升.测试时可以将测试的参数和训练的参数组合起来:分享几个常用的trick1.增加每个step的轮数2.early stop3.用小一些的学习率warmup4.回退到更大的学习率5.nesterov momentum sgd6.搜索初始学习率1.better initialization helps a lot2.use minibatch and choose batch_size(must)3.use batch_norm dropout4.use adam5.plot the learning rate curve6.plot the loss curve.7.lstm gru are almost always better than sample RNN8.use better framework(like tensorflow with tensorboard)9.find hyper parameters used most often in paper10 praycnn的调参主要是在优化函数、embedding的维度还要残差网络的层数几个方面。优化函数方面有两个选择sgd、adam相对来说adam要简单很多不需要设置参数效果也还不错。embedding随着维度的增大会出现一个最大值点也就是开始时是随维度的增加效果逐渐变好到达一个点后而后随维度的增加效果会变差。残差网络的层数与embedding的维度有关系随层数的增加效果变化也是一个凸函数。另外还有激活函数dropout层和batchnormalize层的使用。激活函数推荐使用reludropout层数不易设置过大过大会导致不收敛调节步长可以是0.05一般调整到0.4或者0.5就可找到最佳值。以上是个人调参的一些经验可供参考。1.无论是cnn还是rnnbatch normalization都有用不一定结果提高几个点收敛快多了2.数据初始时normalize得好有时候直接提高2个点比如cifar10转到yuv下normalize再scn3.loss不降了lr就除104. google的inception系列按它论文里说的永远无法复现如何训练深度神经网络老司机的 15 点建议导语印度深度学习专家 Rishabh Shukla 对开发深度神经网络的经验总结。本文为印度深度学习专家、创业者 Rishabh Shukla 在 GitHub 上发表的长博文总结了他过去的开发经验旨在给新入门的开发者提供指导。雷锋网做了不改变原意的编译。在深度学习领域为了高效训练深度神经网络有些实践方法被过来人强烈推荐。在这篇博文中我会覆盖几种最常使用的实践方法从高品质训练数据的重要性、超参数(hyperparameters)到更快创建 DNN(深度神经网络) 原型模型的一般性建议。这些推荐方法中的大多数已被学术界的研究所证实并在论文中展示了相关实验、数学证据比如 Efficient BackProp(Yann LeCun et al.)和 Practical Recommendations for Deep Architectures(Yoshua Bengio)。1. 训练数据许多 ML 开发者习惯把原始训练数据直接扔给 DNN——为什么不这么做呢既然任何 DNN (大多数人的假设)仍然能够给出不错的结果不是吗但是有句老话叫“给定恰当的数据类型一个简单的模型能比复杂 DNN 提供更好、更快的结果”。虽然这有一些例外但在今天这句话仍然没有过时。因此不管你是在计算机视觉( CV)自然语言处理(NLP)还是统计建模(Statistical Modelling)等领域想要对原始数据预处理有几个方法可以得到更好的训练数据获取越大的数据库越好。DNN 对数据很饥渴越多越好。去除所有包含损坏数据的训练样本比如短文字高度扭曲的图像假输出标签包含许多虚值(null values)的属性。Data Augmentation(数据扩张)——生成新样例。以图像为例重新调节增加噪声等等。2. 选择恰当的激励函数(activation function)激励函数是所有神经网络的核心部分之一。激励函数把渴望已久的非线性(non-linearity)加入了模型。多年来Sigmoid 函数 一直是多数人倾向的选择。但是Sigmoid 函数不可避免地存在两个缺陷1. 尾部 sigmoids 的饱和进一步导致梯度消失。2. 不以 0 为中心(输出在 0 到 1 之间)。一个更好的替代选择是 Tanh 函数。数学上来说Tanh 只是调整、平移过的 Sigmoid 函数tanh(x) 2*sigmoid(x) - 1。虽然 Tanh 仍旧存在梯度消失的缺陷但好消息是Tanh 以 0 为中心。因此把 Tanh 作为激励函数能更快地收敛(converge)。我发现使用 Tanh 通常比 Sigmoid 效果更好。你还可以探索其他选择比如 ReLU, SoftSign 等等。对于一些特定任务 它们能够改善上述问题。3. 隐藏单元和隐层(Hidden Units and Layers)的数量保留超出最优数量的隐藏单元一般是比较保险的做法。这是因为任何正则化方法( regularization method)都会处理好超出的单元至少在某种程度上是这样。在另一方面保留比最优数量更少的隐藏单元会导致更高的模型欠拟合(underfitting)几率。另外当采用无监督预训练的表示时(unsupervised pre-trained representations下文会做进一步解释)隐藏单元的最优数目一般会变得更大。因此预训练的表示可能会包含许多不相关信息(对于特定任务)。通过增加隐藏单元的数目模型会得到所需的灵活性以在预训练表示中过滤出最合适的信息。选择隐层的最优数目比较直接。正如 Yoshua Bengio 在 Quora 中提到的“你只需不停增加层直到测试误差不再减少。”4. 权重初始化 (Weight Initialization)永远用小的随机数字初始化权重以打破不同单元间的对称性(symmetry)。但权重应该是多小呢推荐的上限是多少用什么概率分布产生随机数字当使用 Sigmoid 激励函数时如果权重初始化为很大的数字那么 sigmoid 会饱和(尾部区域)导致死神经元(dead neurons)。如果权重特别小梯度也会很小。因此最好是在中间区域选择权重比如说那些围绕平均值均衡分布的数值。幸运的是已经有许多关于初始权重合适取值的研究。这对于高效的收敛非常重要。为初始化均衡分布的权重均匀分布(uniform distribution )或许是最好的选择之一。另外就像论文中所展示的(Glorot and Bengio, 2010)有更多输入连接(fan_in)的单位应该有相对更小的权重。多亏这些十分透彻的试验现在我们已经有了经过检验的公式可以直接用来权重的初始化。比如说在 ~ Uniform(-r, r) 提取的权重对于 tanh 激励 rsqrt(6/(fan_infan_out))对于 sigmoid 激励 r4*(sqrt(6/fan_infan_out)) 。fan_in 是上一层的大小 而 fan_out 是下一层的。5. 学习率这或许是最重要的超参数之一调节着学习过程。如果学习率设置得太小你的模型很可能需要 n 年来收敛。设置得太大再加上不多的初始训练样本你的损失可能会极高。一般来说0.01 的学习率比较保险相比固定学习率在每个周期、或每几千个样例后逐渐降低学习率是另一个选择。虽然这能更快地训练但需要人工决定新的学习率。一般来说学习率可以在每个周期后减半。几年前这种策略十分普遍。幸运的是我们现在有了更好的、基于动能(momentum based)的方法来调整学习率。这取决于误差函数的曲率。另外既然有些参数有更快、或更慢的学习速率它或许能帮助我们针对模型中的单独参数设定不同的学习率。最近有大量关于优化方法的研究导致了自适应学习率(adaptive learning rates)。目前我们有许多选择从老式动能方法( Momentum Method )到 Adagrad、Adam (个人最爱)、 RMSProp 等等。类似于 Adagrad 或 Adam 的方法能替我们省去人工选择初始学习率的麻烦给定合适的时间模型会开始平滑地收敛。当然选择一个特别合适的初始学习率仍然能起到帮助作用。6. 超参数调参扔掉网格搜索拥抱随机搜索网格搜索(Grid Search )在经典机器学习中十分普遍。但它在寻找 DNN 的最优超参数方面一点也不高效。这主要是由于 DNN 尝试不同超参数组合所耗费的时间。随着超参数不断增长网格搜索需要的计算性能会指数级增长。有两种解决办法取决于你之前的经验你可以人工对部分常见超参数调参比如学习率、隐层数目。采用随机搜索(random search)或者随机采样代替网格搜索来选择最优超参数。超参数组合通常在期望范围之内、从均匀分布中被选择出来。加入之前获得的知识来进一步缩小搜寻空间也是有可能的(比如学习率不应该太大也不应该太小)。大家发现随机搜索比网格搜索高效地多。7. 学习方法随机梯度下降( Stochastic Gradient Descent )的老方法也许对于 DNN 不是那么有效率(有例外)。最近有许多研究聚焦于开发更灵活的优化算法比如 Adagrad、Adam,、AdaDelta,、RMSProp 等等。在提供自适应学习率之外这些复杂的方法还对于模型的不同参数使用不同的学习率通常能有更平滑的收敛。把这些当做超参数是件好事你应该每次都在训练数据的子集上试试它们。8. 权重的维度保持为 2 的幂即便是运行最先进的深度学习模型使用最新、最强大的计算硬件内存管理仍然在字节(byte)级别上进行。所以把参数保持在 64, 128, 512, 1024 等 2 的次方永远是件好事。这也许能帮助分割矩阵和权重导致学习效率的提升。当用 GPU 运算这变得更明显。9. 无监督预训练(Unsupervised Pretraining )不管你进行的是 NLP(自然语言处理)、计算机视觉还是语音识别等任务无监督预训练永远能帮助你训练监督、或其他无监督模型NLP 中词向量就(Word Vectors)无所不在你可以用 ImageNet 的数据库使用无监督方式对你的模型预训练或是对于两个类别的监督分类或是更大频域的音频样本来在扬声器消崎模型(speaker disambiguation model)中使用该信息。10. Mini-Batch(小批量) 对比随机学习(Stochastic Learning)训练一个模型的主要目的是学习合适的参数即产生输入到输出的最优映射。这些参数利用每个训练样本进行调参不管你决定使用 batch, mini-batch 还是随机学习。当采用随机学习方法时学习每个训练样本后权重的梯度都会进行调参向梯度加入噪音(随机学习中“随机”的由来)。这样做的结果十分理想比如说训练中加入的噪音使得模型更不容易过拟合。但是随机学习方法也许效率不高。如今的计算设备有非常可观的运算能力随机学习很可能会浪费其中的一大部分。如果我们能计算矩阵相乘那么为什么要限制自己重复单个矢量组之间的乘法呢因此为了更高的吞吐率和更快的学习我推荐使用 mini-batch 而不是随机学习。但是选择适当的 batch 规模同样重要。所以我们能保留一些噪音(相比大规模 batch)与此同时更高效地利用计算性能。一般来说包含 16 个到 128 个样例的 batch(2 的幂)是不错的选择。通常一旦你发现了更重要的超参数(通过随机搜索或是人工搜索)batch 规模就会确性下来。但是有些场景中模型得到训练数据流(比如网络学习)那么采用随机学习就是不错的选择。11. 打乱训练样本这来自于信息理论(Information Theory)——“学习到一件不太可能发生的事却发生了比学习一件很可能发生的事已经发生包含更多的信息。”同样的把训练样例的顺序随机化(在不同周期或者 mini-batch)会导致更快的收敛。如果模型看到的很多样例不在同一种顺序下运算速度会有小幅提升。12. 使用 Dropout 正则化如果有数百万的参数需要学习正则化就是避免 DNN 过拟合的必须手段。你也可以继续使用 L1/L2 正则化但 Dropout 是检查 DNN 过拟合的更好方式(雷锋网按Dropout 是指随机让网络某些隐层节点的权重不工作不工作的那些节点可以暂时认为不是网络结构的一部分但是它的权重会保留下来)。执行 Dropout 很容易并且通常能带来更快地学习。0.5 的默认值是一个不错的选择当然这取决于具体任务。如果模型不太复杂0.2 的 Dropout 值或许就够了。在测试阶段Dropout 应该被关闭权重要调整到相应大小。只要对一个模型进行 Dropout 正则化多一点训练时间误差一定会降低。13. 周期 / 训练迭代次数“对深度学习模型进行多个周期的训练会得到更好的模型”——我们经常听到这句话。但多少周期才是“多”呢其实这里有一个简单的策略继续按照一个固定的样例数或者周期训练模型比如两万个样例或者一个周期。在每批样例之后比较测试误差(test error)和训练误差(train error)如果它们的差距在缩小那么继续训练。另外记得在每批训练之后保存模型的参数所以训练好之后你可以从多个模型中做选择。14. 可视化训练深度学习模型有上千种出差错的方式。我猜大家都遇到过这样的场景模型已经训练了几个小时或者好几天然而在训练完成之后才意识到某个地方出问题了。为了不让你自己神经错乱一定要对训练过程作可视化处理。比较显而易见的措施是保存或打印损失值、训练误差、测试误差等项目的日志。在此之外一个很好的措施是采用可视化库(visualization library )在几个训练样例之后、或者周期之间生成权重柱状图。这或许能帮助我们追踪深度学习模型中的一些常见问题比如梯度消失与梯度爆发(Exploding Gradient)。15. 使用支持 GPU 和自动微分法 (Automatic Differentiation)的库谢天谢地对于快速创建原型模型我们已经有了相当不错的库比如 Theano, Tensorflow, Keras 等等。几乎所有这些深度学习库支持 GPU 计算和自动微分法。所以你不需要深入研究核心 GPU 编程技术(除非你想——这绝对很有意思)。你也不需要写自己的微分代码——在非常复杂的模型上这相当费劲(但若需要你应该有能力去做)。 Tensorflow还提供了分布式计算的支持——如果你是土豪的话.