• 问答
  • 技术
  • 实践
  • 资源
调参经验 | 关于 deep learning(rnn、cnn)
技术讨论

来源 | https://www.zhihu.com/question/41631631
编辑 | 极市平台
本文仅作学术分享,版权属于原作者,侵权联系删除。

话说三人行,必有我师焉。有哪些deep learning(rnn、cnn)调参的经验,看看这些小伙伴的回答,说不准你从中会探索出适合自己的方法~~~

作者:时间旅客
https://www.zhihu.com/question/41631631/answer/1129785528

  1. 不管什么模型,先在一个较小的训练集上train和test,看看它能不能过拟合。如果不能过拟合,可能是学习率太大,或者代码写错了。先调小学习率试一下,如果还不行就去检查代码,先看dataloader输出的数据对不对,再看模型每一步的size是否符合自己期待。

  2. 看train/eval的loss曲线,正常的情况应该是train loss呈log状一直下降最后趋于稳定,eval loss开始时一直下降到某一个epoch之后开始趋于稳定或开始上升,这时候可以用early stopping保存eval loss最低的那个模型。如果loss曲线非常不正常,很有可能是数据处理出了问题,比如label对应错了,回去检查代码。

  3. 不要一开始就用大数据集,先在一个大概2w训练集,2k测试集的小数据集上调参。

  4. 尽量不要自己从头搭架子(新手和半新手)。找一个已经明确没有bug能跑通的其它任务的架子,在它的基础上修改。否则debug过程非常艰难,因为有时候是版本迭代产生的问题,修改起来很麻烦。

  5. 优化器优先用adam,学习率设1e-3或1e-4,再试Radam(LiyuanLucasLiu/RAdam)。不推荐sgdm,因为很慢。

  6. lrscheduler用torch.optim.lr_scheduler.CosineAnnealingLR,T_max设32或64,几个任务上试效果都不错。(用这个lr_scheduler加上adam系的optimizer基本就不用怎么调学习率了)

  7. 有一些任务(尤其是有RNN的)要做梯度裁剪,torch.nn.utils.clip_grad_norm。

  8. 参数初始化,lstm的h用orthogonal,其它用he或xavier。

  9. 激活函数用relu一般就够了,也可以试试leaky relu。

  10. batchnorm和dropout可以试,放的位置很重要。优先尝试放在最后输出层之前,以及embedding层之后。RNN可以试layer_norm。有些任务上加了这些层可能会有负作用。

  11. metric learning中先试标label的分类方法。然后可以用triplet loss,margin这个参数的设置很重要。

  12. batchsize设置小一点通常会有一些提升,某些任务batchsize设成1有奇效。

  13. embedding层的embedsize可以小一些(64 or 128),之后LSTM或CNN的hiddensize要稍微大一些(256 or 512)。(ALBERT论文里面大概也是这个意思)

  14. 模型方面,可以先用2或3层LSTM试一下,通常效果都不错。

  15. weight decay可以试一下,我一般用1e-4。

  16. 有CNN的地方就用shortcut。CNN层数加到某一个值之后对结果影响就不大了,这个值作为参数可以调一下。

  17. GRU和LSTM在大部分任务上效果差不多。

  18. 看论文时候不要全信,能复现的尽量复现一下,许多论文都会做低baseline,但实际使用时很多baseline效果很不错。

  19. 对于大多数任务,数据比模型重要。面对新任务时先分析数据,再根据数据设计模型,并决定各个参数。例如nlp有些任务中的padding长度,通常需要达到数据集的90%以上,可用pandas的describe函数进行分析。

作者:萧瑟
https://www.zhihu.com/question/41631631/answer/94816420

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

参数初始化

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

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

Xavier初始法论文:http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf

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

  1. 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)
  1. 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)
  1. svd初始化:对RNN有比较好的效果。参考论文:https://arxiv.org/abs/1312.6120

数据预处理方式

  1. zero-center,这个挺常用的。

    X -= np.mean(X, axis = 0) # zero-center

    X /= np.std(X, axis = 0) # normalize

  2. PCA whitening,这个用的比较少.

