最近SlavIvanov在Medium上发表了一篇名为《37 Reasons why your Neural Network is not working》的文章,从四个方面(数据集、数据归一化/增强、实现、训练),对我长期的37个总结神经网络调试心得,穿插了很多优秀的个人想法和思考,希望能帮助大家跨过神经网络训练的37个大坑。机器之心整理了这篇文章。神经网络已连续训练12小时。看起来不错:梯度在变化,损失在下降。但是预测结果出来了:全是零值,全是背景,没有检测到任何东西。我问我的电脑,“我做错了什么?”它无法回答。如果你的模型输出垃圾(比如预测所有输出的平均值,或者它的准确率真的很低),你从哪里开始检查?一个神经网络无法训练的原因有很多,所以作者总结了很多debug,发现有些check是经常做的。此列表总结了作者的经验和最佳想法,希望对读者也有所帮助。1.数据集问题1.检查你的输入数据检查输入到网络的输入数据是否正确。例如,我不止一次混淆了图像的宽度和高度。有时我会错误地让输入数据全为零,或者一遍又一遍地对同一批数据执行梯度下降。所以打印/显示几批输入和目标输出并确保它们是正确的。2.尝试随机输入尝试传递随机数而不是真实数据,看看错误是否以同样的方式发生。如果是,则您的网络在某个时候将数据变成了垃圾。尝试层层调试,看看哪里出了问题。3.检查数据加载器你的数据可能没问题,但是读取输入数据到网络的代码可能有问题,所以我们应该打印第一层的输入并在所有操作之前检查它。4.确保输入与输出相关,以检查少数输入样本是否具有正确的标签,并确保打乱输入样本对输出标签也有效。5、输入输出关系是否太随机?输入和输出之间的非随机部分可能相对于随机部分太小了(可以认为股价也是如此),即输入和输出之间的相关性太低。没有单一的方法来检测它,因为它取决于数据的性质。6.数据集中是否有太多噪音?我曾经遇到过这种情况,当我从一个食品网站上抓取图像数据集时,有太多错误的标签以至于网络无法学习。手动检查一些输入样本并查看标签是否大致正确。7.打乱数据集如果你的数据集没有打乱并且有一个特定的序列(按标签排序),这会对学习产生不利影响。您可以打乱数据集以避免它并确保重新排列输入和标签。8.减少类不平衡一张B类图像和1000张A类图像?如果是这种情况,那么您可能需要平衡您的损失函数或尝试其他方法来解决类不平衡问题。9.你有足够的训练样例吗?如果您从头开始训练网络(即不调试),您很可能需要大量数据。对于图像分类,每个类别需要1000张或更多图像。10.确保你取的批次数据不是单个标签。这可能发生在排序的数据集中(即前10000个样本属于同一类)。通过shuffle数据集轻松修复。11.减小batchsize巨大的batchsize会降低模型的泛化能力(参见:https://arxiv.org/abs/1609.04836)2.数据归一化/增强12.归一化特征你的输入已经归一化归一化为零均值和单位方差?13.你是否应用了过多的数据增强?数据扩充具有正则化效果。过度的数据增强,结合其他形式的正则化(权重L2、dropout效应等)会导致网络欠拟合。14.检查预训练模型的预处理如果您使用的是已经预训练的模型,请确保使用与训练模型时相同的归一化和预处理。例如,图像像素应该在[0,1]、[-1,1]或[0,255]范围内吗?15.检查训练、验证和测试集预处理CS231n指出了一个常见的陷阱:“任何预处理数据(例如数据均值)必须仅在训练数据上计算,然后应用于验证、测试数据。例如,计算均值,然后在整个数据集的每个图像中减去它,然后把数据分布到训练、验证和测试集中是一个典型的错误。”此外,检查每个样本或批次中的不同预处理。3.实施问题16.尝试解决问题的更简单版本。这将有助于找出问题的根源所在。例如,如果目标输出是一个对象类和坐标,尝试将预测限制为仅对象类(尝试删除坐标)17.“巧合”找到正确的损失仍然来自CS231n技术:用小参数初始化并且不使用正则化。例如,如果我们有10个类,“偶然”意味着我们将在10%的时间内得到正确的类,Softmax损失是正确类的负对数概率:-ln(0.1)=2.302。然后,尝试增加正则化的强度,这应该会增加损失。18.检查你的损失函数如果你正在实现自己的损失函数,检查错误并添加单元测试。通常,损失可能有些不正确并损害网络的性能。19.验证损失输入如果你正在使用框架提供的损失函数,那么确保你传递给它的是它所期望的。例如,在PyTorch中,我会混淆NLLLoss和CrossEntropyLoss,因为一个需要softmax输入而另一个不需要。20.调整损失权重如果你的损失是由几个较小的损失函数组成的,确保每个损失函数对应的量级是正确的。这可能涉及测试不同的减重组合。21.监控其他指标有时损失并不是预测您的网络是否正确训练的最佳指标。如果可以,请使用其他指标来帮助您,例如精度。22.测试任何自定义层您是否自己在网络中实现了任何层?检查并仔细检查以确保它们按预期工作。23.检查“冻结”的层或变量检查您是否无意中阻止了某些应该可学习的层或变量的梯度更新。24.扩大你的网络。您的网络可能没有足够的表现力来捕获目标函数。尝试添加更多层,或在全连接层中添加更多隐藏单元。25.检查隐藏的维度错误如果你的输入看起来像(k,H,W)=(64,64,64),很容易错过与错误维度相关的错误。对输入维度使用一些“奇怪”的值(例如每个维度的不同质数),并检查它们如何通过网络传播。26.探索梯度检查(Gradientchecking)如果你手动实现梯度下降,梯度检查将确保你的反向传播(backpropagation)按预期工作。4.训练问题27.一个非常小的数据集会过度拟合一小部分数据并确保它有效。例如,仅使用1或2个实例进行训练,看看您的网络是否学会了区分它们。然后训练每个类的更多实例。28.如果不确定,请检查权重初始化,使用Xavier或He初始化。另外,初始化可能会给你不好的局部最小值,所以尝试不同的初始化,看看是否可行。29.改变你的超参数也许你正在使用一组糟糕的超参数。如果可能,请尝试网格搜索。30.减少正则化过多的正则化会导致网络严重欠拟合。减少正则化,比如dropout、batchnorm、weight/biasL2regularization等。在优秀课程《编程人员的深度学习实战》(http://course.fast.ai)中,JeremyHoward推荐先解决underfitting问题。这意味着您对数据进行了充分的过度拟合,然后才处理过度拟合。31.给它一些时间也许你的网络需要更多的时间来训练才能做出有意义的预测。如果你的损失在稳步下降,训练时间长一点。32.从训练模式到测试模式的转换一些框架的层表现得像批量归一化、dropout,而另一些框架在训练和测试期间表现不同。切换到适当的模式有助于网络更好地预测。33.可视化训练监督每一层的激活、权重和更新。确保它们的尺寸匹配。例如,参数更新(权重和偏差)的大小应为1-e3。考虑可视化库,例如Tensorboard和Crayon。在紧要关头,您还可以打印权重/偏差/激活。寻找均值远大于0的层激活。尝试batchnorm或ELU。Deeplearning4j指示权重和偏差直方图中的预期内容:对于权重,一段时间后这些直方图应该具有近似高斯(正态)分布。这些直方图通常从0开始偏差,通常最终近似为高斯分布(LSTM是一个例外)。注意偏离+/-***的参数。注意变大的偏差。如果类的分布不均匀,这有时会发生在分类的输出层。检查图层更新,它们应该具有高斯分布。34.尝试不同的优化器优化器的选择不应该阻碍网络的训练,除非你选择了一个特别糟糕的参数。然而,为任务选择合适的优化器可以大大有助于在最短的时间内获得最多的训练。描述您正在使用的算法的论文应该指定优化器;如果不是,我倾向于选择Adam或带有动量的幼稚SGD。35.GradientExplosion,GradientDisappearance检查隐藏层的安全性,值太大可能代表梯度爆炸。这时候,渐变裁剪(Gradientclipping)可能会有所帮助。检查隐藏层的激活值。Deeplearning4j中有一个很好的指导方针:“一个好的激活标准偏差是在0.5到2.0左右。显着超出此范围可能表示激活消失或爆炸。36.增加和减少学习率低学习率会导致你的模型收敛很慢;高学习率会减少你一开始的损失,但可能会让你很难找到好的解决方案。尝试将您当前的学习率乘以0.1或10。37.克服NaN据我所知,在训练RNN时获得NaN(非数字)是一个大问题。一些解决方法:降低学习率,特别是如果您在前100次迭代中获得NaN。NaN可能是由于除以零或具有零或负数的自然对数造成的。RussellStewart对如何处理NaN有一个很好的说明(http://russellsstewart.com/notes/0.html)。尝试逐层评估您的网络,以便您可以准确地看到NaN出现的位置。原文:https://medium.com/@slavivanov/4020854bd607【本文为《机器之心》专栏原文翻译,微信公众号“机器之心(id:almosthuman2014)”】点这里看看作者的更多好文章
