栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

loss乘以100等价于learning rate乘以100?

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

loss乘以100等价于learning rate乘以100?

导读

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

因为无论是缩放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)
Momentum SGD

Momentum SGD是基于SGD的基础上做了修改,为了解决海森矩阵的不良条件数和随机梯度的方差问题导致训练模型时进入到局部极小值问题而改进的。Momentum SGD梯度的更新过程如下所示:
θ = θ − v t v t = γ ∗ v t − 1 + η ∗ Δ θ J ( θ ) begin{aligned} theta &= theta - v_t \ v_t &= gamma * v_{t-1} + eta * Delta_{theta}J(theta) end{aligned} θvt​​=θ−vt​=γ∗vt−1​+η∗Δθ​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)
Adagrad

Adagrad能够自适应的调整不同参数的学习率,根据参数的历史所有梯度平方值总和的平方根来调整学习率的缩放比例,使得稀疏的特征得到大的学习率更新,对于非稀疏的特征得到较小的学习更新,所以该算法适合处理稀疏特征的数据。参数的更新公式如下:
g t , i = Δ θ J ( θ i ) θ t + 1 , i = θ t , i − η G t , i i + ϵ ∗ g t , i begin{aligned} g_{t,i} &= Delta_{theta}J(theta_i) \ theta_{t+1,i} &= theta_{t,i} - frac{eta}{sqrt{G_{t,ii} + epsilon}} * g_{t,i} end{aligned} gt,i​θt+1,i​​=Δθ​J(θi​)=θt,i​−Gt,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} e−8,用来避免分母为零的情况

接下来我们来讨论,对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,i​−Gt,ii​∗s2 ​+ϵη​∗gt,i​∗s=θt,i​−Gt,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)
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 begin{aligned} E[g^2]_t &= gamma * E[g^2]_{t-1} + (1-gamma) * g_t^2 \ theta_{t+1} &= theta_t - frac{eta}{sqrt{E[g^2]_t}+delta} * g_{t,i} end{aligned} E[g2]t​θt+1​​=γ∗E[g2]t−1​+(1−γ)∗gt2​=θt​−E[g2]t​ ​+δη​∗gt,i​​
不难看出RMSProp其实和Adagrad的计算公式差不多,所以对于RMSProp而言loss乘以s不等价于learning rate乘以s。

Adam

Adam:Adaptive Momnet Estimation,与Adagrad和RMSProp的区别在于计算历史梯度衰减的方法不同。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 ~ begin{aligned} v_t &= beta_{1}v_{t-1} + (1-beta_1)g_t \ u_t &= beta_{2}u_{t-1} + (1 - beta_2)g_t^2\ widetilde{v_t} &= frac{v_t}{1-beta_1^t}\ widetilde{u_t} &= frac{u_t}{1- beta_2^t} \ theta_{t+1} &= theta_t - frac{eta}{sqrt{widetilde{u_t}}+epsilon}widetilde{v_t} end{aligned} vt​ut​vt​ ​ut​ ​θt+1​​=β1​vt−1​+(1−β1​)gt​=β2​ut−1​+(1−β2​)gt2​=1−β1t​vt​​=1−β2t​ut​​=θt​−ut​ ​ ​+ϵη​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是否等价,主要取决于优化器的选择。对于SGD和Moment SGD来说,loss乘以s等价于learning rate乘以s,而对于Adagrad、RMSProp和Adam来说loss乘以s不等价于learning rate乘以s。

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/348023.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号