【W-1】loss不收敛或不下降问题处理经验

目录

  1. 训练集loss不下降
  2. 验证集loss不下降
  3. 测试集loss不下降
  4. 实践总结

loss不下降,分多种情况:训练集不下降,验证集不下降,本文结合其它博客,做个小的总结:

首先看看不同情况:train loss与test loss结果分析

train loss 不断下降,test loss不断下降,说明网络仍在学习;

train loss 不断下降,test loss趋于不变,说明网络过拟合;

train loss 趋于不变,test loss不断下降,说明数据集100%有问题;

train loss 趋于不变,test loss趋于不变,说明学习遇到瓶颈,需要减小学习率或批量数目;

train loss 不断上升,test loss不断上升,说明网络结构设计不当,训练超参数设置不当,数据集经过清洗等问题。

一、训练集loss不下降

1.1 数据集本身的问题

使用简单模型进行测试,比如机器学习的模型,较快能验证。另外检测数据集是否是乱序的。

  • 数据本身以及label是否有异常
  • 数据是否过于脏乱,没有经过清洗
  • 数据输入是否有问题,比如图片与label是否一致
  • 数据经过预处理后,是否丢失特征或者因预处理而出现别的问题
  • 数据量是否过少,网络出现过拟合的现象
  • loss等于87.33不变:查阅相关资料以后发现是由于loss的最大值由FLT_MIN计算得到,FLT_MIN是1.17549435e−38F1.17549435e−38F其对应的自然对数正好是-87.3356,这也就对应上了loss保持87.3356了。
  • loss保持0.69左右:当p=0.5时,loss正好为0.693147

1.2 模型结构和特征工程存在问题

通过参考别人已经设计好并实现和测试过的结构,以及特征工程方案,进行改进和适应性修改,可以更快更好的完成目标任务。当模型结构不好或者规模太小、特征工程存在问题时,其对于数据的拟合能力不足,是很多人在进行一个新的研究或者工程应用时,遇到的第一个大问题。建议使用小的数据集进行测试下。这个问题应该比较容易发现,并且应该第一个排除掉。

调整BN,激活等的顺序,不过这个估计只能调优,不能起到太大作用。

1.3 权重初始化方案有问题

初始化方式比较多样化,可以参考我的其它文档:《【pytorch-2-5-2】深度学习权值初始化的方法》。不过很多网络,不使用初始化,也能进行训练。

1.4 正则化过度

L1 L2和Dropout是防止过拟合用的,建议是训练初期,不启用任何正则化手段。

1.5 增加网络层次

若是非常复杂的问题,比如成千上万的分类问题。若使用单层的神经网络,训练起来肯定不好,loss也不会收敛。建议尝试至少3层的网络。

1.6 选择合适的激活函数、损失函数

在神经网络的激活函数、损失函数方面的选取,也是需要根据任务类型,选取最合适的。

比如,卷积神经网络中,卷积层的输出,一般使用ReLu作为激活函数,因为可以有效避免梯度消失,并且线性函数在计算性能上面更加有优势。而循环神经网络中的循环层一般为tanh,或者ReLu,全连接层也多用ReLu,只有在神经网络的输出层,使用全连接层来分类的情况下,才会使用softmax这种激活函数。

而损失函数,对于一些分类任务,通常使用交叉熵损失函数,回归任务使用均方误差,有自动对齐的任务使用CTC loss等。损失函数相当于模型拟合程度的一个评价指标,这个指标的结果越小越好。一个好的损失函数,可以在神经网络优化时,产生更好的模型参数。

1.7 选择合适的优化器和学习速率

神经网络的优化器选取一般选取Adam,但是在有些情况下Adam难以训练,这时候需要使用如SGD之类的其他优化器。另外减小学习率,使用lr_scheduler逐步降低学习率;这部分建议看看我的另外两篇:《AdamOptimizer及各类优化器》《【pytorch-2-5-1】学习率调整-torch.optim.lr_scheduler》。

1.8 尝试调整的batchsize

若出现上下震动不收敛时候,也有可能是batchsize太小导致的。所以建议增大batchsize试试。这样可以增加训练方向一致性。当然也可能因过大时,模型前期由于梯度的平均,导致收敛速度过慢。

1.9 使用normalization

这个能一定程度加快模型收敛,并起到正则化的作用。具体可见这篇:《【DL-0】》

1.10 数据初始的归一化

数据归一化/归一化

def feature_normalize(data):

mu = np.mean(data,axis=0)

std = np.std(data,axis=0)

return (data - mu)/std

具体可见: https://blog.csdn.net/z_feng12489/article/details/89205558

1.11 训练时间不足

