重磅干货,第一时间送达 大家都遇到过这种情况,训练的时候没什么问题,测试的时候就不对劲了,想找问题,感觉无处入手,那么今天,给你37个建议,看看再说吧。 这个网络在过去12个小时中一直在进行训练。一切看起来都很好:梯度在流动,损失在降低。但是接下来的预测结果是:所有都是0,所有都是背景,没有检测到任何东西。“我做错了什么?”—我问我的电脑,电脑没睬我。 你从哪里开始检查你的模型是否正在输出垃圾(例如预测所有输出的平均值,或者它的准确性非常差)? 由于一些原因,网络可能不会进行训练。在许多调试的过程中,我经常发现自己在执行相同的检查。我把我的经验和最好的想法整理在这个方便的列表里。我希望它们对你也有用。 0. 如何使用这个指南?很多事情都可能出错。但其中一些更有可能出现问题。我通常以这张简短的清单作为紧急第一反应:
如果上面的步骤没有什么用,那么就从下面的列表开始,逐一验证。 I. 数据集的问题1. 检查你的输入数据检查你正在向网络提供的输入数据是否有意义。例如,我不止一次地搞混了图像的宽度和高度。有时,我会不小心把输入全部搞成了0。或者我会反复的使用相同batch。因此,打印/显示两个batch的输入和目标输出,并确保它们是正确的。 2. 尝试随机的输入尝试传递随机数而不是实际数据,看看错误的现象是否相同。如果是的话,这是一个确定的信号,表明你的网络在某个时候正在把数据变成垃圾。试着一层一层地调试看看哪里出错了。 3. 检查你的数据加载你的数据可能没有问题,但是将输入传递到网络的代码可能会有问题。在任何操作之前打印第一层的输入并检查它。 4. 确保输入连接到了输出检查一些输入样本的标签是否正确。还要确保对输入样本的变换对输出标签的作用是相同的。 5. 输入和输出之间的关系是不是太随机了?也许输入和输出之间关系的非随机部分与随机部分相比太小了(有人可能会说股票价格是这样的)。也就是说,输入与输出的关系并不充分。由于这取决于数据的性质,因此没有一种通用的方法来检测这一点。 6. 数据集中是否有太多的噪声?有一次,当我从一个食品网站上抓取图像数据集时,这种情况发生在我身上。有太多不好的标签,网络无法学习。手动检查一些输入样本,看看标签是不是正确。 噪声的截止点有待讨论,因为本文在使用50%损坏标签的MNIST上获得了超过50%的准确性。 7. 打乱数据集如果你的数据集没有被打乱,并且有一个特定的顺序(按标签排序),这可能会对学习产生负面的影响。打乱你的数据集,以避免这种情况。确保你在进行打乱的时候,是把输入和标签一起打乱的。 8. 减少类别的不均衡每一个类别B的图像就有1000个类别A的图像?你可能需要平衡损失函数或尝试其他类别不平衡的方法。 9. 你有足够的训练样本吗?如果你正在从头开始训练一个网络,你可能需要大量的数据。对于图像分类,人们说每个类需要1000个或更多的图像。 10. 确保你的batch里不只包含同一个标签这可能发生在排过序的数据集中(即前10k个样本包含相同的类)。通过打乱数据集很容易修复。 11. 减少batch size这篇文章指出大的batch size会降低模型的泛化能力。 附加1. 使用标准的数据集(如mnist, cifar10 )
II. 数据归一化/增强12. 特征标准化你是否标准化了你的输入使其均值和单位方差为零? 13. 你是不是用了太多的数据增强?增强具有规律性的效果。太多的这些与其他形式的正则化(权值的L2,dropout等等)结合在一起会导致网络欠拟合。 14. 检查你的预训练模型的预处理如果你使用的是预训练模型,请确保你使用的归一化和预处理与训练时的模型相同。例如,图像像素应该在[0,1]、[- 1,1]还是[0,255]范围内? 15. 检查训练/验证/测试集的预处理CS231n指出了一个常见的陷阱:
同时,检查每个样本或batch的预处理的不同之处。 III. 实现中的问题16.尝试解决这个问题的更简单的版本的问题这将有助于找到问题所在。例如,如果目标输出是物体的类别和坐标,请尝试只预测物体的类别。 17.看看“随机”时候的正确的损失再次来自优秀的CS231n:使用小参数进行初始化,没有正则化。例如,如果我们有10个类,在随机的情况下意味着我们将有10%的时候会得到正确的类,Softmax损失是正确类的概率的负对数,因此:-ln(0.1) = 2.302. 在此之后,试着增加正则化强度,这会增加损失。 18. 检查你的损失函数如果你实现了自己的loss函数,那么检查它的bug并添加单元测试。通常,我自己写的损失可能是不正确的,并以一种微妙的方式损害了网络的性能。 19. 验证损失的输入如果你使用的是框架提供的loss函数,请确保你传递给它的是它所期望的。例如,在PyTorch中,我会混淆NLLLoss和CrossEntropyLoss,因为前者需要softmax输入,而后者不需要。 20. 调整损失的权重如果你的损失由几个较小的损失函数组成,请确保它们相对于每个损失函数的大小是正确的。这可能涉及测试不同的损失权重组合。 21. 使用其他的度量方法进行监控有时候,损失并不能很好地预测你的网络是否训练的好。如果可以,使用其他指标,如准确性。 22. 测试所有的自定义的层你自己实现了网络中的一些层吗?反复检查以确保它们按照预期工作。 23. 检查“冻结”的层和变量检查你是否无意中禁用了一些层/变量的梯度的更新。 24. 增加网络的大小也许你的网络的表达能力不足以得到目标函数。尝试在全连接的层中添加更多的层或更多的隐藏单元。 25. 检查隐藏维度的错误如果你的输入看起来像(k, H, W) =(64, 64, 64)那么很容易忽略与错误维度相关的错误。对输入维度使用奇怪的数字(例如,每个维度使用不同的素数),并检查它们如何在网络中传播。 26. 梯度检查如果你手动实现梯度下降,检查梯度,确保你的反向传播工作正常。 IV. 训练问题27. 处理小数据集过拟合数据的一个子集,并确保它能工作。例如,用一两个样本来训练,看看你的网络是否能学会区分它们。再继续使用每个类的更多样本。 28. 检查权值初始化如果不确定的话,使用Xavier或He初始化。另外,初始化可能会导致错误的局部最小值,所以尝试不同的初始化,看看是否有帮助。 29. 改变你的超参数也许你使用了一组特别糟糕的超参数。如果可行,尝试网格搜索。 30. 减少正则化过多的正则化会导致网络严重欠拟合。减少正规化,如dropout、、权重/偏置L2正规化等。在优秀的“Practical Deep Learning for coders”课程中,Jeremy Howard建议首先摆脱欠拟合。这意味着你需要对训练数据进行充分的过拟合,然后再解决过拟合问题。 31. 多给点时间也许你的网络需要更多的时间来训练,才能开始做出有意义的预测。如果你的损失在稳步减少,那就让它继续训练吧。 32. 从训练模式切换到测试模式有些框架具有Batch Norm、drop等层,在训练和测试期间的行为有所不同。切换到适当的模式可能有助于你的网络进行正确的预测。 33. 训练可视化
34. 尝试不同的优化器你选择的优化器不应该会导致你的网络不训练,除非你选择了特别糟糕的超参数。然而,对于一个任务,适当的优化器可以帮助在最短的时间内获得最多的训练。你正在使用的算法的论文中应该会指定优化器。如果不是,我倾向于使用Adam或使用动量的SGD。 查看Sebastian Ruder的excellent post了解更多关于梯度下降优化器的信息。 35. 梯度爆炸/消失
36. 增大/降低学习率较低的学习率会导致模型非常缓慢地收敛。 高学习率将在开始时迅速减少损失,但可能很难找到一个好的解决方案。 把你当前的学习速度乘以0.1或10。 37. 克服NaNs在训练RNN时,获得NaN (Non-a-Number)是一个更大的问题。一些解决方法:
|
|