训练技巧

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

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

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

  4. adam,adadelta等,在小数据上,我这里实验的效果不如sgd, sgd收敛速度会慢一些,但是最终收敛后的结果,一般都比较好。如果使用sgd的话,可以选择从1.0或者0.1的学习率开始,隔一段时间,在验证集上检查一下,如果cost没有下降,就对学习率减半. 我看过很多论文都这么搞,我自己实验的结果也很好. 当然,也可以先用ada系列先跑,最后快收敛的时候,更换成sgd继续训练.同样也会有提升.据说adadelta一般在分类问题上效果比较好,adam在生成问题上效果比较好。

  5. 除了gate之类的地方,需要把输出限制成0-1之外,尽量不要用sigmoid,可以用tanh或者relu之类的激活函数.1. sigmoid函数在-4到4的区间里,才有较大的梯度。之外的区间,梯度接近0,很容易造成梯度消失问题。2. 输入0均值,sigmoid函数的输出不是0均值的。

  6. rnn的dim和embdding size,一般从128上下开始调整. batch size,一般从128左右开始调整.batch size合适最重要,并不是越大越好.

  7. word2vec初始化,在小数据上,不仅可以有效提高收敛速度,也可以可以提高结果.

  8. 尽量对数据做shuffle

  9. LSTM 的forget gate的bias,用1.0或者更大的值做初始化,可以取得更好的结果,来自这篇论文:http://jmlr.org/proceedings/papers/v37/jozefowicz15.pdf, 我这里实验设成1.0,可以提高收敛速度.实际使用中,不同的任务,可能需要尝试不同的值.

  10. Batch Normalization据说可以提升效果,不过我没有尝试过,建议作为最后提升模型的手段,参考论文:Accelerating Deep Network Training by Reducing Internal Covariate Shift

  11. 如果你的模型包含全连接层(MLP),并且输入和输出大小一样,可以考虑将MLP替换成Highway Network,我尝试对结果有一点提升,建议作为最后提升模型的手段,原理很简单,就是给输出加了一个gate来控制信息的流动,详细介绍请参考论文: http://arxiv.org/abs/1505.00387

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

Ensemble

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

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

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

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

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

作者:Towser
https://www.zhihu.com/question/41631631/answer/862075836

总结一下我遇到的小朋友常犯的错:

  1. 一上来就自己动手写模型。建议首先用成熟的开源项目及其默认配置(例如 Gluon 对经典模型的各种复现、各个著名模型作者自己放出来的代码仓库)在自己的数据集上跑一遍,在等程序运行结束的时间里仔细研究一下代码里的各种细节,最后再自己写或者改代码。

  2. 训 RNN 不加 gradient clipping,导致训练一段时间以后 loss 突然变成 Nan。

  3. tying input \& output embedding(就是词向量层和输出 softmax 前的矩阵共享参数,在语言模型或机器翻译中常用)时学习率需要设置得非常小,不然容易 Nan。

  4. 在数据集很大的情况下,一上来就跑全量数据。建议先用 1/100、1/10 的数据跑一跑,对模型性能和训练时间有个底,外推一下全量数据到底需要跑多久。在没有足够的信心前不做大规模实验。

  5. 只喜欢漂亮的模型结构,瞧不起调参数的论文/实验报告,看论文时经常不看超参数设置等细节。举个例子,现在还有相当多的人不知道 BERT 的激活函数是 GELU 而不是 transformer 原论文中的 ReLU(虽然我觉得这一点很无厘头)。在自己没有太多资源实验的情况下,实验报告类文章简直是业界良心好不好!

NLP 领域主要推荐以下几篇:

  • Regularizing and Optimizing LSTM Language Models(LSTM 的训练技巧)

  • Massive Exploration of Neural Machine Translation Architectures(NMT 里各个超参的影响)

  • Training Tips for the Transformer Model(训练 Transformer 时会发生的各种现象)

  • RoBERTa: A Robustly Optimized BERT Pretraining Approach(BERT 预训练技巧,虽然跟大部分人没啥关系)