计算量不同,训练时间不同,若是没有GPU加速,估计训练就更慢了。这种就是等一等了,或者换多GPU加速试试。

1.12 模型训练遇到瓶颈

这里的瓶颈一般包括:梯度消失、大量神经元失活、梯度爆炸和弥散、学习率过大或过小等。

梯度消失时,模型的loss难以下降,就像走在高原上,几乎任何地方都是高海拔,可以通过梯度的检验来验证模型当前所处的状态。有时梯度的更新和反向传播代码存在bug时,也会有这样的问题。

在使用Relu激活函数的时候,当每一个神经元的输入X为负时,会使得该神经元输出恒为0,导致失活,由于此时梯度为0,无法恢复。有一种解决方案是使用LeakyRelu,这时,Y轴的左边图线会有一个很小的正梯度,使得神经网络在一定时间后可以得到恢复。不过LeakyRelu并不常用,因为部分神经元失活并不影响结果,相反,这种输出为0还有很多积极的作用。因为Relu方程输入为负时,输出值为0,利用此特性可以很好地忽略掉卷积核输出负相关信息,同时保留相关信息。

二、验证集loss不下降

调整到本阶段,默认是训练集上的loss可以下降,但验证集上的loss已经不降。大部分是从处理过拟合的手段进行的。

2.1 适当的正则化和降维

正则化是用来解决模型过拟合问题的一个很重要的手段,人为给定一个正则系数lambda,进行权重衰减,将一些相关性不大的特征项的参数衰减到几乎为0,相当于去掉了这一项特征,这跟降维类似,相当于减少了特征维度。而去掉基本无关的维度,那么就避免了模型对于这一维度特征的过分拟合。还有在神经网络两个层之间增加Dropout和Normal等,也起到了抑制过拟合的作用。

2.2 适当降低模型的规模和数据复杂度

过拟合很重要的一个原因也是模型的复杂度太高,除了正则化手段以外,适当减小模型的规模也是很重要的,尽量让神经网络结构的假设空间与预期目标模型需要存储的信息量相匹配。降低数据的维度,类似起到dropout的效果。

2.3 减小batchsize

由于批规范内部的标准化,较小的批大小在某种程度上对应较强的正则化。这是因为批处理的经验平均值/std是完整平均值/std的更近似版本,所以规模和偏移量会使批处理更加"摇摆"。

2.4 使用early stop

停止基于验证损失的训练,在模型即将过度适应时抓住它。

大模型尝试:我只是在早期停止后才提到这一点,但我发现在过去的几次大的模型当然最终会过度适应,但它们的"早期停止"性能通常会比小的模型好得多。

2.5 获取更多的数据集

深度学习就是在有大量数据的基础上发展起来的。深度学习的三件套:数据、模型和硬件。增加数据量,能更好训练模型。

2.6 对数据集做扰动和扩增

这个是直接对现有的数据集做扩容,一定程度上可以再次提高验证集上的准确率,比如对图像做旋转,对声音文件进行加噪处理等。最终的效果虽然比不上同等情况下的数据量的增加带来的效果增益,但是在现有条件下,算是扩增数据量的一个有效的方案。

三、测试集loss不下降

测试集一般为模型之前训练时从未见过的新数据,或者目标应用场景下的真实数据。由于训练集和验证集的loss不下降时,应归为前两节的内容,所以这一节中,我们默认训练集和验证集的loss情况是正常的。如果测试集的loss很高,或者正确率很低,那么一般是因为训练数据的分布和场景与测试数据的分布和应用场景不一致。

3.1 应用场景不一致

比如,一个语音识别模型,输入的数据集都是女性的录音音频,那么对于男性的声音就不能很好的识别出来。这个也是博主之前做语音识别的时候遇到过的一个真实案例,解决方案就是增加含有大量男性录音音频的数据集来训练。

3.2 噪声问题

噪声问题是实际应用场景下,频繁遇到的问题。直接容易理解的案例就是,在语音识别中,标准语音数据集都是在安静环境下采集的数据,但是在实际应用中,我们录音时多多少少会有噪声,那么我们需要专门去处理噪声,比如进行一个降噪处理,或者在训练数据中添加噪声等。在图像的识别中,那么就需要考虑图片中的遮挡、雾霾、旋转、镜像和大小远近等问题。

四、实践总结

在实际工作中,训练4000+的分类模型中,1.5 、1.7 、1.9在实际训练中改善比较明显。

参考文献

【1】 如何解决神经网络训练时loss不下降的问题

【2】https://karpathy.github.io/2019/04/25/recipe/

posted @ 2020-12-04 21:27  忆凡人生  阅读(14823)  评论(0编辑  收藏  举报