Keras-ImageDataGenerator的flow()中的batch_size参数,Model.fit()中的batch_size和steps_per_epoch参数的关系

明确概念

Model.fit方法中的batch_size和steps_per_epoch参数

Model.fit(
    x=None,
    y=None,
    batch_size=None,
    epochs=1,
    validation_data=None,
    steps_per_epoch=None,
    validation_steps=None
)

官方的解释是这样子的:

batch_size

batch_size: Integer or None. Number of samples per gradient update.
If unspecified, batch_size will default to 32.
Do not specify the batch_size if your data is in the form of datasets, generators, or keras.utils.Sequence instances (since they generate batches).
来源:https://keras.io/api/models/model_training_apis/#fit-method

翻译过来就是

batch_size:整数或None。每个梯度更新用到的的样本数量。
如果未指定,batch_size将默认为32。
如果数据是数据集 (datasets)、生成器 (generators) 或keras.utils.Sequence实例的形式 (因为它们生成批量),则不要指定batch_size。

steps_per_epoch

steps_per_epoch:
Integer or None.
Total number of steps (batches of samples) before declaring one epoch finished and starting the next epoch.
When training with input tensors such as TensorFlow data tensors, the default None is equal to the number of samples in your dataset divided by the batch size, or 1 if that cannot be determined.
If x is a tf.data dataset, and ‘steps_per_epoch’ is None, the epoch will run until the input dataset is exhausted.
When passing an infinitely repeating dataset, you must specify the steps_per_epoch argument.
If steps_per_epoch=-1 the training will run indefinitely with an infinitely repeating dataset. This argument is not supported with array inputs. When using tf.distribute.experimental.ParameterServerStrategy: * steps_per_epoch=None is not supported.
来源:https://keras.io/api/models/model_training_apis/#fit-method

翻译过来就是
整数或者为None。
在一个epoch结束并开始下一个epoch之前的总步骤 (step) 数 (数据的批次/batch size)。接下来将称为每个epoch的steps数量
使用TensorFlow数据张量 (tensor) 等输入张量进行训练时,默认值None等于数据集中样本的数量除以batch size,如果无法确定,则为 1。
如果x是tf.data数据集,而’steps_per_epoch’为None时,epoch将一直运行,直到输入数据集耗尽。
当数据集是一个无限重复的数据集 (infinitely repeating dataset) 时,必须指定steps_per_epoch参数。
如果steps_per_epoch=-1,将会无限地运行无限重复的数据集。此参数不支持数组输入。
当使用tf.distribute.experimental.ParameterServerStrategy时不支持steps_per_epoch=None。

向上取整的目的是为了舍弃最后不满足batch_size的数据
————————————————
版权声明:本文为CSDN博主「zhangphil」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zhangphil/article/details/103438558


ImageDataGenerator的flow方法中的batch_size参数

flow(
    x, 
    y=None, 
    batch_size=32, 
    shuffle=True
)

问题:在使用ImageDataGenerator的情况下,flow()中的batch_size和Model.fit()中的batch_size有什么关系呢?

为了解决这个问题,先明确在使用和不使用ImageDataGenerator的情况下,各个参数是如何计算的 (这里使用的是CIFAR100数据集,training set的大小是45000):

不使用ImageDataGenerator,不指定steps_per_epoch和batch_size参数

此时默认batch size=32。

history = model.fit(X_train, y_train,
                    validation_data=(X_valid, y_valid),
                    epochs=200)

每个epoch的steps是1407,1407=45000/32并向上取整,即**training set的大小/batch size并向上取整**。


使用ImageDataGenerator但不指定steps_per_epoch参数

每个epoch的steps是ImageDataGenerator的flow()生成的迭代器的长度,此时,指定batch_size参数是没有作用的。

# Data augmentation
train_datagen = tf.keras.preprocessing.image.ImageDataGenerator(
    horizontal_flip=True,
    fill_mode='nearest')
valid_datagen = tf.keras.preprocessing.image.ImageDataGenerator(
    horizontal_flip=True, 
    fill_mode='nearest')


# flow()生成的迭代器
train_gen = train_datagen.flow(X_train, y_train_cate, 
                               batch_size=256)
valid_gen = valid_datagen.flow(X_valid, y_valid_cate, 
                               batch_size=256)


# flow()生成的迭代器的长度
print(len(train_gen))
print(len(valid_gen))

使用ImageDataGenerator并指定steps_per_epoch参数

如果要改变每个epoch的steps数量,需要指定steps_per_epoch参数,但要注意的是,steps_per_epoch不能大于迭代器的长度,否则会报如下错误:Your input ran out of data; interrupting training. Make sure that your dataset or generator can generate at least steps_per_epoch * epochs batches (in this case, 35600 batches). You may need to use the repeat() function when building your dataset.


现在回到最初的问题

在使用ImageDataGenerator的情况下,flow()中的batch_size和Model.fit()中的batch_size有什么关系呢?

为了解决这个问题,基于具体的数据 (CIFAR100数据集,training set的大小是45000) 做了实验,结果如下:

  • 不使用ImageDataGenerator,在Model.fit()中指定batch_size参数:
Model.fit()的batch_size参数每个epoch中steps数量
321407
64704
128352
256176
  • 使用ImageDataGenerator,在flow()中指定batch_size参数:
ImageDataGenerator的flow()的batch_size参数flow()生成的迭代器的长度
321407
64704
128352
256176

