当前位置: 华文问答 > 数码

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

2016-03-21数码

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

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)

6、初始学习率:

有时受 batch size、sequence length 各种因素的影响,loss 很大(比如说好几万),对于这种数字人是没有数感的,建议首先计算一下 per token loss(如果是多任务,可以每个任务单独算;类似地,某些 CV 任务可以计算 per pixel loss),心里有点感觉。脱离损失函数的形式谈学习率没有意义(例如单是对 batch size 求和或者取平均这个差异就会使梯度差成百上千倍)。

在确定初始学习率的时候,从一个很小的值(例如 1e-7)开始,然后每一步指数增大学习率(例如扩大1.05 倍)进行训练。训练几百步应该能观察到损失函数随训练步数呈对勾形,选择损失下降最快那一段的学习率即可。

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

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

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

10、要有耐心

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

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