当前位置:   article > 正文

loss乘以100等价于learning rate乘以100?_学习率和loss的关系

学习率和loss的关系

导读

看到这个问题的时候,可能你会很直观的认为是等价的,其实等不等价这个应该取决于在更新参数时所选择的优化算法

因为无论是缩放loss还是learning rate最终的影响都是对更新参数时偏移量( Δ \Delta Δ)的影响,而不同的优化算法会导致这个偏移量存在差别,下面我们来讨论一下不同优化算法之间的差别。
在这里插入图片描述

SGD

梯度下降优化算法,也是最常见的一种优化算法,公式如下:
θ = θ − η ∗ Δ θ J ( θ ) \theta = \theta - \eta * \Delta_{\theta}J(\theta) θ=θηΔθJ(θ)

  • η \eta η:学习率
  • Δ θ J ( θ ) \Delta_{\theta}J(\theta) ΔθJ(θ):loss对参数的一阶偏导,所以当我们对loss的尺度进行缩放的时候实际最终都会反应到梯度上面

结论:通过上面的公式不难看出,当loss乘以s时其实就等价于偏导 Δ θ J ( θ ) \Delta_{\theta}J(\theta) ΔθJ(θ)数乘以s,也就等价与学习率 η \eta η乘以s。所以对于SGD而言,loss乘以s等价于learning rate乘以s。下面我们可以用代码来证明一下

import torch
from torch import nn

#保证每次产生的随机数(输入和输出都相同)
torch.manual_seed(28)

class ExampleModel(nn.Module):
    """定义一个简单的神经网络
    """
    def __init__(self):
        super(ExampleModel, self).__init__()
        self.linear_model = nn.Sequential(
            nn.Linear(10,10),
            nn.ReLU(),
            nn.Linear(10,1),
            nn.Sigmoid()
        )
    def forward(self,x):
        return self.linear_model(x**3+x**2+x)


def print_weight_info(input,label,model,opt,loss_scale):
    """输出网络的参数信息
    :param input: 输入
    :param label: 输出
    :param model: 模型
    :param opt: 优化器
    :param loss_scale: loss变化的尺度
    :return:
    """
    output = model(input)
    loss = (label - output) * loss_scale
    opt.zero_grad()
    loss.backward()
    opt.step()
    print(model.linear_model[0].weight)

model = ExampleModel()


input1 = torch.rand(1,10)
label1 = torch.rand(1,)
lr = 0.01

lr_sgd_opt = torch.optim.SGD(model.parameters(),lr=lr)
#lr设置为0.01,loss的尺度扩大10倍
print_weight_info(input1,label1,model,lr_sgd_opt,10)
#lr设置为0.01*10扩大10倍,loss的尺度不做处理
#lr_scale_sgd_opt = torch.optim.SGD(model.parameters(),lr=lr*10)
#print_weight_info(input1,label1,model,lr_scale_sgd_opt,1)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

Momentum SGD

Momentum SGD是基于SGD的基础上做了修改,为了解决海森矩阵的不良条件数随机梯度的方差问题导致训练模型时进入到局部极小值问题而改进的。Momentum SGD梯度的更新过程如下所示:
θ = θ − v t v t = γ ∗ v t − 1 + η ∗ Δ θ J ( θ ) θ=θvtvt=γvt1+ηΔθJ(θ)

θvt=θvt=γvt1+ηΔθJ(θ)

  • γ \gamma γ:动量参数,一般取0.5、0.9和0.99
  • v t v_t vt :t时刻的梯度

结论:通过上面的公式不难看出,对于Momentum SGD来说和SGD一样,loss乘以s等价于learning rate乘以s。证明代码如下:

import torch
from torch import nn

#保证每次产生的随机数(输入和输出都相同)
torch.manual_seed(28)

class ExampleModel(nn.Module):
    """定义一个简单的神经网络
    """
    def __init__(self):
        super(ExampleModel, self).__init__()
        self.linear_model = nn.Sequential(
            nn.Linear(10,10),
            nn.ReLU(),
            nn.Linear(10,1),
            nn.Sigmoid()
        )
    def forward(self,x):
        return self.linear_model(x**3+x**2+x)


def print_weight_info(input,label,model,opt,loss_scale):
    """输出网络的参数信息
    :param input: 输入
    :param label: 输出
    :param model: 模型
    :param opt: 优化器
    :param loss_scale: loss变化的尺度
    :return:
    """
    output = model(input)
    loss = (label - output) * loss_scale
    opt.zero_grad()
    loss.backward()
    opt.step()
    print(model.linear_model[0].weight)

model = ExampleModel()


input1 = torch.rand(1,10)
label1 = torch.rand(1,)
lr = 0.01
#设置momentum SGD的动量为0.9
momentum = 0.9

lr_mom_sgd_opt = torch.optim.SGD(model.parameters(),lr=lr,momentum=momentum)
#lr设置为0.01,loss的尺度扩大10倍
print_weight_info(input1,label1,model,lr_mom_sgd_opt,10)
#lr设置为0.01*10扩大10倍,loss的尺度不做处理
# lr_mom_sgd_opt = torch.optim.SGD(model.parameters(),lr=lr*10,momentum=momentum)
# print_weight_info(input1,label1,model,lr_mom_sgd_opt,1)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52

Adagrad

