自学内容网 自学内容网

24/11/5 算法笔记adagrad 自适应学习率

AdaGrad(Adaptive Gradient Algorithm)是一种用于随机优化的算法,它通过适应每个参数的学习率来优化目标函数。

  1. 自适应学习率: AdaGrad算法的核心特点是为每个参数自适应地调整学习率。这意味着每个参数都有自己的学习率,这取决于该参数的梯度历史信息。这种自适应性使得算法能够根据参数的重要性和变化频率来调整学习率,从而提高优化效率。

  2. 二阶动量: AdaGrad算法引入了二阶动量的概念,通过累积所有过去的梯度平方和来调整学习率。对于每个参数,算法维护一个累积梯度平方和的变量,这个变量随着时间的推进而增加,导致学习率逐渐减小。

  3. 更新规则: AdaGrad的参数更新规则如下: 其中,θt​ 是时间步 t 的参数,η 是初始学习率,Gt​ 是累积梯度平方和,gt​ 是当前步的梯度,ϵ是为了避免除以零而加上的一个小常数(通常取 10^-10)。

  4. 对稀疏数据的鲁棒性: AdaGrad倾向于给不频繁更新的特征分配更大的学习率,这使得它在处理稀疏数据时特别有效。对于那些很少更新的参数,AdaGrad能够给予更大的更新步长,从而确保这些参数有足够的机会进行调整。

  5. 缺点: 尽管AdaGrad在某些情况下表现良好,但它的一个主要缺点是累积梯度平方和会导致学习率迅速减小,这可能会导致训练过程在后期几乎停止。

  6. 对Adam算法的影响: AdaGrad算法是Adam算法的前身之一,它对后续的优化算法发展产生了重要影响,特别是在自适应学习率的设计理念上。

下面是adagrad的代码

import torch

class AdaGrad(torch.optim.Optimizer): 
    def __init__(self, params, lr=1e-3, lr_decay=0, weight_decay=0): #检查参数范围
        if not 0.0 <= lr < 1.0:
            raise ValueError("Invalid learning rate: {}".format(lr))
        if not 0.0 <= lr_decay < 1.0:
            raise ValueError("Invalid lr_decay value: {}".format(lr_decay))
        if not 0.0 <= weight_decay < 1.0:
            raise ValueError("Invalid weight_decay value: {}".format(weight_decay))
        defaults = dict(lr=lr, lr_decay=lr_decay, weight_decay=weight_decay)
        super(AdaGrad, self).__init__(params, defaults)

    def step(self, closure=None):  
        loss = None
        if closure is not None:
            loss = closure() #返回损失

        for group in self.param_groups: #优化器可以对不同参数应用不同的优化设置,这些设置被组织在不同的组(param_groups)中。
            for p in group['params']: 
                if p.grad is None:
                    continue
                grad = p.grad.data 
                if grad.is_sparse:  #梯度稀疏性检查
                    raise RuntimeError('AdaGrad does not support sparse gradients, please consider SparseAdam instead')

                state = self.state[p]  #状态字典

                # State initialization
                if len(state) == 0:
                    state['step'] = 0
                    state['sum'] = torch.zeros_like(p.data)

                state['step'] += 1   #更新迭代步数
  
                state['sum'].add_(grad.pow(2))

                if group['weight_decay'] != 0: #如果设置了权重衰减(group['weight_decay']),则将参数 p 的数据乘以权重衰减系数加到梯度 grad 上。
                    grad.add_(p.data, alpha=group['weight_decay'])

                clr = group['lr'] / (1 + state['step'] * group['lr_decay']) #计算学习率

                denom = state['sum'].sqrt().add_(group['eps'])  # 分母,即累积梯度平方和的平方根加上一个小常数以避免除零
                p.data.addcdiv_(grad, denom, value=-clr)

        return loss

缺点

  1. 学习率持续衰减:AdaGrad算法会累积所有过去的梯度平方和,这导致分母不断增大,从而使学习率持续减小。在训练的后期,学习率可能会变得非常小,导致模型难以继续学习,几乎停止收敛。

  2. 存储梯度平方和:AdaGrad需要为每个参数存储一个累积的梯度平方和,这在参数数量很多时会占用较多的内存,增加内存开销。

  3. 对稀疏数据的过度适应:虽然AdaGrad能够自动提高稀疏特征的学习率,但在某些情况下,这可能导致对这些稀疏特征的过度适应,从而影响模型的泛化能力。

  4. 可能导致训练提前停止:由于学习率的快速下降,AdaGrad可能导致训练过程提前停止,尤其是在处理非平稳目标函数时,这可能会使得模型无法充分学习。


原文地址:https://blog.csdn.net/yyyy2711/article/details/143514939

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!