结论

两个表格是相同的,当使用ImageDataGenerator时,如果将Model.fit()中的steps_per_epoch设置成ImageDataGenerator的flow()生成的迭代器的长度,则flow()中的batch_size参数 = Model.fit()中的batch_size参数

附加一些关于batch_size的总结 (引用)

转载并总结一些文章

batch size的增大和缩小

在合理范围内,增大 Batch_Size 有何好处?

  • 内存利用率提高了,大矩阵乘法的并行化效率提高。
  • 跑完一次 epoch(全数据集)所需的迭代次数减少,对于相同数据量的处理速度进一步加快。
  • 在一定范围内,一般来说 Batch_Size 越大,其确定的下降方向越准,引起训练震荡越小。

盲目增大 Batch_Size 有何坏处?

  • 内存利用率提高了,但是内存容量可能撑不住了。
  • 跑完一次epoch(全数据集)所需的迭代次数减少,要想达到相同的精度,其所花费的时间大大增加了,从而对参数的修正也就显得更加缓慢。
  • Batch_Size 增大到一定程度,其确定的下降方向已经基本不再变化。

来源:https://zhuanlan.zhihu.com/p/277487038
来源:https://www.zhihu.com/question/32673260

总结

  • batch数太小,而类别又比较多的时候,真的可能会导致loss函数震荡而不收敛,尤其是在你的网络比较复杂的时候。
  • 随着batchsize增大,处理相同的数据量的速度越快。
  • 随着batchsize增大,达到相同精度所需要的epoch数量越来越多。
  • 由于上述两种因素的矛盾, Batch_Size 增大到某个时候,达到时间上的最优。
  • 由于最终收敛精度会陷入不同的局部极值,因此 Batch_Size 增大到某些时候,达到最终收敛精度上的最优。
  • 过大的batchsize的结果是网络很容易收敛到一些不好的局部最优点。同样太小的batch也存在一些问题,比如训练速度很慢,训练不容易收敛等。

方差

  • 样本量少的时候会带来很大的方差,而这个大方差恰好会导致我们在梯度下降到很差的局部最优点(只是微微凸下去的最优点)和鞍点的时候不稳定,一不小心就因为一个大噪声的到来导致炸出了局部最优点。
  • 与之相反的,当样本量很多时,方差很小,对梯度的估计要准确和稳定的多,因此反而在差劲的局部最优点和鞍点时反而容易自信的呆着不走了,从而导致神经网络收敛到很差的点上,跟出了bug一样的差劲。

————————————————
版权声明:本文为CSDN博主「zqx951102」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zqx951102/article/details/88918948

batch size大小的选择

  • 8的倍数
  • 稍微大一点(一般而言)
  • 选择一部分数据,跑几个batch看看你的loss是不是在变小,选择一个合适的就可以了。
  • Batch size设置以喂饱你的硬件为主要标准。只要显卡塞得下,首先挑大的。
  • 当感觉训练时噪音不够时,比如收敛碰到鞍点或者局部最小值时,调小batch size。(很少会碰到)
  • 当感觉训练时噪音太大时,调大batch size到喂饱硬件(因为2很少碰到,这也很少做),再不行就调小learning rate,也可以直接调小learning rate。
  • 综合起来用就是常见的带learning rate下降的sgd。开始时依赖batch带来的噪音快速下降,接下来使用较低的learning rate消除这些噪音寻求稳定收敛。一般而言只要batch不太大,样本里的噪音总是够用的
  • 对于大批量训练场景,我们需要确保使用较大的 batch size 训练能够在相同 epochs 前提下获得与较小的 batch size 相近的测试准确度。这里我们之所以保持 epochs 数量不变,是因为从统计学角度来讲,一个 epoch 代表着算法与整体数据集接触一次 ; 而从计算角度来讲,固定 epochs 数量意味着保证浮点运算次数不变。
  • 小的batch size能有效避免样本中的冗余信息。
  • 大的batch能更充分利用GPU。
    ————————————————
    版权声明:本文为CSDN博主「whitenightwu」的原创文章,遵循CC 4.0
    BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/wydbyxr/article/details/84855489

收藏一些关于batch_size的好文章:

有关于batch size的疑惑

1

这个链接中,有人提到:

If your dataset is huge, as it is usually the case when you need to use generators, you would probably like to decay the learning rate within a single epoch (since it includes a big number of data). This can be achieved by setting steps_per_epoch to a value that is less than num_samples // batch_size without affecting the overall number of training epochs of your model. Imagine this case as using mini-epochs within your normal epochs to change the learning rate because your loss has stagnated.

意思是:
如果数据集很大 (当需要使用生成器即generator时),那么可能会需要在一个epoch内降低学习率 (learning rate)。这可以通过设置steps_per_epoch < num_samples//batch_size来实现,而不会影响到训练一个模型需要的epoch总数。把这种情况想象成,当损失停滞时,使用了mini-epochs来改变学习率。

我不是很理解为啥是steps_per_epoch < num_samples//batch_size才会在一个epoch里面降低学习率?如果使用callback.ReduceLROnPlateau()的话,即使不满足steps_per_epoch < num_samples//batch_size,应该也会在一个epoch内降低?

2

关于batch size和学习率的关系还不是很懂,有待探究

如果有什么说错的地方还请指正,欢迎一起讨论~

  • 17
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值