数据增强是图像处理中,特别是在计算机视觉领域中非常流行的一种技术,它通过应用随机(但现实)的变换来增加训练数据的多样性和数量。例如,图像尺寸调整、图像旋转、图像翻转等。这种技术帮助获得已经包含的数据的更多样化的特性,从而得到更好的训练集,进而训练出更好的模型。
注意:在深度学习中,只在训练数据上应用数据增强技术,而不在验证数据或测试数据上应用。
将跳过已经在第一部分中介绍过的代码部分,直接进入本文的内容。
导入库并使用TensorFlow数据集检索数据。
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
import tensorflow_datasets as tfds
from tensorflow.keras import layers
train_dataset, info = tfds.load('horses_or_humans', with_info=True, split='train', as_supervised=True)
val_dataset, val_info = tfds.load("horses_or_humans", with_info=True, split='test', as_supervised=True)
tensorflow.data.Dataset对象是这些数据管道创建的Python迭代器。让看看“train_dataset”中的一个示例。
get_label_name = info.features["label"].int2str
image, label = next(iter(train_dataset))
_ = plt.imshow(image)
_ = plt.title(get_label_name(label))
get_label_name函数将标签(0,1)转换为字符串(“horses”,“humans”)。
让创建第一个数据增强层序列,包括调整大小和重新缩放。个人称它们为“轻量级”增强,因为从视觉上看,它们几乎相同,除了它们改变了形状和底层像素值。在这里,数据集中的原始图像是300 x 300 x 3像素。(最后的3是图像的RGB通道,本文中忽略这一点)
通过调整大小:
IMG_SIZE = 220
resize_and_rescale = tf.keras.Sequential([
layers.experimental.preprocessing.Resizing(IMG_SIZE, IMG_SIZE, input_shape=[300,300,3]),
layers.experimental.preprocessing.Rescaling(1./255)
])
通过重新缩放:
# 因为图像像素范围在[0,255]之间,要将输入范围[0, 255]重新缩放到[0, 1]范围,需要传递scale=1./255
让可视化并查看结果。
result = resize_and_rescale(image)
plt.imshow(result)
print("Image Dimensions were: {0}x{1}".format(image.shape[0], image.shape[1]))
print("Resized Image Dimensions are: {0}x{1}".format(result.shape[0], result.shape[1]))
print()
print(f"Checking the values for Resulted image pixels: MIN -->{result.numpy().min():.4f}, MAX --> {result.numpy().max():.4f}")
继续进行另一组增强层,称这些为“重量级”增强,因为它们的结果会以某种方式改变图像的视觉。
data_augmentation = tf.keras.Sequential([
layers.experimental.preprocessing.RandomFlip("horizontal_and_vertical"),
layers.experimental.preprocessing.RandomRotation((-0.2, 0.3))
])
通过RandomFlip:
# 随机地在水平或垂直方向上翻转图像
通过RandomRotation:
# 旋转图像,随机选择一个角度,范围在函数参数中提供(-0.2, 0.3)->(-20度到30度顺时针)
让可视化这些随机效果在这9次迭代中的表现。
plt.figure(figsize = (10,10))
for i in range(9):
augmented_image = data_augmentation(image)
ax = plt.subplot(3,3,i+1)
plt.imshow(augmented_image[0])
plt.axis("off")
洗牌和批处理train_dataset,并批处理test_dataset,如第一部分中所做的。
train_dataset = train_dataset.shuffle(100).batch(8)
val_dataset = val_dataset.batch(8)
这里有一个非常重要的注意事项,即批量大小。已经将批量大小从32减少到8,这是在第一部分的代码之后进行的超参数调整和实验。模型在训练时对验证数据集给出了随机结果,因此在损失和准确性上有很多噪声,因此为了使模型不要在所有增强数据上泛化太多,减少了批量大小,以减少每次计算损失和通过梯度优化参数时使用图像的数量。
让看看如何非常简单地将所有创建的增强层与彼此以及主CNN模型层累积在一起。
model = tf.keras.models.Sequential([
resize_and_rescale,
data_augmentation,
tf.keras.layers.Conv2D(filters=8, kernel_size=3, activation='relu', padding='same'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Conv2D(filters=16, kernel_size=3, activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Conv2D(filters=32, kernel_size=3, activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(units=64, activation='relu'),
tf.keras.layers.Dense(units=2, activation='softmax')
])
model.summary()
现在,已经非常接近最终训练的模型了,剩下的事情就是编译模型并在训练数据集上拟合它,并通过验证数据集来验证训练。在编译过程中,希望能够自由地改变学习率进行超参数调整,所以直接使用了tensorflow.keras.optimizers中的RMSprop。
from tensorflow.keras.optimizers import RMSprop
model.compile(loss="sparse_categorical_crossentropy", optimizer=RMSprop(learning_rate=0.001), metrics=['accuracy'])
history = model.fit(train_dataset, epochs=5, validation_data=val_dataset)
最后,通过一些图表来可视化训练和验证损失和准确性。
plt.figure(figsize=(8, 4))
plt.plot(range(5), history.history['loss'], 'r', label='training loss')
plt.plot(range(5), history.history['val_loss'], 'b', label='validation Loss')
plt.legend()
plt.xlabel('Number of Epochs')
plt.ylabel("Loss")
plt.show()
plt.figure(figsize=(8, 4))
plt.plot(range(5), history.history['accuracy'], 'r', label='training accuracy')
plt.plot(range(5), history.history['val_accuracy'], 'b', label='validation accuracy')
plt.legend()
plt.xlabel('Number of Epochs')
plt.ylabel("Accuracy")
plt.show()
这就是关于使用TensorFlow及其数据管道(TensorFlow数据集)训练的二分类图像识别模型的系列文章的结束,该模型涉及一些数据增强以避免数据过拟合。
:Gargeya Sharma