深度学习模型调参总结
大部分内容参考自《Machine Learning Yearning》
Bias 和 Variance
偏差(bias)是指算法在训练集上的偏差,也就是错误率,错误越大偏差越大,欠拟合
方差(variance)是指算法在开发集(或测试集)上的表现比训练集上差多少,也可以理解为过拟合,表现 为训练集正确率很高,测试集上的正确率很低
可避免偏差和不可避免偏差
偏差可以分为两个部分,包括可避免偏差和不可避免偏差
如何理解:假设现有一个珍稀动物识别系统,任务难度大,即便由人类来区分,也存在14%的错误率(最优错误率)
现在算法达到:
训练错误率=15%
开发错误率=30%
可以将训练错误率(偏差)分解如下:
最伏错误率(“不可避免偏差”):14%,可以将其认为是学习算法的偏差“不可避免”的部分。
可避免偏差:1%。即训练错误率和最伏误差率之间的差值。
举个例子,该例子中最优错误率是 14%,我们有:
● 训练误差 = 15%
● 开发误差 = 16%
i这种情况下,可避免的偏差误差是 1%,方差误差约为 1%。因此,算法已经做的很好了,几乎没有提升的空间。它只比最佳错误率低 2%
如何设定期望误差率
使用人类表现水平来估计最优错误率,并设置可达到的“期望错误率”。 假设你的算法在某个任务上达到了 10% 的误差,但普通人所能达到的误差是 2% . 由此我们就可以知道最优错误率是 2% 或更低,这也表明可避免偏差至少是 8% . 所以你应当尝试一下降低偏差的技术。更一般地说,有一个合理可实现的“期望错误率”可以帮助你去估计学习算法的可避免偏差。这反过来也帮你决定是否使用误差降低技术
偏差和方差的几种情况和解决方案
1)假设训练集错误率1%,开发集错误率10%,则样本方差大,过拟合
-
修改模型架构
减小模型规模(比如神经元/层的数量),减小网络复杂度
-
增加正则化
-
L 1 Regularization
-
L 2 Regularization
-
Dropout层
-
-
添加Batch Normalization
-
加入提前终止(Early stopping)
-
模型初始化
-
通过特征选择减少输入特征的数量和种类
-
特征降维
-
根据误差分析修改特征
-
检测训练数据集和测试数据是否有相对应的特征,数据分布是否一致,不一致的时候,继续特征工程工作
-
增加训练数据的种类,使得训练数据覆盖所有测试数据的特使用数据增强
-
增加数据量
2)假设训练错误率为15%,开发错误率为16%,这个时候,偏差比较大,欠拟合
-
增加训练epoch
-
增大batch-size
-
调整激活函数(例如使用relu)
-
调整优化算法
-
例如使用Adam
-
增大learning rate
-
-
增加网络复杂度
-
增加网络层数
-
增加卷积层输出的通道数
-
增加全连接层的节点数
-
-
检测训练数据集和测试数据是否有相对应的特征
-
增加训练数据的种类,使得训练数据覆盖所有测试数据的特性,
-
增加外部数据集,如果担心外部数据集污染training set,可以将外部数据集的权重调低一点
-
数据增强
-
3)假设训练错误率为15%,开发错误率为30%,高偏差,高方差
这个时候,先要解决偏差问题,只有在训练集上开始收敛了,才能开始考虑测试集上的方差问题。因此遇到这种情况,先按照高偏差解决,高偏差解决之后,也许可能高方差的问题也就消失了,如果没有消失,在考虑解决高方差的问题。
4)假设训练错误率为0.5%,开发错误率为1%,低偏差,低方差(完美状态)
5)假设训练错误率为0.5%,开发错误率为1%,低偏差,低方差,但是开发集loss在低点持续震荡
-
确认训练集和测试集分布是否存在较大的差异,差异大的话进行特征工程
-
确认是否数据增强做的太多了
-
尝试调整学习率,在不同阶段使用不用学习率
-
思考和检查网络是否还是有点欠拟合,如果还有,解决欠拟合
-
找到更多训练数据,使其能够覆盖较多的样本分布
模型调参Pipeline
-
设定固定随机种子
-
先不要使用数据增强
-
设置合理的baseline
-
过拟合一个batch,然后观察loss最低可以到达多少,对比baseline,如果可以到达很低,进行下一步,如果不行,则考虑 情况2)
-
绘制training和testing 阶段的loss曲线
-
验证loss函数
-
如果train loss 小
-
如果test set 的loss 大,而train set 的loss小,说明过拟合,使用情况1)解决
-
如果test set的loss 也小,那么基本上算是成功了
-
如果test set 的 loss 也小,但是震荡,使用 情况5)解决
-
-
如果train loss 大
进入步骤2)
-
已优化模型如何进一步提高
-
优化网络结构,使用更好的backbone
-
使用更好的LOSS函数,比如:回归问题可以考虑smooth-l1等
-
考虑使用难例挖掘的方法
-
有条件的话,加大batchsize
-
考虑预训练模型
-
观察测试样本,查找case,针对Case来,补充样本+数据增强
-
尝试不同的优化函数,交替训练,fine-tuning
-
不同的权重初始化方法
-
尝试不同的学习率初始值和衰减值
-
考虑在梯度上做文章,可以是梯度裁剪、梯度校验、梯度归一化等方法
-
继续特征工程(往往最有效)