神经网络调优

Oct 3, 2018


神经网络优化

虽然自己已经做了一年的策略工作了,但是神经网络的东西接触的的确不多,工作中几乎为零,最近趁着十一假期恶补一波,也算是亡羊补牢吧。博文原文来自这里

个人浅见,神经网络从20世界中期出现,到2000年以后的突然火爆,与硬件计算能力的提升密不可分。我们试图通过人工设计的算法,给机器更多的智能,神经网络担起了这一重要的任务。但是,神经网络虽然在图像语音和NLP等领域取得了一些成绩,离真正的智能却相去甚远。诺奖得主Thomas J. Sargent公开表示,现在所谓的人工智能,只不过就是统计学。可是究竟什么是智能,恐怕也没人说得清楚,我们只知道目前我们的人工智能发展还处在原始阶段,只能解决一些最初级的问题。

下面我们谈谈具体的问题,当一个神经网络不工作时,我们如何检查可能出现的问题。造成神经网络不工作的原因非常多,一个简单的神经网络往往也有上百个参数,我们只能得到每个参数的值,却不知道这些值的意义,这与一些传统的机器学习方法完全不同,例如朴素贝叶斯,决策树等。所以,神经网络相对于传统的机器学习算法,也更难进行优化或者排查错误。有一些基础的检查工作是必要的。

  1. 使用简单的模型,验证问题的可行性。我们如果想解决一个问题,必须首先确保问题是成立的。使用公认有效的模型在你的数据集上首先进行测试,保证数据没有问题。

  2. 不要使用相对复杂的数据处理方法,例如正则化和数据扩展。
  3. 在微调一个模型的时候,检查数据输入是否与原模型一直保持一致,方便对比。
  4. 数据输入是否正确。
  5. 逐渐增加之前省略的东西,例如正则化等。

数据问题

一、检查输入数据

检查你的输入数据是否正确。例如,我们有的时候会把一张图片的宽度和高度弄反;有时会错误的输入全0数据;有时会使用同一个batch的数据一直重复训练。所以,把训练数据打出来,人工验证它们是否是合法的。

二、尝试使用随机输入

使用随机生成的数据来训练模型,如果产生的损失与你训练数据上的损失相近,说明你在某个点上将数据转换成了垃圾数据,这时需要一层一层的检查来查看错误的位置。

三、检查你的数据载入

你的训练数据也许没有任何问题,但是在载入模型过程中可能会出现问题,检查模型数据的输入和第一层的输出,如果没有任何问题,在加入其余层。

四、检查输入数据和类别的一致性

检查的你的输入数据是否都有正确的类别标签,在进行数据shuffle的时候,也要保证输入数据和类别标签的一致性。

五、输入数据和标签的相关性检查

也许输入数据和标签类别相关性的部分远小于不相关的部分,听起来比较拗口,简单说就是输入数据包含太多无意义的特征,这时也会使神经网络感觉困惑。我在想,这种情况是不是决策树会好一些,因为其一次只考虑一个特征。

六、数据中是否有太多的噪声?

有的时候,数据中会混入部分错误数据,这个时候就需要通过抽样人工检查的方式,来确定错误数据的比例了。

七、shuffle训练数据

如果你的数据在训练的时候没有进行shuffle,而是按照类别(序号)的顺序,那么会对神经网络的训练产生不利的影响。所以,正式训练前对数据进行shuffle,同时保证训练数据和label一起shuffle。

八、检查的你的数据是否有偏

我对这个问题认识深刻,因为曾做深受其困扰。无论使用什么模型,都要保证训练数据的分布和测试数据是一致的,通常的理解,训练数据是越多越好的,但是如果各个类别之间不均衡的增长使得数据失衡,那么模型效果反而会变差。

九、训练数据是否充足

对于不同的模型,需要的训练数据量往往是不一样的。神经网络相比于其他的模型(决策树,LR,SVM)往往需要更多的训练数据。而且越复杂的神经网络,需要的训练数据就越多。

十、保证一个batch中不仅仅包含一个label

这种情况会发生在排序好的训练数据中,比如前10000个训练数据都包含相同的label。所以,训练前还是要记得shuffle训练数据。

十一、减小batch的规模

使用过大的batch进行训练,会弱化模型的泛化能力。具体可以查看这篇论文

附加:使用标准数据集

当我们设计一个新的网络模型时,应考虑在标准数据集上测试模型的效果(mnist,cifar10),而不是直接在自己的数据上进行测试。在标准数据集上,已经有大量的工作来解决各类问题,使用起来也事半功倍。而且,在标准数据集上不会发生标签噪声,数据分布不均匀等各类问题。

数据标准化/增强

十二、标准化处理数据

对数据进行归一化处理,使其均值为0,方差为1一般是一个不错的选择。

十三、是否有太多的增强数据?

使用数据增强,会有正则化的效果,但是,太多的增强数据结合其他的正则化方法(weight L2, dropout,etc)会导致神经网络欠拟合。

十四、检查之前训练的模型

如果你使用了一个之前训练的模型,确保你使用和之前模型一样的归一化方法。例如,之前你将图片的像素数值范围处理成[0,1],[-1,1]或者[0,255]。

十五、数据的预处理是否正确

