深度学习调参及训练技巧(转)

作者:婉儿飞飞

链接:https://www.jianshu.com/p/0b116c43eb16

来源:简书

简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

1. 调参

训练技巧对深度学习来说是非常重要的,作为一门实验性质很强的科学,同样的网络结构使用不同的训练方法训练,结果可能会有很大的差异。这里我总结了近一年来的炼丹心得,分享给大家,也欢迎大家补充指正。

参数初始化

下面几种方式,随便选一个,结果基本都差不多。但是一定要做。否则可能会减慢收敛速度,影响收敛结果,甚至造成Nan等一系列问题。

下面的n_in为网络的输入大小,n_out为网络的输出大小,n为n_in或(n_in+n_out)*0.5

Xavier初始法论文:[http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf](http://link.zhihu.com/?target=http%3A//jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf)

He初始化论文:[https://arxiv.org/abs/1502.01852](http://link.zhihu.com/?target=https%3A//arxiv.org/abs/1502.01852)

* uniform均匀分布初始化: w = np.random.uniform(low=-scale, high=scale, size=[n_in,n_out])

* Xavier初始法,适用于普通激活函数(tanh,sigmoid):scale = np.sqrt(3/n)

* He初始化,适用于ReLU:scale = np.sqrt(6/n)

* normal高斯分布初始化: w = np.random.randn(n_in,n_out) * stdev # stdev为高斯分布的标准差,均值设为0

* Xavier初始法,适用于普通激活函数 (tanh,sigmoid):stdev = np.sqrt(n)

* He初始化,适用于ReLU:stdev = np.sqrt(2/n)

* svd初始化:对RNN有比较好的效果。参考论文:[https://arxiv.org/abs/1312.6120](http://link.zhihu.com/?target=https%3A//arxiv.org/abs/1312.6120)

一次惨痛的教训是用normal初始化cnn的参数,最后acc只能到70%多,仅仅改成xavier,acc可以到98%。

还有一次给word embedding初始化,最开始使用了TensorFlow中默认的initializer(即glorot_uniform_initializer,

也就是大家经常说的无脑使用xavier),训练速度慢不说,结果也不好。

改为uniform,训练速度飙升,结果也飙升。

所以,初始化就跟黑科技一样,用对了超参都不用调;没用对,跑出来的结果就跟模型有bug一样不忍直视。

数据预处理方式

zero-center ,这个挺常用的. X -= np.mean(X, axis = 0) # zero-center X /= np.std(X, axis = 0) # normalize

PCA whitening,这个用的比较少.

训练技巧

要做梯度归一化,即算出来的梯度除以minibatch size

clip c(梯度裁剪): 限制最大梯度,其实是value = sqrt(w12+w22….),如果value超过了阈值,就算一个衰减系系数,让value的值等于阈值: 5,10,15

dropout对小数据防止过拟合有很好的效果,值一般设为0.5,小数据上dropout+sgd在我的大部分实验中,效果提升都非常明显.因此可能的话,建议一定要尝试一下。 dropout的位置比较有讲究, 对于RNN,建议放到输入->RNN与RNN->输出的位置.关于RNN如何用dropout,可以参考这篇论文:http://arxiv.org/abs/1409.2329

adam,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初始化,在小数据上,不仅可以有效提高收敛速度,也可以可以提高结果.

尽量对数据做shuffle

LSTM 的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

来自@张馨宇的技巧:一轮加正则,一轮不加正则,反复进行。

Ensemble

Ensemble是论文刷结果的终极核武器,深度学习中一般有以下几种方式

同样的参数,不同的初始化方式

不同的参数,通过cross-validation,选取最好的几组

同样的参数,模型训练的不同阶段,即不同迭代次数的模型。

不同的模型,进行线性融合. 例如RNN和传统模型.

2. 训练

神经网络的代码,比一般的代码要难调试不少,和编译错误以及运行时程序崩溃相比,神经网络比较棘手的地方,往往在于程序运行正常,但是结果无法收敛,这个检查起来可要麻烦多了。下面是根据我平时调试神经网络的经验,总结的一些比较通用的调试技巧,后续会再写一篇文章,专门介绍一下theano如何进行调试,希望能对大家调试神经网络有所帮助。

遇到Nan怎么办?

Nan问题,我相信大部分人都遇到过,一般可能是下面几个原因造成的:

除0问题。这里实际上有两种可能,一种是被除数的值是无穷大,即Nan,另一种就是除数的值是0。之前产生的Nan或者0,有可能会被传递下去,造成后面都是Nan。请先检查一下神经网络中有可能会有除法的地方,例如softmax层,再认真的检查一下数据。我有一次帮别人调试代码,甚至还遇到过,训练数据文件中,有些值就是Nan。。。这样读进来以后,开始训练,只要遇到Nan的数据,后面也就Nan了。可以尝试加一些日志,把神经网络的中间结果输出出来,看看哪一步开始出现Nan。后面会介绍Theano的处理办法。

梯度过大,造成更新后的值为Nan。特别是RNN,在序列比较长的时候,很容易出现梯度爆炸的问题。一般有以下几个解决办法。对梯度做clip(梯度裁剪),限制最大梯度,其实是value = sqrt(w12+w22….),如果value超过了阈值,就算一个衰减系系数,让value的值等于阈值: 5,10,15。

减少学习率。初始学习率过大,也有可能造成这个问题。需要注意的是,即使使用adam之类的自适应学习率算法进行训练,也有可能遇到学习率过大问题,而这类算法,一般也有一个学习率的超参,可以把这个参数改的小一些。

初始参数值过大,也有可能出现Nan问题。输入和输出的值,最好也做一下归一化。具体方法可以参考我之前的一篇文章:深度学习个人炼丹心得 - 炼丹实验室 - 知乎专栏

神经网络学不出东西怎么办?

可能我们并没有遇到,或者解决了Nan等问题,网络一直在正常的训练,但是cost降不下来,预测的时候,结果不正常。

请打印出训练集的cost值和测试集上cost值的变化趋势,正常情况应该是训练集的cost值不断下降,最后趋于平缓,或者小范围震荡,测试集的cost值先下降,然后开始震荡或者慢慢上升。如果训练集cost值不下降,有可能是代码有bug,有可能是数据有问题(本身有问题,数据处理有问题等等),有可能是超参(网络大小,层数,学习率等)设置的不合理。

请人工构造10条数据,用神经网络反复训练,看看cost是否下降,如果还不下降,那么可能网络的代码有bug,需要认真检查了。如果cost值下降,在这10条数据上做预测,看看结果是不是符合预期。那么很大可能网络本身是正常的。那么可以试着检查一下超参和数据是不是有问题。

如果神经网络代码,全部是自己实现的,那么强烈建议做梯度检查。确保梯度计算没有错误。

先从最简单的网络开始实验,不要仅仅看cost值,还要看一看神经网络的预测输出是什么样子,确保能跑出预期结果。例如做语言模型实验的时候,先用一层RNN,如果一层RNN正常,再尝试LSTM,再进一步尝试多层LSTM。

如果可能的话,可以输入一条指定数据,然后自己计算出每一步正确的输出结果,再检查一下神经网络每一步的结果,是不是一样的。

trial-and-error

先说下我的观点, 调参就是trial-and-error. 没有其他捷径可以走. 唯一的区别是有些人盲目的尝试, 有些人思考后再尝试. 快速尝试, 快速纠错这是调参的关键.

看了杨军的回答. 对于这个回答, 下面的评论里面

说的很对. 这个回答主要内容更多的是侧重理解网络. 而非训练网络.

我要再强调下, 杨军的回答更多的涉及是理解网络而非训练网络. 是的, 没错. 你看完回答中的所有内容, 对不起, 你还是不知道怎么实际训练一个网络, 尤其是复杂任务下的网络(因为简单任务根本不需要, 直接上来效果就会很好, 除非你要刷简单任务的排行榜).

首先说下可视化:

我个人的理解, 对于可视化, 更多的还是帮助人类以自己熟悉的方式来观察网络. 因为, 你是不可能边观察网络, 还边调参的. 你只是训练完成后(或者准确率到达一个阶段后), 才能可视化. 在这之前, 网络没有学习到良好的参数, 你可视化了也没意义, 网络达到不错的准确率了, 你看看其实也就听个响. 同样, 你的网络训练的一塌糊涂, 你可视化也没什么意义, 唯一能够看到的就是中间结果乱七八糟, 或者全黑全白, 这时候你直接看最后准确率就可以知道这网络没救了.

关于权重的可视化[Visualize Layer Weights](现在是否强求smooth其实意义不大, 这个后面说.):

同样, 你看到一个不满足平滑结果的图像, 你知道, 这网络训练的不好, 但是为什么呢? 是数据不好? 没有预处理? 网络结构问题? Learning Rate太大或者太小? 或者就是差了一个LRN层(之前我就遇到, 加个LRN就能出smooth的weights, 当然这其实和预处理有关)?

Smooth是需要看一下的, 心里有个数. 但是具体调参怎么调是没辙的. 第一, 你不可能告诉网络, 这层你得学个边界检测的功能出来. 第二, 不同任务下会有不同的weights(虽然底层的特征有很大的通用性), 你觉得你凭什么来指导一个看图片比你快得多的机器?

再说现在是否需要强求smooth. 现在的趋势是鼓励使用小filter, 3x3大小, 多加层次(这样, 非线性更好点). 换句话说, 3x3的图片, 总共才9个像素, 你怎么判断smooth与否呢? 当然如果你使用大的filter, 一般5x5往上, 运气不差的话, 你是可以看到smooth的结果的.

咱们再说另外一个极端, 一个网络,运行的完美(满足应用要求就算完美), 打开一看, 这weights不smooth啊. 你告诉我, 你打算怎么办? 没错, 具有不平滑的权重的网络同样可以获得很好的结果(这种情况我都习以为常了).

那么可视化网络就不重要了?

非常重要, 但是不在训练这块, 而是帮助理解网络的原理这块. 理解网络原理后, 你才能在设计结构的时候心里有感觉(只是有感觉而已), 网络出了问题, 或者在某些情况下不满意, 有更好的直觉去调整.(没错, 只是直觉, 虽然有些情况下的调整从网络原理来看逻辑上应该可以工作, 但是人家就是不工作, 你能咬机器去么?)

那么怎样训练一个不错的网络呢?

========================================================

我自己的经验, 有下面这些:

基本原则:

快速试错

一些大的注意事项:

1. 刚开始, 先上小规模数据, 模型往大了放, 只要不爆显存, 能用256个filter你就别用128个. 直接奔着过拟合去. 没错, 就是训练过拟合网络, 连测试集验证集这些都可以不用.

为什么?

你要验证自己的训练脚本的流程对不对. 这一步小数据量, 生成速度快, 但是所有的脚本都是和未来大规模训练一致的(除了少跑点循环)

如果小数据量下, 你这么粗暴的大网络奔着过拟合去都没效果. 那么, 你要开始反思自己了, 模型的输入输出是不是有问题? 要不要检查自己的代码(永远不要怀疑工具库, 除非你动过代码)? 模型解决的问题定义是不是有问题? 你对应用场景的理解是不是有错? 不要怀疑NN的能力, 不要怀疑NN的能力, 不要怀疑NN的能力. 就我们调参狗能遇到的问题, NN没法拟合的, 这概率是有多小?

你可以不这么做, 但是等你数据准备了两天, 结果发现有问题要重新生成的时候, 你这周时间就酱油了.

2. Loss设计要合理.

一般来说分类就是Softmax, 回归就是L2的loss. 但是要注意loss的错误范围(主要是回归), 你预测一个label是10000的值, 模型输出0, 你算算这loss多大, 这还是单变量的情况下. 一般结果都是nan. 所以不仅仅输入要做normalization, 输出也要这么弄.

多任务情况下, 各loss想法限制在一个量级上, 或者最终限制在一个量级上, 初期可以着重一个任务的loss

3. 观察loss胜于观察准确率

准确率虽然是评测指标, 但是训练过程中还是要注意loss的. 你会发现有些情况下, 准确率是突变的, 原来一直是0, 可能保持上千迭代, 然后突然变1. 要是因为这个你提前中断训练了, 只有老天替你惋惜了. 而loss是不会有这么诡异的情况发生的, 毕竟优化目标是loss.

给NN一点时间, 要根据任务留给NN的学习一定空间. 不能说前面一段时间没起色就不管了. 有些情况下就是前面一段时间看不出起色, 然后开始稳定学习.

4. 确认分类网络学习充分

分类网络就是学习类别之间的界限. 你会发现, 网络就是慢慢的从类别模糊到类别清晰的. 怎么发现? 看Softmax输出的概率的分布. 如果是二分类, 你会发现, 刚开始的网络预测都是在0.5上下, 很模糊. 随着学习过程, 网络预测会慢慢的移动到0,1这种极值附近. 所以, 如果你的网络预测分布靠中间, 再学习学习.

5. Learning Rate设置合理

太大: loss爆炸, 或者nan

太小: 半天loss没反映(但是, LR需要降低的情况也是这样, 这里可视化网络中间结果, 不是weights, 有效果, 俩者可视化结果是不一样的, 太小的话中间结果有点水波纹或者噪点的样子, 因为filter学习太慢的原因, 试过就会知道很明显)

需要进一步降低了: loss在当前LR下一路降了下来, 但是半天不再降了.

如果有个复杂点的任务, 刚开始, 是需要人肉盯着调LR的. 后面熟悉这个任务网络学习的特性后, 可以扔一边跑去了.

如果上面的Loss设计那块你没法合理, 初始情况下容易爆, 先上一个小LR保证不爆, 等loss降下来了, 再慢慢升LR, 之后当然还会慢慢再降LR, 虽然这很蛋疼.

LR在可以工作的最大值下往小收一收, 免得ReLU把神经元弄死了. 当然, 我是个心急的人, 总爱设个大点的.

6 对比训练集和验证集的loss

判断过拟合, 训练是否足够, 是否需要early stop的依据, 这都是中规中矩的原则, 不多说了.

7 清楚receptive field的大小

CV的任务, context window是很重要的. 所以你对自己模型的receptive field的大小要心中有数. 这个对效果的影响还是很显著的. 特别是用FCN, 大目标需要很大的receptive field. 不像有fully connection的网络, 好歹有个fc兜底, 全局信息都有.

简短的注意事项:

预处理: -mean/std zero-center就够了, PCA, 白化什么的都用不上. 我个人观点, 反正CNN能学习encoder, PCA用不用其实关系不大, 大不了网络里面自己学习出来一个.

shuffle, shuffle, shuffle.

网络原理的理解最重要, CNN的conv这块, 你得明白sobel算子的边界检测.

Dropout, Dropout, Dropout(不仅仅可以防止过拟合, 其实这相当于做人力成本最低的Ensemble, 当然, 训练起来会比没有Dropout的要慢一点, 同时网络参数你最好相应加一点, 对, 这会再慢一点).

CNN更加适合训练回答是否的问题, 如果任务比较复杂, 考虑先用分类任务训练一个模型再finetune.

无脑用ReLU(CV领域).

无脑用3x3.

无脑用xavier.

LRN一类的, 其实可以不用. 不行可以再拿来试试看.

filter数量2^n.

多尺度的图片输入(或者网络内部利用多尺度下的结果)有很好的提升效果.

第一层的filter, 数量不要太少. 否则根本学不出来(底层特征很重要).

sgd adam 这些选择上, 看你个人选择. 一般对网络不是决定性的. 反正我无脑用sgd + momentum.

batch normalization我一直没用, 虽然我知道这个很好, 我不用仅仅是因为我懒. 所以要鼓励使用batch normalization.

不要完全相信论文里面的东西. 结构什么的觉得可能有效果, 可以拿去试试.

你有95%概率不会使用超过40层的模型.

shortcut的联接是有作用的.

暴力调参最可取, 毕竟, 自己的生命最重要. 你调完这个模型说不定过两天这模型就扔掉了.

机器, 机器, 机器.

Google的inception论文, 结构要好好看看.

一些传统的方法, 要稍微了解了解. 我自己的程序就用过1x14的手写filter, 写过之后你看看inception里面的1x7, 7x1 就会会心一笑...

Relu,batchnorm,dropout,adam ,微步幅

relu 是一个很万能的激活函数,可以很好的防止梯度弥散问题, 当然最后一层的激活函数千万慎用relu,如果是连续的用identify, 分类的用softmax ,拟合回归的话我最后一层也经常不用激活函数,直接wx +b就行,

batchnorm也是大杀器,可以大大加快训练速度和模型性能

Dropout 也是防止过拟合的大杀器,如果不知道怎么设比例的话,就直接设置为0.5, 即一半一半,但是测试的时候记得把dropout关掉.

Adam 优化函数应该是收敛非常快的一个优化函数,不过有人说sgd +momentum 速度慢一点但是性能好,但是我用的没感觉性能好.

微步幅是只卷积步幅选择2,然后模板数量逐层翻倍,就是越来越小但越来越厚,反卷积的话对称反过来,这样每次卷积图像就缩小了一半,下采样和池化都可以不加,我一直不加的.

深度学习这么调参训练_深度学习调参及训练技巧(转)相关推荐

  1. 深度学习这么调参训练_深度学习调参技巧

    训练技巧对深度学习来说是非常重要的,作为一门实验性质很强的科学,同样的网络结构使用不同的训练方法训练,结果可能会有很大的差异.这里我总结了近一年来的炼丹心得,分享给大家,也欢迎大家补充指正. 参数初始 ...

  2. 深度学习这么调参训练_深度学习训练的小技巧,调参经验(转)

    经常会被问到你用深度学习训练模型时怎么样改善你的结果呢?然后每次都懵逼了,一是自己懂的不多,二是实验的不多,三是记性不行忘记了.所以写这篇博客,记录下别人以及自己的一些经验. Ilya Sutskev ...

  3. 深度学习这么调参训练_聊一聊深度学习中的调参技巧?

    本期问题能否聊一聊深度学习中的调参技巧? 我们主要从以下几个方面来讲.1. 深度学习中有哪些参数需要调? 2. 深度学习在什么时候需要动用调参技巧?又如何调参? 3. 训练网络的一般过程是什么? 1. ...

  4. 华南理工深度学习与神经网络期末考试_深度学习基础:单层神经网络之线性回归...

    3.1 线性回归 线性回归输出是一个连续值,因此适用于回归问题.回归问题在实际中很常见,如预测房屋价格.气温.销售额等连续值的问题.与回归问题不同,分类问题中模型的最终输出是一个离散值.我们所说的图像 ...

  5. 华南理工深度学习与神经网络期末考试_深度学习算法地图

    原创声明:本文为 SIGAI 原创文章,仅供个人学习使用,未经允许,不能用于商业目的. 其它机器学习.深度学习算法的全面系统讲解可以阅读<机器学习-原理.算法与应用>,清华大学出版社,雷明 ...

  6. 深度学习与无人车导论_深度学习导论

    深度学习与无人车导论 改变游戏规则 图片的信誉归功于: https : //www.digitalocean.com/ 深度学习 已经成为许多新应用程序的主要驱动力,是时候真正了解为什么会这样了. 我 ...

  7. 神经网络调参训练集噪音比例对网络性能的影响

    这次用于实验训练集噪音比例对网络性能的影响,网络结构81*60*2,训练集用的是mnist的训练集的0和1,测试集用的mnist的测试集的0和1,学习率固定位0.1,batchsize=20,试验了训 ...

  8. 电机编码器调零步骤_伺服电机编码器调零对位方法

    伺服电机编码器调零对位方法 伺服电机在拆开检查的时候,有时因为不小心将电机尾部固定的编码器也拆下来了,那要怎么办呢?因为伺服电机编码器动过位置了,编码器原点漂移了,所以需要重新校正.具体如下: 应急调 ...

  9. python调包师_为“Python调包侠” 画像

    很多从事IT行业的朋友:包括运维.测试.数据分析.网络安全,在北上广每月工资1.5万/月以上,有的甚至到达2万/月,碰到职业瓶颈了,工资碰到天花板.有的朋友认为自己会Python编程,其实还是处在&q ...

最新文章

  1. Linux中V4L2使用
  2. 聚合类新闻client初体验
  3. iOS Tips 模拟器屏幕截图
  4. 4 关卡流 进阶_全息武器全解析,记住4个点全区第一就是你!
  5. 面向对象设计原则之2-开放闭合原则
  6. VS项目打包,并自动安装SQL数据库
  7. 字符串的连接最长路径查找
  8. c语言中人脸磨皮算法,人脸磨皮算法
  9. 5G关键技术之D2D
  10. SpringBoot RestTemplate 发送请求 忽略证书不安全
  11. 腾讯内部深度文章曝光:微信向左 手机QQ向右
  12. java 获得唯一 数字_java生成唯一数字
  13. 使用openssl制作https的证书
  14. oracle绝对值求和,Oracle存储过程当中经常使用函数
  15. verilog代码风格——PN序列产生代码
  16. 计算时针与分针之间的夹角
  17. MapGIS 学习资料下载
  18. ECOPASSPORT认证辅导,什么是Eco-Passport认证,Eco-Passport认证的意义
  19. 电脑手机游戏助手TC Games常见掉线及连接问题解决方案?
  20. 操作系统内核为啥用C语言?(C语言特点)

热门文章

  1. java actioncontext_struts2(四) ognl表达式、值栈、actionContext之间的关系
  2. 多模态理论张德禄_观点 | 多模态视角下二语语用道歉行为研究
  3. 我再也不想在创业公司待了!
  4. 【华为OpenEuler】VirtualBox虚拟机与OpenEuler环境搭建教程
  5. 悦淘金:什么才是社交零售的真正逻辑?电商新逻辑
  6. EditText控件
  7. 理解操作系统的进程的概念就如吃饭一样简单
  8. BI+AI 有没有前途?
  9. 一天一个linux小技巧|.(点)是什么意思
  10. 2007-2020年全国各省国有化程度数据