前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PyTorch中的梯度累积

PyTorch中的梯度累积

作者头像
mathor
发布2021-07-28 10:23:22
1.3K0
发布2021-07-28 10:23:22
举报
文章被收录于专栏:mathormathor

我们在训练神经网络的时候,超参数batch_size的大小会对模型最终效果产生很大的影响,通常的经验是,batch_size越小效果越差;batch_size越大模型越稳定。理想很丰满,现实很骨感,很多时候不是你想增大batch_size就能增大的,受限于显存大小等因素,我们的batch_size往往只能设置为2或4,否则就会出现"CUDA OUT OF MEMORY"(OOM)报错。如何在有限的计算资源下,采用更大的batch_size进行训练,或者达到和大batch_size一样的效果?这就是梯度累加(Gradient Accumulation)技术了

以PyTorch为例,正常来说,一个神经网络的训练过程如下:

代码语言:javascript
复制
for idx, (x, y) in enumerate(train_loader):
    pred = model(x)
    loss = criterion(pred, y)
    
    loss.backward()
    optimizer.step()
    optimizer.zero_grad()
    
    if (idx+1) % eval_steps == 0:
        eval()

如果你想设置batch_size=64结果爆显存了,那么不妨设置batch_size=16,然后定义一个变量accum_steps=4,每个mini-batch仍然正常前向传播以及反向传播,但是反向传播之后并不进行梯度清零,因为PyTorch中的loss.backward()执行的是梯度累加的操作,所以当你调用4次loss.backward()后,这4个mini-batch的梯度都会累加起来。但是,我们需要的是一个平均的梯度,或者说平均的损失,所以我们应该将每次计算得到的loss除以accum_steps

代码语言:javascript
复制
accum_steps = 4

for idx, (x, y) in enumerate(train_loader):
    pred = model(x)
    loss = criterion(pred, y)
    
    # normlize loss to account for batch accumulation
    loss = loss / accum_steps
    
    loss.backward()
    
    if (idx+1) % accum_steps == 0 or (idx+1) == len(train_loader):
        optimizer.step()
        optimizer.zero_grad()
        if (idx+1) % eval_steps:
            eval()

总的来说,梯度累加就是计算完每个mini-batch的梯度后不清零,而是做梯度的累加,当累加到一定的次数之后再更新网络参数,然后将梯度清零。通过这种延迟更新的手段,可以实现与采用大batch_size相近的效果

References
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • References
相关产品与服务
批量计算
批量计算(BatchCompute,Batch)是为有大数据计算业务的企业、科研单位等提供高性价比且易用的计算服务。批量计算 Batch 可以根据用户提供的批处理规模,智能地管理作业和调动其所需的最佳资源。有了 Batch 的帮助,您可以将精力集中在如何分析和处理数据结果上。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档