图像训练样本量少时的数据增强技术

在深度学习训练过程中,训练数据是很重要的,在样本量方便,一是要有尽量多的训练样本,二是要保证样本的分布够均匀,也就是各个类别下的样本量都要足够,不能有的很多,有的特别少。但是实际采集数据的过程中,可能经常会遇到样本量不够的情况,这就很容易导致训练出的模型过拟合,泛化能力不足,这时候该怎么办呢?

一种方法是利用预训练好的模型,也就是使用另一个在大量样本下获得足够训练的模型,只要这个模型的训练数据集足够大,而且够通用,那么可以理解为其学到的特征空间层次结构能够有效地作为视觉世界的通用模型基础。就好像你如果看过很多东西了,那么也就拥有了对于世界万物的一个基本判断能力,在此基础上可以进一步做集中突破训练来学会判断特殊的物体,这时候需要的样本量就不需要那么多了。比如说,如果已经在ImageNet下训练了一个网络,可以识别动物及日常用品等,这时候你需要得到一个能够区分猫狗的模型,那么在其基础上进行训练是很有效的,比你单纯在小样本的猫狗图像上重头做训练效果要好。当然,在实际操作中,我们需要保留网络除了分类器部分的前置层(卷积基)及其权重不变,只训练我们新的分类器,这也很好理解,毕竟要利用它的基础嘛。

但本文要讲的不是这个方法,而是另一种思路,即强行增加训练样本数量,生生在已有的样本下再造出一批来,这叫做数据增强

所谓数据增强,就是从已有的图像样本中生造出更多的样本数据,这些图像怎么来呢?方法是使用一些方法,来随机变换生成一些可信图像,这些通过随机变换生成的图像,要保证从逻辑上不会给模型辨认带来困扰,也就是从分类的角度应该依然属于其原本图像同一类,但是又要与原本的图像有一些区别,这样模型在训练时就不会两次看到完全相同的图像,这样就能够观察到更多的内容,也就提升了泛化能力。

产生新图像的随机变换方法大致包括:

  • 随机旋转一些角度
  • 水平横移一定距离
  • 竖直横移一定距离
  • 随机缩放一定范围
  • 进行水平翻转
  • 进行竖直翻转
  • 等等

这些变换方式都是可以考虑的,同时这些变换的组合也是可以的,但是要注意不能产生逻辑上的问题。比如你要训练一个分类猫狗的模型,那可以对某些猫狗图像进行旋转角度、横移、水平翻转,但是竖直翻转可能就不太合适了。又比如你要训练一个文字识别模型,那么可以进行随机缩放、横移,但是无论水平翻转还是竖直翻转可能都不太合适。

通过这些变换及其组合,我们就能得到很多同等类别下又有所区别的图像了。

那怎么实现呢?

当然,最简单的可以自己写代码来加入这些随机扰动,但Keras有更方便的函数来直接进行操作。

ImageDataGenerator是keras.preprocessing.image包下的一个类,可以设置图像的这些随机扰动来生成新的图像数据,简单的代码如下所示:

# -- coding: utf-8 --
import numpy as np
from keras.preprocessing import Image
from keras.preprocessing.image import ImageDataGenerator
import cv2 as cv
import os

img = cv.imread("./photo.png")
img = Image.img_to_array(img)
img = img.reshape((1,) + img.shape)
datagen = ImageDataGenerator(width_shift_range=0.2, height_shift_range=0.2, fill_mode='wrap')
i = 0
for batch in datagen.flow(img, batch_size=1):
    img_name = "./image_%d.jpg" % (i)
    cv.imwrite(img_name, batch[0])
    i += 1
    if i % 4 == 0:
        break

上面代码所实现的就是将一张图像进行随机变换,我设置的变换形式只有在水平和竖直方向进行横移,且横移的范围最多占整个宽、高的20%,另外对于横移空出来的区域,填充方式为“wrap”,这是什么意思待会再解释。