CV也可以推荐几篇:

  • Training ImageNet in 1 Hour(大批量训练技巧)

  • Bag of Tricks for Image Classification with Convolutional Neural Networks(各种训练技巧集大成)

  • Bag of Freebies for Training Object Detection Neural Networks(同上)

  • EfficientNet: Rethinking Model Scaling for Convolutional Neural Networks(当前对参数利用最有效的 CNN,类似地还有一篇 EfficientDet)
  1. 初始学习率:有时受 batch size、sequence length 各种因素的影响,loss 很大(比如说好几万),对于这种数字人是没有数感的,建议首先计算一下 per token loss(如果是多任务,可以每个任务单独算;类似地,某些 CV 任务可以计算 per pixel loss),心里有点感觉。脱离损失函数的形式谈学习率没有意义(例如单是对 batch size 求和或者取平均这个差异就会使梯度差成百上千倍)。在确定初始学习率的时候,从一个很小的值(例如 1e-7)开始,然后每一步指数增大学习率(例如扩大1.05 倍)进行训练。训练几百步应该能观察到损失函数随训练步数呈对勾形,选择损失下降最快那一段的学习率即可。

  2. Adam 可以解决一堆奇奇怪怪的问题(有时 loss 降不下去,换 Adam 瞬间就好了),也可以带来一堆奇奇怪怪的问题(比如单词词频差异很大,当前 batch 没有的单词的词向量也被更新;再比如Adam和L2正则结合产生的复杂效果)。用的时候要胆大心细,万一遇到问题找各种魔改 Adam(比如 MaskedAdam, AdamW 啥的)抢救。

  3. subword 总是会很稳定地涨点,只管用就对了。

  4. GPU 上报错时尽量放在 CPU 上重跑,错误信息更友好。例如 GPU 报 "ERROR:tensorflow:Model diverged with loss = NaN" 其实很有可能是输入 ID 超出了 softmax 词表的范围。

  5. 要有耐心。

这一条放在最后,是因为很多人不把它当一回事儿。可能是觉得这一条不需要写代码所以不重要?我见过太多人因为这条浪费时间了,所以专门强调一下。

有些指标是有滞后性的,需要等训练一段时间才开始动(例如 BN 训练和推断行为不一致,可能训练的准确率已经很高了,但测试准确率很低,这是因为 BN 的统计量还不准,再等等就好了)。很多人训练几步看没什么效果就把程序停掉开始 debug 了,但其实代码毫无问题。如此反复好几天甚至一两周都在原地踏步,其实需要做的仅仅是让程序自个儿安安静静地跑上几个小时或者一天……

作者:Ying Zhang
https://www.zhihu.com/question/41631631/answer/94597396**

补充一点,adam收敛虽快但是得到的解往往没有sgd+momentum得到的解更好,如果不考虑时间成本的话还是用sgd吧。

再补充一个rnn trick,仍然是不考虑时间成本的情况下,batch size=1是一个很不错的regularizer, 起码在某些task上,这也有可能是很多人无法复现alex graves实验结果的原因之一,因为他总是把batch size设成1......

作者:hzwer
https://www.zhihu.com/question/41631631/answer/859040970**

总结一下在旷视实习两年来的炼丹经验,我主要做了一些 RL,图像质量,图像分类,GAN 相关的任务,日常大概占用 5 - 10 张卡。

可复现性和一致性

有的同学在打比赛的时候,从头到尾只维护若干份代码,每次载入前一次的训练参数,改一下代码再炼,俗称老丹。这样会有几个问题:某次引入一个 bug,过了很久才发现,然后不知道影响范围;得到一个好模型,但是不知道它是怎么来的;忘了自己的 baseline,不知道改动是正面还是负面。

要尽可能确保每一个模型有可复现性,实践上建议代码不应该在训练后再改动,训练新的模型时,把旧的代码复制一遍。得到的实验结果要开个文档记下来以便日后总结,避免遗忘。我经常通过阅读自己和别人的记录来得到灵感。

实验一致性上也要多做努力,理想状态是有合理的基准来测模型的性能,同一个代码不应该由于超参的微小改动而有显著结果差异。出现这种情况可能是数据太少或基准设置不当。

资源利用

对于新入行的同学,不要试图在玩具级别的数据集或任务上做靠谱的研究,比如 MNIST。

不是每一个实验都要出一个好模型,实验是为了验证结论的。如果每个实验都要 8 张卡跑两个星期,人力物力都耗不起。尽力把实验控制在单卡一天以内,理想状态是半天得一次结论。理论上来说,水多加面面多加水(加数据加计算量)的做法无限涨点。建议先设一个目标,比如说就是在一天的训练时间下做对比实验。

我的实践经验是,首先用小图小模型,比如 128 x 128 输入的 ResNet18;用 cProfile 来找性能瓶颈,比如我发现某个模型,训练的时候有一大半时间耗费在等数据,数据处理中一大半时间在调用 numpy 的 round 函数,前期把精力集中在提高做实验的效率上。

模型不 work

