你的神经网络不工作的37个原因

37 Reasons why your Neural Network is not working

原文链接:https://blog.slavv.com/37-reasons-why-your-neural-network-is-not-working-4020854bd607

网络已经训练了12个小时了。看起来一切都好:梯度稳定,损失在降低。但是当检测的时候就是检测不出来东西。到底哪里出了问题呢?

下面是一些很好的检查策略。

0. 如何使用这份指南

很多地方可以出错,但是一些优先级高的问题需要先处理。

  1. 首先使用一个对这个类型的数据有用的简单模型(例如,对于图像可以用VGG)。如果可以,使用标准loss。
  2. 关掉全部附加操作。如:regularization和数据增强
  3. 如果是finetuning一个模型,再次检查一下预处理(preprocessing),它应该和原始模型训练一样。?
  4. 检验输入数据是正确的。
  5. 从非常小的数据集开始(2-20个样本)。在这个数据集上过拟合然后逐渐添加更多的数据。
  6. 开始逐渐把之前关掉的小功能添加回来:augmentation/regularization, custom loss functions,尝试更复杂的模型。

如果完成了上述步骤还是不行的话,开始从下面的列表一个一个的验证。

I. 数据问题

1. 检查你的输入数据

检查你喂给网络的输入数据是否正确。举个例子,我不止一次的将图像的宽与高搞混。有时候,我错误地将全部都是零的数据喂给模型。或者一遍又一遍地使用同一个batch。所以打印一组batches的输入和目标输出,看看它们是否正确。

2. 尝试随机输入

尝试将随机数字作为输入而不是实际的数据,看看是否表现的一样。如果是,很确定是你的网络再某一些点上将数据变成了垃圾。试着一层一层的debugging,看看哪里出了问题。

3. 检查data loader

你的数据可能没事但将它们传入网络的代码可能错了。在做任何操作之前打印网络第一层的输入,检查一下。

4. 确保输入是连接着输出标签的

检查一些输入样本是否有正确的标签。确保打乱输入样本时输出标签也跟着变化。

5. 输入和输出的关联性太随机了吗?

输入和输出的关联性并不大。

6. 数据集中的脏数据太多?

检查一些输入样本是否有正确的标签。

7. 打乱数据集

如果你的数据集从未被打乱过,而且有特定的顺序(标签顺序),这对学习是个负面影响。打乱数据集避免这个情况。确保同时打乱输入和输出标签。

8. 减少类别失衡

如果有类别失衡的情况,你可能需要平衡你的损失函数。

9. 是否有足够多的训练数据

如果你从头训练一个网络(not finetuning),你可能需要大量的数据。对于图像分类,对每个类别你可能需要1000个图像或者更多。

10. 确认你的batches不会包含单一的标签

可能出现在有序的数据集的情况。打乱数据集避免这个情况。

11. 减小batch大小

非常大的batch会减少模型的generalization能力。

Addition 1. 首先使用标准的数据集

在测试新的网络结构或写新代码时,首先使用标准的数据集而不是你自己的数据集。这是因为这些数据集有相关的问题已经被解决了。而且不会有标签错误,训练测试分布不同等等数据集相关的问题。

II. 数据 Normalization/Augmentation

12. Standardize the features

你的输入是否平均值为0,方差为1。

13. 数据增强做太多了?

过多的数据增强再加上regularization(weight L2,dropout,等)可以导致网络欠拟合。

14. 检查预训练模型的preprocessing

如果你使用预训练的模型。确保在训练的时候使用同样normalization和preprocessing。例如,图像的像素值应该在范围[0, 1], [-1, 1]或[0, 255]。

15. 检查训练/验证/测试集的预处理

在CS231n中指出。所有的预处理统计必须只在训练集上进行计算,然后应用于验证/测试集。例如,在整个数据集上计算平均值并减去它,然后再分成训练/验证/测试集会出现错误。

在每一个样本和batch上检查不同的预处理。

III. 实现错误

16. 尝试解决一个简单版本的问题

这会帮助找到bug在哪。例如,当目标输出是一个目标类别和坐标,试着先只预测类别。

17. 查看正确的损失

来自CS231n:

确保在初始化小参数时得到预期的损失。最好先单独检查data loss (因此将正则化强度设置为零)。例如,对于使用Softmax分类器的CIFAR-10,我们期望初始损失为2.302,因为我们期望每个类的扩散概率为0.1(因为有10个类),而Softmax损失是正确类的负对数概率,因此:-ln(0.1) = 2.302。对于Weston Watkins SVM,我们期望所有期望的边距都被破坏(因为所有的分数都近似为零),因此期望损失9(因为每个错误的类的边距为1)。如果您没有看到这些损失,那么初始化可能会有问题。

在这之后,尝试提高正则化强度应该可以提高损失。

18. 检查你的损失函数

