一、问题
在深度学习时,一般将数据集划分成训练集和测试集。如果最终的训练结果不满意,一般就是以下两种情况:
(1)训练集的准确率不高,测试集的准确率也不高;(欠拟合)
(2)训练集的准确率非常高,测试集的准确率比训练集差上许多。(过拟合)
对于第(1)种情况,一般是因为模型自身的问题,比如模型本身选择的不对,模型的类型不对或者模型的深度太浅了,需要重新选择合适的模型。
对于第(2)种情况,通过训练过程中的损失值变化可以判断出过拟合情况的发生。例如下面的两个图,训练集上的损失一直在下降,但验证集的损失函数在某个点往后,与训练集损失下降的趋势不同,损失反而在抬升。
除了从损失函数的变化图可以看出,从正确率的变化上也能看出来。训练集的正确率已经接近1,但验证集在经过很长一段时间的训练后,正确率无法继续上升了,也能表明发生了过拟合现象。
二、解决方法
1.交叉验证
将整个数据集划分成三部分:训练集、验证集和测试集。每完成一次训练,就会在用当前训练得到的模型参数在验证集上进行验证。将整个训练过程中,在验证集上取得最好表现的参数保存下来,用于在测试集上进行使用,作为测试集的性能评估。
所以交叉验证的方法本质上是一个参数寻优的过程,通过提前验证,将表现最好的模型参数保存了下来。
2.正则化项
给损失函数添加网络系数的正则化项,防止过拟合。常用的有L1正则化和L2正则化:
PyTorch中的实现:通过优化器的weight_decay项来设置
3. 动量
用于跳出局部最小值,获取全局最优。
在PyTorch当中,对于随机梯度优化器SGD,只需要设置参数 momentum 就可以实现。
对于Adam优化器,自身就带有动量的机制,就不用设置了。
4.学习率衰减
根据损失函数值的变化,自动调整学习的步长,以获得全局更优的结果。
5. Early Stopping 提前终止训练
6.Dropout
训练时控制全连接层之间节点更新的比例,避免过拟合
实现:添加Dropout层,系数是放弃更新梯度的节点的比例
在测试时,就不用dropout了,要人为将模型切换到测试模式:
7.降低模型的复杂度(表达能力)
8.增加数据集的规模(核心方法)√
9.借鉴 Adaboost 的思想,多训练(有放回的进行训练集取样,用于训练)几个不同结构的模型,采用投票的方式来分类,这种方法也能有效提升模型的泛化能力√