先把锦上添花的东西去掉,比如数据增广,玄学学习率和超参,魔幻损失函数,异形模型。如果世界上有一个非要加旋转增广和 1.96e-4 学习率 42 batchsize,配上四种混合损失函数才能训练好的模型,它应该存在于灵能文明。可以先造一些尽量玩具的模型,验证代码正确性。『需要进一步改进』
先确认影响模型性能的组件。感性认识就是,数据是否需要增加或增广。模型是大了还是小了,再根据速度和精度期望开始寻找合适的模型。能用全卷积的任务,少用全连接层,参数量小。基本模型上 ResNet, Unet 结构还是主流。

当你的模型有 Batch Normalization,初始化通常不需要操心,激活函数默认 Relu 即可(某引用数万的大佬说的)。一般顺序是 Conv - BN - Relu。如果没有 BN(很多任务上,BN降低训练难度,但是可能影响最终性能 ),试着要做一些数据归一化。

虽然有至少十种激活函数,但在 Relu 外只推荐试一下 Swish。优化器只推荐 Momentum 和 Adam。在这些方面做尝试意义不大,如果性能提升反倒可能说明模型不成熟。不推荐做人肉模型设计,比如把某层卷积改大一点,或者微调一下通道数。除非有特别 insight,不要自己乱设计新组件。

超参上,learning rate 最重要,推荐了解 cosine learning rate 和 cyclic learning rate,其次是 batchsize 和 weight decay。当你的模型还不错的时候,可以试着做数据增广和改损失函数锦上添花了。

作者:京东白条
https://www.zhihu.com/question/41631631/answer/776852832

相信很多刚开始接触深度学习朋友,会感觉深度学习调参就像玄学一般,有时候参数调的好,模型会快速收敛,参数没调好,可能迭代几次loss值就直接变成Nan了。

记得刚开始研究深度学习时,做过两个小例子。一个是用tensorflow构建了一个十分简单的只有一个输入层和一个softmax输出层的Mnist手写识别网络,第一次我对权重矩阵W和偏置b采用的是正态分布初始化,一共迭代了20个epoch,当迭代完第一个epoch时,预测的准确度只有10%左右(和随机猜一样,Mnist是一个十分类问题),当迭代完二十个epoch,精度也仅仅达到了60%的样子。然后我仅仅是将权重矩阵W初始化方法改成了全为0的初始化,其他的参数均保持不变,结果在训练完第一个epoch后预测精度就达到了85%以上,最终20个epoch后精度达到92%。另一个例子是回归问题的预测,当时采用的SGD优化器,一开始学习率设定的0.1,模型可以正常训练,只是训练速度有些慢,我试着将学习率调整到0.3,希望可以加速训练速度,结果没迭代几轮loss就变成Nan了。于是从那时起我就深刻的感受到参数调节在深度学习模型训练中的重要意义。

其实上述问题产生的原因也很好理解,对于参数初始化,因为我们学习的本来就是权重W与偏置b,如果初始化足够好,直接就初始化到最优解,那都不用进行训练了。良好的初始化,可以让参数更接近最优解,这可以大大提高收敛速度,也可以防止落入局部极小。对于学习率,学习率如果取太大,会使模型训练非常震荡,可以想象我们最小化一个二次抛物线,选取一个很大的学习率,那么迭代点会一直在抛物线的两边震荡,收敛不到最小值,甚至还有螺旋上升迭代点的可能。

下面对深度学习调参技巧谈些心得,虽说不能让你通过以下阅读成为一个调参高手,但最起码可以提供一些调参的思路。

1.激活函数选择

常用的激活函数有relu、leaky-relu、sigmoid、tanh等。对于输出层,多分类任务选用softmax输出,二分类任务选用sigmoid输出,回归任务选用线性输出。而对于中间隐层,则优先选择relu激活函数(relu激活函数可以有效的解决sigmoid和tanh出现的梯度弥散问题,多次实验表明它会比其他激活函数以更快的速度收敛)。另外,构建序列神经网络(RNN)时要优先选用tanh激活函数。

2.学习率设定

一般学习率从0.1或0.01开始尝试。学习率设置太大会导致训练十分不稳定,甚至出现Nan,设置太小会导致损失下降太慢。学习率一般要随着训练进行衰减。衰减系数设0.1,0.3,0.5均可,衰减时机,可以是验证集准确率不再上升时,或固定训练多少个周期以后自动进行衰减。

3.防止过拟合

