深度玄学:你的网络不work的37种原因
2018/4/10 18:15:47 中国科学院自动化研究所

    

     如何利用这篇guide

     深度学习的程序可能出错的地方有很多,这其中有一些错误发生频率比其他更高。通常我会从如下一些方面先行入手:

     ◆从简单并且得到广泛应用的网络开始,如VGG,如果可以的话使用标准的损失函数。

     ◆暂时去掉所有的trick,如数据增强(Data Augmentation)和正则化(regularization)。

     ◆如果是微调(finetuning)模型,再次检查数据的预处理,保证其和原始网络训练时一致。

     ◆检查输入数据是正确的。

     ◆从很少量的数据开始(2-20样本),使其过拟合,然后逐渐增加样本。

     ◆逐渐增加trick,数据增强,正则化,新的损失函数,更复杂的网络等等。

     如果上面的仍然不work的话,请按照下面的逐条实验。

     1.数据集问题

    

     1)检查输入数据

     检查输入给网络的数据是不是有意义的。比如,我不止一次将高度和宽度混淆(输入的图像是转置的)。有时因为数据预处理的错误输入的是全0图像。或者将同一batch的图像反复送入网络。所以,先打印出几个batch的输入保证正确性。

     2)尝试随机输入

     尝试输入随机数量的样本检查是否出现相同的错误。如果仍然出现同样的错误,说明网络本身有问题。这时尝试逐层调试。

     3)检查Data loader

     不同的框架有不同的data loader,如tensorflow的tfrecords,keras的imagegenerator等。数据本身可能没什么问题,但data loader可能有出错地方。先打印第一层的输入进行检查。

     4)确保网络输入和输出是一致的

     检查输入和预定的输出(label)是不是一致的,比如是否同时进行相同的shuffle。

     5)输入和输出的关系是否太过随机?

     可能输入和输出的关系随机的成分更大,关系成分更小,如股票预测。这种情况下输入和输出不存在有效的关系。没有通用的方法检查这种情况,因为这决定于数据。

     6)数据集标签噪音是否过大?

     这种情况多发于自己从网上爬数据或者某些小型比赛。比如我从食物网站爬数据时经常有很多标签是不正确的。先手动检查一部分数据的标签是不是有很大噪声。

     7)打乱(shuffle)数据

     如果你的数据没有打乱而是有一定顺序的,这可能会给网络学习带来很负面的影响。确保你的数据经过了shuffle。

     8)减小数据不平衡

     数据的不平衡指的是不同类别样本数量相差很大,如医疗数据就经常出现这种情况。数据的不平衡会导致损失函数的不平衡。由于篇幅限制,本文不再讨论如何平衡数据,可以参考https://machinelearningmastery.com/tactics-to-combat-imbalanced-classes-in-your-machine-learning-dataset/。(可能需要科学上网哦)

     9)训练样本是否足够

     如果网络是从头开始训练而不是fine-tuning,那么可能需要大量的数据。对于分类任务来说,通常一个类需要1000样本甚至更多。

     10)确保一个batch中样本不是都属于同一类

     这种情况可能发生于样本是有序的情况下,不过通过shuffle可以很容易解决这个问题。

     11)减小batch size

     论文《On Large-Batch Training for Deep Learning: Generalization Gap and Sharp Minima》指出非常大的batch可能会减弱网络的泛化性能。

     Additional:使用标准数据集

     当测试新的网络时首先使用标准的数据集如mnist而不是自己的数据,因为标准数据集标签噪声很小。如果网络在标准数据集上能够很好工作那么网络本身可能没有问题。

     2.数据增强和归一化

    

     12)归一化数据

     检查是否将输入归一化为0均值标准方差。

     13)数据增强是否太过?

     数据增强有正则化的效果,但是太多的数据增强和其他形式的正则化如dorpout, l2 regularization一起可能会导致欠拟合。

     14)查看预训练网络的预处理方式

     如果你使用的是预训练的网络,确保你用了相同的预处理方式。如图像像素范围在[0,1],[-1,1]还是[0,255]。

     15)检查对于训练集、验证集、测试集的预处理

     斯坦福CS231课程对于数据预处理有详细论述,参考http://cs231n.github.io/neural-networks-2/#datapre

     数据预处理必须只在训练集上计算,然后将参数用于验证集和测试集的处理。

     3.实现过程问题

    

     16)尝试解决问题的简化版本

     这将帮助找到问题的来源。如当需要解决的问题是找到物体的具体位置和类别,可以先尝试暂时忽略定位任务,只完成分类任务

     17)寻找正确的损失“at chance”

     参考自CS231n,

     http://cs231n.github.io/neural-networks-3/#sanitycheck。

     "at chance"的意思是如果有10类样本,"at chance"会得到10%的正确率,这时Softmax的损失应该为-ln(0.1)=2.302。可以对比自己网络的损失检查。

     18)检查损失函数

     如果损失函数是自己实现的不是标准损失函数,检查是否有错,可以进行单独的输入测试。

     19)检查损失函数的输入

     如果损失函数来自于深度学习框架如tensorflow自带,确保你的输入和规定的一致。如在pytorch中NLLLoss和CrossEntropyLoss的输入容易被混淆,前者需要输入softmax形式的输入,而后者不需要。

     20)调整损失权重

     如果你的损失函数是有几个小的损失函数组成,检查他们的权重是否合理。不同组合的权重可能会导致结果差异很大。

     21)监控其他度量(metrics)

     有时损失并不是最合适的预测,如果可以的话,监测其他度量如准确率。

     22)检查自己写的layer(custom layer)

     如果自己写了框架中没有的层,一定要再三确保所写的layer正常工作。

     23)检查layer或变量是否“forzen”

     检查是否不小心将需要学习的layer或者变量”frozen”了。

     24)增加网络深度/宽度

     可能你的网络出现了欠拟合的问题,尝试增大网络。如增加卷积层或增加全连接层神经元的数目。

     25)检查隐层数据维度是否有误

     如果输入是(64,64,64)这样的维度形式,很容易出现维度错误,如通道维度和宽度互换。这种情况下使用特殊的数字进行检查,如不同的维度使用不同的数字。

     26)检查梯度

     如果有些层是自己手动写的梯度传播公式,检查是否实现有误。(有些框架中自己实现的layer是要自己写梯度)。参考CS231n的梯度检查说明http://cs231n.github.io/neural-networks-3/#gradcheck

     4.训练问题

    

     27)在非常小的数据集上训练

     当数据集比较小时非常容易过拟合。这种情况下需要数据增强,过采样,或者使用外部数据等手段增加数据量。

     28)检查权重初始化方式

     如果不确定哪一种初始化方式对自己网络最有效时,推荐使用Xavier和He初始化。不合适的初始化可能会导致网络进入坏的局部最小值点,所以尝试不同的初始化方式。

     29)改变超参数

     超参数对网络影响很大,如果不确定哪种设置更好,可以采用grid search。参考http://scikit-learn.org/stable/modules/grid_search.html

     30)减弱正则化

     太多的正则可能导致网络能力不足,在适当情况下减弱如dropout, batch norm, weight l2 regularzation等。参考Jeremy的课程http://course.fast.ai/

     31)Give it time

     可能你的网络需要更多的时间去训练才能产出有意义的预测。如果loss在稳定的下降,请给网络更多的时间训练再做决定。

     32)从训练模式转换为测试模式

     Batch Norm,Dropout等层在测试和训练时操作不同,注意在网络设置时这些层参数是否根据训练和测试的不同有所改变。如tensorflow中tf.contrib.layers中的batch norm需要手动传入是否在训练的参数。

     33)训练可视化

     利用tensorboard和crayon等工具对weights/bias/activations等进行可视化,确保他们的值正常。比如weights更新的强度应该在大约1e-3左右。参考https://deeplearning4j.org/visualization#usingui

     34)尝试不同的优化器

     即使不同的优化器也不应该使网络不work除非选用了特别差的参数。即使如此,不同的优化器也会带来不同的效果,选择合适的优化器不仅能带来好的输出,还能节约大量时间。在不清楚用何种优化器时推荐使用Adam或SGD with momentum。

     参考Sebastian的文章

     http://ruder.io/optimizing-gradient-descent/

     35)梯度消失/爆炸

     检查梯度是否出现了很大或很小的情况。检查layer的激活值,Deeplearning4j上有一个很好的指导:a good standard deviation for the activations is on the order of 0.5 to 2.0. Significantly outside of this range may indicate vanishing or exploding activations

     36)增加/减少学习率

     小的学习率会让网络收敛很慢。大的学习率可能会在训练末尾难以找到一个好的解。在你当前的学习率进行10/0.1倍调整。

     37)克服NaNs

     出现Nan是训练网络尤其是RNN时一个非常大的问题。一些可能的帮助手段如下:

     ◆减小学习率,尤其是在前100 iteration就出现Nan

     ◆Nan可能发生在除0或者log0的情况下,检查是否有这些问题

     ◆检查网络每一层,看Nan在哪里先出现的

     5.总结

     现有的经验总结大抵如此,调试网络时候经常像是在搞玄学,但这些经验也能给一些指导,希望对你的工作有所帮助。

    

     更多精彩内容,欢迎关注

     中科院自动化所官方网站:

     http://www.ia.ac.cn

     欢迎后台留言、推荐您感兴趣的话题、内容或资讯,小编恭候您的意见和建议!如需转载或投稿,请后台私信。

     整理:张志鹏

     编辑:鲁宁、欧梨成

     中科院自动化研究所

     微信:casia1956

     欢迎搭乘自动化所AI旗舰号!

    http://weixin.100md.com
返回 中国科学院自动化研究所 返回首页 返回百拇医药