在Backbone不变的情况下,若显存有限,如何增大训练时的batchsize?

大家好,我是灿视。

这道题是之前在我之前的那个AttackOnAIer上发过的一题,来自群友在商汤面试的真题,今天重新梳理下,供大家参考。

问: 在Backbone不变的情况下,若显存有限,如何增大训练时的batchsize?

现在给出一些回答,供各位参考哈~
如果各位有别的想法,可以在留言区留言哈!

使用Trick,节省显寸

  • 使用inplace操作,比如relu激活函数,我们可以使用inplace=True
  • 每次循环结束时候,我们可以手动删除loss,但是这样的操作,效果有限。
  • 使用float16混合精度计算,据有关人士测试过,使用apex,能够节省将近50%的显存,但是还是要小心mean与sum会溢出的操作。
  • 训练过程中的显存占用包括前向与反向所保存的值,所以在我们不需要bp的forward的时候,我们可以使用torch.no_grad()。
  • torch.cuda.empty_cache() 这是del的进阶版,使用nvidia-smi 会发现显存有明显的变化。但是训练时最大的显存占用似乎没变。大家可以试试。
  • 如使用将batchsize=32这样的操作,分成两份,进行forward,再进行backward,不过这样会影响batchnorm与batchsize相关的层。yolo系列cfg文件里面有一个参数就是将batchsize分成几个sub batchsize的。
  • 使用pooling,减小特征图的size,如使用GAP等来代替FC等。
  • optimizer的变换使用,理论上,显寸占用情况 sgd<momentum<adam,可以从计算公式中看出有额外的中间变量。

从反传角度考虑

  • 《Training Deep Nets with Sublinear Memory Cost》

参考陈天奇老师的文章。在训练的时候,CNN的主要开销来自于储存用于计算 backward 的 activation,一般的 workflow 是这样的:

对于一个长度为 N 的 CNN,需要 O(N) 的内存。这篇论文给出了一个思路,每隔 sqrt(N) 个 node 存一个 activation,中需要的时候再算,这样显存就从 O(N) 降到了 O(sqrt(N))。


对于越深的模型,这个方法省的显存就越多,且速度不会明显变慢。其中 p y t o r c h pytorch pytorch本身也有 t o r c h . u t i l s . c h e c k p o i n t torch.utils.checkpoint torch.utils.checkpoint这样的函数实现一样的功能。

补充

对于题目而言,是为了增大 B a t c h Batch Batch s i z e size size。同样,如果显存真的特别有限,我们怎么办呢?

我们也可以将小 b a t c h batch batch s i z e size size的数据达到大 b a t c h batch batch s i z e size size的效果。

举个例子,假设由于显存限制 D a t a L o a d e r DataLoader DataLoader b a t c h batch batch s i z e size size只能设为4,想要通过梯度累积实现 b a t c h batch batch s i z e size size等于16,这需要进行四次迭代,每次迭代的 l o s s loss loss除以4,这里给一个参考代码:


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

首先,获取 l o s s loss loss, 在计算当前梯度,不过我们暂先不清空梯度,是梯度加在已有梯度上。当梯度累加到了一定次数之后,使用 o p t i m i z e r . s t e p ( ) optimizer.step() optimizer.step()将累计的梯度来更新参数。

一定条件下, b a t c h batch batch s i z e size size越大训练效果越好,梯度累加则实现了 b a t c h batch batch s i z e size size的变相扩大。但,增大 b s bs bs的同时,需要我们适当方法学习率。

不过使用 a c c u m u l a t i o n _ s t e p = 8 accumulation\_step=8 accumulation_step=8的效果是不如真实的 b a t c h batch batch s i z e size size放大8倍。因为增大 8 8 8 b a t c h batch batch s i z e size size的图片,其 s u n n i n g _ m e a n sunning\_mean sunning_mean r u n n i n g _ v a r running\_var running_var更加准确。

大家好,我是灿视。目前是位算法工程师 + 创业者 + 奶爸的时间管理者!

我曾在19,20年联合了各大厂面试官,连续推出两版《百面计算机视觉》,受到了广泛好评,帮助了数百位同学们斩获了BAT等大小厂算法Offer。现在,我们继续出发,持续更新最强算法面经。
我曾经花了4个月,跨专业从双非上岸华五软工硕士,也从不会编程到进入到百度与腾讯实习。
欢迎加我私信,点赞朋友圈,参加朋友圈抽奖活动。如果你想加入<百面计算机视觉交流群>,也可以私我。在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值