你有哪些deep learning(rnn、cnn)调参的经验?

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

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

参数初始化。

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

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

Xavier初始法论文:jmlr.org/proceedings/pa

He初始化论文:arxiv.org/abs/1502.0185

  • 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有比较好的效果。参考论文:arxiv.org/abs/1312.6120

数据预处理方式

  • zero-center ,这个挺常用的.X -= np.mean(X, axis = 0) # zero-centerX /= np.std(X, axis = 0) # normalize
  • PCA whitening,这个用的比较少.

训练技巧

  • 要做梯度归一化,即算出来的梯度除以minibatch size
  • clip c(梯度裁剪): 限制最大梯度,其实是value = sqrt(w1^2+w2^2….),如果value超过了阈值,就算一个衰减系系数,让value的值等于阈值: 5,10,15
  • dropout对小数据防止过拟合有很好的效果,值一般设为0.5,小数据上dropout+sgd在我的大部分实验中,效果提升都非常明显.因此可能的话,建议一定要尝试一下。 dropout的位置比较有讲究, 对于RNN,建议放到输入->RNN与RNN->输出的位置.关于RNN如何用dropout,可以参考这篇论文: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或者更大的值做初始化,可以取得更好的结果,来自这篇论文:jmlr.org/proceedings/pa, 我这里实验设成1.0,可以提高收敛速度.实际使用中,不同的任务,可能需要尝试不同的值.
  • Batch Normalization据说可以提升效果,不过我没有尝试过,建议作为最后提升模型的手段,参考论文:Accelerating Deep Network Training by Reducing Internal Covariate Shift
  • 如果你的模型包含全连接层(MLP),并且输入和输出大小一样,可以考虑将MLP替换成Highway Network,我尝试对结果有一点提升,建议作为最后提升模型的手段,原理很简单,就是给输出加了一个gate来控制信息的流动,详细介绍请参考论文: arxiv.org/abs/1505.0038
  • 来自@张馨宇的技巧:一轮加正则,一轮不加正则,反复进行。

Ensemble

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

  • 同样的参数,不同的初始化方式
  • 不同的参数,通过cross-validation,选取最好的几组
  • 同样的参数,模型训练的不同阶段,即不同迭代次数的模型。
  • 不同的模型,进行线性融合. 例如RNN和传统模型.

更多深度学习技巧,请参见我的专栏:炼丹实验室 - 知乎专栏

880 ​59 条评论
​分享
​收藏 ​感谢 收起
528 人赞同了该回答

其实我发现现在深度学习越来越成熟,调参工作比以前少了很多,绝大多数情况自己设计的参数都不如教程和框架的默认参数好,不过有一些技巧我一直都在用的

(1)relu+bn。这套好基友组合是万精油,可以满足95%的情况,除非有些特殊情况会用identity,比如回归问题,比如resnet的shortcut支路,sigmoid什么的都快从我世界里消失了

(2)dropout 。分类问题用dropout ,只需要最后一层softmax 前用基本就可以了,能够防止过拟合,可能对accuracy提高不大,但是dropout 前面的那层如果是之后要使用的feature的话,性能会大大提升