一般常用的防止过拟合方法有使用L1正则项、L2正则项、dropout、提前终止、数据集扩充等。如果模型在训练集上表现比较好但在测试集上表现欠佳可以选择增大L1或L2正则的惩罚力度(L2正则经验上首选1.0,超过10很少见),或增大dropout的随机失活概率(经验首选0.5);或者当随着训练的持续在测试集上不增反降时,使用提前终止训练的方法。当然最有效的还是增大训练集的规模,实在难以获得新数据也可以使用数据集增强的方法,比如CV任务可以对数据集进行裁剪、翻转、平移等方法进行数据集增强,这种方法往往都会提高最后模型的测试精度。

4.优化器选择

如果数据是稀疏的,就用自适应方法,即 Adagrad, Adadelta, RMSprop, Adam。整体来讲,Adam 是最好的选择。SGD 虽然能达到极小值,但是比其它算法用的时间长,而且可能会被困在鞍点。如果需要更快的收敛,或者是训练更深更复杂的神经网络,需要用一种自适应的算法。

5.残差块与BN层

如果你希望训练一个更深更复杂的网络,那么残差块绝对是一个重要的组件,它可以让你的网络训练的更深。

BN层具有加速训练速度,有效防止梯度消失与梯度爆炸,具有防止过拟合的效果,所以构建网络时最好要加上这个组件。

6.自动调参方法

(1)Grid Search:网格搜索,在所有候选的参数选择中,通过循环遍历,尝试每一种可能性,表现最好的参数就是最终的结果。其原理就像是在数组里找最大值。缺点是太费时间了,特别像神经网络,一般尝试不了太多的参数组合。

(2)Random Search:经验上,Random Search比Gird Search更有效。实际操作的时候,一般也是先用Gird Search的方法,得到所有候选参数,然后每次从中随机选择进行训练。另外Random Search往往会和由粗到细的调参策略结合使用,即在效果比较好的参数附近进行更加精细的搜索。

(3)Bayesian Optimization:贝叶斯优化,考虑到了不同参数对应的 实验结果值,因此更节省时间,贝叶斯调参比Grid Search迭代次数少, 速度快;而且其针对非凸问题依然稳健。

7.参数随机初始化与数据预处理

参数初始化很重要,它决定了模型的训练速度与是否可以躲开局部极小。relu激活函数初始化推荐使用He normal,tanh初始化推荐使用Glorot normal,其中Glorot normal也称作Xavier normal初始化;数据预处理方法一般也就采用数据归一化即可。

作者:湮释
https://www.zhihu.com/question/41631631/answer/859424524**

这里说点自己在模型训练,部署和优化时的小经验吧。

网络结构设计

关于SE

SE在分类上是个涨点必备的工具,换言之,堆最高精度是一定要给每个block都加上它的,但是如果需要考虑时间,参数量和精度等的trade-off,无脑堆就没有意义了,这个时候应该要选择在合适的地方使用合适的模块。这个时候,推荐在block数量和添加SE上做权衡,即给部分blcok加上SE,同时砍掉一些block来加速,这样可以在精度差不多的情况下减少一些参数量。当然inference时间这个事需要看具体的应用平台对SE的实现,就是GAP和FC的速度,这就具体问题具体分析了。有余力有卡的人,可以迁移某种NAS方法来做这个的搜索。

关于SE之前忘说了一点,SE在其他任务的使用并不是一帆风顺,之前看过一个回答说是检测上有些情况下会掉点,个人解释是SE是个channel attention,对于一个channel的spatial domain用一个scale值,那对于anchor-based的检测任务,由于在feature map上会放不同scale的anchor,那么一个feature map对应检测的既有大物体又有小物体,而SE中Global Average Pooling之后的结果一般来说是受大物体影响较多的,所以加了SE就会使大物体涨点小物体掉点,最终有些数据集上,总的mAP就会下降,而现在的一些anchor-free的方法,是强行设定一个feature map检一个scale,那么可能就没有这个问题,当然具体anchor-free和这个的关系还需要有心人实验去验证了。

关于激活函数

