如何在 Keras 中正确使用 ImageDataGenerator?
How to correctly use ImageDataGenerator in Keras?
我最近在 Keras 中玩数据扩充,我正在使用基本的 ImageDataGenerator。我通过艰难的方式了解到它实际上是一个生成器,而不是迭代器(因为 type(train_aug_ds)
给出 <class 'keras.preprocessing.image.DirectoryIterator'>
我认为它是一个迭代器)。我也查看了一些关于使用它的博客,但他们没有回答我所有的问题。
所以,我这样加载了我的数据:
train_aug = ImageDataGenerator(
rescale=1./255,
horizontal_flip=True,
height_shift_range=0.1,
width_shift_range=0.1,
brightness_range=(0.5,1.5),
zoom_range = [1, 1.5],
)
train_aug_ds = train_aug.flow_from_directory(
directory='./train',
target_size=image_size,
batch_size=batch_size,
)
为了训练我的模型,我执行了以下操作:
model.fit(
train_aug_ds,
epochs=150,
validation_data=(valid_aug_ds,),
)
它奏效了。我有点困惑它是如何工作的,因为 train_aug_ds
是生成器,所以它应该提供无限大的数据集。文档说:
When passing an infinitely repeating dataset, you must specify the steps_per_epoch argument.
我没做过,但它起作用了。它是否以某种方式推断出步数?另外,它是只使用增强数据,还是批量使用非增强图像?
所以基本上,我的问题是如何正确使用这个生成器和函数 fit
来获得我训练集中的所有数据,包括原始的、非增强的图像和增强的图像,并循环使用它几个times/steps(目前看来每个 epoch 只执行一步)?
我认为文档可能非常混乱,而且我认为行为会因您的 Tensorflow 和 Keras 版本而异。例如,在这个 , the user is describing the exact behavior you are expecting. Generally, the flow_from_directory()
method allows you to read the images directly from a directory and augment them while your model is being trained and as already stated 中,它在每个时期对每个文件夹中的每个样本进行迭代。使用以下示例,您可以通过查看进度条中每个时期的步数来检查是否属于这种情况(在 TF 2.7 上):
import tensorflow as tf
BATCH_SIZE = 64
flowers = tf.keras.utils.get_file(
'flower_photos',
'https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz',
untar=True)
img_gen = tf.keras.preprocessing.image.ImageDataGenerator(
rescale=1./255,
horizontal_flip=True,
)
train_ds = img_gen.flow_from_directory(flowers, batch_size=BATCH_SIZE, shuffle=True, class_mode='sparse')
num_classes = 5
model = tf.keras.Sequential([
tf.keras.layers.Conv2D(16, 3, padding='same', activation='relu', input_shape=(256, 256, 3)),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Conv2D(32, 3, padding='same', activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Conv2D(64, 3, padding='same', activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(num_classes)
])
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True))
epochs=10
history = model.fit(
train_ds,
epochs=epochs
)
Found 3670 images belonging to 5 classes.
Epoch 1/10
6/58 [==>...........................] - ETA: 3:02 - loss: 2.0608
如果像这样用 tf.data.Dataset.from_generator
包裹 flow_from_directory
:
train_ds = tf.data.Dataset.from_generator(
lambda: img_gen.flow_from_directory(flowers, batch_size=BATCH_SIZE, shuffle=True, class_mode='sparse'),
output_types=(tf.float32, tf.float32))
您会注意到进度条看起来像这样,因为 steps_per_epoch
尚未明确定义:
Epoch 1/10
Found 3670 images belonging to 5 classes.
29/Unknown - 104s 4s/step - loss: 2.0364
如果你添加这个参数,你会在进度条中看到步骤:
history = model.fit(
train_ds,
steps_per_epoch = len(from_directory),
epochs=epochs
)
Found 3670 images belonging to 5 classes.
Epoch 1/10
3/58 [>.............................] - ETA: 3:19 - loss: 4.1357
最后,对于你的问题:
How to use this generator correctly with function fit to have all
data in my training set, including original, non-augmented images and
augmented images, and to cycle through it several times/step?
您可以简单地将 steps_per_epoch
增加到 number of samples // batch_size
以上,方法是乘以某个因数:
history = model.fit(
train_ds,
steps_per_epoch = len(from_directory)*2,
epochs=epochs
)
Found 3670 images belonging to 5 classes.
Epoch 1/10
1/116 [..............................] - ETA: 12:11 - loss: 1.5885
现在每个纪元有 116 步,而不是 58 步。
我最近在 Keras 中玩数据扩充,我正在使用基本的 ImageDataGenerator。我通过艰难的方式了解到它实际上是一个生成器,而不是迭代器(因为 type(train_aug_ds)
给出 <class 'keras.preprocessing.image.DirectoryIterator'>
我认为它是一个迭代器)。我也查看了一些关于使用它的博客,但他们没有回答我所有的问题。
所以,我这样加载了我的数据:
train_aug = ImageDataGenerator(
rescale=1./255,
horizontal_flip=True,
height_shift_range=0.1,
width_shift_range=0.1,
brightness_range=(0.5,1.5),
zoom_range = [1, 1.5],
)
train_aug_ds = train_aug.flow_from_directory(
directory='./train',
target_size=image_size,
batch_size=batch_size,
)
为了训练我的模型,我执行了以下操作:
model.fit(
train_aug_ds,
epochs=150,
validation_data=(valid_aug_ds,),
)
它奏效了。我有点困惑它是如何工作的,因为 train_aug_ds
是生成器,所以它应该提供无限大的数据集。文档说:
When passing an infinitely repeating dataset, you must specify the steps_per_epoch argument.
我没做过,但它起作用了。它是否以某种方式推断出步数?另外,它是只使用增强数据,还是批量使用非增强图像?
所以基本上,我的问题是如何正确使用这个生成器和函数 fit
来获得我训练集中的所有数据,包括原始的、非增强的图像和增强的图像,并循环使用它几个times/steps(目前看来每个 epoch 只执行一步)?
我认为文档可能非常混乱,而且我认为行为会因您的 Tensorflow 和 Keras 版本而异。例如,在这个 flow_from_directory()
method allows you to read the images directly from a directory and augment them while your model is being trained and as already stated
import tensorflow as tf
BATCH_SIZE = 64
flowers = tf.keras.utils.get_file(
'flower_photos',
'https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz',
untar=True)
img_gen = tf.keras.preprocessing.image.ImageDataGenerator(
rescale=1./255,
horizontal_flip=True,
)
train_ds = img_gen.flow_from_directory(flowers, batch_size=BATCH_SIZE, shuffle=True, class_mode='sparse')
num_classes = 5
model = tf.keras.Sequential([
tf.keras.layers.Conv2D(16, 3, padding='same', activation='relu', input_shape=(256, 256, 3)),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Conv2D(32, 3, padding='same', activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Conv2D(64, 3, padding='same', activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(num_classes)
])
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True))
epochs=10
history = model.fit(
train_ds,
epochs=epochs
)
Found 3670 images belonging to 5 classes.
Epoch 1/10
6/58 [==>...........................] - ETA: 3:02 - loss: 2.0608
如果像这样用 tf.data.Dataset.from_generator
包裹 flow_from_directory
:
train_ds = tf.data.Dataset.from_generator(
lambda: img_gen.flow_from_directory(flowers, batch_size=BATCH_SIZE, shuffle=True, class_mode='sparse'),
output_types=(tf.float32, tf.float32))
您会注意到进度条看起来像这样,因为 steps_per_epoch
尚未明确定义:
Epoch 1/10
Found 3670 images belonging to 5 classes.
29/Unknown - 104s 4s/step - loss: 2.0364
如果你添加这个参数,你会在进度条中看到步骤:
history = model.fit(
train_ds,
steps_per_epoch = len(from_directory),
epochs=epochs
)
Found 3670 images belonging to 5 classes.
Epoch 1/10
3/58 [>.............................] - ETA: 3:19 - loss: 4.1357
最后,对于你的问题:
How to use this generator correctly with function fit to have all data in my training set, including original, non-augmented images and augmented images, and to cycle through it several times/step?
您可以简单地将 steps_per_epoch
增加到 number of samples // batch_size
以上,方法是乘以某个因数:
history = model.fit(
train_ds,
steps_per_epoch = len(from_directory)*2,
epochs=epochs
)
Found 3670 images belonging to 5 classes.
Epoch 1/10
1/116 [..............................] - ETA: 12:11 - loss: 1.5885
现在每个纪元有 116 步,而不是 58 步。