基于Keras2《面向小数据集构建图像分类模型》——Kaggle猫狗数据集

本文介绍了如何使用Keras和VGG16模型处理小数据集的图像分类问题,包括数据预处理、数据提升、模型训练及预训练网络的bottleneck特征利用。通过40行代码在小数据集上实现80%准确率,通过预训练网络的一分钟内达到90%准确率。讨论了如何避免过拟合并提供了实际的代码示例。
摘要由CSDN通过智能技术生成

概述

在本文中,将使用VGG-16模型提供一种面向小数据集(几百张到几千张图片)构造高效、实用的图像分类器的方法并给出试验结果。

本文将探讨如下几种方法:

  • 从图片中直接训练一个小网络(作为基准方法)

  • 利用预训练网络的bottleneck(瓶颈)特征

  • fine-tune预训练网络的高层

本文需要使用的Keras模块有:

  • fit_generator:用于从Python生成器中训练网络
  • ImageDataGenerator:用于实时数据提升
  • 层参数冻结和模型fine-tune

配置情况

我们的实验基于下面的配置

  • 2000张训练图片构成的数据集,一共两个类别,每类1000张
  • 安装有Keras,SciPy,PIL的机器,如果有NVIDIA GPU那就更好了,但因为我们面对的是小数据集,没有也可以。
  • 数据集按照下面的形式存放(图片名可不遵循以下规则)
    这里写图片描述
    这份数据集来源于Kaggle,可以使用百度网盘下载。原数据集有12500只猫和12500只狗,我们只取了各个类的前1000张图片。另外我们还从各个类中取了400张额外图片用于测试。

下面是数据集的一些示例图片,图片的数量非常少,这对于图像分类来说是个大麻烦。但现实是,很多真实世界图片获取是很困难的,我们能得到的样本数目确实很有限(比如医学图像,每张正样本都意味着一个承受痛苦的病人。对数据科学家而言,我们应该有能够榨取少量数据的全部价值的能力,而不是简单的伸手要更多的数据。这里写图片描述
在Kaggle的猫狗大战竞赛种,参赛者通过使用现代的深度学习技术达到了98%的正确率,本文方法只使用了全部数据的8%,因此这个问题对我们来说更难。

针对小数据集的深度学习

我经常听到的一种说法是,深度学习只有在你拥有海量数据时才有意义。虽然这种说法并不是完全不对,但却具有较强的误导性。当然,深度学习强调从数据中自动学习特征的能力,没有足够的训练样本,这几乎是不可能的。尤其是当输入的数据维度很高(如图片)时。然而,卷积神经网络作为深度学习的支柱,被设计为针对“感知”问题最好的模型之一(如图像分类问题),即使只有很少的数据,网络也能把特征学的不错。针对小数据集的神经网络依然能够得到合理的结果,并不需要任何手工的特征工程。一言以蔽之,卷积神经网络大法好!尤其在计算机视觉领域,许多预训练的模型现在都被公开下载,并被重用在其他问题上以提升在小数据集上的性能。另一方面,深度学习模型天然就具有可重用的特性:比方说,你可以把一个在大规模数据上训练好的图像分类或语音识别的模型重用在另一个很不一样的问题上,而只需要做有限的一点改

数据预处理与数据提升

为了尽量利用我们有限的训练数据,我们将通过一系列随机变换堆数据进行提升,这样我们的模型将看不到任何两张完全相同的图片,这有利于我们抑制过拟合,使得模型的泛化能力更好。

在Keras中,这个步骤可以通过keras.preprocessing.image.ImageGenerator来实现,这个类使你可以:

  • 在训练过程中,设置要施行的随机变换
  • 通过.flow.flow_from_directory(directory)方法实例化一个针对图像batch的生成器,这些生成器可以被用作keras模型相关方法的输入,如fit_generatorevaluate_generatorpredict_generator
    现在让我们看个例子:
from keras.preprocessing.image import ImageDataGenerator

datagen = ImageDataGenerator(
        rotation_range=40,
        width_shift_range=0.2,
        height_shift_range=0.2,
        rescale=1./255,
        shear_range=0.2,
        zoom_range=0.2,
        horizontal_flip=True,
        fill_mode='nearest')

上面显示的只是一部分选项,请阅读文档的相关部分来查看全部可用的选项。我们来快速的浏览一下这些选项的含义

  • rotation_range是一个0~180的度数,用来指定随机选择图片的角度。
  • width_shift和height_shift用来指定水平和竖直方向随机移动的程度,这是两个0~1之间的比例。
  • rescale值将在执行其他处理前乘到整个图像上,我们的图像在RGB通道都是0~255的整数,这样的操作可能使图像的值过高或过低,所以我们将这个值定为0~1之间的数。
  • shear_range是用来进行剪切变换的程度,参考剪切变换
  • zoom_range用来进行随机的放大
  • horizontal_flip随机的对图片进行水平翻转,这个参数适用于水平翻转不影响图片语义的时候
  • fill_mode用来指定当需要进行像素填充,如旋转,水平和竖直位移时,如何填充新出现的像素
    下面我们使用这个工具来生成图片,并将它们保存在一个临时文件夹中,这样我们可以感觉一下数据提升究竟做了什么事。为了使图片能够展示出来,这里没有使用rescaling
from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img

datagen = ImageDataGenerator(
        rotation_range=40,
        width_shift_range=0.2,
        height_shift_range=0.2,
        shear_range=0.2,
        zoom_range=0.2,
        horizontal_flip=True,
        fill_mode='nearest')

img = load_img('data/train/cats/cat.0.jpg')  # this is a PIL image
x = img_to_array(img)  # this is a Numpy array with shape (3, 150, 150)
x = x.reshape((1,) + x.shape)  # this is a Numpy array with shape (1, 3, 150, 150)

# the .flow() command below generates batches of randomly transformed images
# and saves the results to the `preview/` directory
i = 0
for batch in datagen.flow(x, batch_size=1,
                          save_to_dir='preview', save_prefix='cat', save_format='jpeg'):
    i += 1
    if i > 20:
        break  # otherwise the generator would loop indefinitely

下面是一张图片被提升以后得到的多个结果:
这里写图片描述

在小数据集上训练神经网络:40行代码达到80%的准确率

进行图像分类的正确工具是卷积网络,所以我们来试试用卷积神经网络搭建一个初级的模型。因为我们的样本数很少,所以我们应该对过拟合的问题多加注意。当一个模型从很少的样本中学习到不能推广到新数据的模式时,我们称为出现了过拟合的问题。过拟合发生时,模型试图使用不相关的特征来进行预测。例如,你有三张伐木工人的照片,有三张水手的照片。六张照片中只有一个伐木工人戴了帽子,如果你认为戴帽子是能将伐木工人与水手区别开的特征,那么此时你就是一个差劲的分类器

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值