不要认为ReLU的各种改进一定比ReLU好,比如LeakyReLU在某些情况下性能不如ReLU,这样的例子在high-level和low-level任务都有,关于这个有一种理解思路是这样的:很多人认为LeakyReLU保留了负半轴的信息所以会更好,但事实上网络结构只是先验性地提供了一种信息变换方式,在训练过程中BP会根据网络结构来进行对应的构建。举例来说,我们无法确定某个feature map输出的有效值的范围,如果是LeakyReLU,可能有效值(更准确应该叫有用的激活值)正半轴负半轴都有,而ReLU的话,可能网络结构倾向于把有用的值变换到正半轴,无用的值变换到负半轴,正好ReLU就滤掉了,所以无法武断地说哪个更好。例外的是:如果你的任务有一些更强的先验跟这些激活值有关,那是会有明显的优劣的。因此,平常baseline就ReLU,等到后期有卡有时间了,可以换其他激活函数一试。

除了ReLU系,swish是一个挺好用的提点trick,当然这里为了速度一定要用hard版本,与此对应还有sigmoid的hard版本(具体形式参见mobilenet v3),原文中的结果,我个人的使用经验,hard版本比初始版本在常规训练设置下是不会有精度损失的。当然,hard版本速度依然明显慢于ReLU,所以也要根据需求来做取舍(maybe硬件上还能再优化)。理解swish的话,其实就暴力看做一个隐式的attention就好了,所以个人认为attention搞那么多trick的收益真的不太大。

关于norm

这里就只说bn吧,其他norm根据任务而异来使用。关于bn整体的讲解可以去参考Wu Yuxin之前有次线上直播讲的内容,那个非常全面。我就说点bn相关的不太常见的trick吧。

  • bags of tricks那篇提到的zero初始化bn的affine factor的操作,通常大家是用1来初始化,但这篇文章中说到用0来初始化,从而使block主分支为0,shortcut分支直接通向下个block,从而模拟更少层数的训练,具体信息可以参见原论文。

  • 对于一些训练过程中各个迭代之间前向计算图可能不同的情况,由于每个计算节点每次迭代的输入可能不同,所以bn的EMA统计值也许存在问题,这时候我们通常使用后验bn的方法(可以参见Universal slimmable),这在NAS和最近兴起的federal learning里挺常见的。就是训练时拿当前batch的mean和var做norm,但是最终inference并不使用统计出来的EMA,而是在训练完成之后(这里就直接拿pytorch实现来说),将模型设置为训练模式,从训练数据中抽取一个子集,只前向不反传,由于pytorch里train模式的话bn模块会自动统计running mean和running variance,所以就可以搞定bn统计量。当然这里还要提到一个trick,就是在后验bn的时候,对于统计梯度的动量系数要从0.9变到0.99(pytorch里就是把momentum从0.1变为0.01),这样做往往能获得更好的统计结果。原理是:在训练时统计,模型参数值仍在更新,这时候的历史统计值可靠度并不高,所以要用0.9的历史0.1的当前,但是模型训练完毕后,参数已经不会更新了,这时候的历史统计值可信度就很高了,所以用0.99,不过该解释并不是特别严谨,所以事实上偶尔也是存在改了之后没啥用的情况的,酌情食用即可。

作者:SECRET WANG
https://www.zhihu.com/question/41631631/answer/873274948**

