使用神经网络和深度学习模型时需要准备数据。对于复杂的图像对象物件识别的任务,也需要越来越多的数据增强功能。
在这篇文章中,您将了解使用Keras开发深度学习模型时,如何使用数据准备和数据增强来让您的模型的效能更好。
Keras图像增强API
Keras的图像增强(image augmentation) API简单而强大。
Keras提供ImageDataGenerator类别,用于定义图像数据准备和增强的配置。这包括以下功能:
- 图像随机旋转(rotate)
- 图像随机偏移(shift)
- 图像随机推移错切(shear)
- 图像随机翻转(flip)
- Sample-wise 图像像素标准化
- Feature-wise 图像像素标准化
- ZCA 白化转换
- 图像张量维度的重排序
- 储存增强图像数据
- 增强图像生成器可以透过以下的方法创建:
datagen = ImageDataGenerator()
Keras并不是在记忆体中对整个图像数据集执行图像转换操作,而是设计为通过深度学习模型训练过程进行迭代,从而为您动态地创建增强的图像数据。这会减少您的记忆体开销,但在模型训练期间会增加一些额外的时间成本。
创建并配置好ImageDataGenerator之后,您必须用您的数据来训练它。这个步骤将计算实际执行转换到您的图像数据所需的任何统计参数。您可以通过调用数据生成器上的fit( )函数并将传递您的训练数据集来完成这个前置动作。
datagen.fit(train)
数据生成器本身实际上是一个迭代器,当被呼叫时返回一个批量的图像资料。我们可以通过调用flow( )函数来配置批量大小并并获取批量的图像资料。
X_batch, y_batch = datagen.flow(train, train, batch_size=32)
最后我们就可以使用数据生成器。我们不必调用我们模型的fit( )函数,而是调用fit_generator( )函数,并传递数据生成器的实例(instance)和每个循环的步数(steps_per_epoch)以及要训练的循环总数(epochs)。
model.fit_generator(datagen.flow(X_train, Y_train, batch_size=batch_size),
steps_per_epoch=len(X_train)/batch_size,
epochs=nb_epoch)
您可以在Keras文档中了解关于Keras 图像数据生成器API或是图像数据生成器API中文更多信息。
图像增强(Image Augmentation)相关参数的比较
现在您已经知道Keras中的图像增强API是如何工作的,我们来看一些例子。
这些例子中我们将使用MNIST手写数字识别的图像集。首先,让我们看看训练数据集中的前6个图像。
import keras
# Plot images
from keras.datasets import mnist
import matplotlib.pyplot as plt
# load data
( X_train , y_train ), ( X_test , y_test ) = mnist . load_data ()
plt . figure ( figsize = ( 8 , 8 )) #设定每个图像显示的大小
#产生一个3x2网格的组合图像
for i in range ( 0 , 6 ):
plt . subplot ( 330 + 1 + i ) # (331) ->第一个子图像, (332) ->第二个子图像
plt . title ( y_train [ i ])
plt . axis ( 'off' ) #不显示坐标
plt . imshow ( X_train [ i ], cmap = plt . get_cmap ( 'gray' )) # 以灰阶的图像显示
#展现出图像
plt . show ()
运行这个例子会提供了以上的图片,我们可以用它来比较下面例子中的图片准备(image preparation)和增强(augmentation)对图像转换效果的理解。
随机旋转(Random Rotations)
有时您的样本数据中的图像可能在场景中会有不同的旋转的角度。
在训练您的模型时,妳可以透过随机旋转训练数据集里的图像来产生一些新的训练图像来帮助您的模型可以更好地处理图像的旋转问题。
下面的范例通过设置rotation_range参数来创建更多的MNIST数字图像(随机旋转最多可达90度)。
#随机旋转(Random Rotations)
from keras.datasets import mnist
from keras.preprocessing.image import ImageDataGenerator
import matplotlib.pyplot as plt
#载入数据
( X_train , y_train ), ( X_test , y_test ) = mnist . load_data ()
#将图像数据集的维度进行改变
#改变前: [样本数,图像宽,图像高] ->改变后: [样本数,图像宽,图像高,图像频道数]
X_train = X_train . reshape ( X_train . shape [ 0 ], 28 , 28 , 1 )
X_test = X_test . reshape ( X_test . shape [ 0 ], 28 , 28 , 1 )
#将像素值由"整数(0~255)"换成"浮点数(0.0~255.0)"
X_train = X_train . astype ( 'float32' )
X_test = X_test . astype ( 'float32' )
#定义"图像数据增强产生器(ImageDataGenerator)"的参数
datagen = ImageDataGenerator ( rotation_range = 90 )
#透过训练数据集来训练(fit)图像数据增强产生器(ImageDataGenerator)的实例
datagen . fit ( X_train )
#设定要"图像数据增强产生器(ImageDataGenerator)"产生的图像批次值(batch size)
# "图像数据增强产生器(ImageDataGenerator)"会根据设定回传指定批次量的新生成图像数据
for X_batch , y_batch in datagen . flow ( X_train , y_train , batch_size = 9 ):
plt . figure ( figsize = ( 8 , 8 )) #设定每个图像显示的大小
#产生一个3x3网格的组合图像
for i in range ( 0 , 6 ):
plt . subplot ( 331+ i )
plt . title ( y_batch [ i ]) #秀出图像的真实值
plt . axis ( 'off' ) #不显示坐标
plt . imshow ( X_batch [ i ] . reshape ( 28 , 28 ), cmap = plt . get_cmap ( 'gray' ))
plt . show ()
break #跳出回圈
运行以上范例,您可以看到图像已左右旋转至90度的极限。这个”随机旋转”的功能对解决MNIST数字辨识这个问题没有什么帮助,因为MNIST数字有一个标准化的方向,但是当您要辨识的对象或物件需要不同方向的照片来进行训练学习时,这种转换可能有相当的帮助。
随机偏移(Random Shifts)
图像中的对象或物件在图框中的位置可能在最中间。他们可能以各种不同的方式偏离图框的中心点。
您可以训练您的深度学习网络,通过人工创建您的训练数据的偏移图像来让您的模型能够辨识和处理偏离中心的对象或物件。Keras的”图像数据增强产生器(ImageDataGenerator)”支持通过width_shift_range和height_shift_range两个参数设定来对训练数据进行水平和垂直随机转换来产生新图像数据。
#随机偏移(Random Shifts)
from keras.datasets import mnist
from keras.preprocessing.image import ImageDataGenerator
import matplotlib.pyplot as plt
#载入数据
( X_train , y_train ), ( X_test , y_test ) = mnist . load_data ()
#将图像数据集的维度进行改变
#改变前: [样本数,图像宽,图像高] ->改变后: [样本数,图像宽,图像高,图像频道数]
X_train = X_train . reshape ( X_train . shape [ 0 ], 28 , 28 , 1 )
X_test = X_test . reshape ( X_test . shape [ 0 ], 28 , 28 , 1 )
#将像素值由"整数(0~255)"换成"浮点数(0.0~255.0)"
X_train = X_train . astype ( 'float32' )
X_test = X_test . astype ( 'float32' )
#定义"图像数据增强产生器(ImageDataGenerator)"的参数
shift = 0.2
datagen = ImageDataGenerator ( width_shift_range = shift , height_shift_range = shift )
#透过训练数据集来训练(fit)图像数据增强产生器(ImageDataGenerator)的实例
datagen . fit ( X_train )
#设定要"图像数据增强产生器(ImageDataGenerator)"产生的图像批次值(batch size)
# "图像数据增强产生器(ImageDataGenerator)"会根据设定回传指定批次量的新生成图像数据
for X_batch , y_batch in datagen . flow ( X_train , y_train , batch_size = 9 ):
plt . figure ( figsize = ( 8 , 8 )) #设定每个图像显示的大小
#产生一个3x3网格的组合图像
for i in range ( 0 , 6 ):
plt . subplot ( 331+ i )
plt . title ( y_batch [ i ]) #秀出图像的真实值
plt . axis ( 'off' ) #不显示坐标
plt . imshow ( X_batch [ i ] . reshape ( 28 , 28 ), cmap = plt . get_cmap ( 'gray' ))
plt . show ()
break #跳出回圈
运行此范例将创建新的MNIST数字图像的位移版本。同样的,这对于MNIST来说不是必须的,因为手写数字已经居中,但是你可以看到这对于更复杂的图像问题来说可能是有用的。
随机推移错切(Random Shear)
透过一个图像的错切变换,图像以它的中心垂直轴不变动的方式变形。可以用这样的技术来产生新的经过错切变换的图像数据。
Keras的”图像数据增强产生器(ImageDataGenerator)”支持使用shear_range参数设定来对训练数据进行图像错切变换来产生新图像数据。
#随机推移错切(Random Shear)
from keras.datasets import mnist
from keras.preprocessing.image import ImageDataGenerator
import matplotlib.pyplot as plt
#载入数据
( X_train , y_train ), ( X_test , y_test ) = mnist . load_data ()
#将图像数据集的维度进行改变
#改变前: [样本数,图像宽,图像高] ->改变后: [样本数,图像宽,图像高,图像频道数]
X_train = X_train . reshape ( X_train . shape [ 0 ], 28 , 28 , 1 )
X_test = X_test . reshape ( X_test . shape [ 0 ], 28 , 28 , 1 )
#将像素值由"整数(0~255)"换成"浮点数(0.0~255.0)"
X_train = X_train . astype ( 'float32' )
X_test = X_test . astype ( 'float32' )
#定义"图像数据增强产生器(ImageDataGenerator)"的参数
shear_range = 1.25 #推移错切的强度
datagen = ImageDataGenerator ( shear_range = shear_range )
#透过训练数据集来训练(fit)图像数据增强产生器(ImageDataGenerator)的实例
datagen . fit ( X_train )
#设定要"图像数据增强产生器(ImageDataGenerator)"产生的图像批次值(batch size)
# "图像数据增强产生器(ImageDataGenerator)"会根据设定回传指定批次量的新生成图像数据
for X_batch , y_batch in datagen . flow ( X_train , y_train , batch_size = 9 ):
plt . figure ( figsize = ( 8 , 8 )) #设定每个图像显示的大小
#产生一个3x3网格的组合图像
for i in range ( 0 , 6 ):
plt . subplot ( 331+ i )
plt . title ( y_batch [ i ]) #秀出图像的真实值
plt . axis ( 'off' ) #不显示坐标
plt . imshow ( X_batch [ i ] . reshape ( 28 , 28 ), cmap = plt . get_cmap ( 'gray' ))
plt . show ()
break #跳出回圈
随机镜像翻转(Random Flips)
另一个可以提高大型复杂图像问题辨识性能的图像增强法,是在您的图像训练数据中利用图像随机翻转来产生新的图像数据。
Keras的”图像数据增强产生器(ImageDataGenerator)”支持使用vertical_flip和horizontal_flip两个参数设定来对训练数据进行垂直和水平轴随机翻转来产生新图像数据。
#随机镜像翻转(Random Flips)
from keras.datasets import mnist
from keras.preprocessing.image import ImageDataGenerator
import matplotlib.pyplot as plt
#载入数据
( X_train , y_train ), ( X_test , y_test ) = mnist . load_data ()
#将图像数据集的维度进行改变
#改变前: [样本数,图像宽,图像高] ->改变后: [样本数,图像宽,图像高,图像频道数]
X_train = X_train . reshape ( X_train . shape [ 0 ], 28 , 28 , 1 )
X_test = X_test . reshape ( X_test . shape [ 0 ], 28 , 28 , 1 )
#将像素值由"整数(0~255)"换成"浮点数(0.0~255.0)"
X_train = X_train . astype ( 'float32' )
X_test = X_test . astype ( 'float32' )
#定义"图像数据增强产生器(ImageDataGenerator)"的参数
datagen = ImageDataGenerator ( horizontal_flip = True , vertical_flip = True )
#透过训练数据集来训练(fit)图像数据增强产生器(ImageDataGenerator)的实例
datagen . fit ( X_train )
#设定要"图像数据增强产生器(ImageDataGenerator)"产生的图像批次值(batch size)
# "图像数据增强产生器(ImageDataGenerator)"会根据设定回传指定批次量的新生成图像数据
for X_batch , y_batch in datagen . flow ( X_train , y_train , batch_size = 9 ):
plt . figure ( figsize = ( 8 , 8 )) #设定每个图像显示的大小
#产生一个3x3网格的组合图像
for i in range ( 0 , 6 ):
plt . subplot ( 331+ i )
plt . title ( y_batch [ i ]) #秀出图像的真实值
plt . axis ( 'off' ) #不显示坐标
plt . imshow ( X_batch [ i ] . reshape ( 28 , 28 ), cmap = plt . get_cmap ( 'gray' ))
plt . show ()
break #跳出回圈
运行这个范例,您可以看到翻转的数字。翻转数字对于MNIST来说是没有用的,因为它们总是具有正确的左右方向,但是这对于可能具有不同方向的场景中的对象的照片的问题可能是有用的。
影像特征标准化(Feature Standardization)
我们可以把整个数据集中的每个像素值来进行标准化(standardize pixel)。这被称为特征标准化,你可以想像影像特征标准化的程序如同我们对一般表格数据集中每个列会进次的资料标准化。
您可以通过在ImageDataGenerator类别上设置featurewise_center和featurewise_std_normalization的参数来执行影像特征标准化。
#对整个资料集进行"影像特征标准化" , mean=0, stdev=1
from keras.datasets import mnist
from keras.preprocessing.image import ImageDataGenerator
import matplotlib.pyplot as plt
#在keras的backend预设使用tensorflow
#而tensorflow在处理图像是的资料结构是3维的张量(图像宽:width,图像高:height,图像频道:channel)
#载入数据
( X_train , y_train ), ( X_test , y_test ) = mnist . load_data ()
#将图像数据集的维度进行改变
#改变前: [样本数,图像宽,图像高] ->改变后: [样本数,图像宽,图像高,图像频道数]
X_train = X_train . reshape ( X_train . shape [ 0 ], 28 , 28 , 1 )
X_test = X_test . reshape ( X_test . shape [ 0 ], 28 , 28 , 1 )
#将像素值由"整数(0~255)"换成"浮点数(0.0~255.0)"
X_train = X_train . astype ( 'float32' )
X_test = X_test . astype ( 'float32' )
#定义"图像数据增强产生器(ImageDataGenerator)"的参数
datagen = ImageDataGenerator ( featurewise_center = True ,
featurewise_std_normalization = True )
#透过训练数据集来训练(fit)图像数据增强产生器(ImageDataGenerator)的实例
datagen . fit ( X_train )
#设定要"图像数据增强产生器(ImageDataGenerator)"产生的图像批次值(batch size)
# "图像数据增强产生器(ImageDataGenerator)"会根据设定回传指定批次量的新生成图像数据
for X_batch , y_batch in datagen . flow ( X_train , y_train , batch_size = 9 ):
plt . figure ( figsize = ( 8 , 8 )) #设定每个图像显示的大小
#产生一个3x3网格的组合图像
for i in range ( 0 , 6 ):
plt . subplot ( 331+ i )
plt . title ( y_batch [ i ]) #秀出图像的真实值
plt . axis ( 'off' ) #不显示坐标
plt . imshow ( X_batch [ i ] . reshape ( 28 , 28 ), cmap = plt . get_cmap ( 'gray' ))
plt . show ()
break #跳出回圈
ZCA白化转换(ZCA Whitening)
图像的白化变换是为了减少图像像素矩阵中的冗余/去除相关性(共线性)的线性特征所进行的代数运算转换。
进行图像中像素矩阵去除相关性的转换是为了更好地突显图像中的结构和特征到学习演算法。
这个转换的概念在以前大多是使用主成分分析(PCA)技术来执行图像白化。最近,ZCA的技术显示了更好的结果,对图像进行ZCA转换后的图像可以保留原始尺寸的大小,从而使转换后的图像仍然看起来像原始图像(这一点与PCA是不同的)。
您可以通过将zca_whitening参数设置为True来执行ZCA白化转换。
# ZCA白化转换(ZCA Whitening)
from keras.datasets import mnist
from keras.preprocessing.image import ImageDataGenerator
import matplotlib.pyplot as plt
#载入数据
( X_train , y_train ), ( X_test , y_test ) = mnist . load_data ()
#将图像数据集的维度进行改变
#改变前: [样本数,图像宽,图像高] ->改变后: [样本数,图像宽,图像高,图像频道数]
X_train = X_train . reshape ( X_train . shape [ 0 ], 28 , 28 , 1 )
X_test = X_test . reshape ( X_test . shape [ 0 ], 28 , 28 , 1 )
#将像素值由"整数(0~255)"换成"浮点数(0.0~255.0)"
X_train = X_train . astype ( 'float32' )
X_test = X_test . astype ( 'float32' )
#定义"图像数据增强产生器(ImageDataGenerator)"的参数
datagen = ImageDataGenerator ( zca_whitening = True )
#透过训练数据集来训练(fit)图像数据增强产生器(ImageDataGenerator)的实例
datagen . fit ( X_train )
#设定要"图像数据增强产生器(ImageDataGenerator)"产生的图像批次值(batch size)
# "图像数据增强产生器(ImageDataGenerator)"会根据设定回传指定批次量的新生成图像数据
for X_batch , y_batch in datagen . flow ( X_train , y_train , batch_size = 9 ):
plt . figure ( figsize = ( 8 , 8 )) #设定每个图像显示的大小
#产生一个3x3网格的组合图像
for i in range ( 0 , 6 ):
plt . subplot ( 331+ i )
plt . title ( y_batch [ i ]) #秀出图像的真实值
plt . axis ( 'off' ) #不显示坐标
plt . imshow ( X_batch [ i ] . reshape ( 28 , 28 ), cmap = plt . get_cmap ( 'gray' ))
plt . show ()
break #跳出回圈
运行以上范例,您可以在图像中看到相同的一般数字结构以及每个数字的轮廓如何被突显。
储存增强的图像数据(Saving Augmented Images to File)
数据准备和增强由Keras在模型训练的运行中进行。
这对记忆体的使用效率很高,但是您有可能需要在训练期间使用在档案系统中图像档。例如,也许您希望稍后使用不同的套件进行分析,或者只生成一次新增强的图像数据,然后在多种不同的深度学习模型或配置中使用它们。
Keras允许您保存训练期间动态生成的图像。您可以在训练前指定给flow()函数有关于您想保存的目录、文件名前缀和图像文件类型。然后在训练过程中,动态生成的图像将被写入到档案系统中。
下面的范例演示了这一点,并将6个图像写入“images”子目录,前缀为“aug”,文件类型为PNG。
#储存增强的图像数据(Saving Augmented Images to File)
from keras.datasets import mnist
from keras.preprocessing.image import ImageDataGenerator
import matplotlib.pyplot as plt
import os
#载入数据
( X_train , y_train ), ( X_test , y_test ) = mnist . load_data ()
#将图像数据集的维度进行改变
#改变前: [样本数,图像宽,图像高] ->改变后: [样本数,图像宽,图像高,图像频道数]
X_train = X_train . reshape ( X_train . shape [ 0 ], 28 , 28 , 1 )
X_test = X_test . reshape ( X_test . shape [ 0 ], 28 , 28 , 1 )
#将像素值由"整数(0~255)"换成"浮点数(0.0~255.0)"
X_train = X_train . astype ( 'float32' )
X_test = X_test . astype ( 'float32' )
#定义"图像数据增强产生器(ImageDataGenerator)"的参数
datagen = ImageDataGenerator ()
#透过训练数据集来训练(fit)图像数据增强产生器(ImageDataGenerator)的实例
datagen . fit ( X_train )
#产生要保存图像档案的目录
if not os . path . exists ( 'images' ):
os . makedirs ( 'images' )
#设定要"图像数据增强产生器(ImageDataGenerator)"产生的图像批次值(batch size)
# "图像数据增强产生器(ImageDataGenerator)"会根据设定回传指定批次量的新生成图像数据
for X_batch , y_batch in datagen . flow ( X_train , y_train , batch_size = 9 , save_to_dir = 'images' , save_prefix = 'aug' , save_format = 'png' ):
plt . figure ( figsize = ( 8 , 8 )) #设定每个图像显示的大小
#产生一个3x3网格的组合图像
for i in range ( 0 , 6 ):
plt . subplot ( 331 + i )
plt . title ( y_batch [ i ]) #秀出图像的真实值
plt . axis ( 'off' ) #不显示坐标
plt . imshow ( X_batch [ i ] . reshape ( 28 , 28 ), cmap = plt . get_cmap ('gray' ))
plt . show ()
break #跳出回圈
运行范例,您可以看到只有在图像生成时才会也把写入图像写到档案系统中。
用Keras增强图像数据的技巧
图像数据很独特,因为您可以查看数据和数据的转换副本,并快速了解模型如何通过您的图像感知到某种影像特征。
以下是从图像数据准备和增强深度学习中获得最多的一些时间。
- 查看图像数据集花一些时间仔细检查你的数据集。看图像。注意可能有利于模型训练过程的图像准备和增强,例如需要处理场景中不同的轮班,旋转或翻转对象。
- 查看增强过的图像增强操作完成后,查看一些范例图像。理智地知道你正在使用什么样的图像变换是一回事,真正看到范例图像是非常不同的事情。查看您正在使用的单个增强图像以及您计划使用的全套增强图像。您可能会看到简化或进一步增强您的模型训练的方法。
- 评估一整套变换尝试多个图像数据准备和增强方案。通常情况下,您认为这样做不会有好处的转换,最后您可能会对数据增强后对模型的结果感到惊讶。
总结
在这篇文章中,您了解了图像数据准备和增强的一些面向。
您发现了一系列可以轻松使用Keras来使用图像数据增强(data augmentation)应用在深度学习模型的技术。您了解到:
- Keras中的ImageDataGenerator API可以用来动态产生新的转换后的图像来用于训练。
- 图像像素的标准化手法。
- ZCA白化转换。
- 对图像进行随机旋转,移动和翻转。
- 如何将转换后的图像保存到档案系统中以备后用。