所有的数据预处理,必须基于训练数据,然后再应用到测试数据/验证数据,而不是将所有数据一起处理后,再进行训练和测试。例如为了使数据的平均值为0,要计算训练数据的平均值,然后在训练数据,测试数据上进行平移,而不是一起计算所有数据的平均值后进行统一进行平移。

实现问题

十六、先解决简单的问题

任何问题,我们都应该从最简单的问题开始着手。例如:假如我们的预测目标是一个类别和它的坐标,那么我们应该试图先忽略坐标,只预测目标的类别。

十七、逐渐调优

初始化模型时,使用较小的参数,不要加入Regularization,Dropout等。如果你有10个预测类别,那么开始的预测准确率应该为10%,softmax损失大概为-ln(0.1) = 2.302。这时候,再逐渐加入Regulation和Dropout等,观察提升。

十八、检查损失函数

如果你自己设计了你的损失函数,检查它是否正确并且进行单元测试。通常自己设计的损失函数会有一些小问题,这些问题会影响网络的训练。

十九、检查你的损失函数输入

不同的损失函数要求不同的输入形式。有的时候损失函数会要求你的输入时softmax后输出结果,有的时候则要求是softmax前的输出。不同的框架和同一框架下的不同函数都会有差异,所以在使用前要自己阅读文档。

二十、调整损失权重

调整损失权重,一般而言,最终优化的损失会由几个不同的损失相加构成。这个时候要注意调整不同损失在最终损失中所占的比例。一般有1:1开始,但这往往并不是最优的构成。尝试不同的损失构成比例,得到最优结果。

二十一、查看多种不同的指标

有的时候,损失函数并不是最优的指标。除了损失函数,同时关注其他指标,例如准确率等。

二十二、检查自定义层

如果你在网络中自定义了某些层,一定要double-check这些层,确保它们按照你设计的那样工作。

二十三、检查“冷冻”的层或者变量

你是否无意中“冻结”了一些层或者变量,这些层或者变量无法进行学习。如果更新这些层或者变量会有更好的效果。

二十四、增加网络的规模

也许你没有犯任何错误,仅仅是由于网络的复杂度不够而无法拟合数据。试着增加网络的复杂度,引入额外的隐层。

二十五、检查维度对应关系是否正确

如果你的输入数据格式类似(K,H,W)=(64,64,64),那么你很有可能搞错不同的维度,在不同的维度上使用不同的数字是有益的。检查每个维度的数据时如何传播的。

二十六、检查自己实现的优化算法

如果你的优化算法是自己实现的,检查你的梯度反向传播实现是正确的。

训练问题

二十七、小数据集上测试有效性

先在一个小数据集上过拟合,确保模型可以正常工作。例如,对于一个多分类问题,可以先选择两个类别,每个类别选择10个样本,让模型过拟合,如果模型能拟合的很好,再推广到大数据集。

二十八、检查网络参数的权重初始化

如果你对初始化的方式不是很确定,可以使用标准初始化方法。不好的初始化权重,会令网络训练陷入局部最优而无法跳出。尝试不同的初始化方法有时是有效的。

二十九、改变超参数

如果模型的训练效果一直不佳,可能是使用的不合适的超参数。尝试调整超参数,达到最优的训练效果,如果必要可以使用穷举(grid search)。

三十、减少正则化

过度的正则化会导致模型欠拟合。减少正则化处理,例如dropout, batch norm, weight/bias L2 regularization等。在进行训练时,应该首先达到过拟合,再对抗过拟合。

三十一、训练足够长的时间

也许你的模型仅仅只是需要更长的训练时间来达到预期效果。如果损失在保持稳定降低,你需要做的仅仅是让其训练更长的时间。

三十二、从训练模式切换的测试模式

一些神经网络包含batch normal、dropout等在训练和预测时表现不同的网络结构。切换到正确的模式,可以使预测的结果更加准确。

三十三、可视化训练过程

可视化训练过程非常非常的重要,这一点我也深有体会。有的时候只通过log观察损失的变化是远远不够的,要注意观察每一层的参数变化,通过可视化的方式展示数据可以更好的帮你发现问题。参数的更新值应该和你设置的步长基本保持一致。

三十四、尝试不同的优化方法

不同的优化方法,如果超参数设置没有问题,往往都能拟合模型。但是,选择最合适的优化方法可以更好更快的拟合模型。一般论文中都会提到适合的优化算法,如果没有,尽量使用adam或者基本的SGD算法。

三十五、处理梯度爆炸和梯度消失

检查网络层更新,特别大的更新值意味着梯度爆炸。引入梯度截断(Gradient Clipping)是一个不错的选择。检查每一层激活函数输出的标准差,范围在[0.5,2]是不错的值。在这个范围外的值,可能会导致梯度消失或者梯度爆炸。

三十六、增大/减小学习率

过小的学习率会使得模型拟合速度很慢,过大的学习率在开始时会拟合的很快,但是很难找到最优的拟合值。可以尝试动态调整你的学习率,在原有学习率基础上乘以0.1或者10,并且限定上下线。

三十七、克服NaNs

处理这种越界的值是RNN网络中一个重要的问题。有一些处理的方法:

  1. 降低学习率,尤其是在前100轮迭代就得到NaNs值的情况下。
  2. NaNs可能通过除0或者log负数得到,检查是否可能出现这种情况。
  3. 逐层的检查,找到NaNs从哪一层开始出现,发现问题所在。