zoukankan      html  css  js  c++  java
  • pytorch optimizer.step()和loss.backward()和scheduler.step()的关系与区别

    疑问:

    optimizer的step为什么不能放在mini-batch那个循环之外,optimizer.step和loss.backward的区别;

    解惑:

    首先需要明确optimizer优化器的作用,形象地说,优化器就是需要根据网络反向传播的梯度信息来更新网络参数,以起到降低loss函数计数值的作用,这也是机器学习中最一般的方法论。

    从优化器的作用出发,需要使得优化器能够起作用,主要需要两个东西:1.优化器需要知道当前的网络的参数空间,这也是为什么在训练文件中,正式开始训练之前需要将网络参数放到优化器里面,比如使用Pytorch的话总会出现类似如下的代码:

     2. 需要知道反向传播的梯度信息,我们还是从代码入手,如下所示是pytorch中SGD优化算法的step()函数具体写法,具体SGD的写法放在参考部分。

     1 def step(self, closure=None):
     2         """Performs a single optimization step.
     3         Arguments:
     4             closure (callable, optional): A closure that reevaluates the model
     5                 and returns the loss.
     6         """
     7         loss = None
     8         if closure is not None:
     9             loss = closure()
    10 
    11         for group in self.param_groups:
    12             weight_decay = group['weight_decay']
    13             momentum = group['momentum']
    14             dampening = group['dampening']
    15             nesterov = group['nesterov']
    16 
    17             for p in group['params']:
    18                 if p.grad is None:
    19                     continue
    20                 d_p = p.grad.data
    21                 if weight_decay != 0:
    22                     d_p.add_(weight_decay, p.data)
    23                 if momentum != 0:
    24                     param_state = self.state[p]
    25                     if 'momentum_buffer' not in param_state:
    26                         buf = param_state['momentum_buffer'] = d_p.clone()
    27                     else:
    28                         buf = param_state['momentum_buffer']
    29                         buf.mul_(momentum).add_(1 - dampening, d_p)
    30                     if nesterov:
    31                         d_p = d_p.add(momentum, buf)
    32                     else:
    33                         d_p = buf
    34 
    35                 p.data.add_(-group['lr'], d_p)
    36 
    37         return loss

    从上面的代码可以看到step这个函数使用的是参数空间(param_groups)中的grad,也就是当前参数空间对应的梯度,这也就解释了为什么optimizer使用之前需要zero清零,因为如果不清零,那么使用的这个grad就同上一个Mini-batch有关,这不是我们需要的结果。再回过头来看,我们知道optimizer更新参数空间需要基于反向梯度,因为,当调用optimizer.step()的时候应当在loss.backward()之后。这也是经常会碰到的,代码示意如下:

     loss.backward()在前

    optimizer.step()在后。顺序不可颠倒。

    那么为什么optimizer.step()需要放在每个batch训练中,而不是epoch训练中,这是因为mini-batch训练模式是嘉定每一个训练集就只有mini-batch大小,因此实际上可以将每一次Mini-batch看做是一次训练,一次训练更新一次参数空间,因为optimizer.step()放在每个Mini-batch中。

    scheduler.step()按照pytorch的定义是用来更新优化器学习率的,一般是按照epoch为单位进行更换,即多少个epoch后更换一次学习率,因而scheduler.step()放在epoch这个大循环中。

    Pytorch SGD代码:https://github.com/pytorch/pytorch/blob/cd9b27231b51633e76e28b6a34002ab83b0660fc/torch/optim/sgd.py#L63

    原文连接:https://blog.csdn.net/xiaoxifei/article/details/87797935

  • 相关阅读:
    centos ssh远程登陆
    Vim 技巧
    php and js to facebook登陆 最佳实践
    vim 编辑器常规操作
    js 函数定义三种方式
    ORDER BY 默认升序排列
    sql = 和<>遵循的sql-92标准的设置SET ANSI_NULLS ON
    添加FB登陆时,需要curl扩展
    array(1) { [0]=> int(5) }和array(1) { [0]=> string(1) "5" }
    Android第三方推送引擎比较
  • 原文地址:https://www.cnblogs.com/elitphil/p/15543074.html
Copyright © 2011-2022 走看看