图像分类,顾名思义,是一个输入图像,输出对该图像内容分类的描述的问题。它是计算机视觉的核心,实际应用广泛。
图像分类的传统方法是特征描述及检测,这类传统方法可能对于一些简单的图像分类是有效的,但由于实际情况非常复杂,传统的分类方法不堪重负。现在,我们不再试图用代码来描述每一个图像类别,决定转而使用机器学习的方法处理图像分类问题。
目前,许多研究者使用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 数据集。其中有犬类25类,猫类12类。每类有200个图像。我们使用到该数据集中的10个类别的猫的数据,分别是[‘Sphynx’,’Siamese’,’Ragdoll’,’Persian’,’Maine-Coon’,’British-shorthair’,’Bombay’,’Birman’,’Bengal’,’Abyssinian’]。即,共有2000个图像,由于图像大小不一,我们调整大小统一为固定尺寸64X64或128X128。
本项目中,我们主要使用OpenCV预处理图像。一般通过变形、剪裁或亮化随机处理训练集。
赋值
第一种方法: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,我们进行实验。首先,参数如下:
# 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
我们使用了3个卷积层和2个全连接层,然而悲剧的是过度拟合。经过研究发现,对于该构造,我们的数据集过小,网络过于复杂。
最终,我们使用如下参数:
# 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
我们只使用了2个卷积层和2个全连接层。依然不尽人意,经过4000次迭代,结果仍旧过拟合,不过好在测试结果10%优于前者。最终,经过5000次迭代,我们得到43%的精确度,运行时间是半小时以上。
PS:我们使用另一个数据集CIFAR-10进行了实验。
该数据集包含60000个32x32的彩色图像,分为10个类别,每个类别6000个图像。训练集50000个图像,测试集10000个图像。使用同样的网络结构,经过10个小时的训练,最终得到78%的精确度。
第三种方法:Retrain Inception V3
与以上方法相似,训练次数为4000,依据结果进行调整。学习速率依据每批次的图像数量进行调整。80%的数据用来训练,10%用来验证,10%用来测试。
实验结果
第一种方法:KNN,SVM,和BP神经网络
在KNN中,Knn_raw_pixel和Knn_histo的精确度的值比较接近。在5类标签情况下,前者比后者要低,整体来说,原始像素表现更好。
在MLP分类器中,原始像素精确地要低于柱状图精确度。对于整个数据集(10个标签)来讲,原始像素精确度竟然低于随机猜想的精确度。
上面两种sklearn方法都没有得到非常好的性能。对于整个数据集,只有24%的精确度。实验结果证明,sklearn方法不能够有效进行图像分类。为了有效进行图像分类并且提高精确度,有必要使用深度学习的方法。
第二种方法:基于TensorFlow构建CNN
由于过拟合,我们无法得到好的实验结果。运行时间一般为半个小时,由于过拟合,我们认为,运行时间无法预估。通过与方法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
CIO之家 www.ciozj.com 公众号:imciow