最近在训练微调bert预训练模型的时候,gpu内存老是不足,跑不了一个epoch就爆掉了,在网上来来回回找了很多资料,这里把一些方法总结一下:
半精度训练
半精度float16比单精度float32占用内存小,计算更快,但是半精度也有不好的地方,它的舍入误差更大,而且在训练的时候有时候会出现nan的情况(我自己训练的时候也遇到过,解决方法可以参考我的另一篇博客)。
模型在gpu上训练,模型和输入数据都要.cuda()一下,转成半精度直接input.half()和model.half() 就行了。
另外,还有混合精度训练,可以参考:https://zhuanlan.zhihu.com/p/103685761
累积梯度
一般我们在训练模型的时候都是一个batch更新一次模型参数,但是在gpu内存不够的时候batchsize就不能设的比较大,但是batchsize比较小又影响模型的性能和训练速度。
这个时候累积梯度的作用就出来了,累积梯度就是让模型累积几个batch的梯度之后再更新参数,相当于变相增大batchsize。具体的实现代码如下:
# 梯度累积,相当于增大batch_size
loss.backward() # 计算梯度
accumulation_steps = 4
if ((i + 1) % accumulation_steps) ==