数据增强是一种用于提高计算机视觉问题神经网络模型的性能和减少泛化误差的技术。
当使用拟合模型进行预测时,也可以应用图像数据增强技术,以允许模型对测试数据集中每幅图像的多个不同版本进行预测。对增强图像的预测可以取平均值,从而获得更好的预测性能。
在本文章中,您将发现测试时的增强,以改进用于图像分类任务的模型的性能。
完成本文章后,您将知道:
TTA是数据增广技术的应用,通常用于在训练中进行预测。
如何在Keras中从头开始实现测试时增强。
如何使用TTA来提高卷积神经网络模型在标准图像分类任务中的性能。
测试时数据增强(Test-Time Augmentation)
数据增强是一种在模型训练期间通常使用的方法,它使用训练数据集中修改过的样本副本来扩展训练集。
通常使用图像数据来执行数据增强,其中通过执行一些图像操作技术来创建训练数据集中的图像副本,例如缩放、翻转、移动等等。
人工扩展的训练数据集可以产生一个更熟练的模型,因为深度学习模型的性能通常会随着训练数据集的大小继续扩大。此外,训练数据集中图像的修改或增强版本可以帮助模型以不受位置、光照等影响的方式提取和学习特征。
测试时数据增强,简称TTA,是对测试数据集进行数据扩展的一种应用。
具体来说,它涉及到为测试集中的每个图像创建多个扩增副本,让模型对每个图像做出预测,然后返回这些预测的集合。
选择增强是为了让模型有最好的机会对给定的图像进行正确分类,而且模型必须对图像的副本数量进行预测的次数通常很少,比如少于10或20。
通常,执行一个简单的测试时间增加,例如移位、裁剪或图像翻转。
2015年,ILSVRC数据集上取得了当时最先进的成果,题为“Very Deep Convolutional Networks for Large-Scale Image Recognition,”的论文作者使用了水平翻转TTA:
我们还通过水平翻转图像来增强测试集;对原始图像和翻转图像的soft-max类后验图像进行平均,得到图像的最终分数。
类似地,在2015年发表的一篇题为《Rethinking the Inception Architecture for Computer Vision》的论文中,谷歌的作者使用了几剪切技术,他们称之为multi-crop评价。
Keras中TTA
Keras深度学习库并没有提供测试时间增强功能,但是可以很容易地实现。
ImageDataGenerator类可用于测试。例如,将下面的数据生成器配置为水平翻转图像数据增强。
#configureimagedataaugmentationdatagen=ImageDataGenerator(horizontal_flip=True)
然后,扩展可以分别应用到测试数据集中的每个样本。
首先,单个图像的维数可以从rows[channels]扩展到samples[cols ] [channels],单个图像的样本数为1。这将图像数组转换为包含一个图像的样本数组。
#convertimageintodatasetsamples=expand_dims(image, 0)
接下来,可以创建一个迭代器,并且可以使用批大小指定要生成的增强图像的数量,比如10个。
#prepareiteratorit=datagen.flow(samples, batch_size=10)
然后可以将迭代器传递给模型的predict_generator()函数,以便做出预测。具体来说,将生成一批10张增强图像,模型将对每一张图像进行预测。
#makepredictionsforeachaugmentedimageyhats=model.predict_generator(it, steps=10, verbose=0)
最后,可以进行集成预测。在图像多类分类的情况下,对每幅图像进行预测,每个预测包含属于每类图像的概率。
可以使用软投票进行集成预测,其中每个类的概率在预测中求和,通过计算求和预测的argmax()来进行类预测,并返回最大求和概率的索引或类标签。
#sumacrosspredictionssummed=numpy.sum(yhats, axis=0) #argmaxacrossclassesreturnargmax(summed)
我们可以将这些元素绑定到一个函数中,该函数将接受配置的数据生成器、拟合模型和单个图像,并使用测试时间扩展返回一个类预测(整数)。
#makeapredictionusingtest-timeaugmentationdeftta_prediction(datagen, model, image, n_examples): #convertimageintodatasetsamples=expand_dims(image, 0) #prepareiteratorit=datagen.flow(samples, batch_size=n_examples) #makepredictionsforeachaugmentedimageyhats=model.predict_generator(it, steps=n_examples, verbose=0) #sumacrosspredictionssummed=numpy.sum(yhats, axis=0) #argmaxacrossclassesreturnargmax(summed)
现在我们知道了如何使用测试时扩展在Keras中进行预测,让我们通过一个示例来演示这种方法。
数据集和基线模型
我们可以使用标准的计算机视觉数据集和卷积神经网络来演示测试时间的增强。
在此之前,我们必须选择数据集和基线模型。
我们将使用CIFAR-10数据集,包含60000张32×32像素的彩色照片,对象来自10类,如青蛙、鸟、猫、船等。CIFAR-10是一个易于理解的数据集,广泛用于机器学习领域的计算机视觉算法的基准测试。
我们还将使用卷积神经网络(CNN)模型,该模型能够在这个问题上获得良好(优于随机)的结果,但不是最先进的结果。这将足以演示测试时间增强可以提供的性能提升。
通过调用cifar10.load_data()函数,可以通过Keras API轻松加载CIFAR-10数据集,该函数返回一个元组,该元组包含分割为输入(图像)和输出(类标签)组件的训练和测试数据集。
#loaddataset(trainX, trainY), (testX, testY) =load_data()
在建模之前,最好将0-255范围内的像素值归一化到0-1范围内。这确保了输入很小并且接近于零,反过来,这意味着模型的权值将保持很小,从而导致更快更好的学习。
#normalizepixelvaluestrainX=trainX.astype('float32') /255testX=testX.astype('float32') /255
类标签是整数,在建模之前必须转换为一个热编码。
这可以使用to_categorical() Keras实用程序函数来实现。
#onehotencodetargetvaluestrainY=to_categorical(trainY) testY=to_categorical(testY)
现在,我们准备为这个多分类问题定义一个模型。
该模型有一个卷积层,包含32个滤波器映射,使用整流线性激活的3×3内核,“相同的”填充,因此输出与输入的大小和权重初始化相同。接下来是批处理规范化层和最大池化层。
这个模式通过卷积、批处理范数和最大池化层重复,尽管过滤器的数量增加到64个。然后输出被平展,然后由密集层解释,最后提供给输出层作出预测。
#definemodelmodel=Sequential() model.add(Conv2D(32, (3, 3), activation='relu', padding='same', kernel_initializer='he_uniform', input_shape=(32, 32, 3))) model.add(BatchNormalization()) model.add(MaxPooling2D((2, 2))) model.add(Conv2D(64, (3, 3), activation='relu', padding='same', kernel_initializer='he_uniform')) model.add(BatchNormalization()) model.add(MaxPooling2D((2, 2))) model.add(Flatten()) model.add(Dense(128, activation='relu', kernel_initializer='he_uniform')) model.add(BatchNormalization()) model.add(Dense(10, activation='softmax'))
采用Adam优化器。
采用分类交叉熵损失函数进行多类分类,并在训练过程中监测分类精度。
#compilemodelmodel.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
该模型进行3个训练批次,使用的是128幅图像没批。
#fitmodelmodel.fit(trainX, trainY, epochs=3, batch_size=128)
在测试数据集上评估模型。
#evaluatemodel_, acc=model.evaluate(testX, testY, verbose=0) print(acc)
下面列出了完整的示例,它可以在几分钟内轻松地在CPU上运行。
#baselinecnnmodelforthecifar10problemfromkeras.datasets.cifar10importload_datafromkeras.utilsimportto_categoricalfromkeras.modelsimportSequentialfromkeras.layersimportConv2Dfromkeras.layersimportMaxPooling2Dfromkeras.layersimportDensefromkeras.layersimportFlattenfromkeras.layersimportBatchNormalization#loaddataset(trainX, trainY), (testX, testY) =load_data() #normalizepixelvaluestrainX=trainX.astype('float32') /255testX=testX.astype('float32') /255#onehotencodetargetvaluestrainY=to_categorical(trainY) testY=to_categorical(testY) #definemodelmodel=Sequential() model.add(Conv2D(32, (3, 3), activation='relu', padding='same', kernel_initializer='he_uniform', input_shape=(32, 32, 3))) model.add(BatchNormalization()) model.add(MaxPooling2D((2, 2))) model.add(Conv2D(64, (3, 3), activation='relu', padding='same', kernel_initializer='he_uniform')) model.add(BatchNormalization()) model.add(MaxPooling2D((2, 2))) model.add(Flatten()) model.add(Dense(128, activation='relu', kernel_initializer='he_uniform')) model.add(BatchNormalization()) model.add(Dense(10, activation='softmax')) #compilemodelmodel.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy']) #fitmodelhistory=model.fit(trainX, trainY, epochs=3, batch_size=128) #evaluatemodel_, acc=model.evaluate(testX, testY, verbose=0) print(acc)
实例运行表明,该模型能够很好地快速学习问题。