猫狗大战识别准确率直冲 Kaggle Top 2%,手把手教你在 Keras 搭建深度 CNN

猫狗大战

数据集来自 kaggle 上的一个竞赛:Dogs vs. Cats,训练集有25000张,猫狗各占一半。测试集12500张,没有标定是猫还是狗。

下面是训练集的一部分例子:

数据预处理

由于我们的数据集的文件名是以type.num.jpg这样的方式命名的,比如cat.0.jpg,但是使用 Keras 的 ImageDataGenerator 需要将不同种类的图片分在不同的文件夹中,因此我们需要对数据集进行预处理。这里我们采取的思路是创建符号链接(symbol link),这样的好处是不用复制一遍图片,占用不必要的空间。

我们可以从下面看到文件夹的结构,train2里面有两个文件夹,分别是猫和狗,每个文件夹里是12500张图。

导出特征向量

对于这个题目来说,使用预训练的网络是最好不过的了,经过前期的测试,我们测试了 ResNet50 等不同的网络,但是排名都不高,现在看来只有一两百名的样子,所以我们需要提高我们的模型表现。那么一种有效的方法是综合各个不同的模型,从而得到不错的效果,兼听则明。如果是直接在一个巨大的网络后面加我们的全连接,那么训练10代就需要跑十次巨大的网络,而且我们的卷积层都是不可训练的,那么这个计算就是浪费的。所以我们可以将多个不同的网络输出的特征向量先保存下来,以便后续的训练,这样做的好处是我们一旦保存了特征向量,即使是在普通笔记本上也能轻松训练。

为了复用代码,我觉得写一个函数是非常有必要的,那么我们的函数就需要输入模型,输入图片的大小,以及预处理函数,因为 Xception 和 Inception V3 都需要将数据限定在 (-1, 1) 的范围内,然后我们利用 GlobalAveragePooling2D 将卷积层输出的每个激活图直接求平均值,不然输出的文件会非常大,且容易过拟合。然后我们定义了两个 generator,利用 model.predict_generator 函数来导出特征向量,最后我们选择了 ResNet50, Xception, Inception V3 这三个模型(如果有兴趣也可以导出 VGG 的特征向量)。每个模型导出的时间都挺长的,在 aws p2.xlarge 上大概需要用十分钟到二十分钟。 这三个模型都是在 ImageNet 上面预训练过的,所以每一个模型都可以说是身经百战,通过这三个老司机导出的特征向量,可以高度概括一张图片有哪些内容。

最后导出的 h5 文件包括三个 numpy 数组:

  • train (25000, 2048)
  • test (12500, 2048)
  • label (25000,)

