赞
踩
- num_steps_all = len(train_loader) // configs.gradient_accumulation_steps * configs.epochs
- warmup_steps = int(num_steps_all * configs.warmup_proportion)
- scheduler = get_linear_schedule_with_warmup(optimizer, num_warmup_steps=warmup_steps, num_training_steps=num_steps_all)
num_steps_all为更新次数,warmup_steps表示全部训练步骤的前10%,在这一阶段,学习率线性增加;此后,学习率线性衰减。
-
-
- 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

总结来说:梯度累加就是,每次获取1个batch的数据,计算1次梯度,梯度不清空,不断累加,累加一定次数后,根据累加的梯度更新网络参数,然后清空梯度,进行下一次循环。

一定条件下,batchsize越大训练效果越好,梯度累加则实现了batchsize的变相扩大,如果accumulation_steps为8,则batchsize '变相' 扩大了8倍,是我们这种乞丐实验室解决显存受限的一个不错的trick,使用时需要注意,学习率也要适当放大。
gradient_accumulation_steps通过累计梯度来解决本地显存不足问题。
假设原来的batch_size=6,样本总量为24,gradient_accumulation_steps=2
那么参数更新次数=24/6=4
现在,减小batch_size=6/2=3,参数更新次数不变=24/3/2=4
在梯度反传时,每gradient_accumulation_steps次进行一次梯度更新,之前照常利用loss.backward()计算梯度。
如果一个模型是需要多卡并行训练以开大batchsize,而你没有这么多卡。那可以利用梯度累加的性质,在每次反向传播后,先不进行优化器的迭代,多累积几个batch的梯度后,再进行优化器迭代、梯度清零的操作。这样的话,即使使用单卡也可以达到多卡开大batch_size的效果哦~虽然训练会慢一点就是了,但是对卡的要求大大降低了。
作者:知乎用户
链接:https://www.zhihu.com/question/303070254/answer/647888393
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。