初始化
一次惨痛的教训是用normal初始化cnn的参数,最后acc只能到70%多,仅仅改成xavier,acc可以到98%。还有一次给word embedding初始化,最开始使用了TensorFlow中默认的initializer(即glorot_uniform_initializer,也就是大家经常说的无脑使用xavier),训练速度慢不说,结果也不好。改为uniform,训练速度飙升,结果也飙升。所以,初始化就跟黑科技一样,用对了超参都不用调;没用对,跑出来的结果就跟模型有bug一样不忍直视。
记得刚开始研究深度学习时,做过两个小例子。一个是用tensorflow构建了一个十分简单的只有一个输入层和一个softmax输出层的Mnist手写识别网络,第一次我对权重矩阵W和偏置b采用的是正态分布初始化,一共迭代了20个epoch,当迭代完第一个epoch时,预测的准确度只有10%左右(和随机猜一样,Mnist是一个十分类问题),当迭代完二十个epoch,精度也仅仅达到了60%的样子。然后我仅仅是将权重矩阵W初始化方法改成了全为0的初始化,其他的参数均保持不变,结果在训练完第一个epoch后预测精度就达到了85%以上,最终20个epoch后精度达到92%。另一个例子是回归问题的预测,当时采用的SGD优化器,一开始学习率设定的0.1,模型可以正常训练,只是训练速度有些慢,我试着将学习率调整到0.3,希望可以加速训练速度,结果没迭代几轮loss就变成Nan了。于是从那时起我就深刻的感受到参数调节在深度学习模型训练中的重要意义。
其实上述问题产生的原因也很好理解,对于参数初始化,因为我们学习的本来就是权重W与偏置b,如果初始化足够好,直接就初始化到最优解,那都不用进行训练了。良好的初始化,可以让参数更接近最优解,这可以大大提高收敛速度,也可以防止落入局部极小。
tensorflow常用的初始化方法
激活函数选择:
常用的激活函数有relu、leaky-relu、sigmoid、tanh等。对于输出层,多分类任务选用softmax输出,二分类任务选用sigmoid输出,回归任务选用线性输出。而对于中间隐层,则优先选择relu激活函数(relu激活函数可以有效的解决sigmoid和tanh出现的梯度弥散问题,多次实验表明它会比其他激活函数以更快的速度收敛)。另外,构建序列神经网络(RNN)时要优先选用tanh激活函数。
学习率设定:
一般学习率从0.1或0.01开始尝试。学习率设置太大会导致训练十分不稳定,甚至出现Nan,设置太小会导致损失下降太慢。学习率一般要随着训练进行衰减。衰减系数设0.1,0.3,0.5均可,衰减时机,可以是验证集准确率不再上升时,或固定训练多少个周期以后自动进行衰减。
防止过拟合:
一般常用的防止过拟合方法有使用L1正则项、L2正则项、dropout、提前终止、数据集扩充等。如果模型在训练集上表现比较好但在测试集上表现欠佳可以选择增大L1或L2正则的惩罚力度(L2正则经验上首选1.0,超过10很少见),或增大dropout的随机失活概率(经验首选0.5);或者当随着训练的持续在测试集上不增反降时,使用提前终止训练的方法。当然最有效的还是增大训练集的规模,实在难以获得新数据也可以使用数据集增强的方法,比如CV任务可以对数据集进行裁剪、翻转、平移等方法进行数据集增强,这种方法往往都会提高最后模型的测试精度。
优化器选择:
如果数据是稀疏的,就用自适应方法,即 Adagrad, Adadelta, RMSprop, Adam。整体来讲,Adam 是最好的选择。SGD 虽然能达到极小值,但是比其它算法用的时间长,而且可能会被困在鞍点。如果需要更快的收敛,或者是训练更深更复杂的神经网络,需要用一种自适应的算法。
残差块与BN层
如果你希望训练一个更深更复杂的网络,那么残差块绝对是一个重要的组件,它可以让你的网络训练的更深。
BN层具有加速训练速度,有效防止梯度消失与梯度爆炸,具有防止过拟合的效果,所以构建网络时最好要加上这个组件。
自动调参方法:
- Grid Search:网格搜索,在所有候选的参数选择中,通过循环遍历,尝试每一种可能性,表现最好的参数就是最终的结果。其原理就像是在数组里找最大值。缺点是太费时间了,特别像神经网络,一般尝试不了太多的参数组合。
- Random Search:经验上,Random Search比Gird Search更有效。实际操作的时候,一般也是先用Gird Search的方法,得到所有候选参数,然后每次从中随机选择进行训练。另外Random Search往往会和由粗到细的调参策略结合使用,即在效果比较好的参数附近进行更加精细的搜索。
- Bayesian Optimization:贝叶斯优化,考虑到了不同参数对应的 实验结果值,因此更节省时间,贝叶斯调参比Grid Search迭代次数少, 速度快;而且其针对非凸问题依然稳健。
深度学习debug的流程策略
既然消除模型中的错误很难,我们不如先从简单模型入手,然后逐渐增加模型的复杂度。
- 从最简单模型入手;
- 成功搭建模型,重现结果;
- 分解偏差各项,逐步拟合数据;
- 用由粗到细随机搜索优化超参数;
- 如果欠拟合,就增大模型;如果过拟合,就添加数据或调整。