1、训练过程出现NAN的原因

  • 除0问题。这里实际上有两种可能,一种是被除数的值是无穷大,即Nan,另一种就是除数的值是0。之前产生的Nan或者0,有可能会被传递下去,造成后面都是Nan。请先检查一下神经网络中有可能会有除法的地方,例如softmax层,再认真的检查一下数据。我有一次帮别人调试代码,甚至还遇到过,训练数据文件中,有些值就是Nan。。。这样读进来以后,开始训练,只要遇到Nan的数据,后面也就Nan了。可以尝试加一些日志,把神经网络的中间结果输出出来,看看哪一步开始出现Nan。
    (训练日志生成参考:
    ./darknet detector train cfg/voc.data cfg/yolov3.cfg darknet53.conv.74 2>1 | tee visualization/train_yolov3.log
  • 梯度过大,造成更新后的值为Nan。特别是RNN,在序列比较长的时候,很容易出现梯度爆炸的问题。一般有以下几个解决办法。
    对梯度做clip(梯度裁剪),限制最大梯度,其实是value = sqrt(w12+w22….),如果value超过了阈值,就算一个衰减系系数,让value的值等于阈值: 5,10,15。
    减少学习率。初始学习率过大,也有可能造成这个问题。需要注意的是,即使使用adam之类的自适应学习率算法进行训练,也有可能遇到学习率过大问题,而这类算法,一般也有一个学习率的超参,可以把这个参数改的小一些。
  • 初始参数值过大,也有可能出现Nan问题。输入和输出的值,最好也做一下归一化。

2、loss/cost降不下来

网络一直在正常的训练,但是loss/cost降不下来,预测的时候,结果不正常。(cost和loss的变化趋势是一样的)
解决方法:

  • 请打印出训练集的cost值和测试集上cost值的变化趋势,正常情况应该是训练集的cost值不断下降,最后趋于平缓,或者小范围震荡,测试集的cost值先下降,然后开始震荡或者慢慢上升。如果训练集cost值不下降,有可能是代码有bug,有可能是数据有问题(本身有问题,数据处理有问题等等),有可能是超参(网络大小,层数,学习率等)设置的不合理。
    请人工构造10条数据,用神经网络反复训练,看看cost是否下降,如果还不下降,那么可能网络的代码有bug,需要认真检查了。如果cost值下降,在这10条数据上做预测,看看结果是不是符合预期。那么很大可能网络本身是正常的。那么可以试着检查一下超参和数据是不是有问题。
  • 如果神经网络代码,全部是自己实现的,那么强烈建议做梯度检查。确保梯度计算没有错误。
  • 先从最简单的网络开始实验,不要仅仅看cost值,还要看一看神经网络的预测输出是什么样子,确保能跑出预期结果。例如做语言模型实验的时候,先用一层RNN,如果一层RNN正常,再尝试LSTM,再进一步尝试多层LSTM。
  • 如果可能的话,可以输入一条指定数据,然后自己计算出每一步正确的输出结果,再检查一下神经网络每一步的结果,是不是一样的。

3、调参技巧

  • 画图
    画图是一个很好的习惯,一般是训练数据遍历一轮以后,就输出一下训练集和验证集准确率。同时画到一张图上。这样训练一段时间以后,如果模型一直没有收敛,那么就可以停止训练,尝试其他参数了,以节省时间。
    如果训练到最后,训练集,测试集准确率都很低,那么说明模型有可能欠拟合。那么后续调节参数方向,就是增强模型的拟合能力。例如增加网络层数,增加节点数,减少dropout值,减少L2正则值等等。
    如果训练集准确率较高,测试集准确率比较低,那么模型有可能过拟合,这个时候就需要向提高模型泛化能力的方向,调节参数。
  • 从粗到细分阶段调参
    实践中,一般先进行初步范围搜索,然后根据好结果出现的地方,再缩小范围进行更精细的搜索。
    建议先参考相关论文,以论文中给出的参数作为初始参数。至少论文中的参数,是个不差的结果。
    如果找不到参考,那么只能自己尝试了。可以先从比较重要,对实验结果影响比较大的参数开始,同时固定其他参数,得到一个差不多的结果以后,在这个结果的基础上,再调其他参数。例如学习率一般就比正则值,dropout值重要的话,学习率设置的不合适,不仅结果可能变差,模型甚至会无法收敛。
    如果实在找不到一组参数,可以让模型收敛。那么就需要检查,是不是其他地方出了问题,例如模型实现,数据等等。
  • 提高速度
    调参只是为了寻找合适的参数,而不是产出最终模型。一般在小数据集上合适的参数,在大数据集上效果也不会太差。因此可以尝试对数据进行精简,以提高速度,在有限的时间内可以尝试更多参数。
    (1)对训练数据进行采样。例如原来100W条数据,先采样成1W,进行实验看看。
    (2)减少训练类别。例如手写数字识别任务,原来是10个类别,那么我们可以先在2个类别上训练,看看结果如何。
  • 超参数范围
    建议优先在对数尺度上进行超参数搜索。比较典型的是学习率和正则化项,我们可以从诸如0.001 0.01 0.1 1 10,以10为阶数进行尝试。因为他们对训练的影响是相乘的效果。不过有些参数,还是建议在原始尺度上进行搜索,例如dropout值: 0.3 0.5 0.7)。
  • 经验参数
    这里给出一些参数的经验值,避免大家调参的时候,毫无头绪。
    (1)learning rate: 1 0.1 0.01 0.001, 一般从1开始尝试。很少见learning rate大于10的。学习率一般要随着训练进行衰减。衰减系数一般是0.5。 衰减时机,可以是验证集准确率不再上升时,或固定训练多少个周期以后。
    不过更建议使用自适应梯度的办法,例如adam,adadelta,rmsprop等,这些一般使用相关论文提供的默认值即可,可以避免再费劲调节学习率。对RNN来说,有个经验,如果RNN要处理的序列比较长,或者RNN层数比较多,那么learning rate一般小一些比较好,否则有可能出现结果不收敛,甚至Nan等问题。
    (2)网络层数: 先从1层开始。
    (3)每层结点数: 16 32 128,超过1000的情况比较少见。超过1W的从来没有见过。
    (4)batch size: 128上下开始。batch size值增加,的确能提高训练速度。但是有可能收敛结果变差。如果显存大小允许,可以考虑从一个比较大的值开始尝试。因为batch size太大,一般不会对结果有太大的影响,而batch size太小的话,结果有可能很差。
    (5)clip c(梯度裁剪): 限制最大梯度,其实是value = sqrt(w12+w22….),如果value超过了阈值,就算一个衰减系系数,让value的值等于阈值: 5,10,15
    (6)dropout: 0.5
    (7)L2正则:1.0,超过10的很少见。
    (8)词向量embedding大小:128,256
    (9)正负样本比例: 这个是非常忽视,但是在很多分类问题上,又非常重要的参数。很多人往往习惯使用训练数据中默认的正负类别比例,当训练数据非常不平衡的时候,模型很有可能会偏向数目较大的类别,从而影响最终训练结果。除了尝试训练数据默认的正负类别比例之外,建议对数目较小的样本做过采样,例如进行复制。提高他们的比例,看看效果如何,这个对多分类问题同样适用。
    在使用mini-batch方法进行训练的时候,尽量让一个batch内,各类别的比例平衡,这个在图像识别等多分类任务上非常重要。
  • 自动调参
    人工一直盯着实验,毕竟太累。自动调参当前也有不少研究。下面介绍几种比较实用的办法:
    (1)Gird Search. 这个是最常见的。具体说,就是每种参数确定好几个要尝试的值,然后像一个网格一样,把所有参数值的组合遍历一下。优点是实现简单暴力,如果能全部遍历的话,结果比较可靠。缺点是太费时间了,特别像神经网络,一般尝试不了太多的参数组合。
    (2)Random Search。Bengio在Random Search for Hyper-Parameter Optimization中指出,Random Search比Gird Search更有效。实际操作的时候,一般也是先用Gird Search的方法,得到所有候选参数,然后每次从中随机选择进行训练。
    (3)Bayesian Optimization. 贝叶斯优化,考虑到了不同参数对应的实验结果值,因此更节省时间。和网络搜索相比简直就是老牛和跑车的区别。具体原理可以参考这个论文:Practical Bayesian Optimization of Machine Learning Algorithms,这里同时推荐两个实现了贝叶斯调参的Python库,可以上手即用:
    jaberg/hyperopt, 比较简单。
    fmfn/BayesianOptimization, 比较复杂,支持并行调参。

总结
–合理性检查,确定模型,数据和其他地方没有问题。
–训练时跟踪损失函数值,训练集和验证集准确率。
–使用Random Search来搜索最优超参数,分阶段从粗(较大超参数范围训练较少周期)到细(较小超参数范围训练较长周期)进行搜索。

参考资料

这里列了一些参数资料,大家有时间,可以进一步阅读。
Practical recommendations for gradient-based training of deep architectures by Yoshua Bengio (2012)Efficient BackProp, by Yann LeCun, Léon Bottou, Genevieve Orr and Klaus-Robert MüllerNeural Networks: Tricks of the Trade, edited by Grégoire Montavon, Geneviève Orr, and Klaus-Robert Müller.