图像分类之:经典机器学习 Battle 深度学习

前段时间,有个朋友和我提到,自己最近正打算用机器来判别图片中的场景是古镇还是园林,所以我这一期特地写了一篇文章,来描述图像的分类算法。由于最近工作略忙,所以文章断断续续写了好久,终于在自己生日前夕完成,希望可以有所帮助,这样我就可以安心回家吃蛋糕了。

用机器来做图片分类简单来讲就是给机器输入一张图片,机器会输出这幅图片里面的内容。机器学习中提供了很多对数据分类的算法,像KNN(最近邻)、Adaboost、Naive Bayes(朴素贝叶斯)、SVM(支持向量机)、ANN(人工神经网络)等以及最近几年兴起的CNN(卷积神经网络)。

在这篇文章的实作部分,我会挑出KNN、SVM、ANN来实现,使用的是使用经典的scikit-learn(sklearn)库,CNN则使用Keras来实现。

编程的环境需求:

系统:windows / linux

解释器:python 3.6

依赖库:numpy、opencv-python 3、tensorflow、keras、scikit-learn

数据集选择:

由于这几天无法穿越到苏州去采集大量园林和古镇的图片,而且本文还会去实验多分类的情况,但是既然同是图片的分类问题,我决定去网上搜集一些和风景相关的数据集。

突然有一天,在我逛GitHub的时候,它就这样出现了,

在我的世界里

带给我惊喜

情不自已

为此,我给作者写了一份信:

作者在我晚上吃饭的时候给了回复:

这。。。。。。。

看来这条路没走顺,不如去看看一些知名的数据集里有没有自己需要的东西吧,不过有承诺在先,我还是会标注上数据集作者的GitHub地址:(https://github.com/yuweiming70/Landscape-Dataset),毕竟他送了我这么多精美壁纸。

牛津大学的17 Category Flower Dataset

(http://www.robots.ox.ac.uk/~vgg/data/flowers/17/index.html)很漂亮,看起来就是我在寻找的数据集(没错,我判断一个东西是不是自己需要的标准就是漂不漂亮)。这个数据集总共17种花,每种花有80张图片,整个数据集有1360张图片,为了既达到实验的目的又不在训练上耗费太多的时间,我在同一种算法上选取了前两种花和前四种花做对比实验:

由于SVM和ANN的原理会占用太多的篇幅,并且这篇文章的主要目的是为了讲解代码实现,所以这里只介绍下机器学习中最简单的KNN分类器:

KNN是数据挖掘分类技术中最简单的方法之一,k最近邻,从名字大致就可以看出它的含义,就是找出K个离自己最近(相似)的数据,在这K个找到的数据中,看看那个类别最多,那么就认为自己是属于哪一个类别。

关于相似度度量的方法有很多,常见的有欧氏距离、曼哈顿距离、切比雪夫距离(切比雪夫兄跨界实在太多)、汉明距离、余弦相似度(夹角余弦值)等等。

KNN用到的是:欧氏距离(L2):

在数据(向量)只有二维的情况下,两个数据之间的欧氏距离就是两个点在二维坐标系下的直线距离,用初中一年级的数学公式就可以算出来:

当数据推广到多维的时候,两个数据之间的欧式距离就变成了:

距离越小表示两个向量相似度越大。

KNN有着实现方法简单、无需训练的优点,但是由于每次分类都要计算和所有数据之间的相似度,所以当数据维度很大或者数据数量很大的时候,计算会很耗时。

实验(KNN、SVM、ANN):

现在我要使用sklearn中的KNeighborsClassifier( KNN )、SVC( SVM )、MLPClassifier( 多层感知机分类器:ANN ),来实现这三个算法,由于sklearn中的算法模型高度统一化,所以三个程序可以写在同一个例子中,只是在创建分类器模型的时候略有不同:

引入KNeighborsClassifier、SVC、MLPClassifier模块:

引入训练样本分割函数:

引入numpy 和 opencv:

读取图像函数,返回图像列表和标签列表:

由于这三种分类器只接受一维向量的输入,所以将图片拍扁:

分割训练集和测试集(训练集:测试集 = 8 : 2):

图片数据归一化:

创建分类器模型:

训练:

计算准确率:

实验了几次,计算准确率平均值大致得到:

KNN: 73.8%

SVM: 78.5%

ANN: 78.9%

上面只是2分类的情况,现在取4种花来训练,得到准确率:

KNN: 40.1%

SVM: 40.6%

ANN: 41.5%

并且ANN在训练集上的正确率表现为100%, 很明显,已经过拟合,即模型已经呈现了记忆效应。

实验(CNN):

现在来试下卷积神经网络(由于上篇文章已经讲解过卷积神经网络的构建过程,这篇文章就不再赘述):

引入相关模块:

读取图像函数,返回图像列表和标签列表:

One-Hot编码:

分割训练集和测试集(训练集:测试集 = 8 : 2):

图片数据归一化:

构建CNN:

采用了VGG19结构的CNN:

深度很深,训练时间很长,特别耗内存和处理器(训练的时候记得在电脑下面垫冰块):

如果想要快速训练,也可以使用下面的简化模型,效果也还不错:

设置SGD优化器并编译模型:

训练,这里只训练30次:

看看这个模型在测试集上的表现:

准确率96.88%

再试下四种花的情况,在测试集上正确率为 70%,在训练集上正确率为 99.6%,虽然也过拟合,但是比三种经典分类器效果要好很多。

这种感觉就好像CNN把经典机器学习分类器的脸按在地上疯狂的摩擦,不放润滑油的那种。

不过反思一下,如果在进SVM、KNN、ANN之前,可以做一些特征提取,效果应该会更好一些。毕竟CNN训练和运行起来实在是太耗硬件了。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180831G1ZQPR00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券