图像分类方法总结
时间:2023-10-24 20:37:01
1. 描述图像分类问题
图像分类是计算机视觉领域的基本问题。其目的是根据图像的语义信息区分不同类别的图像,以实现最小的分类误差。具体任务要求是从给定的分类集合中给图像分配一个标签。一般来说,单标签图像分类可分为三类:跨物种语义图像分类、子类细粒度图像分类和实例级图像分类。因为VOC数据集是不同物种类型的数据集,因此本文主要讨论跨物种语义级别的图像分类任务。
通常图像分类任务存在以下技术难点:
(1)视角变化:相机可以从多个角度显示同一个物体。
(2)尺寸变化:物体可视尺寸通常会变化。
(3)变形:很多东西的形状不是一成不变的,会有很大的变化。 (4)遮挡:目标对象可能被屏蔽。有时只有一小部分物体是可见的。
(5)光照条件:在像素层面,光照影响很大。
(6)背景干扰:物体可能与背景混合,难以识别。
(7)类内差异:一类物体的个体形状差异很大,比如椅子。这类物体有很多不同的物体,每个物体都有自己的形状。
2. 已有研究进展
图像分类算法通过手工特征或特征学习方法描述整个图像,然后使用分类器判断是否存储 在某种物体中。广泛使用的图像特征具有SIFT,HOG,SURF等。在图像分类的研究中,大多数特征提取过程都是人工设计的, 图像的底层特征是通过浅层学习获得的,与高级图像主题之间仍很大的语义差距 。深度学习利用设定的网络结构, 从训练数据中学习图像的层次结构特征, 能够提取更接近图像高级语义的抽象特征,在图像识别方面的表现远远超过传统方法,因此这里只关注深度学习的进展。
2.1 MNIST与LeNet5
在计算机视觉分类算法的发展中,MNIST 它是第一个具有通用学术意义的基准。这是手写数字的分类标准,包括 60000 训练数据1万 测试数据,图像为灰度图,一般版本大小为 28×28。
90年代末本世纪初,SVM and K-nearest neighbors该方法被广泛使用SVM代表的方法可以MNIST分类错误率降至0.56%仍然超过以神经网络为代表的方法,即LeNet系列网络。LeNet网络诞生于1994年,经过多次迭代才出现于1998年LeNet5.是我们广为人知的版本。
这是一个经典的卷积神经网络,它包含着一些重要的特性,这些特性仍然是现在CNN网络的核心。
(1)卷积层由卷积、池化和非线性激活函数组成。自1998年以来,经过20年的发展,卷积神经网络仍然遵循这一设计理念。其中,卷积发展了许多变体,池化逐渐被带步长的卷积完全取代,非线性激活函数演变成许多变体。
(2)稀疏连接,也就是局部连接,这是以卷积神经网络为代表的技术能够发展至今的最大前提。利用图像的局部相似性,这一区别于传统全连接的方式,推动了整个神经网络技术的发展。
虽然LeNet当时的错误率还停留在0.7%的水平不如同期最好SVM方法,但随着网络结构的发展,神经网络方法很快超过了所有其他方法,错误率降低到0.23%,甚至有的方法已经达到了错误率接近0的水平。
2.2 ImageNet与AlexNet
在本世纪早期,虽然神经网络开始复苏,但由于数据集的规模和硬件的发展,神经网络的训练和优化仍然非常困难。MNIST和CIFAR数据集只有6万张图片,这可能足以满足像10分类这样简单的任务,但在工业界实施更复杂的图像分类任务还远远不够。
2009年,在李飞飞等人数年的整理下,ImageNet数据集发布,从2010年开始每年举行一次ImageNet大规模视觉识别挑战,即ILSVRC。ImageNet总共有1400多万张图片,涵盖2万多个类别,1000类基准常用于论文方法的比较。
在ImageNet在发布的早期,它仍然是SVM和Boost直到2012年,代表性的分类方法才占据优势AlexNet的出现。
AlexNet它是第一个真正意义上的深度网络LeNet与5层相比,其层数增加了3层,网络参数也大大增加,输入也从28变为224,同时GPU它的出现也使学习从此进行GPU训练时代为王。
AlexNet具有以下特点:
(1)网络比LeNet5更深,包括5个卷积层和3个全连接层。
(2)使用Relu激活函数,收敛快,解决Sigmoid梯度弥散问题发生在网络较深时。
(3)加入了Dropout防止过拟合。
(4)使用了LRN归一化层为局部神经元的活动创造了竞争机制,抑制了反馈较小的神经元放大反应较大的神经元,增强了模型的泛化能力。
(5)利用切割翻转等操作增强数据,增强模型的泛化能力。在预测过程中,提取图片的四个角加上中间五个位置,左右翻转图片的平均值,这也是以后刷游戏的基本使用技巧。
(6)分块训练,当年GPU计算能力不如现在强,AlexNet将图像创新地分为上下两部分进行训练,然后在全连接层合并。
(7)总数据参数约为240M,远大于LeNet5。
2.3 分类模型逐年进步
2013年ILSVRC冠军网络的分类任务是Clarifai,但我们更熟悉的是zfnet。hinton的学生Zeiler和Fergus在研究中,利用反卷积技术引入神经网络的可视化,可视化网络的中间特征层,从而检验研究人员激活不同特征及其与输入空间的关系。在此指导下对AlexNet网络进行了简单的改进,包括使用更小的卷积核和步长x11卷积核变成7x7卷积核,将stride从4到2,性能超过原始AlexNet网络。
2014年冠亚军网络分别是GoogLeNet和VGGNet。
其中VGGNet包括两个版本:16层和19层,参数约为550M。全部使用3×3的卷积核和2×2的最大池化核,简化了卷积神经网络的结构。VGGNet它很好地展示了如何通过简单地增加网络层数和深度来提高网络的性能。在今天,VGGNet许多任务仍然被选为基准模型。
GoogLeNet是来自于Google的Christian Szegedy其他人提出的22层网络top-5分类错误率只有6.7%。
GoogleNet的核心是Inception Module,它采用用。一个经典的inception结构包括四个成分。1×1卷积,3×3卷积,5×5卷积,3×最大池化,最后通道组合四个成分的运算结果。这就是Inception Module核心思想。图像可以通过多个卷积核提取不同尺度的信息,然后集成,从而获得更好的图像表征。此后,深度学习模型的分类准确性已达到人类水平(5%)~10%)。
与VGGNet相比,GoogleNet精心设计的模型架构Inception模型在结构下更深更小,计算效率更高。
2015年,ResNet获得分类任务冠军。.57%的错误率超过了人类的识别水平,并以152层的网络架构创造了新的模型记录。ResNet采用跨层连接,成功缓解了深层神经网络中的梯度消散问题,为数千层网络训练提供了可能。
许多经典模型仍然在2016年诞生,包括在分类比赛中获得第二名ResNeXt,101层的ResNeXt可以达到ResNet152的精度只有后者复杂性的一半,核心思想是分组积累。也就是说,输入通道首先分组,经过几个平行分支的非线性变换,最终合并。
在ResNet在此基础上,密集连接DenseNet在前馈过程中,将每层与其他层连接起来。对于每层网络,前面所有网络的特征图都被用作输入,其特征图也被后面的网络层用作输入。
DenseNet与梯度相比,中密度连接也可以缓解梯度消失的问题ResNet,它可以加强特征传播和特征再利用,减少参数数量。DenseNet相较于ResNet内存和计算资源较少,性能较好。
2017年,也是ILSVRC图像分类比赛的最后一年,SeNet赢得冠军。该结构仅采用特征重校准策略来处理特征,通过学习获得每个特征通道的重要性,并根据重要性降低或提高相应特征通道的重要性。
卷积神经网络在特征表达方面具有很大的优势。随着网络深度的增加,模型提取的特征越来越抽象,图像主题的语义越来越多。不确定性越小,识别能力越强。虽然基本的图像分类任务,特别是比赛接近饱和,但实际的图像任务仍然存在许多困难和挑战。比如分类任务分类不平衡,细粒度分类任务分类内方差很大,分类任务包含无限负样本。
3. 方法与实现
3.1 数据处理
考虑到模型性能与数据集数量密切相关,密切相关,数据不足导致培训不足,本文通过预处理数据和提高分类性能来提高模型的泛化性。主要包括调整图像大小、镜像、剪切、旋转和随机擦除。
在学习神经网络时,通常采用批量学习的方法来提高效率。在具体实现中,模型接受张量,因此原始数据应首先处理成张量形式。然后对图像进行预处理,将尺寸调整到统一尺寸,以适应模型训练;同时,读取图像的目的是使部分激活函数的梯度不太小,加速收敛。
图像镜像、剪切、旋转和随机擦除不仅可以增加数据集的数量,还可以增加训练过程中识别图像的难度和例子,使模型能够学习更有效的特征。
3.2 基准模型
由于深度残差网络的简洁性和有效性,我们方法的基准网络模型采用深度残差网络ResNet。
深度残差网络是2015年提出的深度卷积网络。一旦出生,就会出现ImageNet获得图像分类、检测、定位三项冠军。 一般来说,增加网络的宽度和深度可以很好地提高网络的性能,深网络一般优于浅网络效果,通过实验发现,当网络层数达到一定数量时,网络性能饱和,然后增加网络性能开始退化,但退化不是由拟合引起的,因为我们发现训练精度和测试精度下降,这表明当网络变得非常以后,深度网络就变得难以训练了。 ResNet的出现其实就是为了解决网络深度变深以后的性能退化问题。如下图所示,ResNet主要通过残差网络结构使优化的目标变为H(x)=F(x)+x(x就是该结构的输入),通过这种结构以后就把优化的目标由H(x)转化为H(x)-x,这时候就不是把上面几层训练到一个等价映射了,而是将其逼近与0,这样训练的难度比训练到一个等价映射下降了很多,同时解决网络太深难训练的问题。
残差网络结构
深度残差网络分类
如上图所示,按照网络模型输出层数的不同,残差网络可以分为ResNet 18、ResNet 34、 ResNet 50、 ResNet 101等。我们分别在这几个基准模型进行了图像分类任务的实现。
3.3 损失函数
多分类问题最常用的方法是设置n个输出节点,其中n为类别的个数。对于每一个样例,网络模型可以得到的一个n维数组作为输出结果。数组中的每一个维度(也就是每一个输出节点)对应一个类别。在理想情况下,如果一个样本属于类别k,那么这个类别所对应的输出节点的输出值应该为1,而其他节点的输出都为0。
交叉熵是最好的评判方法之一。交叉熵刻画了两个概率分布之间的距离,它是分类问题中使用比较广的一种损失函数。本文采用的是加权的交叉熵函数,按照不同类别图像的数量设置权值,目的是平衡不同类别的图像的数量。
3.4 算法流程
(1)数据处理:将数据按需处理为张量、随机组成批量、归一化、标准化以及一些数据增强等效果。
(2)模型定义:定义ResNet模型,设计网络层数,层的类别,包括卷积,池化,批标准化,激活函数的设置。
(3)参数更新:训练模型的过程最基本的就是更新参数,更新参数与模型紧密相关,因此可以把最基础的单次参数更新和模型合在一起包装成一个对象,在训练过程中更新参数时,喂给这个模型数据,然后使用这个对象的行为来实现单次更新。具体流程为根据model生成模型对象,对这些层进行初始化,接受批数据,根据定义好的优化方法,更新对象内的模型参数。
(4)模型选择:模型选择的准则是根据任务需要来的,每次更新完参数测试模型是否满足条件,符合就停止算法,不符继续。
3.5 具体实现
我们的方法实现基于Pytorch深度学习框架,将所有图像调整大小为300*300,批次大小设置为32,模型包括ResNet 18、ResNet 34、 ResNet 50、 ResNet 101,并导入在ImageNet数据集的预训练模型,初始学习率大小设置为1e-3,优化方法选取随机梯度下降方法,动量设置为0.9,训练轮数为16。
4. 算法与工具
图像分类主要使用的 5 个方法是 KNN、SVM、BP 神经网络、CNN 和迁移学习。
五个方法可分为 3 类方法:
第一类方法:使用 KNN、SVM、BP 神经网络这些课堂算法。这些算法强大易实现。我们主要使用 sklearn 实现这些算法。
第二类方法:尽管传统的多层感知器模型已成功应用于图像识别,但由于其节点之间的全连接性,它们遭遇了维度的难题,从而不能很好地扩展到更高分辨率的图像。因此我们使用深度学习框架 TensorFlow 打造了一个 CNN。
第三个方法:重新训练一个被称作 Inception V3 的预训练深度神经网络的最后一层,同样由 TensorFlow 提供。Inception V3 是为 ImageNet 大型视觉识别挑战赛训练的,使用了 2012 年的数据。这是计算机视觉的常规任务,其中模型试图把全部图像分为 1000 个类别,比如斑马、达尔阿提亚人和洗碗机。为了再训练这一预训练网络,我们要保证自己的数据集没有被预训练。
4.1实现
第一类方法:预处理数据集,并使用 sklearn 实现 KNN、SVM、BP 神经网络。
首先,我们使用 OpenCV 包定义了 2 个不同的预处理函数:第一个是图像到特征向量,它可以重调图像大小,并把图像转化为行像素列表;第二个是提取颜色直方图,即使用 cv2.normalize 从 HSV 颜色空间提取 3D 颜色直方图,并平化(flatten)结果。
接着,建构若干个我们需要解析的参数。由于想要同时测试整个数据集和带不同数量标签的子数据集的精确度,我们构建了一个作为参数的数据集并解析进我们的程序。我们同样构建了用于 k-NN 方法的邻元素数作为解析参数。
之后,我们开始提取数据集中的每一图像特征,并将其放入数组。我们使用 cv2.imread 读取每一图像,通过从图像名称中提取字符串来拆分标签。在我们的数据集中,我们使用相同格式——类别标签. 图像序号.jpg——设置名称,因此我们可以轻易提取每张图像的分类标签。接着我们使用这两个函数提取 2 种特征并附加到数组 rawImages,而之前提取的标签附加到数组标签。
下一步是使用从 sklearn 包导入的函数 train_test_split 拆分数据集。这个集具有后缀 RI,RL 是 rawImages 和标签对的拆分结果,另一个是特征和标签对的拆分结果。我们使用 85% 的数据集作为训练集,余下的 15% 作为测试集。
最后,我们应用 KNN、SVM、BP 神经网络函数评估数据。对于 KNN 我们使用 KNeighborsClassifier,对于 SVM 我们使用 SVC,对于 BP 神经网络我们使用 MLPClassifier。
第二类方法:使用 TensorFlow 构建 CNN。TensorFlow 的全部目的在于使你打造一张计算图(使用 Python 等语言),接着在 C++ 中执行该图(在相同计算量的情况下,C++比 Python 更高效)。
TensorFlow 也可自动计算优化图变量所需的梯度,从而使模型表现更好。这是由于该图由简单的数学表达式组合而成,因此可通过导数链式法则计算全图的梯度。
一张 TensorFlow 图包含以下几个部分,每一部分将在下文详述:
• 占位符变量,用于输入数据到图。
• 优化向量以使卷积网络表现更好。
• 卷积网络的数学公式。
• 可用于指导变量优化的成本衡量标准。
• 更新变量的优化方法。
CNN 架构由一堆不同的层组成,这些层通过可微分函数可把输入量转化为输出量。
因此,在我们的实现中,第一层是保存图像,接着我们使用 2 x 2 最大池化和修正线性单元(ReLU)的构建 3 个卷积层。输入是 4 维张量:
图像序号。
每一图像的 Y 轴。
每一图像的 X 轴。
每一图像的通道(channel)。
输出是另一个 4 维张量:
图像序号,与输入相同。
每一图像的 Y 轴。如果使用 2x2 池化,接着输入图像的高和宽除以 2。
每一图像的 X 轴。同上。
由卷积滤波器生成的通道。
接着,我们我们在网络末端构建了 2 个全连接层。输入是一个 2 维的形状张量 [num_images、num_inputs]。输出也是一个 2 维的形状张量 [num_images、num_outputs]
然而,为了连接卷积层和全连接层,我们需要一个平层(Flatten Layer)以把 4 维向量减少至可输入到全连接层的 2 维。
CNN 末端通常是一个 softmax 层,它可归一化来自全连接层的输出,因此每一元素被限制在 0 与 1 之间,并且所有元素总和为 1。
为了优化训练结果,我们需要一个成本衡量标准并在每次迭代中将成本降至最少。这里我们使用的成本函数是交叉熵(tf.nn.oftmax_cross_entropy_with_logits()),并在所有的图像分类中取交叉熵的平均值。优化方法是 tf.train.AdamOptimizer(),它是梯度下降的高级形式。这是一个可被调节的参数学习率。
第三种方法:再训练 Inception V3。现代目标识别模型有数以百万计的参数,并可能需要花费数周的时间才能完全训练一个模型。迁移学习是一种采用在分类数据集(如 ImageNet)中已训练的模型而快速完成这一工作的方法,因为其只需要重新训练新类别的权重就行。虽然这样的模型并没有完全训练的模型表现好,但对于许多应用来说,这是非常高效的,因为其不需要 GPU 并可以在笔记本上花半个小时就完成训练。
首先我们需要获取预训练模型,并移除旧的顶层神经网络,然后再基于我们的数据集重新训练一个输出层。虽然猫的所有品种并没有在原始 ImageNet 数据集和全训练的模型中体现,但迁移学习的神奇之处就在于其可以利用已训练模型用来识别某些目标的底层特征,因为底层特征可以在很多不更改的情况下应用于很多识别任务。然后我们分析本地的所有图片并计算每张的瓶颈值(bottleneck values)。因为每张图片在训练过程中重复使用了多次,所以计算每个瓶颈值需要花费大量时间,但我们可以加快缓存这些瓶颈值,也就可以省去重复的计算。
该脚本将运行 4000 次训练步。每一步从训练集中随机选择 10 张图片,并从缓存中搜索其瓶颈值,然后再将它们训练最后一层以得到预测。这些预测会通过对比真实标注值而通过反向传播过程更新最后一层的权重。
5. 结论
基于以上比较,我们可以看到:
KNN、SVM 和 BP 神经网络对于某些特定图像分类任务是不够的。
虽然我们会在 CNN 中过拟合,但这仍然比那些课堂方法要好。
迁移学习在图像分类问题上效率很高,功能强大。它准确快速,可以在短时间内完成训练——而且不需要 GPU 的帮助。即使你只有一个很小的数据集,它也可以达到很好的效果,并且减少了过拟合的概率。
我们已经从图像分类任务中学到了很多,这类任务与课堂上的其他分类任务大不相同。数据集相对较大且稠密,需要的网络十分复杂,且大多方法依赖于 GPU 的计算能力。
经验:
裁剪或重调图像,使其更小
在训练的每个迭代中随机选择一个小 batch
在验证集进行验证的时候随机选择一个小 batch,在训练过程中频繁记录验证分数
可以使用 Image Augmentation 处理图片,增大数据集体量
对于图像分类任务,我们需要比 200 x 10 的更大的数据集,CIFAR-10 数据集包含 6 万张图像。
越复杂的网络需要越大的数据集进行训练
小心过拟合
参考文献
[1] CS231n Convolutional Neural Networks for Visual Recognition:http://cs231n.github.io/convolutional-networks/
[2] TensorFlow Convolutional Neural Networks:https://www.tensorflow.org/tutorials/deep_cnn
[3] How to Retrain Inception』s Final Layer for New Categories:https://www.tensorflow.org/tutorials/image_retraining
[4] k-NN classifier for image classification:http://www.pyimagesearch.com/2016/08/08/k-nn-classifier-for-image-classification/
[5] Image Augmentation for Deep Learning With Keras:http://machinelearningmastery.com/image-augmentation-deep-learning-keras/
[6] Convolutional Neural Network TensorFlow Tutorial:https://github.com/Hvass-Labs/TensorFlow-Tutorials/blob/master/02_Convolutional_Neural_Network.ipynb