(图片由AI科技大本营付费下载自视觉中国)
作者 | Slav Ivanov
译者 | 吴金笛
校对 | 丁楠雅、林亦霖
编辑 | 王菁
来源 | 数据派THU(ID:DatapiTHU)
【导语】本文列举了在搭建神经网络过程中的37个易错点,并给出了解决建议。
有一个网络已经训练了12个小时。一切看起来都很好:梯度是逐渐变化的,损失在减少。但接下来的预测:都是零,所有的图像背景都没有被检测到。“我做错了什么?”——我问我的电脑,但它没有回答我。
你从哪里开始检查是否你的模型输出了垃圾(例如,预测输出了平均值,或者它的准确性真的很差)?
由于许多原因,神经网络可能不会进行训练。在许多调试过程中,我经常发现自己在做同样的检查。我把我的经验和最好的想法整理在这个便利的列表中,希望它们对你也有用。
目录
1. 如何使用本指南?
2. 数据集问题
3. 数据规范化或增强的问题
4. 实现问题
5. 训练问题
1.如何使用本指南?
很多方面都可能出错。但是其中一些比其他的更有可能被防范。我通常从以下简短的清单开始,作为紧急的第一反应:
1. 从一个已知适用于这类数据的简单模型开始(例如,图像的VGG)。如果可能,使用标准损失。
2. 关闭所有的附加功能,例如正则化和数据增强。
3. 如果对一个模型进行微调,要仔细检查预处理,因为它应该与原始模型的训练相同。
4. 验证输入数据是否正确。
5. 从一个非常小的数据集(2-20个样本)开始。对它进行过度拟合,并逐渐添加更多的数据。
6. 开始逐步添加所有被省略的部分:增强/正则化、自定义损失函数、尝试更复杂的模型。
如果上面的步骤没有解决问题,那就根据下面的列表逐一验证。
2.数据集问题
检查你向网络输入的数据是否有意义。例如,我不止一次搞混了图像的宽度和高度。有时候,我会错误地输入全0数据。或者我会一遍又一遍地使用相同的批次。因此,打印/显示几批输入和目标输出,以确保它们是正确的。
尝试传入随机数而不是实际数据,看看错误是否相同。如果是这样,这是一个确定的信号,说明你的网络在某个时候将数据转换为了垃圾。试着一层一层或一个操作一个操作的调试看看哪里出错了。
你的数据可能没问题,但是将输入传递到网络的代码可能会出错。在任何操作之前打印并检查第一层的输入。
检查一些输入样本是否有正确的标签。同时确保对输入样例进行打乱的方式与输出标签的相同。
也许与随机部分相比,输入输出关系中的非随机部分太小了(人们可能认为股价就是这样的)。即输入与输出不充分相关。没有一种通用的方法来检测这一点,因为这取决于数据的性质。
当我从一个食品网站上抓取一个图像数据集时,这种情况发生在我身上。有很多网络无法学习的不好的标签。手动检查一批输入样本,看看标签是否正常。
截止点是有争议的,因为有论文使用50%损坏的标签使MNIST的准确度达到50%以上。
https://arxiv.org/pdf/1412.6596.pdf
如果你的数据集没有被打乱,并且有一个特定的顺序(按标签排序),这可能会对学习产生负面影响。打乱你的数据集以避免这种情况。确保输入和标签打的乱顺序相同。
是否每个B类图像对应1000个A类图像?那么你可能需要平衡你的损失函数或尝试其他类不平衡方法。
https://machinelearningmastery.com/tactics-to-combat-imbalanced-classes-in-your-machine-learning-dataset/
如果你正在从零开始训练一个网络(即不是微调),你可能需要大量的数据。对于图像分类,人们认为每个类需要1000张或更多的图像。
https://stats.stackexchange.com/questions/226672/how-few-training-examples-is-too-few-when-training-a-neural-network/226693#226693
这可能发生在排序的数据集中(即前10k个样本包含相同的类)。通过打乱数据集很容易解决。
有论文指出,批量较大会降低模型的泛化能力。
https://arxiv.org/abs/1609.04836
3.数据则正则化或增强
你是否将输入标准化为零均值和单位方差?
增强具有正则化作用。与其他形式的正则化(权重L2、dropout等)结合使用过多会导致网络不匹配。
如果你使用的是预训练模型,请确保使用的规范化和预处理与训练时使用的模型相同。例如,一个图像像素是否应该在[0,1]、[- 1,1]或[0,255]范围内。
CS231n指出了一个常见的陷阱:
“…任何预处理统计数据(例如数据平均值)必须只计算在训练数据上,然后应用于验证/测试数据。例如,计算平均值并从整个数据集中的每个图像减去它,然后将数据分割为训练集/验证集/测试集,这是一个错误。”
此外,检查每个样本或批次的不同预处理。
4.实现问题
这将有助于找到问题所在。例如,如果目标输出是一个对象类和坐标,则尝试将预测限制为对象类。
同样来自优秀的CS231n:使用小参数初始化,无需正则化。例如,如果我们有10个类,随机意味着我们将在10%的时间内得到正确的类,而Softmax损失是正确类的概率的对数的相反数,所以:-ln(0.1) = 2.302。
在此之后,尝试增加正则化强度,这会增加损失。
如果你实现了自己的损失函数,请检查它是否有错误并添加单元测试。通常情况下,我的损失值会略微不正确,并小程度的降低网络的性能。
如果你正在使用框架提供的损失函数,请确保传递给它的是它所期望的值。例如,在PyTorch中,我将混合NLLLoss和CrossEntropyLoss,因为前者需要一个softmax输入,而后者不需要。
如果损失由几个较小的损失函数组成,请确保它们相对于每个损失函数的大小是正确的。这可能需要测试不同的损失权重的组合。
有时候,损失并不最好的预测器来判断你的网络是否在正常训练。如果可以,请使用其他指标,如准确性。
是否网络中的某一层是你自己实现的?请反复检查以确保它们按预期工作。
检查是否无意中禁用了一些应该被学习的层/变量的梯度更新。
也许你的网络的表现力不足以捕获目标功能。尝试在完全连接的层中添加更多层或更多隐藏单元。
如果你的输入是(k, H, W) =(64, 64, 64),那么很容易忽略与错误维度相关的错误。对输入维使用奇怪的数字(例如,每个维使用不同的素数),并检查它们如何在网络中传播。
如果你手工实现梯度下降,进行梯度检查可以确保你的反向传播能够正常工作。
更多信息可参阅:
http://ufldl.stanford.edu/tutorial/supervised/DebuggingGradientChecking http://cs231n.github.io/neural-networks-3/#gradcheck https://www.coursera.org/lecture/machine-learning/gradient-checking-Y3s6r
5.训练问题
对一小部分数据进行过度拟合,并确保其工作正常。例如,只训练1或2个例子,看看你的网络能否学会区分这些。继续对每个类别添加更多的示例。
如果不确定,请使用Xavier或He初始化。此外,你的初始化可能会导致错误的局部最小值,因此尝试不同的初始化,看看是否有帮助。
也许你使用了一组特别糟糕的超参数。如果可行,尝试网格搜索。
过多的正则化会导致网络严重不拟合。减少正则化,如dropout、batch norm、weight/bias L2正则化等。在优秀的“程序员实践深度学习”课程中,Jeremy Howard建议首先摆脱不拟合。这意味着你要对训练数据进行充分的过拟合,然后才能解决过拟合问题。
也许你的网络在开始做出有意义的预测之前需要更长的时间来训练。如果你的损失在稳步下降,就再训练更多的时间。
有些框架具有Batch Norm、Dropout等层,其他层在训练和测试期间的行为有所不同。切换到适当的模式可能有助于你的网络正确预测。
(1)监视每一层的激活、权重和更新。确保它们的大小匹配。例如,参数更新的大小(权重和偏差)应该是1-e3。
(2)考虑一个可视化库,比如Tensorboard和Crayon。在紧要关头,你还可以打印权重/偏差/激活。
(3)注意那些平均值远远大于0的层激活。尝试Batch Norm或ELUs。
(4)Deeplearning4j指出了在权重和偏差的直方图中应该期望什么。
“对于权重,这些直方图应该在一段时间后具有近似高斯(正态)分布。对于偏差,这些直方图通常从0开始,并且通常以近似高斯分布结束(LSTM是一个例外)。注意那些发散到+/-∞的参数。注意那些非常大的偏移量。如果类别的分布非常不平衡,有时可能会在输出层中进行分类。”
检查层的更新,他们应该形成一个高斯分布。
你选择的优化器不应该阻止你的网络进行训练,除非你选择了特别糟糕的超参数。然而,合适的任务优化器有助于在最短的时间内获得最多的训练。该论文指出你正在使用的算法应该指定优化器。如果没有,我倾向于使用Adam或带动量的普通SGD。
查看这篇由Sebastian Ruder撰写的优秀文章,了解更多关于梯度下降优化器的知识。
http://ruder.io/optimizing-gradient-descent/
(1)检查层的更新,因为非常大的值可以说明梯度爆炸。梯度剪切可能会有所帮助。
(2)检查层激活。Deeplearning4j提供了一个很好的指导方针:“激活的良好标准偏差在0.5到2.0之间。明显超出这一范围可能意味着消失或爆炸的激活。”
低学习率将导致你的模型收敛得非常缓慢。
高学习率会在开始时迅速减少损失,但可能很难找到一个好的解决方案。
用你目前的学习速度乘以0.1或10来解决问题。
在训练RNN时,据我所知,得到一个NaN(Non-a-Number)是一个更大的问题。一些解决方法:
降低学习速度,特别是如果你在前100次迭代中得到了NaNs。
NaNs可以由除以0,或0或负数的自然对数产生。
Russell Stewart在如何应对NaN中有很好的建议。
http://get.mysecurify.com/view/item_81593.html
试着一层一层地评估你的网络,看看NaNs出现在哪里。
作者介绍:
Slav,企业家和开发者,也是SaaS公司Encharge - marketing automation software的联合创始人。
译者介绍:
吴金笛,雪城大学计算机科学硕士一年级在读。迎难而上是我最舒服的状态,动心忍性,曾益我所不能。我的目标是做个早睡早起的Cool Girl。
原文标题:
37 Reasons why your Neural Network is not working
原文链接:
https://blog.slavv.com/37-reasons-why-your-neural-network-is-not-working-4020854bd607
(*本文为 AI科技大本营转载文章,转
载请联系原作者)
2019 中国大数据技术大会(BDTC)历经十一载,再度火热来袭!
豪华主席阵容及百位技术专家齐聚,15 场精选专题技术和行业论坛,超强干货+技术剖析+行业实践立体解读,深入解析热门技术在行业中的实践落地。
【早鸟票】
与
【特惠学生票】
限时抢购,扫码了解详情!
推荐阅读