设置好变换方式后,就可以通过datagen.flow来生成数据了,传入的参数包括图像和处理数量,我们这就处理一张图。在循环中这个类会不断地随机组合变换来生成新图像,我们把生成的新图像保存下来,并且设置只生成四张就停,这里比如设置停止条件,否则它会一直生成下去的。

现在我们来具体说一说ImageDataGenerator包含哪些变换方式,从Keras中文手册中我们能看到它包含这些参数:

  • featurewise_center:布尔值,使输入数据集去中心化(均值为0), 按feature执行
  • samplewise_center:布尔值,使输入数据的每个样本均值为0
  • featurewise_std_normalization:布尔值,将输入除以数据集的标准差以完成标准化, 按feature执行
  • samplewise_std_normalization:布尔值,将输入的每个样本除以其自身的标准差
  • zca_whitening:布尔值,对输入数据施加ZCA白化
  • zca_epsilon: ZCA使用的eposilon,默认1e-6
  • rotation_range:整数,数据提升时图片随机转动的角度
  • width_shift_range:浮点数,图片宽度的某个比例,数据提升时图片水平偏移的幅度
  • height_shift_range:浮点数,图片高度的某个比例,数据提升时图片竖直偏移的幅度
  • shear_range:浮点数,剪切强度(逆时针方向的剪切变换角度)
  • zoom_range:浮点数或形如[lower,upper]的列表,随机缩放的幅度,若为浮点数,则相当于[lower,upper] = [1 - zoom_range, 1+zoom_range]
  • channel_shift_range:浮点数,随机通道偏移的幅度
  • fill_mode:;‘constant’,‘nearest’,‘reflect’或‘wrap’之一,当进行变换时超出边界的点将根据本参数给定的方法进行处理:
    • 'constant': kkkkkkkk|abcd|kkkkkkkk (cval=k)
    • 'nearest': aaaaaaaa|abcd|dddddddd
    • 'reflect': abcddcba|abcd|dcbaabcd
    • 'wrap': abcdabcd|abcd|abcdabcd
  • cval:浮点数或整数,当fill_mode=constant时,指定要向超出边界的点填充的值
  • horizontal_flip:布尔值,进行随机水平翻转
  • vertical_flip:布尔值,进行随机竖直翻转
  • rescale: 重放缩因子,默认为None. 如果为None或0则不进行放缩,否则会将该数值乘到数据上(在应用其他变换之前)
  • preprocessing_function: 将被应用于每个输入的函数。该函数将在图片缩放和数据提升之后运行。该函数接受一个参数,为一张图片(秩为3的numpy array),并且输出一个具有相同shape的numpy array
  • data_format:字符串,“channel_first”或“channel_last”之一,代表图像的通道维的位置。该参数是Keras 1.x中的image_dim_ordering,“channel_last”对应原本的“tf”,“channel_first”对应原本的“th”。以128x128的RGB图像为例,“channel_first”应将数据组织为(3,128,128),而“channel_last”应将数据组织为(128,128,3)。该参数的默认值是~/.keras/keras.json中设置的值,若从未设置过,则为“channel_last”

比如我对这张图像使用上面的代码处理:

原图

那么会得到四张经过处理的图:

image_0.jpg
image_1.jpg
image_2.jpg
image_3.jpg

可以看到,对同一张图,就得到了四张新的变换后的图,仔细看会发现,这些变换是会组合的。可以看到对于这种图,竖直移动更是几乎看不出操作痕迹。

这样样本量就翻了四倍啦,经过实验,在猫狗分类模型上能将精度从72%提升到82%,提升的效果还是非常明显的,所以有这方面困扰的可以试一下。


查看作者首页

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,817评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,329评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,354评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,498评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,600评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,829评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,979评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,722评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,189评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,519评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,654评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,940评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,762评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,993评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,382评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,543评论 2 349

推荐阅读更多精彩内容