发布时间:2023-05-31 17:00
关于梯度问题我们首先要明白梯度会出现什么样的情况,然后才能根据这些情况去解决遇到的问题,话不多说现在开始
常见的梯度问题是什么?一般就是两种:梯度弥散和梯度爆炸
一、造成梯度弥散的原因
1、激活函数饱和
2、样本中的奇异样本引起模型无法收敛(奇异样本就是混进样本中的其他数据,比如猫狗识别数据中出现了一张猪的图片)
3、使用反向传播算法传播梯度的时候,随着网络传播深度的增加,梯度的幅值会急剧减小,会导致浅层神经元的权重更新非常缓慢,不能有效的学习
4、从数学的角度来看,因为梯度是连乘的,所以在梯度较小时会导致梯度消失(例子:0.3的20次方甚至更大次方会导致算出来的梯度无限接近0,所以会导致梯度消失。造成的原因和第三点相似,层次太深了会导致梯度不断下降甚至消失,还可能在反向传播梯度的过程中浅层神经元权重更新慢,学习效率降低)
5、学习率过大导致模型震荡无法收敛
二、造成梯度爆炸的原因
1、神经网络初始化的权值过大,每层网络反向求导的结果都大于1,这样梯度相乘就会变得更大
2、学习率太大导致梯度爆炸
一、如何从以上方向解决梯度弥散
1、针对激活函数饱和的问题,可以用relu、leak_relu、mish等激活函数代替
sigmoid或者tanh等激活函数
分析:sigmoid函数值在[0,1],relu函数值在[0,正无穷],sigmoid函数的梯度随着x的增大或者减小会消失,而relu不会,小于0的部分会直接给值为0,一定程度上还减缓了网络的复杂程度防止网络的过拟合
2、对于数据中的奇异样本,我们可以先清洗掉明显有问题的数据,之后对数据进行标准化处理,使得所有的数据都限定在一个范围内,有利于网络的快速收敛。
3、针对网络太深以及梯度连乘导致的梯度趋于0的情况我们可以适当的优化一下网络比如减小网络的深度或者利用残差结构来解决这个问题
4、针对学习率过大导致模型不收敛的问题我们可以适当的调整学习率,比如然学习率成周期性的衰减(余弦退火)或者成线性的衰减
二、解决梯度爆炸的问题
1、重设初始化权值(可以采用标准正态分布采样)
2、针对学习率太大的问题最简单的办法就是减小学习率
既然上面提到了标准化,我在这里也把标准化的的好处梳理一下
1、数据做了标准化(即减均值除方差),相当于将数据统一了量纲,使其形成了一个正态分布,这样可以使得模型的学习速度加快,即可以增大学习率
2、减弱对初始化的强依赖性,标准化后的量纲都一样,所有的值都在一个较小的范围内
3、可以防止梯度爆炸或者梯度弥散的现象
那么如何去做标准化以及在哪个位置做标准化呢?
1、首先对于网络的输入我们需要做标准化,可以自己写标准化的公式也可以直接调用torch自带的api —transforms.Normalize(mean=[0.5,],std=[0.5,]),里面的参数自己根据情况设置
2、其次在网络中同样需要对每一层都做标准化,对于深度学习网络模型而言一般采用BatchNorm做标准化,当然了还有一些其他的标准化方法见下图,不同的方法根据网络的具体需求而定,针对batchnorm来说它的计算过程沿着通道计算每个batch的均值u
沿着通道计算每个batch的方差σ^2
对x做归一化,x’=(x-u)/开根号(σ^2+ε)
加入缩放和平移变量γ和β ,归一化后的值,y=γx’+β
加入缩放平移变量的原因是:保证每一次数据经过归一化后还保留原有学习来的特征,同时又能完成归一化操作,加速训练。 这两个参数是用来学习的参数。