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

【梯度下降】zero

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

【梯度下降】zero

参考链接:
https://www.jb51.net/article/189433.htm
https://www.jianshu.com/p/c59b75f1064c


如果不了解梯度下降的原理,请参考(一)

一、zero_grad的用途

零梯度可改变:可利用requires_grad_()方法修改tensor的requires_grad属性.可以调用.detach()或with torch.no_grad():,姜不再计算张量的梯度,跟踪张量的历史记录.这点在评估模型、测试模型阶段中常常用到.

用法:

model.zero_grad()
optimizer.zero_grad()
二、zero_grad的原代码

model.zero_grad()的原代码

for p in self.parameters():
    if p.grad is not None:
        p.grad.detach_()
        p.grad.zero_() 

optimizer.zero_grad()的原代码

for group in self.param_groups:
    for p in group['params']:
        if p.grad is not None:
            p.grad.detach_()
            p.grad.zero_()

当使用optimizer = optim.Optimizer(net.parameters())设置优化器时,此时优化器中的param_groups等于模型中的parameters(),此时,二者是等效的,从二者的源码中也可以看出来。

当多个模型使用同一个优化器时,二者是不同的,此时需要根据实际情况选择梯度的清除方式。当一个模型使用多个优化器时,二者是不同的,此时需要根据实际情况选择梯度的清除方式 三、在每轮训练的时候梯度清零的原因

首先了解pytorch的机制。在pytorch中有前向计算图反向计算图两个独立的机制。并且pytorch会默认对梯度进行累加。默认累加的好处是当在多任务中对前面共享部分的tensor进行了多次计算操作后,调用不同任务loss的backward,那些tensor的梯度会自动累加,缺点是当你不想先前的梯度影响到当前梯度的计算时需要手动清零 。
总结知乎大佬的:
EPO1:

for idx, data in enumerate(train_loader):
    xs, ys = data
    pred1 = model1(xs)
    pred2 = model2(xs)
    

    loss1 = loss_fn1(pred1, ys)
    loss2 = loss_fn2(pred2, ys)
    
    ******
    loss = loss1 + loss2
    optmizer.zero_grad()
    loss.backward()
    ++++++
    optmizer.step()

从PyTorch的设计原理上来说,在每次进行前向计算得到pred时,会产生一个用于梯度回传的计算图,这张图储存了进行back propagation需要的中间结果,当调用了.backward()后,会从内存中将这张图进行释放上述代码执行到******时,内存中是包含了两张计算图的,而随着求和得到loss,这两张图进行了合并,而且大小的变化可以忽略执行到++++++时,得到对应的grad值并且释放内存。这样,训练时必须存储两张计算图,而如果loss的来源组成更加复杂,内存消耗会更大
作者:Forever123
链接:https://www.zhihu.com/question/303070254/answer/608153308
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    Edition2为了减小每次的内存消耗,借助梯度累加,又有 ,有如下变种
for idx, data in enumerate(train_loader):
    xs, ys = data
    
    optmizer.zero_grad()
    # 计算d(l1)/d(x)
    pred1 = model1(xs) #生成graph1
    loss1 = loss_fn1(pred1, ys)
    loss1.backward()  #释放graph1

    # 计算d(l2)/d(x)
    pred2 = model2(xs)#生成graph2
    loss2 = loss_fn2(pred2, ys)
    loss2.backward()  #释放graph2

    # 使用d(l1)/d(x)+d(l2)/d(x)进行优化
    optmizer.step()

可以从代码中看出,利用梯度累加,可以在最多保存一张计算图的情况下进行multi-task任务的训练。另外一个理由就是在内存大小不够的情况下叠加多个batch的grad作为一个大batch进行迭代,因为二者得到的梯度是等价的综上可知,这种梯度累加的思路是对内存的极大友好,是由FAIR的设计理念出发的。

   我没看懂

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

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

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