神经网络故障排查

1.前言

这里结合了我们的经验以及网上提供的一些资源,总结了在定位卷积神经网络系统问题时的一些方法。我们主要聚焦在利用深度神经网络实现的有监督学习。这里的实现默认是Python3.6 Tensorflow(TF)。

假设我们利用一个卷积神经网络来训练模型,然后评估的结果达不到我们的预期,下面的步骤将是定位问题和逐步提升我们模型的方法思想。首先先总结下在开始故障排除之前必须要做的事情,这些故障问题将按照常见程度进行排序,我们优先一起看看最常见的故障问题。

2. 在排查故障之前

下面是你在coding你的深度学习算法时的最佳实践。
1. 选择适合的日志和变量名称:在tensorflow中,你可以根据名字取跟踪不同的变量,并且在Tensorboard中可视化出来。最重要的是,每一步都保证你在跟踪相关参数,比如:step_number, accuracy, loss,learning_rate 等,以及更加专业的衡量指标(比如分词任务里的mean_intersection_over_union aka mean_iou 等)。
2. 保证你的网络是链路正确的:利用Tensorboard和其他 debugging 技术来保证你的计算图里每一个操作都有正确的输入和输出。并且要保证把训练数据和标签输入神经网络之前,要对数据做充分的预处理。
3. 运用数据增强技术:这个不常用,但是如果你是在处理图片的问题时,你将会看到当你运用数据增强技术时,比如:镜像,旋转,随机截取,缩放,添加噪声和弹性变形等,计算结果是会得到很大的提升的。TF直接提供了这些操作的API。
4. 对所有层运用权重初始化和正则化技术:避免将权重初始化为一样的值,更糟糕的是都初始化为0。如果这样做将会引入对称性和潜在梯度消失等问题,有可能会引入更糟糕的问题。一般而言,当你在权重初始化有困难时,就可以在你的网络层中应用Batch Normalization。
5. 确保正则化项不超过损失函数中的其他项:先关掉正则化,确定损失函数的数量级;然后适当地调节正则化权重,保证当你增加正则化强度时,损失函数也增大了。
6. 尝试去过拟合小批数据集:先关闭正则化,弃权和数据增强等,然后选取数据集的一小部分,用神经网络对这小部分数据训练几个回合(epoch)。保证你可以基本上可以实现0损失,如果不行,那么说明某些环节出问题了。在某些案例中,实现0损失是一件很具有挑战性的事情,例如:在语义图像分割中,如果你的损失函数在softmax等对数激活函数和每一像素正确标签之间涉及到交叉熵,那么要想实现0损失是一件很难的事情。相反,你应该尝试着去实现100%正确率。(可以参考 tf.metrics.accuracy)
7. 当实现第6点的过程中,尝试找出适合的学习率:最佳学习率通常是选择不引起训练指标发散的最大学习率。有一种设置学习率的经验方法是,先用一个较大的学习率去训练模型,如果训练指标不收敛,然后尝试用3倍小的学习率再训练,直到收敛为止。
8. 检查梯度:如果在计算图中使用自定义操作,那么梯度检查是特别相关的。

3. 损失值没有提高

如果在训练了几个epoch之后,模型的损失值没有提高或者变得更差,那么:
1. 保证你选用了适合的损失函数
2. 选用一个体面的优化器
3. 确定变量在训练:检查这一点,需要你去研究Tensorboard面板了,或者写一个脚本去计算各个张量范数的变化过程。
4. 调节初始化学习率以及应用适合的学习率计划:这可能是最有效的补救方式了。如果损失值越来越差,很有可能是学习率太大。另一方面,如果损失值一直不怎么变化,那么很有可能是学习率太小了。通常,当你确定一个有效的初始化学习率时,你需要实行学习率衰减计划。有些优化器,比如adam,就是内部有自己的一套机制在控制学习率衰减。然而有时学习率更新通常不够积极,那么在优化器的顶部自定义学习率计划是个不错的主意。
5. 保证没有过拟合:有多种方式会发生过拟合,也有多种方法防止过拟合。可视化出学习率随着训练过程的曲线图。如果曲线看起来像个抛物线,那么就很有可能过拟合了。

4. 变量没有训练

利用Tensorboard面板,或者自己写个脚本去计算各个张量在每个训练回合的值变化。如果某个变量没有得到训练:
1. 先保证这是TF里的一个可训练变量: 可以具体参照TF GraphKeys。
2. 确保没有梯度消失:如果下游的变量(靠近输出层的变量)在训练,但上游的变量(靠近输入层的变量)几乎没有什么变化,那么应该是发生反向传播梯度消失了。
3. 确保ReLUs有效:如果大量的神经元没有起到什么作用,那么就需要重视下权重初始化了,运用一个更柔和的学习率衰减计划,并且尝试降低权重衰减正则化。

5.梯度消失和梯度爆炸

  1. 考虑运用更好的权重初始化:在训练开始的时候,如果梯度更新太缓慢,那么这一点就很相关了。
  2. 考虑改变激活函数: 如果你是用的ReLUs激活函数,那么可以考虑用Leaky ReLUs或者MaxOut激活函数替换。一定要禁止sigmoid激活函数,并且一般也要远离tanh。
  3. 如果是RNN,那么就考虑用LSTM单元格

6.过拟合

过拟合是比较常见的,这个可以在训练集和验证集的正确率曲线的差距中呈现出来。
1. 运用数据增强技术
2. 运用弃权(dropout):弃权的原理和随机森林类似。
3. 增加正则化
4. 实行Batch Normalization
5. 边训练边验证。有些过拟合可能是在模型训练了多个epoch之后才发生的。这个时候需要实现每个epoch训练完及时验证的策略,中途发现过拟合了,就可以关闭模型了。
6. 如果还是失败了,可以运用一个更小的网络

7.还可以尝试的策略

  1. 考虑应用一个带有权重的损失函数:例如在语义图像分割中,要求网络可以分类输入图片的每一个像素,有些类别相比于其他类别很少发生,这种情况下,给这些稀有类别分配权重将会提高mean_iou指标。
  2. 改变网络:有可能是你的网络太深或者太浅了。
  3. 考虑应用模型融合
  4. 用带有步长的卷积单元去替代最大/平均池化层
  5. 全面地研究超参的变化情况
  6. 改变随机种子
  7. 如果还是不行,想办法获取到更多的训练数据

你可能感兴趣的:(数据挖掘和机器学习)