2017 年已到最后一个月的尾巴,那圣诞节还会远吗?不知道各位对于圣诞节有什么安排或一些美好的回忆,我记得最清楚的还是每年圣诞节前一晚那些包装好的苹果,寓意平平安安。那谈到圣诞节,不可或缺的主角 ——“ 圣诞老人 ” 会出现在各地的大街小巷、各种画册上,本文将带领读者使用 Keras 完成 “ 圣诞老人 ” 图像的分类,算是圣诞节前的预热活动吧。

在介绍正式内容前,读者可以先看这篇内容:
在本教程的第一部分, 将介绍本文使用的数据集;其次使用Python 和 Keras 训练一个卷积神经网络模型,该模型能够检测一个图像中是否存在圣诞老人, 所选的网络结构类似于LeNet 网络; 最后, 在 一系列的图像 上 评估 本文搭建的 模型,然后讨论一 下本文方法的局限性以及如何拓展等 。“圣诞老人”和“非圣诞老人” 数据集
为了
训练搭建的模型
,
本文
需要两
类
图像
集
:
-
图像
含
圣诞老人(“
圣诞老人”
);
-
图像
不包含
圣诞老人(“
不是圣诞老人”
)
基于卷积神经网络和Keras搭建的第一个图像分类器


第2-8 行是 需要 导入的Python 包 ,其中conv2d 表示 执行卷积 ,maxpooling2d 表示执行 最大 池化,Activation 表示 特定的激活函数 类型,Flatten 层用来将输入 “ 压平 ” ,用于卷积层到全连接层的过渡, Dense 表示全连接层。 真正创建Lenet 网络结构是代码的第10-12 行, 每当定义了一个新的卷积神经网络结构 时, 我喜欢:
-
把它
放在
自己的类
中
(
为了
命名空间
及便于
组织)
-
创建一个静
立建造函数,来完成整个模型的建立
- weight:输入图像的宽度
- height:输入图像的高度
- depth:输入图像的通道数(1表示单通道图像灰度,3表示标准的RGB图像)
- claclasses:想要组织的层类别总数
第1第4 行定义我们的模型,第 15 行 初始化inputshape ,第18-19 行 正常更新inputshape
现在我们已经初始化我们的模型 , 可以开始添加 其它 层, 代码如下 :
第21-25
行创建第一个
CONV->RELU->POOL
层,
卷积层使用20
个大小
5x5
的滤波器,之后紧跟
RELU
激活函数,最后使用窗口大小为
2x2
的最大池化操作;
之后定义第二个CONV->RELU->POOL
层:
这次
卷积层使用50
个
滤波器
,滤波器个数的增加加深整个
网络体系结构。
最终的代码块
是将数据“
压平
”
以连接全连接层:
第33
行能
将maxpooling2d
层
的输出
压扁成一个单
向量;
第34
行显示
全连接层包含500
个节点,然后
紧跟一个ReLU
激活
函数;
第38
行
定义另一个全连接层,
该层的
节点数等于
分类
的类别数,Dense
层送入softmax
分类器
输出每类的概率值;
第42 行 返回 模型的 调用函数 ;
使用Keras训练卷积神经网络图像分类器
打开一个新的文件 并命名为train_networkpy ,并插入以下代码打开

第2 - 18 行导入程序 需要的 数据 包 ;
下面开始 解析命令行参数:

这里有两个需要命令行参数,--dataset 和--model ,以及accuracy/loss 图 的路径选择 。其中--dataset 表示模型的训练集, --model 表示训练分类器后保存的模型 ,如果--plot 未指定,则默认为plot.PNG 。
接下来,设置一些训练变量 、 初始化列表并 设置 图像路径:

第32-34 行定义模型的 训练次数 、 初始学习率 以及 批量大小 ;
第38 和 39 行 初始化数据和标签列表 , 这些列表 对应 存储图像 以及类别标签;
第42-44 行获取输入图像路径并将图像随机打乱;
现在 对 图像进行预处理:

该循环简单的将每个图像的尺寸重新调整为28×28 大小 (为LeNet 所需要的空间尺寸)
能够提取标签是由于 我们的数据目录结构 如下所示 :

因此,imagePath 的一个例子为 :

从ImagePath 提取 标签 ,结果 为 :

下一步,将数据集分为训练数据集和测试数据集:

第61 行 进一步预处理输入数据 , 按比例 将 数据点[ 0, 255 ] 缩放到[ 0, 1 ] 范围内;
然后 第66-67 行将 75% 数据作为训练集, 25% 数据作为测试集;第 70-71 行对标签进行独热编码; 随后, 通过以下操作增加数据量:

第74-76 行 创建一个图像发生器 ,对数据集图像 进行随机旋转 、 移动 、 翻转 、剪切等,通过这种操作允许我们能用 一个较小的数据集实现 好 的结果。
继续深入学习Keras 训练 图像 分类器:
第80-83 行使用 Adam 优化器, 由于本文是一个二分类问题,可以 使用二进制交叉熵损失函数 (binary cross-entropy )。但 如果执行的分类 任务多于两类 , 损失函- 数更换为 类别交叉熵 (categorical_crossentropy )
第87-89 行调用 model.fit_generator 开始训练网络,第 93 行保存模型参数,最后画出图像分类器的性能结果:

为了 训练网络 模型 , 需要 打开一个终端执行以下命令:
可以看到, 当 网络训练了25 个回合后, 模型的测试精度为97.40% ,损失函数也很低 ,如下图 所示 :

评估卷积神经网络图像分类器
打开一个新的文件 并命名为test_networkpy ,然后开始进行评估 :
第2-7 行导入 需要的 数据 包 ,另外注意导入的load_model 是训练过程中保存的模型 。
下一步,解析命令行参数:

需要两个命令行参数:--model 和输入--image ,然后加载图像预处理:
预处理与前面几乎一模一样,这里不做过多的解释,只是第25 行通过 np.expand_dims 对数据额外 添加 了 一个维度 , 如果忘记添加维度,它将导致 调用model.predict 时出现 错误 。现在加载 图像分类器模型 并 进行预测:
第29 行加载模型,第 32 行做出预测。 最后 画出头像以及预测标签 :

第35 行建立标签,第 36 行选择对应的概率值,第 37 行将标签文本显示在图像的左上角, 第40-42 行调整 图 像 大小为标准的宽度以确保它 适应电脑 屏幕,最后, 第45 行 显示输出图像 ,第46 行表示当 一个键被按下 结束显示。
以下是包含圣诞老人图像的实验结果:


以下是不包含圣诞老人图像的实验结果:


本文图像分类模型的局限性
本文 图像分类 器有一些局限性:
第一个是 输入图像尺寸28×28 很小 。 一些示例图像 (图像中圣诞老人本身已经很小)调整尺寸为28×28 后 大大 降低 圣诞老人的尺寸 。
最优的 卷积神经网络正常接受 输入 图像 大小一般为200-300 像素 ,因此一些 较大 尺寸 的图像将帮助我们建立一个更强大的 图像 分类器。然而,使用更大的分辨率的图像 会加深网络模型的深度和复杂度, 这将意味着需要收集更多的训练数据, 以及 昂贵的计算训练过程。
因此,如果 各位读者想 提高 本文模型的精度话,有以下四点建议:
-
收集更多的训练数据(
超过5000
幅“
圣诞老人”
图像
)
;
-
利用高分辨率的图像在训练。 64×64
、128×128
像素
的图像可能效果会更
理想
;
-
在
训练
过程中使用一个更深层次的网络体系结构
;
-
阅读Deep Learning for Computer Vision with Python
,
里面有更多关于
自定义数据集
等内容
的细节
;
总结
-
本文教你学
会
利用Keras
和
Pyhton
训练LeNet模型,并用来完成
是否含有圣诞老人形象的图像分类
,最终目标
可以
是建立一个应用程序类似于Not Hotdog
;
- “
圣诞老人”
图像
数据集(460
幅)
是
按照
之前的教程——通过谷歌图片采集深度学习的图像
获得,而“
没有圣诞老人
”
的
图像
数据集是由
从UKBench数据集
中挑选得到;
-
在
一系列的测试图像
上
评估
本文搭建的网络模型
,在每一种情况下,
本文模型都能对输入图像
分类
正确
。
作者信息

Adrain Rosebrock , 企业家 、 博士,专注于图像搜索引擎 。
Linkedin: www.linkedin.com/in/adrian-r…
本文由北邮@爱可可-爱生活 老师推荐,阿里云云栖社区 组织翻译。
文章原标题《Image classification with Keras and deep learning 》,作者: Adrain Rosebrock ,译者:海棠,审阅:。
文章为简译,更为详细的内容,请查看原文