使用 Tensorflow 进行图像分类:流式数据的数据增强(第 2 部分)

介绍

本文是文章第 1 部分的延续 ,我们在第 1 部分中讨论了一般数据管道以及我们如何使用 TensorFlow 数据管道:Tensorflow 数据集。查看第一部分:https://mp.weixin.qq.com/s/TPg_1KT6u47-9KrMSpoqzg

简单回顾一下,我们通过从“Horses-and-Human”数据集上的“TensorFlow Datasets”中提取、转换和加载数据创建了一个二进制图像分类器。如果你不熟悉这个概念,我建议你也看看那篇文章。

在本文中,我们将创建一个类似的二元图像分类器,但与之前不同,这次我们将通过数据增强处理过拟合。我们将使用数据增强作为序列模型层,这些层将在实际进入卷积层和最大池化层之前转换模型中的流数据。

这使我们能够在运行时模型训练中使用已经存储的数据和更多样化的示例。

但在此之前:什么是数据增强?

什么是数据增强?

数据增强是图像处理中一种非常流行的技术,尤其是计算机视觉,通过应用随机(但现实)的变换来增加训练数据的多样性和数量。

例如,图像调整大小、图像旋转、图像翻转等等。这种技术帮助我们获得更多样化的数据,从而产生更好的训练集,从而得到更好的训练模型。

注意:在深度学习中,当我们使用数据增强时,我们只将技术应用于训练数据,而不是验证数据,也不应用于测试数据。

将跳过第1部分中已经涵盖的那些部分的代码说明,直接进入本文的内容。

让我们编码

导入库并使用 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 通道,我们在本文中忽略这一点)

调整大小:我改变的图像的尺寸:300×300×3 - > 220 X 220×3

使用重新缩放:我更改最初位于 [0,255] –> [0,1] 之间的所有像素值,图像看起来相同但底层像素值会发生变化,尽管它们相对而言代表相同的颜色和特征。

IMG_SIZE = 220
## Becuase Pixel range in Images are between [0,255], To rescale an input in the [0, 255] range
# to be in the [0, 1] range, you would pass scale=1./255
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)
])

让我们可视化并查看结果。

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}")

转向另一组增强层,我称这些增强层为重增强,因为它们的结果以某种方式改变了图像的视觉效果。

注意:请记住,所有这些层都使用 4 个输入维度,第 4 个是用于批处理中的图像数量,即 BATCH_SIZE(它从形状中的每个其他值中首先出现),对于视觉检查,我们将使用tf.expand_dims函数来在这件事上提供帮助。

## Heavier Augmentation
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 度顺时针) 中提供的范围中选择的随机度数旋转图像。

print(image.shape)
image = tf.expand_dims(image, 0)
print(image.shape)

让我们可视化这 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")

对训练数据集进行混洗和批处理,并对测试数据集进行批处理,如前面第 1 部分所述。

train_dataset = train_dataset.shuffle(100).batch(8)
val_dataset = val_dataset.batch(8)

有一件事情是非常重要的,就是批量大小。与第 1 部分的代码相比,我将批量大小从 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

与之前的 8个时期相比,仅在5 个时期内,查看训练数据和验证数据的损失和准确性的结果和收敛情况。

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 数据集)对“Horses-and-Human”数据集进行二进制图像分类系列的结尾,这些数据管道(Tensorflow 数据集)通过一些数据增强进行训练,以避免对数据过度拟合。

☆ END ☆

如果看到这里,说明你喜欢这篇文章,请转发、点赞。微信搜索「uncle_pn」,欢迎添加小编微信「 woshicver」,每日朋友圈更新一篇高质量博文。

扫描二维码添加小编↓

Guess you like

Origin blog.csdn.net/woshicver/article/details/119834077