炼丹总原则
![](https://i-blog.csdnimg.cn/blog_migrate/9bcc92f1afe05d6f013bf9113977413e.png)
图来自参考链接[1]
首先对于所有的深度学习模型,我们都希望达到的最终目的:它能够真正解决实际问题。这也就意味着不仅需要它们在见过的数据集上表现好(训练集、甚至包括测试集),还要在未来的生产环境中对未知数据的表现也要足够好,这对我们“炼丹”工程师也就提出了要求。
那么我们怎么去训练模型,并且评价一个模型的好坏呢?
通常的一个做法是将收集到的数据集进行划分,划分为训练集与测试集(训练集标注标签,测试集标签在训练阶段不可用)。此外,训练集还要划分为训练集与验证集。训练集作为模型训练所用的数据,验证集用于选择模型超参数,防止过拟合,而测试集用于检验模型的实际能力(模拟在未来场景中的效果)。
![](https://i-blog.csdnimg.cn/blog_migrate/c1f70515bcb18f6a44b8878359df4dcd.png)
在数据比赛中(例如Kaggle),通常会设置三个数据集,一个是训练集、一个是测试集(public),另一个也是测试集(private)。为什么需要两个测试集呢?如果只有一个测试集的话,当模型训练好提交后及时反馈,即使看不到测试集标签,那我们也直接根据测试集的效果来调整策略。这样可能导致模型疯狂地拟合这个测试集的效果,导致测试集不能真实地检验模型能力。因此构建了两个测试集(public+private),限制模型提交次数并只返回模型在public上的效果,最终以private的结果来衡量模型效果。
因此正确的做法是以public上的结果作为参考,只以训练集和测试集来调整模型。
不同情况下的炼丹策略
1. 训练集效果很差
首先检查数据预处理方式、以及程序是否有误,排除人为因素影响。如果模型本身的设置没有出错,而训练集效果不好,这说明训练出现了欠拟合现象。通常有两种原因:① 模型拟合能力不够;② 优化问题。
① 模型拟合能力不够:说明当前这个问题所采用的模型过于简单,比如你让一层的线性模型去做图像理解,肯定是做不好的。通常所采用的办法就是:换模型,换更复杂、容量更大的模型。
② 优化问题:这就是调参的问题了,我们可以换用更好的优化方式,更好的优化器,以及尝试不同的损失函数等等,可以查看我其他关于调参的文章。
除此之外,还有一种情况:模型本身的能力够,但就是优化不好,如同ResNet文中提到的那样,更深的模型反而出现了退化现象。这个问题在某种程度上来说也属于优化问题,可以考虑换用学术界中泛化能力更好的模型,或者调整模型结构,例如ResNet就引入了skip connection
。
2. 训练集效果好、验证集效果差
通常训练集越验证集来自同一个数据分布(训练集划分为训练集+验证集),首先检查是否在数据划分方式上出现了问题。排除这就出现了过拟合现象,通过有以下几种方法解决:
① 引入更多训练数据:真实数据越多,训练集的分布越接近真实分布,那么测试集的效果将会越好 ;
② 数据增广:使用合理的数据增广手段,模拟真实数据;
③ 提前结束训练:控制训练轮次,在测试集误差提升前结束训练,保存模型;
④ 引入正则化手段:通常有L1正则 / L2正则;
⑤ Dropout:训练时随机丢弃部分输出,可详见这篇博客
3. 训练集效果好、验证集效果好、测试集效果差
出现训练集效果好、验证集效果好,但是测试集的效果差,这说明存在训练集数据与测试集数据分布不一致。一般来说,比赛会防止这种情况的出现。而现实的应用中,这种情况无法避免,就比如我们无法奢求一个在ImageNet上训练得很优秀的模型在二次元世界的物体分类上表现得很好。这就涉及到迁移学习、域自适应方面的知识了,可以关注我之后的博客。
参考
[1] 李宏毅2021机器学习