1.简介
在上一篇文章里,我们介绍了RMSProp,在AdaGrad的基础上引入了衰减量,从而解决不断地累加二阶动量导致最终学习率会接近于0以及训练提前终止的问题,AdaDelta在这基础上做了进一步改进。
2.AdaDelta
类似于RMSProp,AdaDelta也使用了衰减的方法使得二阶动量不会一直累加,公式如下:
其中,为当前step的二阶动量,
为上一个step的二阶动量,
为历史二阶动量的衰减率。
同时AdaDelta还不光考虑了二阶动量,还应该考虑一阶的影响,认为应该在学习率上去乘以一个描述的项,这就是
平方的指数衰减移动均方根(RMS)。所以最终的更新公式为:
其中,为
平方的指数衰减移动均方根(RMS),
为当前step的二阶动量,
为增加分母稳定性的系数,
为当前step的梯度,
为学习率。
3.思考
从公式上出发,AdaDelta实际上是使用更新量的平方的指数加权平均来动态得到代替了全局的标量学习率,意味着更新量的平方越小,那么学习率也就更小,这样会更有助于模型训练前期的快速更新和后期的逐渐收敛,实现了自适应的学习率计算。
但是同时会对的值特别敏感,因为第一步的学习率系数就是
,如果小了的话前期更新就会很慢,如果大了的话后期更新就会比较震荡。
4.pytorch代码
AdaDelta的伪代码流程如下,可以看到与RMSProp的区别就是加入了。
以下代码为pytorch官方AdaDelta的代码。
def _single_tensor_adadelta(
params: List[Tensor],
grads: List[Tensor],
square_avgs: List[Tensor],
acc_deltas: List[Tensor],
*,
lr: float,
rho: float,
eps: float,
weight_decay: float,
maximize: bool,
differentiable: bool,
):
for (param, grad, square_avg, acc_delta) in zip(
params, grads, square_avgs, acc_deltas
):
grad = grad if not maximize else -grad
if weight_decay != 0:
grad = grad.add(param, alpha=weight_decay)
if torch.is_complex(param):
square_avg = torch.view_as_real(square_avg)
acc_delta = torch.view_as_real(acc_delta)
grad = torch.view_as_real(grad)
square_avg.mul_(rho).addcmul_(grad, grad, value=1 - rho)
std = square_avg.add(eps).sqrt_()
delta = acc_delta.add(eps).sqrt_()
if differentiable:
delta = delta.clone()
delta.div_(std).mul_(grad)
acc_delta.mul_(rho).addcmul_(delta, delta, value=1 - rho)
if torch.is_complex(param):
delta = torch.view_as_complex(delta)
param.add_(delta, alpha=-lr)
业务合作/学习交流+v:lizhiTechnology
如果想要了解更多优化器相关知识,可以参考我的专栏和其他相关文章:
【优化器】(一) SGD原理 & pytorch代码解析_sgd优化器-优快云博客
【优化器】(二) AdaGrad原理 & pytorch代码解析_adagrad优化器-优快云博客
【优化器】(三) RMSProp原理 & pytorch代码解析_rmsprop优化器-优快云博客
【优化器】(四) AdaDelta原理 & pytorch代码解析_adadelta里rho越大越敏感-优快云博客
【优化器】(五) Adam原理 & pytorch代码解析_adam优化器-优快云博客
【优化器】(六) AdamW原理 & pytorch代码解析-优快云博客
【优化器】(七) 优化器统一框架 & 总结分析_mosec优化器优点-优快云博客
如果想要了解更多深度学习相关知识,可以参考我的其他文章: