Keras神经网络的学习与使用(4)-数据增强

十年热恋 提交于 2019-11-25 19:24:30

数据增强的作用

深度学习有3个核心要素,分别是:

  • 优秀的算法设计
  • 高性能的计算能力
  • 大数据

因此在我们拥有优秀的算法设计和高性能的计算能力的同时,我们也需要大量的高质量数据。
但是,对于个人,学校团队甚至普通的工程师团队来说,数据的搜集能力都是十分有限的。缺乏大量高质量的训练样本,便难以训练处一个具有很好泛化能力的模型。因此,我们就需要一些数据集扩充的方法,即我们常说的数据增强

数据增强的概述

对于图像处理的场景,数据增强自然是对图片而言。数据增强就是指对图片数据进行变换、修改,使其变成新的图片数据,从而扩充我们的图片数据集。
图片数据增强的方法主要包括以下几个:

  • 随机裁剪
  • 颜色改变
  • 水平或竖直翻转
  • 随机改变大小
  • 加入噪声
  • 对图片进行仿射变换

通过使用数据增强的方法来实现数据集的扩充,可以使训练后的模型具有更好的鲁棒性,尤其是对噪声的抵抗能力得到强化,进而提高训练后模型的泛化能力
鲁棒性:

1.模型具有较高的精度或有效性,这也是对于机器学习中所有学习模型的基本要求;
2.对于模型假设出现的较小偏差,只能对算法性能产生较小的影响; 主要是:噪声(noise)
3.对于模型假设出现的较大偏差,不可对算法性能产生“灾难性”的影响;主要是:离群点(outlier)

泛化能力

在机器学习方法中,泛化能力通俗来讲就是指学习到的模型对未知数据的预测能力。在实际情况中,我们通常通过测试误差来评价学习方法的泛化能力。如果在不考虑数据量不足的情况下出现模型的泛化能力差,那么其原因基本为对损失函数的优化没有达到全局最优。

Keras实现数据增强

Keras为我们提供的数据增强功能是通过ImageDataGenerator类来实现的。ImageDataGenerator类主要通过生成器(generator)的方式来产生经过变化的新图片。生成器是Python提供的一个高级特性,对于list这样的容器,其中的元素是预先存储在内存中的。而生成器的特点是其中的一个元素一边生成,一边使用。换句话说,当我们遍历list时,遍历的是已经存在于list中的元素,而生成器中的元素是在遍历的过程中同时生成的,这是一种流式的效果。

keras.preprocessing.image.ImageDataGenerator(                  featurewise_center=False,                  samplewise_center=False,                  featurewise_std_normalization=False,                  samplewise_std_normalization=False,                  zca_whitening=False,                  zca_epsilon=1e-6,                  rotation_range=0,                  width_shift_range=0.,                  height_shift_range=0.,                  brightness_range=None,                  shear_range=0.,                  zoom_range=0.,                  channel_shift_range=0.,                  fill_mode='nearest',                  cval=0.,                  horizontal_flip=False,                  vertical_flip=False,                  rescale=None,                  preprocessing_function=None,                  data_format='channels_last',                  validation_split=0.0,                  interpolation_order=1,                  dtype='float32') 
  • featurewise_center:布尔值,是否将输入数据的均值设置为0。
  • samplewise_center:布尔值,是否将每个样本的均值设置为0。
  • featurewise_std_normalization:布尔值,是否将输入特征除以其标准值。
  • samlewise_std_normalization:布尔值,是否将每个输入样本除以其标准差。
  • zca_epsilon:ZCA白化的ε值,默认为1e-6。
  • zca_whitening:布尔值,决定是否应用ZCA白化的方式进行数据增强。
  • rotation_range:整数值,决定随机旋转的度数。
  • width_shift_range:浮点数、整数或者其数组,水平位置平移值。
  • height_shift_range:浮点数、整数或者其数组,垂直位置平移值。
  • shear_range:浮点数,图片剪切的强度。
  • zoom_range:浮点数或者一个区间,表示随机缩放的范围,形如[0.1, 0.2],分别表示其上界和下界。
  • channel_shift_range:浮点数,随机通道偏移的幅度。
  • fill_mode:“constant” “nearest” “reflect”或“wrap”之一,默认为“nearest”。当进行变换时,超出边界的点将根据本参数给定的方法进行处理。假设填充序列“abcd”两侧的数值,其中每个参数的填充方式如下。
  1. constant:kkkkkkkk|abcd|kkkkkkkk(假设cval参数值为k时)
  2. nearest:aaaaaaaa|abcd|dddddddd
  3. reflect:abcddcba|abcd|dcbaabcd
  4. wrap:abcdabcd|abcd|abcdabcd
  • cavl:浮点数或整型,详见fill_mode参数;
  • horizontal_flip:布尔值,是否随机水平翻转;
  • vertical_flip:布尔值,是否随机垂直翻转;
  • rescale:重缩放因子的数值,将数据乘以所提供的参数值。如果不指定该参数则默认为None。如果是None或0,则不进行缩放;
  • preprocessing_function:指定一个回调函数,这个函数会在其它任何操作之前运行。这个函数需要一个参数——图片数据(秩为3的Numpy张量)
  • data_format:图像数据格式。
  • validation_split:是一个在[0, 1]区间的浮点数,表示保留用于验证的图像比例。
