深度学习——激活函数、损失函数、优化器
深度学习——激活函数、损失函数、优化器
- 1、激活函数
- 1.1、一些常见的激活函数
- 1.1.1、sigmoid
- 1.1.2、softmax
- 1.1.3、tanh
- 1.1.4、ReLU
- 1.1.5、Leaky ReLU
- 1.1.6、PReLU
- 1.1.7、GeLU
- 1.1.8、ELU
- 1.2、激活函数的特点
- 1.2.1、非线性
- 1.2.2、几乎处处可微
- 1.2.3、计算简单
- 1.2.4、非饱和性
- 1.2.5、单调性、输出范围有限
- 2、损失函数
- 2.1、深度估计回归损失
- 2.1.1、L1损失函数
- 2.1.2、L2损失函数
- 2.1.3、smooth L1损失函数
- 2.1.4、log cosh损失函数:
- 2.1.5、==RMSE:均方根误差==
- 2.1.6、MAE:平均绝对误差
- 2.1.7、iRMSE
- 2.1.8、REL系列
- 2.1.9、 δ \delta δ :阈值精度
- 2.1.10、log系列
- 2.2、分类损失
- 2.2.1、交叉熵损失:
- 2.2.2、Focal Loss
- 2.3、目标检测损失函数
- 2.3.1、IoU Loss交并比损失
- 3.2、GIoU Loss:泛化的IoU损失
- 2.3.3、DIoU
- 2.3.4、CIoU
- 2.3.5、EIoU->F-EIoU
- 3、优化器
- 3.1、SGD、BGD、MBGD
- 3.2、SGD with Momentum
- 3.3、NAG
- 3.4、AdaGard(自适应梯度)
- 3.5、RMSprop算法
- 3.6、Adadelta
- 3.7、Adam 适应性矩估计
- 3.8、Adamw
- 3.9、各个优化器特点以及演化对比
1、激活函数
激活函数将非线性引入到网络中,没有激活函数相当于原始的感知机,只有线性操作,近似为矩阵相乘操作,加入激活函数后可以更好地拟合非线性函数。
1.1、一些常见的激活函数
1.1.1、sigmoid
σ ( x ) = 1 1 + e − x \sigma(x) = \frac{1}{1+e^{-x}} σ(x)=1+e−x1
特点:将负无穷到正无穷的输入映射到0-1,处处连续可导,可以用于二分类,导数为 σ ′ ( x ) = σ ( x ) ( 1 − σ ( x ) ) \sigma'(x)=\sigma(x)(1-\sigma(x)) σ′(x)=σ(x)(1−σ(x))
缺点:在输出值接近0或1时会出现饱和现象,在反向传播时梯度较小,容易梯度消失,从而无法完成深层网络的训练。输出不是0均值的,会导致后层的神经元的输入是非0均值的信号,这会对梯度产生影响。并且计算复杂度较高,因为涉及到指数。
1.1.2、softmax
S o f t m a x ( x i ) = e x i Σ j e x j Softmax(x_i)=\frac{e^{x_i}}{\Sigma_j{e^{x_j}}} Softmax(xi)=Σjexjexi
softmax可以将上一层的原始数据进行归一化,转化为一个(0,1)之间的数值,这些数值可以被当作概率分布,用来作为多分类的目标预测值,一般作为神经网络的最后一层,接收上一层网络的输入值,然后将其转化为概率。sigmoid是softmax的一个特例,sigmoid函数只能用于预测值为0或1的二元分类。
1.1.3、tanh
σ ( x ) = e x − e − x e x + e − x \sigma(x) = \frac{e^x-e^{-x}}{e^x+e^{-x}} σ(x)=ex+e−xex−e−x
输出范围在-1~1,相比sigmoid函数,是0均值,会比sigmoid函数要好一些,但是仍然会存在容易梯度消失的问题。并且计算复杂度仍然较高。
1.1.4、ReLU
σ ( x ) = { 0 x < 0 x x ⩾ 0 \sigma(x) = \begin{cases} 0 & x<0 \\ x & x \geqslant 0 \end{cases} σ(x)={0xx<0x⩾0
或者 σ ( x ) = m a x ( 0 , x ) \sigma(x) = max(0,x) σ(x)=max(0,x)
整流线性单元,使用ReLU的SGD算法收敛速度比sigmoid和tanh快,在x>0时不会出现梯度消失问题,在x<0时,梯度为0,无法传播到前一层。计算复杂度低。
缺点:输出不是0均值的,并且在x<0时会存在神经元坏死问题,梯度无法传播,其后面的神经元梯度都为0,无法更新参数。
1.1.5、Leaky ReLU
σ ( x ) = { α x x < 0 x x > 0 \sigma(x) = \begin{cases} \alpha x & x<0 \\ x & x>0 \\ \end{cases} σ(x)={αxxx<0x>0
alpha默认0.01;为解决ReLU神经元坏死的问题,引入了LeakReLU,使得激活函数在负数区域也存在微小的梯度,而梯度是固定的斜率。
1.1.6、PReLU
σ ( x ) = { a x x < 0 x x > 0 \sigma(x) = \begin{cases} ax & x<0 \\ x & x>0 \\ \end{cases} σ(x)={axxx<0x>0
和LeakReLU不同的是这里的参数 a a a是可学习的
1.1.7、GeLU
σ ( x ) = 1 1 + e − 1.702 x \sigma(x) = \frac{1}{1+e^{-1.702x}} σ(x)=1+e−1.702x1
在Transformer里面用的多一些
1.1.8、ELU
σ ( x ) = { α ( e x − 1 ) x < 0 x x > 0 \sigma(x) = \begin{cases} \alpha(e^x-1) & x<0 \\ x & x>0 \\ \end{cases} σ(x)={α(ex−1)xx<0x>0
有负数饱和区域,从而对噪声有一些鲁棒性。可以看做是介于ReLU和Leaky ReLU之间的一个函数。当然,这个函数也需要计算exp,从而计算量上更大一些。
1.2、激活函数的特点
1.2.1、非线性
即导数不能是常数,来保证多层网络不退化成单层线性网络
1.2.2、几乎处处可微
几乎处处可微保证了在优化中梯度的可计算性,ReLU仅在有限个点处不可微。有限个不可微的点对优化结果不会有很大的影响。
1.2.3、计算简单
因为每一个神经元的输出都需要经过激活函数,简单的函数像是ReLU更适合做激活函数。
1.2.4、非饱和性
Sigmoid在正负区域都有饱和区,ReLU在负半轴有饱和区,饱和区参数无法得到有效更新,leakyReLU就是为了解决这个问题。
1.2.5、单调性、输出范围有限
2、损失函数
2.1、深度估计回归损失
2.1.1、L1损失函数
L1损失函数:最小绝对值偏差、最小绝对值误差:是目标值与估计值的绝对差值的总和。缺点:不稳定。收敛速度慢。优点:对离群点异常值更具有鲁棒性。
L 1 ( y ^ − y ) = ∑ i = 0 m ∣ y ( i ) − y ^ ( i ) ∣ L_1(\hat{y}-y)=\sum_{i=0}^m\left|y^{(i)}-\hat{y}^{(i)}\right| L1(y^−y)=i=0∑m y(i)−y^(i)
torch.nn.L1Loss(size_average=None, reduce=None, reduction='sum')
# size_average与reduce已经被弃用,具体功能可由reduction替代。
l1_loss = torch.nn.L1Loss(size_average=None, reduce=None, reduction='sum') # 创建实例
loss = l1_loss(src,tgt)
L 1 ( y ^ − y ) = 1 N ∑ i = 0 m ∣ y ( i ) − y ^ ( i ) ∣ L_1\left(\hat{y}-y\right)=\frac1N\sum_{i=0}^m\left|y^{(i)}-\hat{y}^{(i)}\right| L1(y^−y)=N1i=0∑m y(i)−y^(i)
torch.nn.L1Loss(size_average=None, reduce=None, reduction='mean')
,相当于MAE平均绝对误差。
torch.nn.functional.l1_loss(src, tgt, reduction='mean')
torch.mean(torch.abs(src-tgt))
(src-tgt).abs().mean()
如果是np.ndarray的话
np.mean(np.abs(src-tgt))
np.ndarray没有.abs()方法,只有类np.abs()函数
2.1.2、L2损失函数
L2损失函数:均方误差:是目标值与估计值的差值的平方和。缺点:对异常值更敏感。梯度更新方向容易受离群点主导。
L 2 ( y ^ , y ) = ∑ i = 0 m ( y ( i ) − y ^ ( i ) ) 2 L_2(\hat{y},y)=\sum_{i=0}^m(y^{(i)}-\hat{y}^{(i)})^2 L2(y^,y)=i=0∑m(y(i)−y^(i))2
torch.nn.MSELoss(size_average=None, reduce=None, reduction='sum')
torch.sum(torch.pow(src-tgt,2))
np.sum(np.power(src-tgt,2))
L 2 ( y ^ , y ) = 1 N ∑ i = 0 m ( y ( i ) − y ^ ( i ) ) 2 L_2(\hat{y},y)=\frac1N\sum_{i=0}^m(y^{(i)}-\hat{y}^{(i)})^2 L2(y^,y)=N1i=0∑m(y(i)−y^(i))2
torch.nn.MSELoss(size_average=None, reduce=None, reduction='mean')
,相当于MSE均方误差。
torch.mean(torch.pow(src-tgt,2))
np.mean(np.power(src-tgt,2))
2.1.3、smooth L1损失函数
smooth L1损失函数:平滑之后的L1损失函数:分段函数,来消除L1的折点不光滑问题。当误差的绝对值较小时采用MSE,当误差的绝对值较大时采用MAE。
S m o o t h L 1 = 0.5 x 2 , ∣ x ∣ < 1 ∣ x ∣ − 0.5 , x < − 1 或者 x > 1 SmoothL_1=\begin{aligned}&0.5x^2,\mid x\mid<1\\&\mid x\mid-0.5,x<-1\text{或者}x>1\end{aligned} SmoothL1=0.5x2,∣x∣<1∣x∣−0.5,x<−1或者x>1
torch.nn.SmoothL1Loss(size_average=None, reduce=None, reduction='mean', beta=1.0)
上面公式里面的默认beta为1。
Huber Loss:对异常值鲁棒,集MAE和MSE的优势于一身。
当预测偏差小于δ时,采用平方误差MSE,
在pytorch中torch.nn.HuberLoss(reduction=‘mean’),pytorch中的smoothL1好像也具有类似的功能,是一样的。
2.1.4、log cosh损失函数:
双曲余弦对数
对于较小的X值,log(cosh(x))约等于(x ** 2) / 2;对于较大的X值,则约等于abs(x) - log(2)。这意味着Log-cosh很大程度上工作原理和平均方误差很像,但偶尔出现错的离谱的预测时对它影响又不是很大。它具备了Huber损失函数的所有优点,但不像Huber损失,它在所有地方都二次可微。
但Log-cosh也不是完美无缺,如果始终出现非常大的偏离目标的预测值时,它就会遭受梯度问题。
2.1.5、RMSE:均方根误差
R M S E = 1 N ∑ i = 1 N ( D p r e d i − D g t i ) 2 \mathrm{RMSE}=\sqrt{\frac1N\sum_{i=1}^N\left(D_{pred}^i-D_{gt}^i\right)^2} RMSE=N1i=1∑N(Dpredi−Dgti)2
深度估计常常采用RMSE作为误差衡量指标。
2.1.6、MAE:平均绝对误差
MAE相对于RMSE更加具有鲁棒性,因为它不会受到平方项的影响,因此对异常值(大误差)不那么敏感,其计算公式如下:
MAE = 1 N ∑ i = 1 N ∣ D p r e d i − D g t i ∣ \text{MAE}=\frac1N\sum_{i=1}^N\lvert D_{pred}^i-D_{gt}^i\rvert MAE=N1i=1∑N∣Dpredi−Dgti∣
2.1.7、iRMSE
iRMSE:逆均方根误差,值越大表示性能越好错误,
i R M S E = 1 N ∑ i = 1 N ( 1 D p r e d i − 1 D g t i ) 2 \mathrm{iRMSE}=\sqrt{\frac1N\sum_{i=1}^N(\frac1{D_{pred}^i}-\frac1{D_{gt}^i})^2} iRMSE=N1i=1∑N(Dpredi1−Dgti1)2
iMAE:逆平均绝对误差:
i M A E = 1 N ∑ i = 1 N ∣ 1 D p r e d i − 1 D g t i ∣ \mathrm{iMAE}=\frac1N\sum_{i=1}^N|\frac1{D_{pred}^i}-\frac1{D_{gt}^i}| iMAE=N1i=1∑N∣Dpredi1−Dgti1∣
2.1.8、REL系列
平均相对误差,REL的值表示平均相对误差的百分比,强调了深度估计的准确性。REL越小,表示模型的深度估计与真实深度的平均相对误差越小,模型性能越好,其计算公式如下:
abs REL:
a b s REL = 1 N ∑ i = 1 N ∣ D p r e d i − D g t i D g t i ∣ abs\text{ REL}=\frac{1}{N}\sum_{i=1}^{N}\lvert\frac{D_{pred}^{i}-D_{gt}^{i}}{D_{gt}^{i}}\rvert abs REL=N1i=1∑N∣DgtiDpredi−Dgti∣
sq REL:
s q REL = 1 N ∑ i = 1 N ( D p r e d i − D g t i ) 2 D g t i sq\text{ REL}=\frac1N\sum_{i=1}^N\frac{\left(D_{pred}^i-D_{gt}^i\right)^2}{D_{gt}^i} sq REL=N1i=1∑NDgti(Dpredi−Dgti)2
2.1.9、 δ \delta δ :阈值精度
1.25 1.25^2 1.25^3
定义为:
t h r e s h = max ( D g t i D p r e d i , D p r e d i D g t i ) = δ < τ thresh=\max\Bigg(\frac{D_{gt}^i}{D_{pred}^i},\frac{D_{pred}^i}{D_{gt}^i}\Bigg)=\delta<\tau thresh=max(DprediDgti,DgtiDpredi)=δ<τ
对每个像素返回0或1,然后对整幅图取平均,其中 是给定的阈值通常为(1.25, 1.25^2, 1.25^3)。该指标与REL通常为室内数据集常用指标。
2.1.10、log系列
RMSE log:
R M S E log = 1 N ∑ i = 1 N ( ln ( D p r e d i ) − ln ( D g t i ) ) 2 RMSE\log=\sqrt{\frac{1}{N}\sum_{i=1}^{N}\left(\ln\left(D_{pred}^{i}\right)-\ln\left(D_{gt}^{i}\right)\right)^{2}} RMSElog=N1i=1∑N(ln(Dpredi)−ln(Dgti))2
log10:
log 10 = 1 N ∑ i = 1 N ∣ log 10 ( D p r e d i ) − log 10 ( D g t i ) ∣ \log10=\frac1N\sum_{i=1}^N\left|\log_{10}\left(D_{pred}^i\right)-\log_{10}\left(D_{gt}^i\right)\right| log10=N1i=1∑N log10(Dpredi)−log10(Dgti)
si log:
s i log = 1 N ∑ i = 1 N ( ln ( D p r e d i ) − ln ( D g t i ) ) 2 − l a m b d a × ( 1 N ∑ i = 1 N ( ln ( D p r e d i ) − ln ( D g t i ) ) ) 2 si\log=\sqrt{\frac{1}{N}\sum_{i=1}^{N}\left(\ln\left(D_{pred}^{i}\right)-\ln\left(D_{gt}^{i}\right)\right)^2-lambda\times\left(\frac{1}{N}\sum_{i=1}^{N}\left(\ln\left(D_{pred}^{i}\right)-\ln\left(D_{gt}^{i}\right)\right)\right)^2} silog=N1i=1∑N(ln(Dpredi)−ln(Dgti))2−lambda×(N1i=1∑N(ln(Dpredi)−ln(Dgti)))2
lambda通常为0.5
2.2、分类损失
2.2.1、交叉熵损失:
CrossEntropyLoss用于二分类或多分类问题。
- 信息量: I ( x ) = − log ( P ( x ) ) I(x)=-\log(P(x)) I(x)=−log(P(x))信息量的大小和事件发生的概率成反比。
- 信息熵:信息熵是在结果出来之前对可能产生的信息量的期望,要考虑随机变量的所有可能取值, H ( X ) = − Σ i = 1 n p ( x i ) log ( p ( x i ) ) H(X)=-\Sigma_{i=1}^{n} p(x_i)\log(p(x_i)) H(X)=−Σi=1np(xi)log(p(xi))
- 相对熵:又被称为KL散度,相对熵等价于两个概率分布的信息的差值:假设 p ( x ) p(x) p(x)为样本真实分布, q ( x ) q(x) q(x)为样本预测分布,则相对熵为: D K L ( p ∣ ∣ q ) = H p q ( X ) − H p p ( X ) = Σ i = 1 n p ( x i ) log ( p ( x i ) q ( x i ) ) D_{KL}(p||q) = H_{pq}(X)-H_{pp}(X)=\Sigma_{i=1}^n p(x_i) \log (\frac{p(x_i)}{q(x_i)}) DKL(p∣∣q)=Hpq(X)−Hpp(X)=Σi=1np(xi)log(q(xi)p(xi))
KL散度越小,说明两个分布(真实和预测)越接近, - 交叉熵:Cross Entropy
设p(x)、q(x)分别是离散随机变量X的两个概率分布,其中p(x)是目标分布,q(x)是预测分布,则交叉熵为:
H ( p , q ) = Σ i p ( x i ) log 1 log q ( x i ) = − Σ i p ( x i ) log q ( x i ) H(p,q)=\Sigma_{i}p(x_i)\log{\frac{1}{\log q(x_i)}}=-\Sigma_{i}p(x_i)\log q(x_i) H(p,q)=Σip(xi)loglogq(xi)1=−Σip(xi)logq(xi)
可以看到交叉熵是把KL散度中的固定的部分给去掉了
2.2.2、Focal Loss
主要是来解决单阶段目标检测中正负样本数量级不平衡问题。基于二分类交叉熵损失函数提出Focal Loss,的一个动态缩放迭代交叉熵损失。Focal Loss降低了容易分类的样本是损失占比,将更多的注意力放在难的、被错误分类的样本上。
loss = F.binary_cross_entropy_with_logits(pred, label, reduction='none')
# binary_cross_entropy_with_logits表示损失函数内部已经带了计算logit的操作,无需在传入这个loss函数之前手动使用sigmoid/softmax将之前的网络的输入映射到[0,1]之间。label通常是独热码,维度大小与pred相同,
pred_prob = pred.sigmoid() # 转为概率
p_t = label * pred_prob + (1-label) * (1-pred_prob)
modulating_factor=(1.0-p_t) ** gamma
# 对于在0标签处预测的概率比较大,这个因子会比较大,对于在1标签处预测的概率比较小的,这个因子也会比较大,对于概率很接近标签的,这个会比较小,从而动态缩放。
loss *= modulating_factor
BCE:二值交叉损失
2.3、目标检测损失函数
2.3.1、IoU Loss交并比损失
目标检测也可以用回归损失,让四个坐标值回归到目标值,但IoU损失是主流。
IoU表示交集与并集的面积比值。
IoU Loss = -ln(交集面积/并集面积)
部分来源于知乎。
3.2、GIoU Loss:泛化的IoU损失
当预测框与候选框没有重叠时,交集为0,损失为0,此时IoU无法计算两者之间的距离,梯度消失,而且IoU不管两个框的对齐方向问题。GIoU找到两个框最小闭合凸面C,然后再计算C中排除掉A和B后的面积占C原始面积的比值,最后再用原始的IoU减去这个比值得到泛化后的IoU值。
2.3.3、DIoU
2.3.4、CIoU
2.3.5、EIoU->F-EIoU
3、优化器
来源https://juejin.cn/post/7084409806492008456
一阶优化器:SGD、SDGwith Momentum、NAG(牛顿动量法)、AdaGrad(自适应梯度)、RMSProp(均方差传播)、Adam、Nadam、共轭梯度法
二阶优化器:牛顿法、拟牛顿法、BFGS、L-BFGS
其中:AdaGrad算法,RMSProp算法,Adam算法以及AdaDelta算法是自适应学习率算法
3.1、SGD、BGD、MBGD
假设待优化的模型参数为 θ \theta θ,目标函数(损失函数)为 J ( θ ) J(\theta) J(θ),学习率为 η \eta η,迭代周期epoch为t,则可以得到:
损失函数 J ( θ ) 关于当前参数 θ 的梯度: g t = ∇ θ J ( θ ) 损失函数J(\theta)关于当前参数\theta的梯度:g_t=\nabla_\theta J(\theta) 损失函数J(θ)关于当前参数θ的梯度:gt=∇θJ(θ)
在梯度下降算法中,沿着梯度的方向不断减小模型参数,参数更新为:
θ t + 1 = θ t − η ⋅ ∇ θ J ( θ ) = θ t − η ⋅ g t \theta_{t+1}=\theta_t-\eta \cdot \nabla_\theta J(\theta)=\theta_t-\eta \cdot g_t θt+1=θt−η⋅∇θJ(θ)=θt−η⋅gt
标注的梯度下降每次迭代都要遍历所有样本,这会使得训练过程极其缓慢
SGD:随机梯度下降
在每次迭代中仅使用一个随机选择的训练样本来计算梯度,并更新模型参数,训练成本低,但是不稳定,收敛速度慢,可能会收敛到局部最优解。通常,SGD收敛速度要比BGD快。
BGD:批量梯度下降
使用整个训练数据集所有样本的梯度,根据学习率更新模型参数,收敛方向更稳定,训练很慢,迭代次数相对较少。
MBGD:小批量梯度下降,对SGD和BGD的折中,每次使用batch_size个样本对参数进行更新。在合理的范围内增大batchsize能够确定更准确的收敛方向,减小震荡,增大并行率。但是batchsize过大,会导致迭代次数减小(相同epoch下),需要花费可能更多时间训练。
3.2、SGD with Momentum
参数更新时在一定程度上保留之前更新的方向,同时又利用batch的梯度微调最终的更新方向,SGD只使用了当步参数的梯度,随机性较大,如果将历次迭代的梯度按比例融合,可能更稳定。
假设 m t m_t mt表示 t t t时刻的动量, β \beta β表示动量因子,通常取0.9,即下降的方向只要是此前累计的方向,在SGD的基础上增加动量,则参数更新公式为:
M t = β ⋅ M t − 1 + η ⋅ g t θ t + 1 = θ t − M t M_t = \beta \cdot M_{t-1}+\eta \cdot g_t \\ \theta_{t+1} =\theta_t-M_t Mt=β⋅Mt−1+η⋅gtθt+1=θt−Mt
一阶动量 M t M_t Mt是各个时刻梯度方向的指数移动平均值,约等于最近 1 ( 1 − β ) \frac{1}{(1-\beta)} (1−β)1个时刻的梯度向量和的平均值。
动量可以减小震荡,在梯度方向相同时,动量可以加速参数更新,从而加速收敛。前后梯度不一致时能够抑制震荡,越过局部极小值,(加速收敛,减小震荡)
3.3、NAG
M t = β ⋅ M t − 1 + η ⋅ ∇ θ J ( θ − γ ⋅ M t − 1 ) θ t + 1 = θ t − M t M_t=\beta \cdot M_{t-1}+\eta \cdot \nabla_\theta J(\theta-\gamma \cdot M_{t-1}) \\ \theta_{t+1}=\theta_t-M_t Mt=β⋅Mt−1+η⋅∇θJ(θ−γ⋅Mt−1)θt+1=θt−Mt
进一步进入nesterov动量,从SGD with Momentum可以看出,无论当前位置的梯度为什么,参数更新都一定会先走一个 β ⋅ M t − 1 \beta \cdot M_{t-1} β⋅Mt−1,再根据之前位置处的参数小更新一下,于是NAG方法让参数先走 β ⋅ M t \beta \cdot M_t β⋅Mt,再根据走之后的位置处的梯度更新。这样如果前方的梯度更大,则迈步更大。
3.4、AdaGard(自适应梯度)
针对SGD中始终使用一个学习率的问题,AdaGard在每次进行参数更新的时候,对于每个参数,初始化一个s=0,然后每次将该参数的梯度平方求和累加到这个变量s上,而在更新这个参数的时候,学习率就变成:
G t = G t − 1 + g t 2 θ t + 1 = θ t − η G t + ϵ ⋅ g t G_t=G_{t-1} + g_t^2 \\ \theta_{t+1}=\theta_{t}-\frac{\eta}{\sqrt{G_t+\epsilon}} \cdot g_t Gt=Gt−1+gt2θt+1=θt−Gt+ϵη⋅gt
但是这种方法会存在二阶动量一直累加的问题,学习率迟早要很小。
3.5、RMSprop算法
RMSprop在有些情况下避免AdaGrad算法中学习率不断单调下降以至于过早衰减的缺点。
RMSprop首先计算每次迭代梯度g的平方的指数衰减移动平均Gt。例如 β = 0.9 \beta=0.9 β=0.9
G t = β ⋅ G t − 1 + ( 1 − β ) ⋅ g t 2 G_t=\beta \cdot G_{t-1} + (1-\beta) \cdot g_t^2 Gt=β⋅Gt−1+(1−β)⋅gt2
其中 β \beta β是自定义衰减率。例如0.9。
然后根据指数衰减移动平均来更新参数
θ t + 1 = θ t − η G t + ϵ ⋅ g t \theta_{t+1}=\theta_{t}-\frac{\eta}{\sqrt{G_t+\epsilon}} \cdot g_t θt+1=θt−Gt+ϵη⋅gt
3.6、Adadelta
为了接近AdaGard多次迭代后,学习率逐渐下降至0的问题,AdaGrad在一个窗口w中对梯度进行求和,而不是对梯度平方一直累加,这和RMSprop的做法类似。
但是Adadelta不光考虑了二阶动量,还考虑了一阶的影响。Adadelta实际上是使用更新量的平方的指数加权平均来动态得到代替了全局的标量的学习率,意味着更新量的平方越小,则学习率也就越小。
G t = β ⋅ G t − 1 + ( 1 − β ) ⋅ g t 2 u t = β ⋅ u t − 1 + ( 1 − β ) ⋅ Δ θ t 2 θ t + 1 = θ t − η ⋅ u t + ϵ G t + ϵ ⋅ g t G_t=\beta \cdot G_{t-1} + (1-\beta) \cdot g_t^2 \\ u_t = \beta \cdot u_{t-1} + (1-\beta) \cdot \Delta\theta_t^2 \\ \theta_{t+1} = \theta_{t}-\eta \cdot \frac{\sqrt{u_t+\epsilon}}{\sqrt{G_t+\epsilon}} \cdot g_t Gt=β⋅Gt−1+(1−β)⋅gt2ut=β⋅ut−1+(1−β)⋅Δθt2θt+1=θt−η⋅Gt+ϵut+ϵ⋅gt
3.7、Adam 适应性矩估计
Adam是一种可以替代传统随机梯度下降过程的一阶优化算法,和SDG不同之处在于:
- SGD保持单一的学习率更新所有权重,学习率在训练过程中并不会改变,Adam通过计算梯度的一阶矩估计和二阶矩估计为不同的参数设计独立的自适应学习率。
Adam算法计算了梯度的二阶矩均值。和梯度的指数移动均值,超参数beta1和beta2控制了这些移动均值的衰减率。 - Adam算法结合了RMSprop算法和动量法,不但使用动量作为参数更新方向,而且可以自适应调整学习率来改进梯度下降。
- Adam的参数:
η \eta η:学习率,(0.001)
beta1:一阶矩估计的指数衰减率(0.9)
beta2:二阶矩估计的指数衰减率(0.999)
默认参数就可以解决大部分问题。 - 计算步骤:
首先计算梯度平方的指数加权平均
G t = β 2 ⋅ G t − 1 + ( 1 − β 2 ) ⋅ g t 2 G_t=\beta_2 \cdot G_{t-1} + (1-\beta_2) \cdot g_t^2 Gt=β2⋅Gt−1+(1−β2)⋅gt2
计算梯度的指数加权平均(动量法)
M t = β 1 ⋅ M t − 1 + ( 1 − β 1 ) ⋅ g t M_t=\beta_1 \cdot M_{t-1} + (1-\beta_1 ) \cdot g_t Mt=β1⋅Mt−1+(1−β1)⋅gt
其中 β 1 \beta_1 β1和 β 2 \beta_2 β2分别为两个移动平均的衰减率,0.9和0.999
然后对偏差进行修正
M t ^ = M t 1 − β 1 t G t ^ = G t 1 − β 2 t \hat{M_t} = \frac{M_t}{1-\beta_1^t} \\ \hat{G_t} = \frac{G_t}{1-\beta_2^t} Mt^=1−β1tMtGt^=1−β2tGt
计算参数更新参数
θ t + 1 = θ t − η G t ^ + ϵ M t ^ \theta_{t+1} = \theta_t-\frac{\eta}{\sqrt{\hat{G_t}+\epsilon}} \hat{M_t} θt+1=θt−Gt^+ϵηMt^
3.8、Adamw
在Adam中可能会存在不收敛的问题,因为随着二阶动量的不断累加,学习率会越来越小,但是不一定会按照合适的速率缩小,如果在模型收敛之前就已经过于小,则最后收敛不到想要的位置。并且在很多数据集上Adam泛化性并不如SGD with Momentum,这里面一个重要原因就是Adam中L2正则项并不像SGD中那么有效。
AdamW使用了更严谨的权重衰减,其权重衰减只在最后更新公司中使用,不参与动量计算。 λ \lambda λ是正则化系数
M t = β 1 M t − 1 + ( 1 − β 1 ) g t G t = β 2 G t − 1 + ( 1 − β 2 ) g t 2 M t ^ = M t 1 − β 1 t G t ^ = G t 1 − β 2 t θ t + 1 = θ t − η ⋅ ( M t ^ G t ^ + ϵ + λ ⋅ θ t ) M_t=\beta_1 M_{t-1} + (1-\beta_1 ) g_t \\ G_t=\beta_2 G_{t-1} + (1-\beta_2)g_t^2 \\ \hat{M_t} = \frac{M_t}{1-\beta_1^t} \\ \hat{G_t} = \frac{G_t}{1-\beta_2^t} \\ \theta_{t+1} = \theta_t - \eta \cdot (\frac{\hat{M_t}}{\sqrt{\hat{G_t}+\epsilon}}+ \lambda \cdot \theta_t) Mt=β1Mt−1+(1−β1)gtGt=β2Gt−1+(1−β2)gt2Mt^=1−β1tMtGt^=1−β2tGtθt+1=θt−η⋅(Gt^+ϵMt^+λ⋅θt)
3.9、各个优化器特点以及演化对比
GD(梯度下降)/BGD(批量梯度下降):使用全部训练集,沿着梯度反方向以固定学习率更新参数。
缺点:计算全局梯度耗时长;对所有参数使用相同学习率;只根据当前时刻梯度,容易陷入局部最优解。
SGD(随机梯度下降):相较于GD,只使用1个样本的来计算梯度。
优点:对于大数据集可以更快进行更新。
缺点:学习率固定;使用一个样本的梯度,优化过程震荡,需要长时间才能收敛。
MBGD(小批量梯度下降):相较于SGD,使用一个batch的样本的梯度。收敛更稳定。
Momenum(动量优化):在SGD/MBGD基础上引入动量,每次的更新量不是梯度*学习率,而是动量。 M t = β ⋅ M t − 1 + η ⋅ g t M_t = \beta \cdot M_{t-1}+\eta \cdot g_t Mt=β⋅Mt−1+η⋅gt
优点:加速收敛,抑制震荡,跳出局部最优解。
缺点:需要人工设置动量参数,学习率固定。
AdaGrad(自适应梯度优化器):自适应学习率,与梯度平方和有关
G t = G t − 1 + g t 2 θ t + 1 = θ t − η G t + ϵ ⋅ g t G_t=G_{t-1} + g_t^2 \\ \theta_{t+1}=\theta_{t}-\frac{\eta}{\sqrt{G_t+\epsilon}} \cdot g_t Gt=Gt−1+gt2θt+1=θt−Gt+ϵη⋅gt
但是这种方法会存在二阶动量一直累加的问题,学习率迟早要很小。
RMSProp(均方根传播):相较于AdaGrad,使用指数移动平均来解决学习率一直变小的问题。
G t = β ⋅ G t − 1 + ( 1 − β ) ⋅ g t 2 G_t=\beta \cdot G_{t-1} + (1-\beta) \cdot g_t^2 Gt=β⋅Gt−1+(1−β)⋅gt2
但是模型还是会对初始学习率敏感。
Adadelta:相较于RMSProp,用梯度更新量的平方的指数加权平均,来动态的替代全局标量的学习率,避免了优化器对学习率的敏感。
G t = β ⋅ G t − 1 + ( 1 − β ) ⋅ g t 2 u t = β ⋅ u t − 1 + ( 1 − β ) ⋅ Δ θ t 2 θ t + 1 = θ t − η ⋅ u t + ϵ G t + ϵ ⋅ g t G_t=\beta \cdot G_{t-1} + (1-\beta) \cdot g_t^2 \\ u_t = \beta \cdot u_{t-1} + (1-\beta) \cdot \Delta\theta_t^2 \\ \theta_{t+1} = \theta_{t}-\eta \cdot \frac{\sqrt{u_t+\epsilon}}{\sqrt{G_t+\epsilon}} \cdot g_t Gt=β⋅Gt−1+(1−β)⋅gt2ut=β⋅ut−1+(1−β)⋅Δθt2θt+1=θt−η⋅Gt+ϵut+ϵ⋅gt
Adam(自适应矩估计):结合了Momentum和RMSProp的优点,既保留了动量,又有自适应学习率。和SGD with Momentum相比,自适应学习率可以很大程度上避免学习率选择不当带来的训练震荡或收敛速度慢的问题。