本文为🔗365天深度学习训练营 中的学习记录博客
原作者:K同学啊|接辅导、项目定制
我的环境:
1.语言:python3.7
2.编译器:pycharm
3.深度学习环境:TensorFlow2.5
在本节中,我们将学会如何进行数据增强,并通过数据增强用少量数据达到非常非常棒的识别准确率。
本节将展示两种数据增强方式,以及如何自定义数据增强方式并将其放到我们代码当中,两种数据增强方式如下
- 将数据增强模块嵌入model中
- 在Dataset数据集中进行数据增强
一.前期工作
1.设置GPU
若是使用的是cpu可忽略
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import os, PIL, pathlib
import matplotlib.pyplot as plt
import tensorflow as tf
import numpy as np
#隐藏警告
import warnings
warnings.filterwarnings('ignore')
gpus = tf.config.list_physical_devices("GPU")
if gpus:
gpu0 = gpus[0]
tf.config.experimental.set_memory_growth(gpu0, True)
tf.config.set_visible_devices([gpu0],"GPU")
二、数据预处理
1、加载数据
data_dir = 'E:/TF环境/T8_data'
img_height = 224
img_width = 224
batch_size = 32
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
validation_split=0.3,
subset="training",
seed=12,
image_size=(img_height, img_width),
batch_size=batch_size)
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
validation_split=0.3,
subset="training",
seed=12,
image_size=(img_height, img_width),
batch_size=batch_size)
Found 3400 files belonging to 2 classes.
Using 2380 files for training.
Found 3400 files belonging to 2 classes.
Using 2380 files for training.
由于原始数据集不包含测试集,因此需要创建一个。使用 tf.data.experimental.cardinality 确定验证集中有多少批次的数据,然后将其中的 20% 移至测试集。
val_batches = tf.data.experimental.cardinality(val_ds)
test_ds = val_ds.take(val_batches // 5)
val_ds = val_ds.skip(val_batches // 5)
print('Number of validation batches: %d' % tf.data.experimental.cardinality(val_ds))
print('Number of test batches: %d' % tf.data.experimental.cardinality(test_ds))
cardinality
函数返回一个tf.data.experimental.Cardinality
对象,表示数据集的元素数量。Cardinality
对象可以具有以下值之一:
UNKNOWN
:表示无法确定元素数量。FINITE
:表示元素数量是有限的,可以通过遍历数据集来计算出确切数量。INFINITE
:表示元素数量是无限的,无法通过遍历数据集来计算出确切数量。
请注意,tf.data.experimental.Cardinality
对象是一个枚举,可使用.numpy()
方法将其转换为NumPy数组形式。
根据给出的代码片段,假设val_ds
是一个tf.data.Dataset对象,它表示验证集数据。以下是对代码的逐行解读:
-
通过使用
tf.data.experimental.cardinality
函数估计val_ds
中的批次数量,并将结果保存在val_batches
变量中。 -
使用整除运算符
//
来计算val_batches
的五分之一,并将结果作为test_ds
中批次的数量。test_ds
由val_ds
的前面5分之1的批次组成,可以使用take
方法从val_ds
中获取这些批次。 -
使用整除运算符
//
来计算val_batches
的四分之四,并将结果作为val_ds
中剩余批次的数量。val_ds
由val_ds
中跳过前面5分之1批次后剩下的批次组成,可以使用skip
方法来实现。 -
使用
tf.data.experimental.cardinality
函数估计调整后的val_ds
中的批次数量,并打印输出验证集的批次数量。 -
使用
tf.data.experimental.cardinality
函数估计调整后的test_ds
中的批次数量,并打印输出测试集的批次数量。
总结:上述代码用于将验证数据集(val_ds
)划分为验证集(val_ds
)和测试集(test_ds
)。根据验证集的批次数量,通过跳过和获取批次来划分数据集,并打印输出划分后验证集和测试集的批次数量。
Number of validation batches: 60
Number of test batches: 15
class_names = train_ds.class_names
print(class_names)
['cat', 'dog']
2、配置数据集
AUTOTUNE = tf.data.experimental.AUTOTUNE
def preprocess_image(image,label):
return (image/255.0,label)
# 归一化处理
train_ds = train_ds.map(preprocess_image, num_parallel_calls=AUTOTUNE)
val_ds = val_ds.map(preprocess_image, num_parallel_calls=AUTOTUNE)
test_ds = test_ds.map(preprocess_image, num_parallel_calls=AUTOTUNE)
train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
3、可视化数据
plt.figure(figsize=(15, 10)) # 图形的宽为15高为10
for images, labels in train_ds.take(1):
for i in range(8):
ax = plt.subplot(5, 8, i + 1)
plt.imshow(images[i])
plt.title(class_names[labels[i]])
plt.axis("off")
plt.show()
三、数据增强
数据增强(Data Augmentation)是机器学习和计算机视觉中的一种常见技术,用于扩充训练数据集的多样性。通过对原始数据进行各种随机或确定性的变换操作,可以生成具有差异性的新样本。
数据增强的目的是提高模型的泛化能力和鲁棒性,减轻过拟合问题,并且可以帮助模型更好地适应不同类型的输入数据。通过应用各种变换操作,数据增强可以扩展训练集,增加样本的数量和多样性,从而改善模型的性能。
常见的数据增强操作包括但不限于:
- 随机裁剪:在图像中随机选取一部分区域作为新样本。
- 翻转和旋转:水平、垂直翻转或任意角度旋转图像。
- 平移和缩放:在图像上进行平移或缩放操作。
- 加噪声:向图像中添加随机噪声,如高斯噪声、椒盐噪声等。
- 亮度和对比度调整:调整图像的亮度和对比度,使其具有不同的外观。
数据增强通常在模型训练阶段的数据预处理步骤中应用。通过在每个训练迭代中对原始数据进行随机变换,可以增加模型对输入数据的鲁棒性,并提高模型在真实世界中的表现。
需要注意的是,在应用数据增强时需要根据具体任务和数据集的特点选择适当的增强操作,并避免引入任意或无效的变换。此外,数据增强应与验证集和测试集的预处理保持一致,以确保模型在评估阶段接收到的数据与训练阶段一致。
我们可以使用 tf.keras.layers.experimental.preprocessing.RandomFlip 与 tf.keras.layers.experimental.preprocessing.RandomRotation 进行数据增强。
- tf.keras.layers.experimental.preprocessing.RandomFlip:水平和垂直随机翻转每个图像
- tf.keras.layers.experimental.preprocessing.RandomRotation:随机旋转每个图像
data_augmentation = tf.keras.Sequential([
tf.keras.layers.experimental.preprocessing.RandomFlip("horizontal_and_vertical"),
tf.keras.layers.experimental.preprocessing.RandomRotation(0.2),
])
# 第一层表示进行随机的水平和垂直翻转,而第二层表示按照 0.2 的弧度值进行随机旋转。
# 将图像添加到批次
image = tf.expand_dims(images[i], 0)
# 随机使用一张照片尝试一下看看效果:
plt.figure(figsize=(8, 8))
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")
plt.show()
1.将其嵌入model中
model = tf.keras.Sequential([
data_augmentation,
layers.Conv2D(16, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
])
这个方法的好处就是:
数据增强这块的工作可以得到GPU的加速(如果你使用了GPU训练的话),
注意: 只有在模型训练时(Model.fit)才会进行增强,在模型评估(Model.evaluate)以及预测(Model.predict)时并不会进行增强操作。
2.在Dataset数据集中进行数据增强
batch_size = 32
AUTOTUNE = tf.data.AUTOTUNE
def prepare(ds):
ds = ds.map(lambda x, y: (data_augmentation(x, training=True), y), num_parallel_calls=AUTOTUNE)
return 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(len(class_names))
])
在准备对模型进行训练之前,还需要再对其进行一些设置。以下内容是在模型的编译步骤中添加的:
- 损失函数(loss):用于衡量模型在训练期间的准确率。
- 优化器(optimizer):决定模型如何根据其看到的数据和自身的损失函数进行更新。
- 评价函数(metrics):用于监控训练和测试步骤。以下示例使用了准确率,即被正确分类的图像的比率。
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
开始训练~
epoch = 20
history = model.fit(
train_ds,
validation_data=val_ds,
epochs=epoch
)
loss,acc = model.evaluate(test_ds)
print('Acuracy',acc)
15/15 [==============================] - 1s 29ms/step - loss: 3.0438e-05 - accuracy: 1.0000
Acuracy 1.0
五、自定义增强函数
以上代码定义了一个名为aug_img
的函数,用于对输入图像进行数据增强操作:
-
在函数内部定义了一个名为
seed
的变量,其取值使用random.randint(0,9)
生成一个随机整数,并与0组成元组。 -
使用
tf.image.stateless_random_contrast
函数对输入图像进行随机对比度增强操作。参数image
是输入图像,lower
和upper
分别表示对比度增强的下限和上限。seed
参数传递了之前生成的随机种子,用于确定随机性。返回经过随机对比度增强后的图像。 -
将经过数据增强操作后的图像作为函数的返回值。
总结:给定一张图像作为输入,aug_img
函数使用随机生成的种子对其进行随机对比度增强操作,并返回增强后的图像。这个函数可以作为数据增强流程的一部分,在训练过程中应用于图像数据以增加样本的多样性和泛化能力。
import random
# 这是大家可以自由发挥的一个地方
def aug_img(image):
seed = (random.randint(0,9), 0)
# 随机改变图像对比度
stateless_random_brightness = tf.image.stateless_random_contrast(image, lower=0.1, upper=1.0, seed=seed)
return stateless_random_brightness
image = tf.expand_dims(images[3]*255, 0)
print("Min and max pixel values:", image.numpy().min(), image.numpy().max())
Min and max pixel values: 11.709176 255.0
我们随机使用一张图片改变其对比度:
plt.figure(figsize=(8, 8))
for i in range(9):
augmented_image = aug_img(image)
ax = plt.subplot(3, 3, i + 1)
plt.imshow(augmented_image[0].numpy().astype("uint8"))
plt.axis("off")
plt.show()