首页 » 漏洞 » 干货 | 模型表现不好怎么办?37条妙计助你扭转局势

干货 | 模型表现不好怎么办?37条妙计助你扭转局势

 

雷锋网 AI 科技评论按:读论文,看别人的模型的时候仿佛一切都顺利成章,可是等到自己训练模型的时候,麻烦一个接一个…… 雷锋网 (公众号:雷锋网) AI 科技评论找到了一篇国外大神 Slav Ivanov 写的绝招文编译如下,给大家介绍37个好办法!

你的神经网络已经跑了12个小时训练,看上去一切都很完美:梯度运转良好,损失也在降低。但是做预测的时候却一团糟:所有都是0,什么也监测不到。“我哪一步做错了呢?”你迷茫地问你的电脑,而电脑却笑而不语。

如果你的模型输出来的都是辣鸡——例如你想预测所有输出的平均值,或者模型的精度很低——该从哪儿开始检查?

可能出错的地方多了去了。经过很多次的调试,我常常做此类检查。我根据自己的经验以及很多好的想法,写了以下这个指引。希望对你们也有用。

目录

0、如何使用本指引

一、数据库问题

二、数据归一化/增强问题

三、执行问题

四、训练问题

0. 如何使用本指引

很多问题可能会出错。不过有一些问题相对容易解决。通常我先从这个急救列表开始:

1. 先从一个简单的模型入手,找一个对此类数据证明可行的模型,例如针对图像就用VGG。如果可能的话就选一个标准的损失函数。

2. 把花哨的小玩意都卸了,例如归一化和数据增强。

3. 微调模型的时候,仔细检查数据预处理,因为它必须跟原始模型的训练数据一致。

4. 确认输入数据正确。

5. 从一个很小的数据库入手(2-20个样本)。用这个调试好了,再慢慢增加更多数据。

6. 慢慢把省略的每一个部件都加回来:增强、归一化、定制的损失函数、更复杂的模型。

如果以上的步骤不管用,再根据下面这个更长的列表来一项项确认。

一、数据库问题   干货 | 模型表现不好怎么办?37条妙计助你扭转局势

- 老板:你给我的数据对吗?

- 程序猿:这么多年来我给你的数据都是错的。怎么今天想到找茬了。

- 老板:你说啥?

程序猿:我说数据完全准确。

1. 检查输入数据

检查你输入网络的数据是否正确。举个例子,我好几次把图像的长和宽搞混了。有时候,我一不小心全部输入的都是0。有时候,我把同一个批次的数据用了一遍又一遍。所以,打印显示你想要的输入和输出,确保数据正确。

2. 试试随机输入

试试输入随机数据而非真实数据,看看是不是会得到一样的错误。如果是的话,那你的网络肯定是某一个点出错了,可以试试一层层、一个指令一个指令地调试,看看是哪个点出了错。

3. 检查数据导入

可能你的数据是对的,但是用来导入数据到网络的代码可能有问题。在任何动作之前,把第一层的数据打印出来看看。

4. 确保输入和输出相连

检查一下是不是输入样本都有正确的标签。再把输入数据打乱,看看输出标签是不是也会打乱。

5. 输入和输出之间的关系是不是太随机

可能输入和输出之间的非随机部分,与随机部分相比太少了,例如股票就是这样。换句话说,输入和输出之间的关联不够。对于这一点没有万全的办法,因为这得看数据的情况。

6. 数据库中的噪音是否过多

我发生过这样的错误,把一个食物网站的图像弄坏了。错误的标签太多,网络没法进行学习。手动检查一些输入样本,看看标签有没有问题。

业界没有统一的分水线,一篇论文曾在50%标签错误的情况下,实现了高于50%的精度。

7. 打乱数据库

如果数据库没有打乱,而是用标签进行了排序,有可能会影响到网络的学习。打乱数据库的顺序,防止这个问题。确保输入和标签一起打乱。

8. 减少类偏斜问题

A类图像是不是比B类多出了一千倍?那你得平衡你的损失函数,或者尝试其他类偏斜问题的解决方法。

9. 你有足够的训练例子吗?

如果你从零训练一个神经网络,也就是说,没有经过调试,你可能需要很多的数据。对于数据分类问题,很多人说每一类都需要一千个、甚至更多的图像。

10. 确保一个批次的数据里不包含单一标签

在经过排序的数据库中可能出现这个问题,例如,一万个样本包含同一个类别。这个很好解决,只要打乱排序就好了。

11. 减少mini-batch大小

一篇论文指出,一个非常大的mini-batch会减少模型泛化的能力。

增补1:使用标准数据库(例如mnist和cifar10)

感谢 @hengcherkeng 网友的贴士:

测试新的神经网络架构或者写新代码的时候,首先使用标准数据库,而非你自己的数据。这是因为这些数据库有很多参考结果,都是可以解决的。这样就防止了以下的问题:标签噪音、训练/测试分布差别、数据库比较困难等等。

二、数据归一化/增强

12、把特征归一化

你把输入归一化了为平均值为0且方差为1了吗?

13、数据增强是否过度

增强带有归一化的效果。过度增强会带来其他形式的归一化(weight L2、Dropout 等等),可能导致网络调试不足。

