调参

大力出奇迹。

调参的关键是“快速尝试,快速验证、快速纠错”。

你在训练模型的时候,它也在训练你。

调参没有捷径可走,唯一的区别是有些人盲目尝试,有些人思考后再尝试。

常见调参方法:

  • 训练数据预处理

  • 选择合适的激活函数

  • 确定网络隐层层数和个数

  • 权值初始化

  • 确定学习率

  • 选择优化算法

  • 正则优化

可视化

可视化侧重于理解网络:以人类可理解的方式观察网络,帮助理解网络的原理。

可以可视化网络的中间特征图、激活情况、权值、t-SNE、DeconvNet等。

也可以可视化训练过程,如Loss随迭代次数的情况、Softmax的分布等等。

待我有空时好好研究一番。

验证集

尽量在验证集上调参。

通过验证集Loss和正确率可以判断是否过拟合、是否需要停止训练、是否需要调整学习率等。

  • 若模型在训练集和验证集上都满足目标,模型表现的非常好,这时就不用调参了。

  • 若模型在训练集上的Loss降到一个很小的值,但是验证集的Loss相对较大,这时可能过拟合了。

  • 若模型在训练集和验证集上的Loss都比较大,这时可能欠拟合了。

设计模型之初

在设计模型之初,要大力出奇迹!小规模的数据,模型尽量深,卷积核尽量多,强行让模型拟合训练集,得到一个过拟合的网络。

这时候遇到的问题是如何解决过拟合。通常给模型加正则化、增加训练数据、降低网络的复杂度。

  • 可以验证程序是否正确,这样速度快。

  • 如果小数据大网络都没有过拟合,那说明网络的设计有问题,检查数据输入、网络结构、目标函数、度量方式、训练方式等等。

学习率的设置

优先调学习率。

学习率会在很大程度上影响模型的表现。同样的模型采用不同的学习率可能会表现迥异。

学习率太大,会发生Loss爆炸,容易出现nan。

学习率太小,学习较慢,Loss变化慢。

初始可以选择0.01,然后随着迭代逐步减少。

  • 如果在验证集上性能不再增加,可以让学习率除以2或者5或者10,然后继续训练。

  • 在网络训练的前部分Loss一直降,而后部分不再降,这后部分的训练就需要降低学习率了。

  • 如果说Loss设计的合理,但是一开始容易爆炸,可以先用小的学习率训练,等Loss降下来后再慢慢调大学习率,后面再慢慢调小学习率。

Loss相关

  • 设计是否合理:一般来说,分类就是Softmax,回归就是L2损失。如果Loss比较大,考虑对网络输出也做归一化,比如位置用百分比的形式。

  • Loss加上正则。

  • Loss数量级:在多任务情况下,各Loss限制在一个数量级上,或者最终限制在一个数量级上,初期着重一个任务的Loss。

  • 多观察Loss:准确率虽然是评测指标,但是在训练过程中有可能突变。而Loss的变化一般不会发生突变。

  • 对比训练集和验证集的Loss,从而做出判断。

数据处理

数量越多、质量越高、标签越准确越好。

  • 输入:归一化(范围0到1)、正则化(0均值,1标准差)。除了方便计算外,归一化后具有相同的标度,利于找到全局最优解。

  • 打乱数据:shuffle。

  • 尽量移除不良数据。

  • 数据增强:各种数据增强。

训练

模型的训练是在拟合训练集的规律,模型的使用是将规律作用于测试集。
假设训练集和测试集所包含的规律是大方向相同,小细节存在差异的。
如果模型在训练集上一直训练下去,那么它会很好的拟合训练集所有的大方向规律和小细节规律,过拟合就必然了。

  • 初始化:参数的初始化至关重要,无脑用xavier。但是也不一定哪个好,所以多试试。

  • 预训练:CNN更加适合分类问题,如果任务比较复杂,可以先考虑用分类任务训练一个模型,再用该模型进行微调(finetune)。

  • 优化函数:sgd + momentum,速度慢,但性能好。或者,adam,收敛快。

  • Epoch代数:一般迭代几十到几百代。

  • Batch size:一般从几十到几百皆可。也不要过大,过大容易过拟合。

  • weight decay取0.005,momentum取0.9。

结束训练

  • 要根据任务留给网络一些学习的时间,Loss可能走S型下降。不要在网络效果不好时放弃网络,也不要在网络效果好的时候早停。

  • 观察Softmax确认分类网络学习是否充分:分类网络是学习类别之间的界限,网络会慢慢的从类别模糊到类别清晰。
    观察Softmax输出的概率分布,以二分类为例:刚开始的网络预测都在0.5上下,很模糊;随着网络的训练,网络预测会慢慢移动到0,1附近。
    所以,如果网络预测分布靠中间,再学习学习。

  • 早停:可以采用No-improvement-in-N的方式。

网络结构

  • 激活函数:使用ReLU。ReLU是一个万能的激活函数,可以有效的防止梯度弥散问题。Sigmoid函数由于其函数的性质是传统神经网络的最佳选择,但在深层网络中会引起梯度弥散和非零中心问题。

  • 最后一层一般不用激活函数:连续值预测用identity激活函数,分类用Softmax,回归不使用激活函数,直接wx+b。

  • 卷积核:大小使用3x3,数量尽量2^n。数量逐层翻倍。前几层的卷积核数量也不要太少,否则学不出底层特征。
    将参数设置为2的指数倍将有效提高矩阵分片、张量计算等操作的硬件处理效率。

  • 使用Dropout:可以防止过拟合,同时相当于做了集成。在测试的时候把Dropout关掉。

  • 尽量使用Batch Normalization,可以大大加快训练速度,也可以提升模型性能。

  • 尝试使用shortcut。

  • 多尺度融合:使用多尺度的图片输入,或者网络内部利用多尺度的结果。

  • 尝试使用Inception结构。

  • 尝试使用残差结构。

  • 调整模型的层数和卷积核数量 / 调整隐层的数量和每个隐层的结点数量。这一步会改变模型的容量。调整后需要再从新调参。
    增大模型的层数可以以让模型获得更好的非线性,增加模型的容量,缺点是模型更难训练,面临梯度弥散的风险,从而引入死单元。
    增加卷积核的数量可以在不引入训练困难的情况下让模型更好的拟合训练集,但是更容易过拟合。

Reference