keras.preprocessing.image.ImageDataGenerator.flow( x, 	  y=None, 	   batch_size=32, 	   shuffle=True, 	   sample_weight=None, 	   seed=None, 	   save_to_dir=None, 	   save_prefix='', 	   save_format='png', 	   subset=None): 

接收numpy数组和标签为参数,生成经过数据提升或标准化后的batch数据,并在一个无限循环中不断的返回batch数据

  • x:样本数据,秩应为4.在黑白图像的情况下channel轴的值为1,在彩色图像情况下值为3

  • y:标签

  • batch_size:整数,默认32

  • shuffle:布尔值,是否随机打乱数据,默认为True

  • save_to_dir:None或字符串,该参数能让你将提升后的图片保存起来,用以可视化

  • save_prefix:字符串,保存提升后图片时使用的前缀, 仅当设置了save_to_dir时生效

  • save_format:“png"或"jpeg"之一,指定保存图片的数据格式,默认"jpeg”

  • yields:形如(x,y)的tuple,x是代表图像数据的numpy数组.y是代表标签的numpy数组.该迭代器无限循环.

  • seed: 整数,随机数种子

使用示例:
注:本示例是在pycharm下运行,在flow()方法中需要设置正确的路径。

import numpy as np from keras.preprocessing.image import ImageDataGenerator, img_to_array, load_img  datagen = ImageDataGenerator(     rotation_range=40, width_shift_range=0.2, height_shift_range=0.2, rescale=1 / 255,     shear_range=20, zoom_range=0.2, horizontal_flip=True, fill_mode='nearest')  img = load_img('demo.jpg') x = img_to_array(img) # 扩展数组的形状 x = np.expand_dims(x, 0)  # 生成20张图片 i = 0 for batch in datagen.flow(x, batch_size=1, save_to_dir='genreate_images',                           save_prefix='new',                           save_format='jpg'):     i += 1     if i == 20:         break print('image generate finished!') 

自己实现数据增强

import cv2 import numpy as np import scipy.ndimage as ndi   def do_random_crop_and_rotation(image_array, translation_factor, zoom_range):     height = image_array.shape[0]     width = image_array.shape[1]      x_offset = np.random.uniform(0, translation_factor * width)     y_offset = np.random.uniform(0, translation_factor * height)      offset = np.array([x_offset, y_offset])      scale_factor = np.random.uniform(zoom_range[0], zoom_range[1])     crop_matrix = np.array([[scale_factor, 0], [0, scale_factor]])      image_array = np.rollaxis(image_array, axis=-1, start=0)     # ndi.interpolation 插值     image_channel =[ndi.interpolation.affine_transform(image_channel, crop_matrix, offset=offset,                                                         order=0, mode='nearest',                                                         cval=0.0) for image_channel in image_array]      image_array = np.stack(image_channel, axis=0)     image_array = np.rollaxis(image_array, 0, 3)     return image_array   if __name__ == '__main__':    raw_img = cv2.imread('demo.jpg')    cropped_and_rotated_img = do_random_crop_and_rotation(raw_img, 0.3, [0.75, 1.25])    cv2.imwrite('new_demo.jpg', cropped_and_rotated_img)  

该函数实现的事仿射变换,利用仿射变换对图片进行旋转与裁剪。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!