如何在Keras中正确使用ImageDataGenerator完成数据增强与模型训练
疑问1:未指定steps_per_epoch仍可正常运行的原因
你用flow_from_directory返回的DirectoryIterator不是无状态的无限生成器,它内部会遍历目标目录统计所有图片的总数量,存储在实例的n属性中,同时实现了__len__方法。当你把它传入model.fit时,Keras会自动读取它的长度,按steps_per_epoch = 总样本数 // batch_size(有余数则向上取整)自动推断步数,只有当你传入自定义的、没有实现长度方法的纯无限生成器时,才需要手动指定该参数。
疑问2:生成批次的内容组成
默认配置下,批次中所有样本都是原始图像经过随机增强后的结果,不会包含未增强的原始图像。ImageDataGenerator的逻辑是每读取一张原始图像,就按照你设置的增强参数做一次随机变换,直接输出变换后的结果,每一轮遍历原始数据集时,同一张原始图的增强结果都是随机的,不会重复。
疑问3:实现需求的配置方法
你需要的效果可以通过以下步骤实现:
- 首先创建两个
ImageDataGenerator实例,两个生成器都指向同一个训练集目录,设置相同的seed保证样本顺序对齐:- 无增强实例:仅保留
rescale参数,用于输出原始归一化后的图像 - 增强实例:保留你现在所有的增强参数,用于输出增强后的图像
- 无增强实例:仅保留
- 手动指定
steps_per_epoch参数控制每轮遍历次数:- 先获取单轮遍历原始数据集的默认步数:
default_steps = len(train_aug_ds) - 如果你需要每轮遍历2次(1次原始+1次增强),就设置
steps_per_epoch = default_steps * 2
- 先获取单轮遍历原始数据集的默认步数:
- 可以用
tf.data.Dataset把两个生成器的输出拼接,完整示例逻辑如下:
import tensorflow as tf # 无增强生成器 train_plain = ImageDataGenerator(rescale=1./255) train_plain_ds = train_plain.flow_from_directory(directory='./train', target_size=image_size, batch_size=batch_size, seed=42) # 增强生成器 train_aug_ds = train_aug.flow_from_directory(directory='./train', target_size=image_size, batch_size=batch_size, seed=42) # 转为tf.data.Dataset并合并 ds_plain = tf.data.Dataset.from_generator(lambda: train_plain_ds, output_types=(tf.float32, tf.float32), output_shapes=((None, *image_size, 3), (None, num_classes))) ds_aug = tf.data.Dataset.from_generator(lambda: train_aug_ds, output_types=(tf.float32, tf.float32), output_shapes=((None, *image_size, 3), (None, num_classes))) train_combined_ds = tf.data.Dataset.sample_from_datasets([ds_plain, ds_aug]) # 训练配置 model.fit( train_combined_ds, epochs=150, steps_per_epoch = default_steps * 2, validation_data=valid_aug_ds, )
内容的提问来源于stack exchange,提问作者dosvarog
相关产品推荐
相关产品推荐