菜炼丹师不请自来,工具主要使用 tensorflow兼用pytorch,做的东西主要是low level和mid level vision,比如super resolution,style transfer,image2image translation,generative models。

  1. 很重要但容易被忽视的一点是,模型不能得到预期的结果,有可能是网络结构搭错了。pytorch可能好一些,tensorflow里面的函数式网络定义很容易出现有些层并没有实际进入back propogation。建议先生成tflite或者pb文件,然后用可视化工具比如Netron来看一下网络结构和梯度传播。

  2. batch size和learning rate是个人看来最重要的超参,这两个参数又是互相影响的。之前在8卡服务器跑imagenet的时候看的论文印象中这两个参数可以按线性调节,即batch size增大一倍,learning rate也可以相应增大一倍。大模型,大batch size,有batch norm可以用较大的学习率(1e-3这样子,imagenet上面有batch size256直接用0.1初始学习率的),目前我做gan based image2image translation一般是batch size16,learning rate 2e-4或者3e-4,训练非常稳定

  3. 常见的数据预处理一般是rescale到(-1, 1), 即除以127.5然后减去1,或者rescale到(0, 1),即除以255,或者rescale之后减去均值除以方差。如果用全卷积网络做输出是image的任务,我一般用前两种;第三种常见于各种分类检测以及其他输出是label的任务。

  4. 初始化方法有很多,但是目前直接xavier或者he/msra initializer就可以了,有bn的话问题都不大。需要用其他的基本也不会看这种入门经验贴了。

  5. 最常见的data agmentation是random crop,random flip (herizontal, vertical),骚一点可以加random hue,random contrast,color space shift等等,虽然我很怀疑他们的用处(自己的实验里面用处不大,不过刷点的实验我做得少)

  6. 常见的optimizer很多,不过建议验证算法第一次跑直接上adam,稳定收敛快。如果想刷点可以sgd with momentum。学习率衰减可以用线性,指数,consine,阶梯,不过刷点任务我做得少.

  7. 几种gan loss里面,vanilla gan自然是最不稳定的,lsgan在我这边的任务里面好一些,condition gan可以用lsgan代替vanillagan。wgan和wgan gp理论上是minimize wasserstein distance会更稳定,但是在我这里生成质量并不是很好。用spectral norm不仅稳定,生成的图片也比较美观。当然这有可能是task specific,但是我至少在三个任务(style transfer,pix2pix,super resolution)上面用lsgan+spectral norm取得了很好的效果,且不用调超参/gan loss。

  8. 讲一点task specific的东西:原先的srgan/esrgan都会引入perceptual loss/vgg loss,但是换lsgan+spectral norm以后,去掉perceptual loss还能生成细节提高且不会产生大量artifacts的结果。另外在有图像作为condition的gan任务中,使用全卷积patch discriminator+patch gan loss可以有效提高质量。

  9. 全卷积网络生成任务中bn可能没啥用,甚至导致负效果(参考edsr)。

  10. deconvolution可能导致checkerboard artifacts(棋盘格效应),可以考虑pixel shuffle或者resize+convolution或者total variation loss来规避。要是还不行就扁鹊三连吧。

  11. to be continued.

作者:zhou yu
https://www.zhihu.com/question/41631631/answer/94829260**

  1. 无论是cnn还是rnn,batch normalization都有用,不一定结果提高几个点,收敛快多了

  2. 数据初始时normalize得好,有时候直接提高2个点,比如cifar10,转到yuv下normalize再scn
  3. loss不降了lr就除10

  4. google的inception系列按它论文里说的永远无法复现

作者:张馨宇
https://www.zhihu.com/question/41631631/answer/91743153

有两个东西:

  1. Hinton老爷子的公开课,说了很多;

  2. 一本书,《Neural Networks:Tricks of the Trade》

作者:Necther

https://www.zhihu.com/question/41631631/answer/782304546

  1. 要注意不同的网络结构学习率是不一样的 甚至差上数量级 如果碰见网络不收敛 检查数据标注是正确的 就要考虑学习率是否过大

  2. 先训练几轮看一下情况 观察loss下降的速度,如果震荡 就要调小学习率

  3. 注意数据多少和 学习率衰减的关系 尤其是ocr这种需要大量样本的场景 太少数据量相当于 字都没有看全 不能够马上迭代到下一个批次

作者:笨小孩

https://www.zhihu.com/question/41631631/answer/107680023**

本人做rnn的文本相关研究,一直使用adam,下降速度巨快,看别人论文也尝试过adadelta和adagrad,但不知是姿势不对还是别的原因效果很差,batch-size大小设置在50(训练集大小为17w),dropout随大流0.5,另外我发现l2取值对我的结果影响挺大的,之前一直跟着别人论文用0.001,我换成0.0001以后发现提升了1\%。

作者:Cai Ji
https://www.zhihu.com/question/41631631/answer/92408405**

最近在看 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

作者:二十世纪少年
https://www.zhihu.com/question/41631631/answer/679143046

看到别人都回答了很多,我随便讲几个自己经常用的。

  1. 神经元个数一般设置为2的n次方。计算机处理数据是二进制,设置为2的n次方计算速度据说会变快,我在训练word2vec时一般都设定为128维输出,rnn的隐藏层也经常设置128个神经元**

  2. 经常使用BatchNormalization或layer normalization层。BatchNormalization层在每个batch上将前一层的激活值重新规范化,即使得其输出数据的均值接近0,标准差接近1。有着加速收敛速度,控制过拟合等好处。大多数神经网络都可以加这层,加了也没什么坏处。注意,由于词向量的特性,在nlp(自然语言)领域,最好使用layer normalization层做规范化!

  3. 及时early stop。盯着模型训练时在验证集上每轮的度量指标值,选择一个指标值很好的时间点,及时停止继续batch,防止过拟合。

- END -

  • 0
  • 0
  • 2319
收藏
暂无评论