如果你不想自己计算特征向量,可以直接在这里下载导出的文件:GitHub releases(http://t.cn/R6xSIoG)

参考资料:

  • ResNet 15.12
  • Inception v3 15.12
  • Xception 16.10

载入特征向量

经过上面的代码以后,我们获得了三个特征向量文件,分别是:

  • gap_ResNet50.h5
  • gap_InceptionV3.h5
  • gap_Xception.h5

我们需要载入这些特征向量,并且将它们合成一条特征向量,然后记得把 X 和 y 打乱,不然之后我们设置validation_split的时候会出问题。这里设置了 numpy 的随机数种子为2017,这样可以确保每个人跑这个代码,输出都能是一样的结果。

构建模型

模型的构建很简单,直接 dropout 然后分类就好了。

我们还可以对模型进行可视化:

训练模型

模型构件好了以后,我们就可以进行训练了,这里我们设置验证集大小为 20% ,也就是说训练集是20000张图,验证集是5000张图。

我们可以看到,训练的过程很快,十秒以内就能训练完,准确率也很高,在验证集上最高达到了99.6%的准确率,这相当于一千张图只错了4张,可以说比我还厉害。

预测测试集

模型训练好以后,我们就可以对测试集进行预测,然后提交到 kaggle 上看看最终成绩了。

预测这里我们用到了一个小技巧,我们将每个预测值限制到了 [0.005, 0.995] 个区间内,这个原因很简单,kaggle 官方的评估标准是 LogLoss,对于预测正确的样本,0.995 和 1 相差无几,但是对于预测错误的样本,0 和 0.005 的差距非常大,是 15 和 2 的差别。参考 LogLoss 如何处理无穷大问题,下面的表达式就是二分类问题的 LogLoss 定义。

$$\textrm{LogLoss} = - \frac{1}{n} \sum_{i=1}^n \left[ y_i \log(\hat{y}_i) + (1 - y_i) \log(1 - \hat{y}_i)\right]$$

还有一个值得一提的地方就是测试集的文件名不是按 1, 2, 3 这样排的,而是按下面的顺序排列的:

因此我们需要对每个文件名进行处理,然后赋值到 df 里,最后导出为 csv 文件。

总结

我们可以从上图中看到,模型对于前十个样本都给出了很肯定的预测,提交到 kaggle 以后,得分也是很棒,0.04141,在全球排名中可以排到20/1314。我们如果要继续优化模型表现,可以使用更棒的预训练模型来导出特征向量,或者对预训练模型进行微调(fine-tune),或者进行数据增强(data augmentation)等。

本文授权转载自Udacity知乎机构号,作者杨培文 , Udacity 机器学习项目 reviewer,特此感谢!

原文发布于微信公众号 - 新智元(AI_era)

原文发表时间:2017-03-27

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏PaddlePaddle

【目标检测】SSD目标检测

场景文字识别 目标检测任务的目标是给定一张图像或是视频帧,让计算机找出其中所有目标的位置,并给出每个目标的具体类别。对于人类来说,目标检测是一个非常简单的任务。...

5739
来自专栏量子位

想尝试搭建图像识别系统?这里有一份TensorFlow速成教程

李林 编译整理 量子位 出品 | 公众号 QbitAI 从我们见到的各种图像识别软件来看,机器似乎能认出人脸、猫、狗、花草、各种汽车等等日常生活中出现的物体,但...

5497
来自专栏生信小驿站

无监督学习 聚类分析②划分聚类分析

同样是聚类分析,上一次介绍的是层次聚类分法,这种方法输出的聚类树状图是其最大的优点,但是层次分析法的缺点就在于适合的样本数比较小,大概在150个左右。所以,当我...

981
来自专栏利炳根的专栏

学习笔记CB010:递归神经网络、LSTM、自动抓取字幕

递归神经网络(RNN),时间递归神经网络(recurrent neural network),结构递归神经网络(recursive neural network...

5924
来自专栏Python中文社区

支持向量机原理推导(二)

專 欄 ❈ exploit,Python中文社区专栏作者。希望与作者交流或者对文章有任何疑问的可以与作者联系: Email: 15735640998@163....

1995
来自专栏素质云笔记

caffe︱ImageData层、DummyData层作为原始数据导入的应用

Part1:caffe的ImageData层 ImageData是一个图像输入层,该层的好处是,直接输入原始图像信息就可以导入分析。 在案例中利用Image...

77410
来自专栏Coding迪斯尼

从零开始构造一个识别猫狗图片的卷积网络

在深度学习的项目实践中,往往会遇到两个非常难以克服的难题,一是算力,要得到精确的结果,你需要设计几千层,规模庞大的神经网络,然后使用几千个GPU,把神经网络布置...

2212
来自专栏用户2442861的专栏

文本分类(六):使用fastText对文本进行分类--小插曲

http://blog.csdn.net/lxg0807/article/details/52960072

3891
来自专栏Petrichor的专栏

深度学习: 经典 数据集 汇总

官网:www.cs.toronto.edu/~kriz/cifar 介绍:CIFAR-10数据集说明、TensorFlow CNN 测试CIFAR-10数据...

4823
来自专栏AI研习社

TensorFlow | 自己动手写深度学习模型之全连接神经网络

前半个多月总共写了三篇深度学习相关的理论介绍文章,另外两个月前,我们使用逻辑回归算法对sklearn里面的moons数据集进行了分类实验,最终准确率和召回率都达...

56810

扫码关注云+社区

领取腾讯云代金券