本篇笔记主要记录了TensorFlow中对图片数据进行增强的两种方法。
1、使用keras预处理层
tf.keras.layers.Ressize 改变图片大小
tf.keras.layers.Rescaling 归一化
#对图片大小进行统一,并归一化
IMG_SIZE = 180
resize_and_rescale = tf.keras.Sequential([
layers.Resizing(IMG_SIZE, IMG_SIZE),
layers.Rescaling(1./255)
])
tf.keras.layers.RandomFlip 随机翻转
tf.keras.layers.RandomRotation 随机旋转
#对图片进行随机翻转和旋转
data_augmentation = tf.keras.Sequential([
layers.RandomFlip("horizontal_and_vertical"),
layers.RandomRotation(0.2),
])
tf.keras.layers.RandomContrast 随机调整图片的对比度
tf.keras.layers.RandomCrop 随机裁剪图片
tf.keras.layers.RandomZoom 随机缩放图片
在进行数据增强的操作后,如何使用这些图像成了重中之重。目前有两种处理方式:
①使预处理层成为模型的一部分
model = tf.keras.Sequential([
resize_and_rescale,
data_augmentation,
layers.Conv2D(16, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
])
当使用model.save导出模型时,预处理层会和其他网络层一同保存。如果再次在其他数据集上使用此模型,会根据已经设定好的预处理层再次标准化图像。测试时,数据增强预处理层是停用的,只有在调用model.fit的时候,才会对输入图像进行增强。model.evaluate和model.predict并不会对图像进行处理。
②将预处理层应用于数据集
aug_ds = train_ds.map(
lambda x, y: (resize_and_rescale(x, training=True), y))
#匿名函数对x和y进行处理,使用map函数将处理后的x和y一一对应
通过这种方式对数据集进行批次增强,数据增强在CPU上异步进行,此时可以使用dataset.prefetch预读取将GPU上的模型训练和数据预处理重叠。而且在调用model.save时,预处理层并不会随模型一并导出。在保存模型或者重现时,需要将其加到模型上。
演示:
batch_size = 32
AUTOTUNE = tf.data.AUTOTUNE
def prepare(ds, shuffle=False, augment=False):
ds = ds.map(lambda x, y: (resize_and_rescale(x), y),
num_parallel_calls=AUTOTUNE)
#数据增强
if shuffle:
ds = ds.shuffle(1000)
ds = ds.batch(batch_size)
#每32个分为一个batch
#仅仅在训练层使用数据增强
if augment:
ds = ds.map(lambda x, y: (data_augmentation(x, training=True), y),
num_parallel_calls=AUTOTUNE)
return ds.prefetch(buffer_size=AUTOTUNE)
train_ds = prepare(train_ds, shuffle=True, augment=True)
val_ds = prepare(val_ds)
test_ds = prepare(test_ds)
model = tf.keras.Sequential([
layers.Conv2D(16, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Conv2D(32, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Conv2D(64, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Flatten(),
layers.Dense(128, activation='relu'),
layers.Dense(num_classes)
])
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
epochs=5
history = model.fit(
train_ds,
validation_data=val_ds,
epochs=epochs
)
loss, acc = model.evaluate(test_ds)
print("Accuracy", acc)
2、使用tf.image
使用tf.data和tf.image编写数据增强层,常见的调整方式有:
tf.image.flip_left_right 左右翻转
tf.image.rgb_to_grayscale 变为灰度图
tf.image.adjust_brightness 调整亮度
tf.image.central_crop 裁剪图像中心区域
tf.image.adjust_saturation 调整饱和度
除此之外,还有一些随机变换帮助泛化和拓展数据的方式。
tf.image.stateless_random_brightness
tf.image.stateless_random_contrast
tf.image.stateless_random_crop
tf.image.stateless_random_flip_left_right
tf.image.stateless_random_flip_up_down
tf.image.stateless_random_hue
tf.image.stateless_random_jpeg_quality
tf.image.stateless_random_saturation
经过这些api处理的输出图像,仅仅取决于输入。在随机调整的过程中,每一步都要求输入一个随机的seed值,只要是同一个seed,无论调用多少次输出的都是相同的结果。