本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢.
持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情
前言
根据经验,我们知道对于给定的图像,即使我们平移,旋转或缩放图像,图像的标签也将保持不变。数据增强是从给定的图像集中创建更多图像的一种方法,即通过旋转,平移或缩放它们并将它们映射到原始图像的标签,以扩充数据集。 在我们的认知中:即使图像稍微旋转或图像中的人从图像的中间移至图像的最右侧,该图像的分类标签仍然不会改变。因此,我们能够通过旋转和平移原始图像来创建更多训练数据,而每个图像相对应的标签并不会改变。
数据集与模型分析
数据集介绍
在本节中,我们将研究 CIFAR-10
数据集, CIFAR-10
数据集中的图片有 10
个类别,每张图片均为 32x32
的彩色图像,每个类别有 6000
个图像。因此,共有 50000
个训练图像和 10000
个测试图像。类别标签分别为 plane
、 car
、 bird
、 cat
、 deer
、 dog
、 frog
、 horse
、 ship
和 truck
。
模型分析
我们首先分析用于实现 CIFAR-10
分类的卷积神经网络 ( Convolutional Neural Networks
, CNN
) 模型,模型分类策略如下:
CIFAR-10 CNN
在本节中,我们将使用 keras.preprocessing.image
包中的 ImageDataGenerator
方法来实现数据增强。为了理解数据增强的优势,我们使用一个简单示例,在该示例中,分别计算具有数据增强和不具有数据增强的情况下使用同样的 CNN
架构分类 CIFAR-10
数据集的准确率。
使用数据增强提高神经网络性能
不使用数据增强的模型准确率
在本节中,我们首先计算不增加数据集时模型的准确率。 首先,导入所需库和数据集:
from matplotlib import pyplot as plt import numpy as np from keras.utils import np_utils from keras.models import Sequential from keras.layers import Dense, Dropout, Activation, Flatten from keras.layers import Conv2D, MaxPooling2D, BatchNormalization from keras import regularizers from keras.datasets import cifar10 (x_train, y_train), (x_test, y_test) = cifar10.load_data()
查看加载的图像样本及其相应的标签:
labels = ['plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck'] plt.subplot(221) plt.imshow(x_train[0]) plt.title(labels[y_train[0][0]]) plt.subplot(222) plt.imshow(x_train[1]) plt.title(labels[y_train[1][0]]) plt.subplot(223) plt.imshow(x_train[2]) plt.title(labels[y_train[2][0]]) plt.subplot(224) plt.imshow(x_train[3]) plt.title(labels[y_train[3][0]]) plt.show()
对加载后的数据进行预处理:
x_train = x_train.astype('float32') / 255. x_test = x_test.astype('float32') / 255. n_classes = x_train.shape[0] y_train = np_utils.to_categorical(y_train, n_classes) y_test = np_utils.to_categorical(y_test, n_classes)
构建并编译模型,本节中,我们使用了较高的学习率,因此模型可以在更少的时间内更快地收敛,用于更快地比较不进行数据增强和使用数据增强方案的不同。正常情况下,我们一般令模型使用较小的学习率并训练更多的 epoch
:
input_shape = x_train[0].shape weight_delay = 0.0001 model = Sequential() model.add(Conv2D(32, (3,3), padding='same', input_shape=input_shape, kernel_regularizer=regularizers.l2(weight_delay))) model.add(Activation('relu')) model.add(BatchNormalization()) model.add(Conv2D(32, (3,3), padding='same', kernel_regularizer=regularizers.l2(weight_delay))) model.add(Activation('relu')) model.add(BatchNormalization()) model.add(MaxPooling2D(pool_size=(2,2))) model.add(Dropout(0.2)) model.add(Conv2D(64, (3,3), padding='same', kernel_regularizer=regularizers.l2(weight_delay))) model.add(Activation('relu')) model.add(BatchNormalization()) model.add(Conv2D(64, (3,3), padding='same', kernel_regularizer=regularizers.l2(weight_delay))) model.add(Activation('relu')) model.add(BatchNormalization()) model.add(MaxPooling2D(pool_size=(2,2))) model.add(Dropout(0.2)) model.add(Conv2D(128, (3,3), padding='same', kernel_regularizer=regularizers.l2(weight_delay))) model.add(Activation('relu')) model.add(BatchNormalization()) model.add(Conv2D(128, (3,3), padding='same', kernel_regularizer=regularizers.l2(weight_delay))) model.add(Activation('relu')) model.add(BatchNormalization()) model.add(MaxPooling2D(pool_size=(2,2))) model.add(Dropout(0.2)) model.add(Flatten()) model.add(Dense(n_classes, activation='softmax'))
最后,拟合模型,训练完成后可以看到,该卷积神经网络的准确率约为 68%
:
from keras.optimizers import Adam adam = Adam(lr=0.01) model.compile(loss='categorical_crossentropy', optimizer=adam, metrics=['acc']) history = model.fit(x_train, y_train, batch_size=32, epochs=20, verbose=1, validation_data=(x_test,y_test))
通过数据增强来提高模型的准确率
接下来,我们使用数据增强,来增加训练数据集数量,然后训练与上节相同的模型。使用 keras.preprocessing.image
包中的 ImageDataGenerator
方法来扩充数据集:
from keras.preprocessing.image import ImageDataGenerator data_gen = ImageDataGenerator( rotation_range=20, width_shift_range=0, height_shift_range=0, fill_mode='nearest') data_gen.fit(x_train)
在上面的代码中,我们生成了新图像,新图像在 0
到 20
度之间随机旋转。通过数据生成器后的图像样本如下,与上一节未旋转的图像相比,图像会有略微的倾斜:
from keras.preprocessing.image import array_to_img plt.subplot(221) x = x_train[:4] y = y_train[:4] batch_img = data_gen.flow(x, y, batch_size=4) print(batch_img[0][1][0][0]) plt.imshow(array_to_img(batch_img[0][0][0])) plt.title(labels[batch_img[0][1][0][0]]) plt.subplot(222) plt.imshow(array_to_img(batch_img[0][0][1])) plt.title(labels[batch_img[0][1][1][0]]) plt.subplot(223) plt.imshow(array_to_img(batch_img[0][0][2])) plt.title(labels[batch_img[0][1][2][0]]) plt.subplot(224) plt.imshow(array_to_img(batch_img[0][0][3])) plt.title(labels[batch_img[0][1][3][0]]) plt.show()
接下来,通过数据生成器传递训练数据集,并训练与上一节架构与超参数完全相同的模型,但使用的训练数据集通过数据增强得以扩充:
input_shape = x_train[0].shape weight_delay = 0.0001 model = Sequential() model.add(Conv2D(32, (3,3), padding='same', input_shape=input_shape, kernel_regularizer=regularizers.l2(weight_delay))) model.add(Activation('relu')) model.add(BatchNormalization()) model.add(Conv2D(32, (3,3), padding='same', kernel_regularizer=regularizers.l2(weight_delay))) model.add(Activation('relu')) model.add(BatchNormalization()) model.add(MaxPooling2D(pool_size=(2,2))) model.add(Dropout(0.2)) model.add(Conv2D(64, (3,3), padding='same', kernel_regularizer=regularizers.l2(weight_delay))) model.add(Activation('relu')) model.add(BatchNormalization()) model.add(Conv2D(64, (3,3), padding='same', kernel_regularizer=regularizers.l2(weight_delay))) model.add(Activation('relu')) model.add(BatchNormalization()) model.add(MaxPooling2D(pool_size=(2,2))) model.add(Dropout(0.2)) model.add(Conv2D(128, (3,3), padding='same', kernel_regularizer=regularizers.l2(weight_delay))) model.add(Activation('relu')) model.add(BatchNormalization()) model.add(Conv2D(128, (3,3), padding='same', kernel_regularizer=regularizers.l2(weight_delay))) model.add(Activation('relu')) model.add(BatchNormalization()) model.add(MaxPooling2D(pool_size=(2,2))) model.add(Dropout(0.2)) model.add(Flatten()) model.add(Dense(n_classes, activation='softmax')) from keras.optimizers import Adam adam = Adam(lr=0.01) model.compile(loss='categorical_crossentropy', optimizer=adam, metrics=['acc'])
以上代码构建的模型与上一节中完全相同,以便比较使用数据增强和未使用数据增强场景下,模型性能的变化:
history = model.fit_generator(data_gen.flow(x_train, y_train, batch_size=32), steps_per_epoch=x_train.shape[0] // 32, epochs=20, validation_data=(x_test,y_test))
在以上代码中, fit_generator
方法会在生成的新图像上拟合模型, datagen.flow
根据使用的数据增强策略,生成新的训练数据。同时,我们还指定了每个 epoch
中模型训练的步数,即数据集中数据总数与批大小的比值 steps_per_epoch=x_train.shape[0] // 32
。看以看到,此模型的准确率约为 72%
,比仅使用给定的数据集(不进行数据增强)的准确率更高:
Be First to Comment