图像分类,顾名思义,是一个输入图像,输出对该图像内容分类的描述的问题.它是计算机视觉的核心,实际应用广泛.
图像分类的传统方法是特征描述及检测,这类传统方法可能对于一些简单的图像分类是有效的,但由于实际情况非常复杂,传统的分类方法不堪重负.现在,我们不再试图用代码来描述每一个图像类别,决定转而使用机器学习的方法处理图像分类问题.
目前,许多研究者使用 CNN 等深度学习模型进行图像分类;另外,经典的 KNN 和 SVM 算法也取得不错的结果.然而,我们似乎无法断言,哪种方法对于图像分来问题效果最佳.
本项目中,我们做了一些有意思的事情:
将业内普遍用于图像分类的 CNN 和迁移学习算法与 KNN,SVM,BP 神经网络进行比较.
获取深度学习经验.
探索谷歌机器学习框架 TensorFlow.
下面是具体实施细节.
一,系统设计
在本项目中,用于实验的 5 种算法为 KNN,SVM,BP 神经网络,CNN 以及迁移学习.我们采用如下三种方式进行实验
KNN,SVM,BP 神经网络是我们在学校能够学到的.功能强大而且易部署.所以第一步,我们主要使用 sklearn 实现 KNN,SVM,和 BP 神经网络.
由于传统的多层感知机模型在图像识别方面效果甚佳,但由于其节点间的全连接模式对于其延展性造成了阻碍,因此对于高分辨率的图像,识别率不是很理想.所以这一步,我们用 Google TensorFlow 框架构建 CNN.
对于已经预训练过的深度神经网络 Inception V3 进行重训练.Inception V3 由 TensorFlow 提供,使用 ImageNet 自 2012 年以来的数据进行训练.ImageNet 是计算机视觉领域一个经典挑战,参赛者试图用模型将全部图像放至 1000 个分类中.为了要重新训练已经预训练好的模型,我们必须保证我们自己的数据集没有被预训练过.
二,实施
第一种方法:使用 sklearn 预处理数据以及实现 KNN,SVM 和 BP 神经网络.
步骤 1,使用 openCV 包,定义 2 个预处理函数,分别是图像特征向量(用来调整图像大小并将图像扁平化成一系列行像素)和提取颜色直方图(使用 cv2.normalize 从 HSV 色域中提取一个 3D 颜色直方图并做平滑处理).
步骤 2,构造参数.由于我们试图在整个数据集以及具有不同类别数目的子数据集上进行性能测试,所以我们把各个数据集看作为参数,以便进行实验分析.另外,我们还设置了 KNN 中的邻居数目作为参数.
步骤 3,提取图像特征并写入数组.我们使用 cv2.imread 函数读取图像,根据规范化的图像名称进行分类.然后运行第步骤 1 中提到的 2 个函数,分别得到 2 种图像特征并写入数组.
步骤 4,使用函数 train_test_split 分割数据集.85% 的数据作为训练集,15% 的数据作为测试集.
步骤 5,使用 KNN,SVM 和 BP 神经网络方法去评估数据.对于 KNN,使用 KNeighborsClassifier,对于 SVM,使用 SVC,对于 BP 神经网络,使用 MLPClassifier.
第二种方法:基于 TensorFlow 构建 CNN.使用 TensorFlow 得到计算图并在 C++ 中实现,比 Python 更高效.
TensorFlow 中使用到的的几个概念:占位符,变量,数学公式,成本计量,最优方法,CNN 体系结构.
步骤 1,第一层放置图像.
步骤 2,构建 3 层卷积层(3 Convolutional layers),2X2 的 max-pooling 和 ReLU.输入是 4 维张量:【图像编号,Y 坐标,X 坐标,通道】.输出是另一个经处理得到的 4 维张量:【图像编号(不变),Y 坐标,X 坐标,通道】.
步骤 3,构建 2 层全连接层(2 Fully-Connected Layers).输入是 2 维张量:【图像编号,输入编号】.输出是 2 维张量【图像编号,输出编号】.使用
步骤 4,使用合并层(Flatten Layer)链接卷积层和全连接层.
步骤 5,使用 softmax layer 标准化输出.
步骤 6,优化训练结果.我们使用交叉熵(cross entropy)作为成本计量函数,取其均值.最优方法使用 tf.train.AdamOptimizer().
第三种方法:Retrain Inception V3.使用 Retrain Inception V3 ,并利用迁移学习减少工作量.
我们得到 pre-trained 模型,移除原有顶层,训练新模型.然后分析在磁盘上的所有图像并计算它们的 bottleneck 值.脚本会运行 4000 次.每次运行都会从训练集中随机选取 10 个图像,找到它们的 bottleneck 值并注入最后一层得到预测结果.然后在反向传播过程中,根据预测结果和实际标签的比较结果去更新每层的权重.
四,实验
实验中使用到的数据集是 Oxford-IIIT Pet 数据集.
http://www.robots.ox.ac.uk/~vgg/data/pets/
其中有犬类 25 类,猫类 12 类.每类有 200 个图像.我们使用到该数据集中的 10 个类别的猫的数据,分别是 ['Sphynx','Siamese','Ragdoll','Persian','Maine-Coon','British-shorthair','Bombay','Birman','Bengal','Abyssinian'].即,共有 2000 个图像,由于图像大小不一,我们调整大小统一为固定尺寸 64X64 或 128X128.
五,赋值
第一种方法:KNN,SVM,和 BP 神经网络
第一部分:使用 sklearn 预处理数据以及实现 KNN,SVM 和 BP 神经网络.在 image_to_feature_vector 函数中,我们设定尺寸 128X128.经试验表明,图像尺寸越大,结果越精确,运行负担越大.最终我们决定使用 128X128 的尺寸.在 extract_color_histogram 函数中,设定每个通道的容器数量为 32,32,32.对于数据集,使用 3 种数据集.第一个是具有 400 个图像,2 个标签的子数据集.第二个是具有 1000 个图像,5 个标签的子数据集.第三个是整个数据集,1997 个图像,10 个标签.
在 KNeighborsClassifier 中,我们只改变邻居数量且存储结果作为每个数据集的最佳 K 值,其他参数默认.
在 MLPClassifier 中,我们设定每层有 50 个神经元.
在 SVC 中,最大迭代次数是 1000,类权重是 "balanced".
依据数据集,2 个标签到 10 个标签不同,运行时间大约为 3 到 5 分钟不等.
第二种方法:基于 TensorFlow 构建 CNN
由于在整个数据集中运行时间过长,我们在每个迭代中分批次处理.每批次一般有 32 个或 64 个图像.数据集分为 1600 个图像的训练集,400 个图像的验证集,300 个图像的测试集.
本方法中有大量的参数可调整.学习速率设定为 1x10^-4;图像大小设定为 64x64 和 128x128;然后是层和形状,然而有太多的参数可调整,我们依据经验并进行实验去得到最佳结果.
为了得到最佳的 layers,我们进行实验.首先,参数如下:
我们使用了 3 个卷积层和 2 个全连接层,然而悲剧的是过度拟合.经过研究发现,对于该构造,我们的数据集过小,网络过于复杂.
# Convolutional Layer 1. filter_size1 = 5 num_filters1 = 64
# Convolutional Layer 2. filter_size2 = 5 num_filters2 = 64
# Convolutional Layer 3. filter_size3 = 5 num_filters3 = 128
# Fully-connected layer 1. fc1_size = 256
# Fully-connected layer 2. fc1_size = 256
最终,我们使用如下参数:
我们只使用了 2 个卷积层和 2 个全连接层.依然不尽人意,经过 4000 次迭代,结果仍旧过拟合,不过好在测试结果 10% 优于前者.最终,经过 5000 次迭代,我们得到 43% 的精确度,运行时间是半小时以上.
# Convolutional Layer 1. filter_size1 = 5 num_filters1 = 64
# Convolutional Layer 2. filter_size2 = 3 num_filters2 = 64
# Fully-connected layer 1. fc1_size = 128
# Number of neurons in fully-connected layer.
# Fully-connected layer 2. fc2_size = 128
# Number of neurons in fully-connected layer.
# Number of color channels for the images:
# 1 channel for gray-scale. num_channels = 3
PS:我们使用另一个数据集 CIFAR-10 进行了实验.
CIFAR-10: https://www.cs.toronto.edu/~kriz/cifar.html
该数据集包含 60000 个 32x32 的彩色图像,分为 10 个类别,每个类别 6000 个图像.训练集 50000 个图像,测试集 10000 个图像.使用同样的网络结构,经过 10 个小时的训练,最终得到 78% 的精确度.
第三种方法:Retrain Inception V3
与以上方法相似,训练次数为 4000,依据结果进行调整.学习速率依据每批次的图像数量进行调整.80% 的数据用来训练,10% 用来验证,10% 用来测试.
五,实验结果
第一种方法:KNN,SVM,和 BP 神经网络
由于过拟合,我们无法得到好的实验结果.运行时间一般为半个小时,由于过拟合,我们认为,运行时间无法预估.通过与方法 1 比较,可以得出:即使 CNN 过拟合训练集,实验结果依旧优于方法 1.
第三种方法:Retrain Inception V3
整个训练过程不超过 10 分钟,且我们得到了非常好的结果.事实证明,深度学习和迁移学习十分强大.
Demo:
六,结论
基于以上实验比较,我们得出:
KNN,SVM,和 BP 神经网络在图像分类中不够有效.
即使在 CNN 中过拟合,CNN 的实验结果依旧比传统分类算法好.
迁移学习在图像分类问题上非常有效.运行时间短且结果精准,能够良好地解决过拟合和数据集过小的问题.
通过本次项目,我们得到了许多宝贵的经验,如下所示:
调整图像使其更小.
对于训练的每次迭代,随机选取小批次数据.
随机选取小批次数据作为验证集进行验证,并且在训练期间反馈验证评分.
利用 Image Augmentation 把输入图像集转变为可调整的更大的新数据集.
图像数据集要大于 200x10.
复杂网络结构需要更多的训练集.
小心过拟合.
参考文献
1. CS231n Convolutional Neural Networks for Visual Recognition
2. TensorFlow Convolutional Neural Networks
3. How to Retrain Inception's Final Layer for New Categories
4. k-NN classifier for image classification
5. Image Augmentation for Deep Learning With keras
6. Convolutional Neural Network TensorFlow Tutorial
Note: The first method is performed by Ji Tong
https://github.com/JI-tong
Originally published at gist.github.com.
来源: http://www.jianshu.com/p/7ea915aaaeda