我们先来看一张图:
这张图是由四种batch_size训练得到的结果,有1、4、8、32四种,如果让你去对号入座,你会如何排序选择呢?
根据一般的经验来讲,选择大的batch_sizie,那么对于一个epoch来讲,batch的数目(step=epoch内的样本数//batch_size)就会变少,自然而然训练速度就会加快,因为一个batch只会得到基于batch_size数量的平均值,无论batch_sizi多大,只能得到1个均值。与之对应的,选择小的Batch_size,则会增加训练次数,训练速度变慢。
也就是说,如果有1000个样本,batch_size=1,10,100,对应的训练次数分别是:1000,100,10,所需要训练的时间逐步递减。
接着上面的,如果选择了大的batch_size,则在内存空间中,如果GPU的话,则采取矩阵级的并行计算,这些计算过程都将存储在GPU内存中,如果你的GPU显存够大,那么在一定程度上是可以选择较大的batch_size(当然也要结合数据集的属性),如果小的显存选择了大的batch_size,那么在训练过程中,会出现显存溢出、内存空间不够的问题。
这在一定程度上,也属于“空间换时间”的一种方法吧。
梯度下降是一个常谈的问题,总而言之就是:
根据训练结果与实际结果的差值,得到Loss损失函数,并用不同的梯度下降方法使整个模型Loss损失逐渐变小的过程。
紧接着就是梯度下降常谈的问题:
优化方法与学习率的选择(这个时候Batch_size已经结束工作,已经产生了唯一的loss,后续工作需[SGD/Adam, w,b]参与)。
不过,这里主要是谈batch_size对训练的波动影响。
如果选择了大的batch_size,那么得到的这个损失函数则是代表一批大的数据的“均值损失”。
现在,思考一个问题,这样的“均值损失”,对于batch中的样本来讲,是好还是坏?
假如现在有:东、南、西、北四个样本,他们对于loss的结果分别为:
东:3.0 西:2.0 南:10.0 北:3.0
如果是线性的损失函数,均值损失可能为:18/4=4.25k+b
如果是非线性的损失函数,均值损失可能为:f(4.25)
可以看出,这样能够极大的避免batch_样本中的个别样本所带来的loss影响,如:南,10.0。
这样来看,每个样本期望Loss是属于自己的Loss,这样可能会引起loss的参差不齐,梯度下降的幅度也会参差不齐,产生振荡。
而大批次的样本训练,就会减缓loss振荡的效应,使整个样本集朝着稳定的loss下降速率(不是下降方向,个人理解)。
以下图为例:
如果说波动振荡较大,是不是说选的batch_size不够大,通用特征不够明显,不同的batch产生不同的结果,导致loss损失随之抖动?
如果batch_size有两个选项:8,32,那么你认为哪个是8,哪个是32。
在本次VGG16的训练过程中(迁移二分类),结果可能与你预料的相反:
第一个是8,第二个是32。
为什么会出现这样的问题,batch_size取得大不应该是更平滑吗?
下面就引出了重点---数据的特征与噪声。
=============>>
在小的时候,就学过一句话“即使是再动听的音乐,在别人心中也可能是一种噪声。”
对于数据集中的样本与模型训练的关系来讲,其实是一样的道理。
数据对于模型,只有两样起作用:特征与噪声。
特征是我们要模型去学习的主要内容。
噪声是我们要模型去弱化的主要内容。
想象一个有趣的问题:
对于模型来讲,如果把特征与噪声认反了,会出现怎样的结果?
就是说,我每次学到噪声的内容更多一些,模型根据每次的噪声得到的值与真值做loss损失计算,每次的损失自然是会波动极大。这个时候是与你选batch_size的大小无关的,因为,不管batch_size如何选,都是噪声结果在做loss计算,而噪声自然是无规律可循的。
模型本身是无认知能力的,它只会结合多特征与真值的关系,进行判断与权重更新,只会根据输入的tensor做回归计算。
模型只会让每次输入的tensor结果,更加去接近真实值。
例如:
现在输入的是无规律的噪声X-1,X-2:
输入的是tensor=>X-1,真值为CLASS-1,得到Loss-X1,根据下降方法,找到一个极小点,更新权重W。
输入的是tensor=>X-2,真值为CLASS-2,得到Loss-X2,根据下降方法,找到一个极小点,更新权重W。
这样的结果会是什么,模型学不到任何东西,也没有参考意义。
现在输入的是有规律的噪声X-1,X-2:
输入的是tensor=>X-1,真值为CLASS-1,得到Loss-X1,根据下降方法,找到一个极小点,更新权重W。
输入的是tensor=>X-2,真值为CLASS-2,得到Loss-X2,根据下降方法,找到一个极小点,更新权重W。
这个时候,就会得到一个结果:将噪声认为是特征。
想象一下,如果有两条狗,CLASS-A,CLASS-B,他俩唯一的区别就是眼睛颜色不同,那么对于我们人来讲,除了眼睛之外的“特征”全为噪声,我们只需要根据眼睛来判断就好了。
一般的,对于模型来讲,如果输入的:
(噪声=背景,以下统称噪声)
1.规律噪声>特征:
对于卷积网络来讲,规律的噪声与特征混合在一起,卷积过后,可能仍包含规律的噪声与特征,网络可能会根据真值,来减弱噪声部分的权重,增强特征部分的权重,这个时候仍是有学习能力的。
2.规律噪声>>特征:
这个时候,就比较恐怖了,就好比一张公园的图片,里面有狗或者猫,你让我去判断这张图片是狗还是猫!
如果数据集提前不去噪声,这个时候再加上一个较大的batch_size会有什么样的结果?
====>
那么损失计算的将是占比较大的“噪声结果的均值损失”,这完全和真正想学的特征没有关系了。
结果一定会出现损失与准确率来回波动的情况,因为:规律的噪声一成不变,而你的标签值却是不同的,反复学习,模型无法判别。
而开头放置的图片,就是在这样的场景下产生的,他们的batch_size大小分别是(从左到右,从上到下):1,4,8,32。
这里我们暂不谈数据集对模型训练的影响,只谈batch_size的影响。
对于一个正常的数据集,我们需要去衡量噪声与特征的占比情况,并以此来权衡batch_size的取值大小,因为,这关乎到模型的收敛情况。
必要情况下,削减数据的噪声占比,修改模型的输入-学习方式,并以此扩大batch_size,学到更好的泛化特征,增加模型训练速度。
总而言之,大的batch_size是会泛化特征,但是,要清楚,泛化的是谁的特征?噪声还是真实特征?
batch_size的选择是一个技术活,消耗时间、占用内存、收敛情况、收敛准确率等,都需要结合自身经验以及场景去做综合判断,不能走网上的教条规律。
--本次仅记录日常训练出现的batch_size波动问题。