图像数据加强是人工增长训练集的一种方式,主要是经过修改数据集中的图片达成。html
更多的训练数据带来的是更有效的深度学习模型,同时,数据加强技术会产生更多的图片变体,这些变体会提升模型对新图片的泛化能力。前端
在 Keras 框架中,ImageDataGenerator 类提供了数据加强的相关功能。python
在本教程中,你将学会如何在训练模型时使用图像数据加强技术。android
在完成本教程后,你将明白下面几点:ios
让咱们开始吧。git
本教程被分为如下八个部分,他们分别是:github
深度学习网络的表现老是和数据量成正比的。后端
数据加强是一种人工的在原有数据基础上增长新训练数据的方法,是利用特定领域的技术将训练集的数据转变成一个新的数据达成的。数组
图像数据加强大概是最众所周知的一种数据加强方法,主要是涉及建立一个和原始图片属于同一类别的变形后的图片。网络
从图像处理领域咱们能够得到不少的变形方法,好比:平移、翻转、缩放等等。
这么作的主要意图是用合理的新数据去扩展训练数据。换句话说,咱们可让模型看到更多样性的训练数据。举个例子,若是咱们对一只猫进行水平的翻转,这个是有意义的,由于摄像头的拍摄角度多是左边也多是右边。可是作垂直翻转就没什么意义而且不太适合,由于模型不太会接收到一个头上脚下的猫。
因此,咱们应该明白,咱们必定要根据训练数据和问题领域的具体场景来慎重的选择应用于训练集的数据加强方法。此外,有一种比较有效的方法,就是在小的原型数据集上作一些独立的实验来度量加强后的模型是否在性能上有所提高。
现代的深度学习方法,像卷积神经网络(CNN),均可以学习到图片中的位置无关性特征。数据加强能够帮助模型去学习这种性质而且可使得模型对一些变化也不敏感,好比左到右和上到下的顺序、照片的光照变化等等。
这些图片数据的加强通常是应用于训练集而不是验证集和测试集。这些数据加强方法不一样于那些须要在各个与模型交互的数据集上都保持一致的预处理方法,好比调整图片大小与缩放像素值等。
如今就参加个人7天电子邮件速成课(包含示例代码)。
点击注册还有能够得到课程的免费 PDF 版本。
咱们须要一个样本图片来展现标准的数据加强技术。
本教程中,咱们会用到一个已经得到使用许可,由 AndYaDontStop 拍摄,名为 Feathered Friend 的鸟类照片。
下载这张照片,并保存在你的工做目录命名为 ‘bird.jpg‘。
Feathered Friend,做者 AndYaDontStop。
保留部分权力.
Keras 框架能够在训练模型时,自动使用数据加强。
能够利用 ImageDataGenerator 类 达到这一目的。
首先,能够在类实例化时传入特定的参数到构造函数来配置对应的加强方法。
该类支持一系列的加强方法,包括像素值的缩放,可是咱们只关注如下五种主要的图像数据加强方法:
width_shift_range
和 height_shift_range
参数设置图像平移。一个经过构造函数实例化 ImageDataGenerator 的例子。
# 建立数据生成器
datagen = ImageDataGenerator()
复制代码
一旦构造完成,这个数据集的迭代器就被建立了。
这个迭代器每次迭代会返回一个批次的加强数据。
利用 flow() 函数能够将读入了内存的数据集建立为一个迭代器,示例代码以下:
# 读取图片数据集
X, y = ...
# 建立迭代器
it = dataset.flow(X, y)
复制代码
或者,能够对指定的文件路径的数据集建立一个迭代器,在这个文件夹中,不一样子类的数据须要存放到不一样的子文件夹中。
...
# 建立迭代器
it = dataset.flow_from_directory(X, y, ...)
复制代码
迭代器建立完成后,能够经过调用 fit_generator() 函数来训练神经网络。
steps_per_epoch
参数须要设定为能包含整个数据集的批次数。举个例子,若是你的原始数据是 10000 张图片,同时你的 batch_size 设置为 32,那么当你训练一个基于加强数据的模型时,一个合理的 steps_per_epoch
应该设置为 ceil(10,000/32),或者说 313 个批次。
# 定义模型
model = ...
# 在加强数据集上拟合模型
model.fit_generator(it, steps_per_epoch=313, ...)
复制代码
数据集中的图片并无被直接使用,而是将加强后的图片提供给模型。因为加强的图片表现是随机的,允许修改后的图片以及接近原图(例如,几乎没有加强的图片)的数据被生成并在训练中使用。
数据的生成器也可使用在验证集和测试集上。一般来讲,用于验证集和测试集的 ImageDataGenerator 会和训练集的 ImageDataGenerator 有相同的像素值缩放配置(本教程未涉及),可是不会涉及到数据加强。这是由于数据加强的目的是为了能够人工的扩充训练数据集的数量,进而去提升模型在未作加强的数据集上的表现。
如今咱们已经熟悉了 ImageDataGenerator 的用法,那么我去看几个具体的针对于图像数据的加强方法。
咱们会单独的展现每一种方法加强后的图片效果图。这是一种很好的事件方式,建议在在配置大家本身的数据加强时也这么作。在训练过程当中,同时采用好几种加强方法也是很常见的。这里为了达到展现的效果,咱们分章节单独的讨论每个加强方法。
平移意味着将图片上的全部像素沿着某一个方向移动,能够是水平或者垂直,同时要保证大小没有变化。
这也意味着一些原有的像素点会被移出图片,那么就会有一块区域的像素值须要从新指定。
width_shift_range
和 height_shift_range
两个参数分别用来控制水平和垂直方向平移的大小,它们是在 ImageDataGenerator 类被构造的时候传入的。
这两个参数能够被指定为一个 0 到 1 之间的小数,表明着平移距离相对于宽度或者高度的百分比。或者,也能够被指定为一个确切的像素值。
具体来讲,实际的平移值会在没有平移和百分比(或者具体的像素值)之间选取一个,用该值来处理图片,距离来讲,就是在 [0, value] 之间选择。或者,你能够传入一组指定的元组或数组,肯定具体的最大和最小值来进行采样,举个例子:[-100, 100] 或者 [-0.5, 0.5]。
下面展现的就是一个将平移参数 width_shift_range
设置为 [-200, 200] 像素,并画出对应结果的代码。
# 水平平移加强的例子
from numpy import expand_dims
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
from keras.preprocessing.image import ImageDataGenerator
from matplotlib import pyplot
# 读入图片
img = load_img('bird.jpg')
# 转换为 numpy 数组
data = img_to_array(img)
# 扩展维度
samples = expand_dims(data, 0)
# 生成数据加强迭工厂
datagen = ImageDataGenerator(width_shift_range=[-200,200])
# 准备迭代器
it = datagen.flow(samples, batch_size=1)
# 生成数据并画图
for i in range(9):
# 定义子图
pyplot.subplot(330 + 1 + i)
# 生成一个批次图片
batch = it.next()
# 转换为无符号整型方便显示
image = batch[0].astype('uint32')
# 画图
pyplot.imshow(image)
# 展现图片
pyplot.show()
复制代码
执行这段代码,经过配置 ImageDataGenerator 会生成一个图片加强实例,并建立一个迭代器。这个迭代器会在一个循环中被执行 9 次并画出每一次通过加强后的图片。
我经过观察画出的结果能够发现,图片会进行随机的正向或者负向的平移,同时平移带来的空白区域会使用边缘区域的像素来填充。
随机平移数据加强结果图
下面是相似的例子,经过调整 height_shift_range
参数实现垂直平移,其中该参数被设置为 0.5。
# 垂直平移加强的例子
from numpy import expand_dims
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
from keras.preprocessing.image import ImageDataGenerator
from matplotlib import pyplot
# 读图
img = load_img('bird.jpg')
# convert to numpy array
data = img_to_array(img)
# 扩展维度
samples = expand_dims(data, 0)
# 建立一个生成器
datagen = ImageDataGenerator(height_shift_range=0.5)
# 准备迭代器
it = datagen.flow(samples, batch_size=1)
# 生成样本和画图
for i in range(9):
# 定义子图
pyplot.subplot(330 + 1 + i)
# 生成一个批次的图片
batch = it.next()
# 转换为整形显示
image = batch[0].astype('uint32')
# 画图
pyplot.imshow(image)
# 显示
pyplot.show()
复制代码
运行这段代码,就能够随机的产生经过正向或者负向平移的加强图片。
能够发现水平位移或者垂直位移,不管是正向平或者负向均可以有效的加强对应的图片,可是那些被从新填充的部分对模型就没什么意义了。
值得一提的是,其余的填充方式是能够经过 “fill_mode” 参数来指定的。
垂直随机平移的效果图
图片的翻转就是在垂直翻转时颠倒全部行的像素值,在水平翻转时颠倒全部列的像素值。
翻转的参数是构造 ImageDataGenerator 类时,分别经过 boolean 型的参数 horizontal_flip 或者 vertical_flip 来指定的。针对于以前提到的鸟的图片,水平翻转是有意义的,而垂直翻转是没什么意义的。
而对于航拍图片、天文图片和显微图片而言,垂直翻转很大多是有效的。
下面的例子就是经过控制 horizontal_flip 参数来实现图片翻转加强的例子。
# 水平翻转示例
from numpy import expand_dims
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
from keras.preprocessing.image import ImageDataGenerator
from matplotlib import pyplot
# 读图
img = load_img('bird.jpg')
# 转为 numpy 数组
data = img_to_array(img)
# 扩展维度
samples = expand_dims(data, 0)
# 建立生成器
datagen = ImageDataGenerator(horizontal_flip=True)
# 准备迭代器
it = datagen.flow(samples, batch_size=1)
# 生成图片并画图
for i in range(9):
# 定义子图
pyplot.subplot(330 + 1 + i)
# 生成一个批次图片
batch = it.next()
# 转化为整型方便显示
image = batch[0].astype('uint32')
# 画图
pyplot.imshow(image)
# 显示
pyplot.show()
复制代码
执行这段程序会产生 9 张加强后的图片。
咱们会发现水平的翻转只是在一部分的图片上被使用了。
随机水平翻转的加强结果
旋转加强是随机的对图片进行 0 到 360 度的顺时针旋转。
旋转也会致使部分的数据被移出图片框,会产生一些没有像素值的区域,这些区域也须要被填充
下面的例子经过控制 rotation_range 参数在 0 到 90 度之间去旋转图片,来展现随机旋转加强的效果。
# 旋转加强示例
from numpy import expand_dims
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
from keras.preprocessing.image import ImageDataGenerator
from matplotlib import pyplot
# 读图
img = load_img('bird.jpg')
# 转为 numpy 数组
data = img_to_array(img)
# 扩展维度
samples = expand_dims(data, 0)
# 建立生成器
datagen = ImageDataGenerator(rotation_range=90)
# 准备迭代器
it = datagen.flow(samples, batch_size=1)
# 生成图片并画图
for i in range(9):
# 定义子图
pyplot.subplot(330 + 1 + i)
# 生成一个批次图片
batch = it.next()
# 转化为整型方便显示
image = batch[0].astype('uint32')
# 画图
pyplot.imshow(image)
# 显示
pyplot.show()
复制代码
执行这个例子,会产生旋转图片的示例,其中空白区域是经过最邻近法进行填充的。
随机旋转加强的结果图
图片的亮度加强能够是使图片变亮、使图片变暗或者兼顾二者。
这样是为了使模型在训练过程当中覆盖不一样的亮度水平。
我能够在 ImageDataGenerator() 的构造函数中传入 brightness_range 参数来指定一个最大值和最小值范围来选择一个亮度数值。
值小于 1.0 的时候,会变暗图片,如 [0.5 , 1.0],相反的,值大于 1.0 时,会使图片变亮,如 [1.0,1.5],当值为 1.0 时,亮度不会变化。
下面的例子展现了亮度在 0.2(20%) 到 1 之间变化的随机亮度加强的效果。
# 亮度加强示例
from numpy import expand_dims
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
from keras.preprocessing.image import ImageDataGenerator
from matplotlib import pyplot
# 读图
img = load_img('bird.jpg')
# 转为 numpy 数组
data = img_to_array(img)
# 扩展维度
samples = expand_dims(data, 0)
# 建立生成器
datagen = ImageDataGenerator(brightness_range=[0.2,1.0])
# 准备迭代器
it = datagen.flow(samples, batch_size=1)
# 生成图片并画图
for i in range(9):
# 定义子图
pyplot.subplot(330 + 1 + i)
# 生成一个批次图片
batch = it.next()
# 转化为整型方便显示
image = batch[0].astype('uint32')
# 画图
pyplot.imshow(image)
# 显示
pyplot.show()
复制代码
运行示例你会看到不一样数值调暗图片的效果。
随机亮度加强生成的图片
缩放加强就是随机的缩放图片,利用在图片周围新增像素或者插值来实现。
在 ImageDataGenerator 类的构造函数内传入 zoom_range 来配置缩放的尺度。该参数能够是一个浮点数也能够是数组或者元组。
若是指定为一个浮点数,那么缩放的范围是 [1 - value , 1 + value] 之间。举个例子,若是你设置的参数为 0.3,那么你的缩放范围就是 [0.7, 1.3] 之间,换言之就是 70% (放大)到 130%(缩小)之间。
缩放量是从缩放区域中对每一个维度(宽,高)分别均匀随机抽样获得的。
缩放参数有点不直观。须要明白一点,当数值小于 1.0 时图片会放大,如 [ 0.5 , 0.5] 会使图片中的目标变大或者拉近 50%,一样的,若是数值大于 1.0 时,图拼啊会被缩小 50%,如 [ 1.5 , 1.5 ] 目标会被缩小到或者拉远。当系数为 1.0 时,图片不会有什么变化。
下面的例子展现了让图片中目标变大的例子。
# 尺度缩放加强示例
from numpy import expand_dims
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
from keras.preprocessing.image import ImageDataGenerator
from matplotlib import pyplot
# 读图
img = load_img('bird.jpg')
# 转为 numpy 数组
data = img_to_array(img)
# 扩展维度
samples = expand_dims(data, 0)
# 建立生成器
datagen = ImageDataGenerator(zoom_range=[0.5,1.0])
# 准备迭代器
it = datagen.flow(samples, batch_size=1)
# 生成图片并画图
for i in range(9):
# 定义子图
pyplot.subplot(330 + 1 + i)
# 生成一个批次图片
batch = it.next()
# 转化为整型方便显示
image = batch[0].astype('uint32')
# 画图
pyplot.imshow(image)
# 显示
pyplot.show()
复制代码
运行示例就能够获得缩放图片,该图片展现了一个在宽和高尺度变化不一样的例子,因为宽高的缩放尺度不一样,图像的纵横比也会发生变化。
随机缩放加强的效果图
该部分会提供更多的资源供你进一步的学习。
本教程带你探索了图像数据加强在模型训练时的应用。
你应该有如下收获:
还有别的问题? 请在下方留言,我会尽我所能回答你的问题。
若是发现译文存在错误或其余须要改进的地方,欢迎到 掘金翻译计划 对译文进行修改并 PR,也可得到相应奖励积分。文章开头的 本文永久连接 即为本文在 GitHub 上的 MarkDown 连接。
掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 Android、iOS、前端、后端、区块链、产品、设计、人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划、官方微博、知乎专栏。