如果你实现的你自己的损失函数,使用单元测试,检查一下有没有bug。有时候,损失函数轻微的错误可以轻微的影响网络的性能。

19. 检验损失输入

如果你使用框架提供的loss函数,请确保传递给它的是它所期望的。例如,在PyTorch中,我将混合NLLLoss和CrossEntropyLoss,因为前者需要一个softmax输入,而后者不需要。

20. 调整损失权重

如果损失由几个较小的损失函数组成,请确保它们相对于每个损失函数的大小是正确的。这可能需要测试不同的权重组合。

21. 监控其他度量

对于你的网络是否训练的正确,有时候损失不是最好的监控器。如果可以,也可以使用其他度量如正确率。

22. 测试每一个自定义层

你在网络中有你自己自定义的层吗?多次确认确保它们工作正常。

23. 检查是否有frozen层或变量

检查一下是否有无意中禁用了一些应该可学习的层/变量的梯度更新。

24. 增加网络大小

也许您的网络的表达能力不足以到达目标函数。尝试在全连接层中添加更多层或更多隐藏单元。

25. 检查隐藏层维度错误

如果你的输入像这样 (k, H, W) = (64, 64, 64),这会很容易错过错误的关联维度。先使用不同的数字作为输入维度的值,然后检查是否正确。

26. 探索梯度检查

如果你手动实现的梯度下降,梯度检查确保向后传播是正确的。

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

IV. 训练错误

27. 从一个很小的数据集开始解决问题

过拟合一个很小的数据集的子集,然后确保训练正常。例如,一个类别只训练一个或两个样本,然后看网络是否可以学到它们的不同。然后每个类别加入更多的样本。

28. 检查权重初始化

如果不确定,就使用 XavierHe 初始化。另外,你的初始化可能会领向一个坏的局部最低值,所以试一下不同的初始化看看是否有帮助。

29. 检查你的超参数

可能你使用的特别坏的超参数设置。如果可以,试一试grid search

30. 减少regularization

太多的regularization可以造成网络严重的欠拟合。减少regularization像dropout,batch norm,weight/bias L2 regularization等等。在这个教程中,建议要首先避免欠拟合。这意味着你先要充分的过拟合,然后再解决过拟合。

31. 给模型多点时间

在你的网络开始做有意义的预测之前,可能它需要更多的时间去训练。如果你的loss稳定下降,就让它继续训练。

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

有一些架构有一些层像Batch Norm,Dropout和其他的在训练和测试表现不同的层。转换为合适的模型对模型正确预测可能会帮助。

33. 训练可视化

  • 监视每一层的激活、权重和更新。确保它们的量级匹配。例如,参数更新的量级(权重和偏差)应该是1-e3。

  • 考虑一个可视化库,比如Tensorboard和Crayon。在紧要关头,你还可以打印权重/偏差/激活。

  • 注意那些平均值远远大于0的层激活。尝试Batch Norm或ELUs。

  • Deeplearning4j指出了在权重和偏见的直方图中应该期望什么:

    “对于权重,这些直方图应该在一段时间后具有近似高斯(正态)分布。对于偏差,这些直方图通常从0开始,并且通常以近似高斯分布结束(LSTM是一个例外)。注意那些发散到+/-∞的参数。注意那些非常大的偏见。如果类的分布非常不平衡,这有时会发生在用于分类的输出层。”

  • 检查层更新,它们应该有一个高斯分布。

34. 尝试不同的优化器

你选择的优化器不应该阻止你的网络进行训练,除非你选择了特别糟糕的超参数。然而,对任务使用适当优化器有助于在最短的时间内获得最多的训练。你正在使用的论文描述算法的时候应该有指定了优化器。如果没有,我倾向于使用Adam或带动量的普通SGD。

更多关于梯度下降优化器的内容看这篇优秀的博文

35. 梯度爆炸/消失

  • 检查层更新,因为非常大的值可以表明爆炸梯度。梯度裁剪可能会有所帮助。
  • 检查层激活。Deeplearning4j提供了一个很好的指导:“激活的良好标准偏差在0.5到2.0之间。明显超出这一范围可能意味着激活消失或爆炸。”

36. 学习率增加/减少

一个很低的学习率会导致你的模型收敛非常慢。

一个很高的学习率可以再开始的时候很快降低损失,但是可能很难找到最好的权重。

通过将当前的学习率乘以0.1或10来测试最佳的学习率。

37. 解决NaNs

据我所知,在训练RNNs时,获得一个NaN(Non-a-Number)是一个很大的问题。一些解决方法:

  • 降低学习速度,特别是如果你在前100次迭代中得到了NaNs。
  • 除以零或零的自然对数或负数可以导致NaNs。
  • Russell Stewart对如何解决NaNs有很好的建议。
  • 试着一层一层地评估你的网络,看看NaNs出现在哪里。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值