(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的东西,其实网络设计上博大精深,这也远超过我的水平范畴,只说一些很简单的

(1)卷积核的分解。从最初的5×5分解为两个3×3,到后来的3×3分解为1×3和3×1,再到resnet的1×1,3×3,1×1,再xception的3×3 channel-wise conv+1×1,网络的计算量越来越小,层数越来越多,性能越来越好,这些都是设计网络时可以借鉴的

(2)不同尺寸的feature maps的concat,只用一层的feature map一把梭可能不如concat好,pspnet就是这种思想,这个思想很常用

(3)resnet的shortcut确实会很有用,重点在于shortcut支路一定要是identity,主路是什么conv都无所谓,这是我亲耳听resnet作者所述

(4)针对于metric learning,对feature加个classification 的约束通常可以提高性能加快收敛

手机码字,想到再加
528 ​53 条评论
​分享
​收藏 ​感谢 收起
109 人赞同了该回答
补充一点,adam收敛虽快但是得到的解往往没有sgd+momentum得到的解更好,如果不考虑时间成本的话还是用sgd吧。
再补充一个rnn trick,仍然是不考虑时间成本的情况下,batch size=1是一个很不错的regularizer, 起码在某些task上,这也有可能是很多人无法复现alex graves实验结果的原因之一,因为他总是把batch size设成1。。。
109 ​28 条评论
​分享
​收藏 ​感谢
61 人赞同了该回答
有两个东西:
1、Hinton老爷子的公开课,说了很多;
2、一本书,《Neural Networks:Tricks of the Trade》
61 ​2 条评论
​分享
​收藏 ​感谢
15 人赞同了该回答
没做过CNN,RNN,调过连续值DNN,以下经验仅限于CTR
1.样本要足够随机
2.样本要做归一化
3.激活函数要视样本输入选择
4.minibatch很重要,几百到几千是比较合适的(很大数据量的情况下)
5.learning rate很重要,可以直接用adagrad or adadelta,省去一些麻烦,然后把冲量调到0.9以上
6.权重初始化,可用高斯分布乘上一个很小的数
15 ​5 条评论
​分享
​收藏 ​感谢
62 人赞同了该回答
62 ​1 条评论
​分享
​收藏 ​感谢
14 人赞同了该回答
小白一枚,在这里总结一下我在试验中观察到的现象(必然有理解错误的地方):
1. Adam收敛速度的确要快一些,可是结果总是不如其他优化算法,如果很看重结果不在乎速度还是用其他的试试。
2. Dropout的放置位置以及大小非常重要,求大神能分享经验.....
3. Relu并不是一定比Tanh好,如果不太懂的话,用的不合适,可能会导致梯度消失?(不知道是不是网络结构问题,为什么一用relu梯度一会儿就变成Nan)
4. pretrain 的 Embedding在训练中不调优泛化能力要更好一些,调优的话参数会增加好多啊。
另:心得体会
1. 深度学习真是一门实验科学,很多地方解释不了为什么好,为什么不好。
2.如果你机器配置很不到位,也没有人带你,毕业设计千万别选深度学习,天天愁,好坑啊。
未完待续..........
14 ​11 条评论
​分享
​收藏 ​感谢
11 人赞同了该回答

cnn的调参主要是在优化函数、embedding的维度还要残差网络的层数几个方面。

  1. 优化函数方面有两个选择:sgd、adam,相对来说adam要简单很多,不需要设置参数,效果也还不错。
  2. embedding随着维度的增大会出现一个最大值点,也就是开始时是随维度的增加效果逐渐变好,到达一个点后,而后随维度的增加,效果会变差。
  3. 残差网络的层数与embedding的维度有关系,随层数的增加,效果变化也是一个凸函数。

另外还有激活函数,dropout层和batchnormalize层的使用。激活函数推荐使用relu,dropout层数不易设置过大,过大会导致不收敛,调节步长可以是0.05,一般调整到0.4或者0.5就可找到最佳值。

以上是个人调参的一些经验,可供参考。

11 ​添加评论
​分享
​收藏 ​感谢
14 人赞同了该回答
写代码这件事情居然变得像老中医看病一样需要摸索调参真是让人难过
14 ​3 条评论
​分享
​收藏 ​感谢
14 人赞同了该回答

最近在看 Karpathy 的 cs231n, 还没看完, 不过过程中总结了一下他提到的一些技巧:

关于参数:
  • 通常情况下, 更新参数的方法默认用 Adam 效果就很好
  • 如果可以载入全部数据 (full batch updates), 可以使用 L-BFGS

Model Ensembles:
  • 训练多个模型, 在测试时将结果平均起来, 大约可以得到 2% 提升.
  • 训练单个模型时, 平均不同时期的 checkpoints 的结果, 也可以有提升.
  • 测试时可以将测试的参数和训练的参数组合起来:
while True:
  data_batch = ...
  loss = network.forward(data_batch)
  dx = network.backward()
  x += - learning_rate * dx
  x_test = 0.995 * x_test + 0.005 * x # use for test set
14 ​5 条评论
​分享
​收藏 ​感谢
20 人赞同了该回答
分享几个常用的trick:
1.增加每个step的轮数
2.early stop
3.用小一些的学习率warmup
4.回退到更大的学习率
5.nesterov momentum sgd
6.搜索初始学习率
20 ​7 条评论
​分享
​收藏 ​感谢
15 人赞同了该回答

1.better initialization helps a lot

2.use minibatch and choose batch_size(must)

3.use batch_norm &dropout

4.use adam

5.plot the learning rate curve

6.plot the loss curve.

7.lstm &gru are almost always better than sample RNN

8.use better framework(like tensorflow with tensorboard)

9.find hyper parameters used most often in paper

10 pray

15 ​添加评论
​分享
​收藏 ​感谢
1 人赞同了该回答

基于网格搜索,用坐标下降法调参。然而这个方法太容易收敛到局部最优,所以容易想到加入模拟退火的策略。

分享一个自己写的自动调参工具chncwang/laozhongyi

1 ​添加评论
​分享
​收藏 ​感谢
8 人赞同了该回答
1.无论是cnn还是rnn,batch normalization都有用,不一定结果提高几个点,收敛快多了
2.数据初始时normalize得好,有时候直接提高2个点,比如cifar10,转到yuv下normalize再scn
3.loss不降了lr就除10
4. google的inception系列按它论文里说的永远无法复现
8 ​4 条评论
​分享
​收藏 ​感谢
3 人赞同了该回答
刚刚总结了一下Deep Learning 的最优化方法,包括Adam,RMSProp,SGD,Momentum,adaGrad,以及一些传统的二阶优化方法等等,欢迎一起交流
博文地址:
blog.csdn.net/BVL101011
3 ​添加评论
​分享
​收藏 ​感谢
3 人赞同了该回答
momentum,初始一两轮设置成很小的数值,根据我的实验结果可以加快收敛速度和提升效果
3 ​1 条评论
​分享
​收藏 ​感谢
2 人赞同了该回答

做 hyper-parameter tuning 的话,感觉过去几年用 bayesian optimization 的很多。有几个商业和开源的实现。

近来也有基于 random sampling 的 Hyperband 方法出现,效果都是 case by case 的。

最重要的还是找到正确的 loss function,其它就交给这些方法去调吧。
2 ​添加评论
​分享
​收藏 ​感谢
2 人赞同了该回答
这种事情怎么能上手呢?
我都是上差分进化……
2 ​1 条评论
​分享
​收藏 ​感谢
2 人赞同了该回答
本人做rnn的文本相关研究,一直使用adam,下降速度巨快,看别人论文也尝试过adadelta和adagrad,但不知是姿势不对还是别的原因效果很差,batch-size大小设置在50(训练集大小为17w),dropout随大流0.5,另外我发现l2取值对我的结果影响挺大的,之前一直跟着别人论文用0.001,我换成0.0001以后发现提升了1%
2 ​1 条评论
​分享
​收藏 ​感谢

神经网络使用心得--欢迎新手借鉴,老手批评指正 - CaffeCN深度学习社区
我个人写的,发表在caffecn上,在此引用。比较实用。

0 ​添加评论
​分享
​收藏 ​感谢
网络结构很重要,根据输入的vector大小定网络参数多少。一般比输入vector大小大一个数量级。亲测有效
0 ​添加评论
​分享
​收藏 ​感谢
往往是看不见的手起着决定性作用
0 ​添加评论
​分享
​收藏 ​感谢

多试。

没有人能打包票这个trick就能在你的网络结构上面work。你看dcgan,G最后一层为啥不加BN,这个是没有道理的。所以多看paper,然后觉得有用就去试,没用换下一个。

0 ​3 条评论
​分享
​收藏 ​感谢

Batch Normalization 算是个大杀器,训练速度快,效果好,关键还不会过拟合

0 ​添加评论
​分享
​收藏 ​感谢

1、optimizer可以用adam或者rmsprop,效果上看adam最好,但是优化速度太慢了

2、尝试缩小learning rate,或者直接用learning rate decay来动态调整

3、batch_norm

4、dropout(必备佳品)

0 ​添加评论
​分享
​收藏 ​感谢
1 人赞同了该回答
27个回答太少了,我说一个,学习率很多时候都可以调一调,很有惊喜
1 ​添加评论
​分享
​收藏 ​感谢
1 用遗传算法优化网络结构
2 随机样本分布,防止大数据淹没小数据。
0 ​2 条评论
​分享
​收藏 ​感谢
作为一名码农刚接触深度学习1.数据分十份,八份训练,一份验证,一份测试。
2.dropoutprob在训练时设为0.5,验证和测试的时候设为1.0。
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值