一、为什么会有batch_size参数 经常做训练的童鞋们都知道,batch_size是一个很重要的超参数,每次训练支取batch_size个数据集进行训练,那么,为啥不取全部呢,答案可想而知,应为内存不够呀,放不下呀,小数据集还好,内存勉强够,勉强放的下,但是花费大量的时间加载了数据后,训练了一个epoch之后,发现参数不对,需要重新调参,然后中断训练,花1s调了个参数,花费2h加载了数据,不累么?!所以需要batch_size这个参数。
虽然全部的数据集可以更好的确定样本总体的方向,但是一次性处理整个数据集,是非常不明智的!
二、batch_size对学习的影响 使用batch_size之后,就变成批梯度下降法(min-batches learning),如果数据集足够充分,那么使用一半(甚至少得多)的数据算出来的梯度与全部数据集训练出来的梯度是几乎一样的。那么batch_size多大合适呢?
当batch_size=1时,也即是每次只取一个样本进行训练,每次只根据一个样本的梯度选择方向进行下降,每个样本身上个体差异大于样本的共性,因此梯度修正的方向,整体来说是朝着正确的方向,但是每一步走的都很杂乱,走了很多弯路,因此收敛速度很慢。
文章图片
合理的范围内,增加batch_size的好处:
- 内存利用率提高了,大矩阵乘法的并行化效率提高。
- 加快数据的处理速度
- 在一定范围内,一般batch_size越大,其确定的下降方向越准,训练震荡越小。
- 跑完一次epoch所需要的迭代次数减少,参数的更新次数也减少了,因此精度也会收到影响
- batch_size增大到一定程度,其确定的下降方向已经基本不再变化
for i, (inputs, labels) in enumerate(trainloader):
optimizer.zero_grad()# 梯度清零
outputs = net(inputs)# 正向传播
loss = criterion(outputs, labels)# 计算损失
loss.backward()# 反向传播,计算梯度
optimizer.step()# 更新参数
加入梯度累加之后的代码:
for i, (inputs, labels) in enumerate(trainloader):
outputs = net(inputs)# 正向传播
loss = criterion(outputs, labels)# 计算损失函数
loss = loss / accumulation_steps# 损失标准化
loss.backward()# 反向传播,计算梯度
if (i+1) % accumulation_steps == 0:
optimizer.step()# 更新参数
optimizer.zero_grad()# 梯度清零
修改点有两个:
1、loss 变为 loss / accumulation_steps
2、 accumulation_steps 之后再更新
四、梯度累加如何增加batch_size 【实践|增加batch_size的一种方法(梯度累加)】因为你每次求出来的loss是一个批次内预测和标签误差的平均值,当你用梯度累计的时候求出几个批次的平均值,当然要再平均一下保证它等效大批次的平均值。
推荐阅读
- 神经网络|一个神经网络有多少个神经元()
- 神经网络|复数神经网络_如果神经网络状态为复数会发生什么()
- 技术知识|为什么说BP神经网络就是人工神经网络的一种()
- 机器学习|什么是卷积神经网络
- 深度学习|卷积神经网络
- 人工智能|十年AI谁“最能打”(何恺明最佳论文“刷”状元,谷歌机构排名第一)
- 姿态估计|人体姿态估计综述
- AI章|深度篇——人脸识别(一) ArcFace 论文 翻译
- python|CUDA11.4、CUDNN、Pytorch安装