Adagrad能够自适应的调整不同参数的学习率,根据参数的历史所有梯度平方值总和的平方根来调整学习率的缩放比例,使得稀疏的特征得到大的学习率更新,对于非稀疏的特征得到较小的学习更新,所以该算法适合处理稀疏特征的数据。参数的更新公式如下:
g t , i = Δ θ J ( θ i ) θ t + 1 , i = θ t , i − η G t , i i + ϵ ∗ g t , i gt,i=ΔθJ(θi)θt+1,i=θt,iηGt,ii+ϵgt,i

gt,iθt+1,i=ΔθJ(θi)=θt,iGt,ii+ϵ ηgt,i

  • g t , i g_{t,i} gt,i t t t时刻参数 θ i \theta_{i} θi的梯度
  • θ t \theta_{t} θt t t t时刻参数 θ \theta θ的值
  • G t , i i G_{t,ii} Gt,ii G t G_{t} Gt是一个对角矩阵,第 i i i行元素 e i i e_{ii} eii表示的是过去到现在第 i i i个参数 θ i \theta_i θi的梯度的平方和
  • ϵ \epsilon ϵ:通常取 e − 8 e^{-8} e8,用来避免分母为零的情况

接下来我们来讨论,对loss和learning rate乘以s对参数 θ \theta θ的更新会有什么影响,先讨论对loss乘以s
θ t + 1 , i = θ t , i − η G t , i i ∗ s 2 + ϵ ∗ g t , i ∗ s = θ t , i − η G t , i i + ϵ / s ∗ g t , i \theta_{t+1,i} = \theta_{t,i} - \frac{\eta}{\sqrt{G_{t,ii} * s^2} + \epsilon} * g_{t,i} * s = \theta_{t,i} - \frac{\eta}{\sqrt{G_{t,ii}} + \epsilon / s} * g_{t,i} θt+1,i=θt,iGt,iis2 +ϵηgt,is=θt,iGt,ii +ϵ/sηgt,i
因为 ϵ \epsilon ϵ是极小值,所以我们可以忽略它的影响。通过上式就能够说明,当使用Adagrad优化算法时,乘以s对于参数的更新没有影响。而对于learning rate而言,它会使得参数更新的更快(s大于1)或更慢(s小于1),所以使用Adagrad优化算法的时候,loss乘以s不等价于learning rate乘以s
证明的代码如下:

input1 = torch.rand(1,10)
label1 = torch.rand(1,)
lr = 0.01
# lr_opt = torch.optim.Adagrad(model.parameters(),lr=lr)
#lr设置为0.01,loss的尺度不变
# print_weight_info(input1,label1,model,lr_opt,1)
#loss的尺度扩大10倍
# print_weight_info(input1,label1,model,lr_opt,10)
#lr设置为0.01*10扩大10倍,loss的尺度不做处理
lr_opt = torch.optim.Adagrad(model.parameters(),lr=lr*10)
print_weight_info(input1,label1,model,lr_opt,1)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

RMSProp

RMSProp针对梯度平方和累积的越来越大的问题,而采用了历史梯度平方衰减平均值来代替梯度的平方和。动态的梯度平均值 E [ g 2 ] t E[g^2]_t E[g2]t取决于当前时刻以及上一时刻的平均值,计算公式如下
E [ g 2 ] t = γ ∗ E [ g 2 ] t − 1 + ( 1 − γ ) ∗ g t 2 θ t + 1 = θ t − η E [ g 2 ] t + δ ∗ g t , i E[g2]t=γE[g2]t1+(1γ)g2tθt+1=θtηE[g2]t+δgt,i

E[g2]tθt+1=γE[g2]t1+(1γ)gt2=θtE[g2]t +δηgt,i
不难看出RMSProp其实和Adagrad的计算公式差不多,所以对于RMSProp而言loss乘以s不等价于learning rate乘以s

Adam

Adam:Adaptive Momnet Estimation,与AdagradRMSProp的区别在于计算历史梯度衰减的方法不同。Adam没有使用梯度的平方衰减,而是采用了类似于动量的梯度衰减,计算公式如下:
v t = β 1 v t − 1 + ( 1 − β 1 ) g t u t = β 2 u t − 1 + ( 1 − β 2 ) g t 2 v t ~ = v t 1 − β 1 t u t ~ = u t 1 − β 2 t θ t + 1 = θ t − η u t ~ + ϵ v t ~ vt=β1vt1+(1β1)gtut=β2ut1+(1β2)g2t~vt=vt1βt1~ut=ut1βt2θt+1=θtη~ut+ϵ~vt

vtutvt ut θt+1=β1vt1+(1β1)gt=β2ut1+(1β2)gt2=1β1tvt=1β2tut=θtut +ϵηvt
v t v_t vt:梯度的一阶估计
u t u_t ut:梯度的二阶估计
v t ~ \widetilde{v_t} vt :梯度一阶估计的偏差修正
u t ~ \widetilde{u_t} ut :梯度二阶估计的偏差修正
β 1 \beta_1 β1通常取0.9, β 2 \beta_2 β2通常取0.999

转换一下公式可以发现,对于Adam来说,loss乘以s不等价于learning rate乘以s

总结

我们通过理论公式的推导以及实践的代码证明,最终发现对loss或learning rate乘以缩放尺度参数s是否等价,主要取决于优化器的选择。对于SGDMoment SGD来说,loss乘以s等价于learning rate乘以s,而对于AdagradRMSPropAdam来说loss乘以s不等价于learning rate乘以s

注意:上面在讨论loss与learning rate乘以s之间的关系时,我们并不考虑weight decay的影响。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/133407
推荐阅读
相关标签
  

闽ICP备14008679号