14、检查预训练模型的预调试

如果你使用的是预训练模型,训练的时候一定要使用跟模型相同的归一化和预处理。例如,图像像素应该在哪个范围内,[0,1]、[-1,1]还是[0,255]?

15、检查训练/验证/测试数据库

CS231n 指出了一个常见漏洞:

“...任何预处理数据,例如数据平均值,都必须只在训练数据中计算,然后应用到验证/测试数据上。举个例子,计算平均数,然后从数据库的每一个图像中减掉平均值,再将数据库分割为训练/验证/测试数据,这样就错了。”

另外,还需要在每一个样本或者批次中检查不同的预处理。

三、执行问题

干货 | 模型表现不好怎么办?37条妙计助你扭转局势

- 这一大坨就是你的机器学习系统。

- 把数据输入这一大坨线性代数,然后等着答案吐出来。

- 如果答案错了怎么办?

- 那就把这一大坨搅和搅和,直到答案对了为止。  

16. 把大问题变成小问题

这有助于定位问题出在哪儿。举个例子,如果目标输出是一个目标类别或者坐标,可以将预测仅限于目标类别。

17. “随机”寻找正确的损失

还是来自于杰出的 CS231n:以小参数开始,不用归一化。例如,如果我们有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. 尝试梯度检查

如果你手动执行梯度下降,梯度检查能确保反向传播运行正常。

四、训练问题

干货 | 模型表现不好怎么办?37条妙计助你扭转局势

图像中可以识别出来一辆汽车。

27. 用很小很小的数据库

用一个很小的数据库子集用于调试,确保运行正常。例如,只用一两个例子进行训练,看你的神经网络能否学会区分这些例子。然后再在每一个类型增加例子。

28. 检查权重初始化

如果不确定的话,初始化就用 Xavier 或者 He。另外,初始化有可能导致一个错误的区域最小值,所以要尝试几个不同的初始化方法,看看有没有用。

29. 改变超参数

可能你用的超参数组有问题。如果可能的话,试试网格搜索。

30. 减少归一化

过度归一化可能让网络无法调试。减少一些归一化,例如 dropout、批次常规、weight / bias L2 归一化,等等。Jeremy Howard 在其杰出的课程“程序员深度学习实操”中,建议首先排除欠拟合。这意味着你必须充足地优化训练数据,然后再去处理过度优化的问题。

31. 交给时间

可能你的神经网络需要更多时间来训练,才能做出有意义的预测。如果你的损失在稳健降低,那就再让它多训练一段时间。

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

一些带有 Batch Norm、Dropout 等其他层的框架,在训练和测试的时候表现不同。转换到合适的模式有助于神经网络有效地预测。

33. 将训练视觉化

- 监测每一层的初始化、权重和更新。确保它们的强度互相匹配。例如,参数更新的强度应该为1-e3。

- 考虑 Tensorboard 和 Crayon 等视觉化库。简单来说,你还可以打印输出权重、偏压或者初始化。

- 注意层初始化的平均值有没有大大超过0. 可以试试 Batch Norm 或者 ELU。

- 对于权重和偏压的柱状图,网友 Deeplearning4j 这样说道:

“关于权重,柱状图一段时间以后应该大致是一个高斯(正态)分布。关于偏压,柱状图基本上是从0开始,通常最后也会接近高斯分布(长短期记忆网络则是一个例外)。要留心趋近于正/负无穷的参数。要留心变得非常大的偏压。如果类别分布非常不平衡,这有时候就会发生在分类中的输出层。”

- 检查层更新,它们应该是高斯分布。

34. 试试不同的优化器

你选的优化器应该不会妨碍神经网络的训练,除非你选的超参数特别有问题。但是,适合某一任务的优化器有助于在最短的时间内完成最多的训练。看看介绍算法的论文,里面应该说名该使用什么优化器。如果没有说的话,我倾向于使用 Adam 或者就用带有 momentum 的 SGD。

35. 梯度消失与梯度爆炸

- 检查层更新,因为很大的值意味着梯度爆炸。梯度剪裁可能有用。

- 检查层初始化。网友 Deeplearning4j 提供了很好的指引:“对于初始化,好的标准方差是在0.5到2.0的范围内。如果远远超出了这个范围,可能就是消失或者爆炸初始化。”

36. 增加或减少学习率

如果学习率低,模型的收敛会非常地慢。

如果学习率高,开始的损失会很快减少,但是可能很难找到一个满意的答案。

可以拿你现在的学习率做一些小改动试试,乘以0.1或乘以10。

37. 消除NaN

训练循环神经网络时,如果看到NaN就问题大了。解决办法包括:

- 减少学习率,尤其是如果前一百次迭代就出现NaN的话。

- 如果计算中包含除以0、求0或负数的自然对数,就会出现NaN。

- 一层层地检查神经网络,看看NaN是从哪儿出来的。

如果各位读者还有什么好办法,欢迎在留言区分享,大家以开源共享的精神帮更多的人解决更多的问题。

via Slavv Blog ,雷锋网 AI 科技评论编译

雷锋网版权文章,未经授权禁止转载。详情见 转载须知

原文链接:干货 | 模型表现不好怎么办?37条妙计助你扭转局势,转载请注明来源!

0