【PyTorch】PyTorch中的梯度累加
PyTorch中的梯度累加
使用PyTorch实现梯度累加变相扩大batch
PyTorch中在反向传播前为什么要手动将梯度清零? - Pascal的回答 - 知乎
https://www.zhihu.com/question/303070254/answer/573037166
这种模式可以让梯度玩出更多花样,比如说梯度累加(gradient accumulation)
传统的训练函数,一个batch是这么训练的:
for i,(images,target) in enumerate(train_loader):
# 1. input output
images = images.cuda(non_blocking=True)
target = torch.from_numpy(np.array(target)).float().cuda(non_blocking=True)
outputs = model(images)
loss = criterion(outputs,target)
# 2. backward
optimizer.zero_grad() # reset gradient
loss.backward()
optimizer.step()
- 获取loss:输入图像和标签,通过infer计算得到预测值,计算损失函数;
optimizer.zero_grad()清空过往梯度;loss.backward()反向传播,计算当前梯度;optimizer.step()根据梯度更新网络参数
简单的说就是进来一个batch的数据,计算一次梯度,更新一次网络
使用梯度累加是这么写的:
for i,(images,target) in enumerate(train_loader):
# 1. input output
images = images.cuda(non_blocking=True)
target = torch.from_numpy(np.array(target)).float().cuda(non_blocking=True)
outputs = model(images)
loss = criterion(outputs,target)
# 2.1 loss regularization
loss = loss/accumulation_steps
# 2.2 back propagation
loss.backward()
# 3. update parameters of net
if((i+1)%accumulation_steps)==0:
# optimizer the net
optimizer.step() # update parameters of net
optimizer.zero_grad() # reset gradient
- 获取loss:输入图像和标签,通过infer计算得到预测值,计算损失函数;
loss.backward()反向传播,计算当前梯度;- 多次循环步骤1-2,不清空梯度,使梯度累加在已有梯度上;
- 梯度累加了一定次数后,先
optimizer.step()根据累计的梯度更新网络参数,然后optimizer.zero_grad()清空过往梯度,为下一波梯度累加做准备;
总结来说:梯度累加就是,每次获取1个batch的数据,计算1次梯度,梯度不清空,不断累加,累加一定次数后,根据累加的梯度更新网络参数,然后清空梯度,进行下一次循环。
一定条件下,batchsize越大训练效果越好,梯度累加则实现了batchsize的变相扩大,如果 accumulation_steps 为8,则batchsize '变相' 扩大了8倍,是我们这种乞丐实验室解决显存受限的一个不错的trick,使用时需要注意,学习率也要适当放大。
更新1:关于BN是否有影响,之前有人是这么说的:
As far as I know, batch norm statistics get updated on each forward pass, so no problem if you don't do
.backward()every time.
BN的估算是在forward阶段就已经完成的,并不冲突,只是 accumulation_steps=8 和真实的batchsize放大八倍相比,效果自然是差一些,毕竟八倍Batchsize的BN估算出来的均值和方差肯定更精准一些。
更新2:根据李韶华的分享,可以适当调低BN自己的momentum参数:
bn自己有个momentum参数:x_new_running = (1 - momentum) * x_running + momentum * x_new_observed. momentum越接近0,老的running stats记得越久,所以可以得到更长序列的统计信息
我简单看了下PyTorch 1.0的源码:https://github.com/pytorch/pytorch/blob/162ad945902e8fc9420cbd0ed432252bd7de673a/torch/nn/modules/batchnorm.py#L24,BN类里面momentum这个属性默认为0.1,可以尝试调节下。
借助梯度累加,避免同时计算多个损失时存储多个计算图
PyTorch中在反向传播前为什么要手动将梯度清零? - Forever123的回答 - 知乎
https://www.zhihu.com/question/303070254/answer/608153308
原因在于在PyTorch中,计算得到的梯度值会进行累加。
而这样的好处可以从内存消耗的角度来看。
1. Edition1
在PyTorch中,multi-task任务一个标准的train from scratch流程为:
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的来源组成更加复杂,内存消耗会更大。
2. Edition2
为了减小每次的内存消耗,借助梯度累加,又有 ,有如下变种。
for idx, data in enumerate(train_loader):
xs, ys = data
optmizer.zero_grad()
# 计算d(l1)/d(x)
pred1 = model1(xs) #生成graph1
loss = loss_fn1(pred1, ys)
loss.backward() #释放graph1
# 计算d(l2)/d(x)
pred2 = model2(xs)#生成graph2
loss2 = loss_fn2(pred2, ys)
loss.backward() #释放graph2
# 使用d(l1)/d(x)+d(l2)/d(x)进行优化
optmizer.step()
可以从代码中看出,利用梯度累加,可以在最多保存一张计算图的情况下进行multi-task任务的训练。
3. Other
另外一个理由就是在内存大小不够的情况下叠加多个batch的grad作为一个大batch进行迭代,因为二者得到的梯度是等价的。
综上可知,这种梯度累加的思路是对内存的极大友好,是由FAIR的设计理念出发的。
相关链接
- PyTorch中在反向传播前为什么要手动将梯度清零? - 知乎:https://www.zhihu.com/question/303070254
- https://discuss.pytorch.org/t/why-do-we-need-to-set-the-gradients-manually-to-zero-in-pytorch/4903/9
【PyTorch】PyTorch中的梯度累加的更多相关文章
- PyTorch官方中文文档:torch.nn
torch.nn Parameters class torch.nn.Parameter() 艾伯特(http://www.aibbt.com/)国内第一家人工智能门户,微信公众号:aibbtcom ...
- PyTorch官方中文文档:torch.optim 优化器参数
内容预览: step(closure) 进行单次优化 (参数更新). 参数: closure (callable) –...~ 参数: params (iterable) – 待优化参数的iterab ...
- [pytorch] PyTorch Hook
PyTorch Hook¶ 为什么要引入hook? -> hook可以做什么? 都有哪些hook? 如何使用hook? 1. 为什么引入hook?¶ 参考:Pytorch中autogra ...
- 从头学pytorch(二) 自动求梯度
PyTorch提供的autograd包能够根据输⼊和前向传播过程⾃动构建计算图,并执⾏反向传播. Tensor Tensor的几个重要属性或方法 .requires_grad 设为true的话,ten ...
- pytorch 查看中间变量的梯度
pytorch 为了节省显存,在反向传播的过程中只针对计算图中的叶子结点(leaf variable)保留了梯度值(gradient).但对于开发者来说,有时我们希望探测某些中间变量(intermed ...
- Pytorch入门中 —— 搭建网络模型
本节内容参照小土堆的pytorch入门视频教程,主要通过查询文档的方式讲解如何搭建卷积神经网络.学习时要学会查询文档,这样会比直接搜索良莠不齐的博客更快.更可靠.讲解的内容主要是pytorch核心包中 ...
- PyTorch官方中文文档:PyTorch中文文档
PyTorch中文文档 PyTorch是使用GPU和CPU优化的深度学习张量库. 说明 自动求导机制 CUDA语义 扩展PyTorch 多进程最佳实践 序列化语义 Package参考 torch to ...
- PyTorch官方中文文档:torch
torch 包 torch 包含了多维张量的数据结构以及基于其上的多种数学操作.另外,它也提供了多种工具,其中一些可以更有效地对张量和任意类型进行序列化. 它有CUDA 的对应实现,可以在NVIDIA ...
- [Pytorch]Pytorch中tensor常用语法
原文地址:https://zhuanlan.zhihu.com/p/31494491 上次我总结了在PyTorch中建立随机数Tensor的多种方法的区别. 这次我把常用的Tensor的数学运算总结到 ...
随机推荐
- Zookeeper服务注册与发现原理浅析
了解Zookeeper的我们都知道,Zookeeper是一种分布式协调服务,在分布式应用中,主要用来实现分布式服务的注册与发现以及分布式锁,本文我们简单介绍一下Zookeeper是如何实现服务的注册与 ...
- Acwing-279-自然数拆分(背包)
链接: https://www.acwing.com/problem/content/281/ 题意: 给定一个自然数N,要求把N拆分成若干个正整数相加的形式,参与加法运算的数可以重复. 求拆分的方案 ...
- mysql 8.0.18 手工安装记录
mysql 8.0.18 手工安装记录 为了日常方便,特记录如下. 一.安装系统依赖包 #.系统依赖包安装 yum -y install make gcc-c++ cmake bison-devel ...
- @ApiParam和@RequestHeader接收参数的区别
一.代码 @ApiOperation(value = "查询学生信息") @GetMapping(value = "/select/student") @Api ...
- [转] Linux环境变量配置文件以及启动顺序
转自:https://blog.csdn.net/bjnihao/article/details/51775854 一.环境变量配置文件: 对所有用户都起作用 /etc/profile /etc/pr ...
- 并行计算基础(1)(GPU架构介绍)
一.常用术语 Task:任务.可以完整得到结果的一个程序,一个程序段或若干个程序段.例如搬砖. Parallel Task:并行任务.可以并行计算的任务.多个人搬砖. Serial Execution ...
- IE8 浏览器文本模式变为杂项(quirks)页面变形的解决方法
IE8 浏览器文本模式(document.documentMode)变为杂项(quirks)页面变形的解决方法. 正常情况下 document.documentMode 输出为8,而变为杂项之后doc ...
- HDU 6669 Game
hdu题面 解题思路 首先我们要选一个起点,这个起点应该在第一个区间内,然后再看第二个区间在左边还是右边以便移动,但转念一想,我们可以把起点直接选在前一堆区间的交集上,于是思路就有了--依次把所有区间 ...
- 2-sat基础详解
(大量引用<2-SAT解法浅析 -by 华中师大一附中 赵爽><由对称性解2-SAT问题> Great_Influence关于P4782 [模板]2-SAT 问题的题解.在此对 ...
- JPA 开发写SQL时候遇见的困难点
官方文档 https://docs.spring.io/spring-data/jpa/docs/1.11.16.RELEASE/reference/html/#repositories.specia ...