图像分类基本流程及 KNN 分类器

1. 图像分类以及基本流程

1.1 什么是图像分类

  所谓图像分类问题,就是已有固定的分类标签集合,然后对于输入的图像,从分类标签集合中找出一个分类标签,最后把分类标签分配给该输入图像。虽然看起来挺简单的,但这可是计算机视觉领域的核心问题之一,计算机视觉领域中很多看似不同的问题(比如物体检测和分割),都可以被归结为图像分类问题。

1.2 图像分类的挑战

  物体分类与检测的难点与挑战在本文中分为3个层次:实例层次、类别 层次和语义层次,如图 1 所示 [1] 


图 1 .物体分类与检测研究存在的困难与挑战

 

  (1) 实例层次。针对单个物体实例而言,通常于图像采集过程中、光照条件拍摄视角距离的不同而造成的尺寸变化、物体自身的非刚体形变以及其他物体的部分遮挡,使得物体实例的表观特征产生很大的变化,给视觉识别算法带来了极大的困难

  (2) 类别层次。困难与挑战通常来自3个方面,首先是类内差大,也即属于同一类的物体表观特征差别比较大,其原因有前面提到的各种实例层次的变化,但这里更强调的是类内不同实例的差别,例如图2 (a) 所示,同样是椅子,外观却是千差万别,而从语义上来讲,具有“坐”的功能的器具都可以称为椅子;其次是类间模糊性,即不同类的物体实例具有一定的相似性,如图2 (b)所示,左边的是一只狼,右边的是一只哈士奇,但我们从外观上却很难分开二者;再次是背景的干扰,在实际场景下,物体不可能出现在一个非常干净的背景下,往往相反,背景可能是非常复杂的、对我们感兴趣的物体存在干扰的,这使得识别问题的难度大大增加。

  (3) 语义层次。困难和挑战与图像的视觉语义相关,这个层次的困难往往非常难处理,特别是对现在的计算机视觉理论水平而言,一个典型的问题称为多重稳定性。如图3所示,图3(c) 左边既可以看成是两个面对面的人,也可以看成是一个燃烧的蜡烛;右边则同时可以解释为兔子或者小鸭。同样的图像,不同的解释,这既与人的观察视角、关注点等物理条件有关,也与人的性格、经历等有关,而这恰恰是视觉识别系统难以处理的部分。

 


图 2 .分类与检测存在挑战的例子

 

1.3 图像分类的基本流程

  在机器学习中常常采用基于数据驱动的方法进行图像分类。所谓基于数据驱动的方法,就是给计算机很多数据,然后实现学习算法,让计算机学习到每个类的外形的方法。基于这种方法的完整流程如下

  (1) 输入:输入是包含 N 个图像的集合,每个图像的标签是 K 种分类标签中的一种。这个集合称为训练集。

  (2) 学习:这一步的任务是使用训练集来学习每个类到底长什么样。一般该步骤叫做训练分类器或者学习一个模型。

  (3) 评价:让分类器来预测它未曾见过的图像的分类标签,并以此来评价分类器的质量。我们会把分类器预测的标签和图像真正的分类标签对比。毫无疑问,分类器预测的分类标签和图像真正的分类标签如果一致,那就是好事,这样的情况越多越好。

2. K - Nearest Neighbor分类器

2.1 Nearest Neighbor分类器

  它的原理是拿着测试图片和训练集中每一张图片去比较,然后将它认为最相似的那个训练集图片的标签赋给这张测试图片。在 CIFAR­10 中,就是比较 32x32x3 的像素块。最简单的方法就是逐个像素比较,最后将差异值全部加起来。换句话说,就是将两张图片先转化为两个向量 和 ,然后计算他们的 L1 距离: 

d1(I1,I2)=∑p|Ip1−Ip2|d1(I1,I2)=∑p|I1p−I2p|


作为评价标准,我们常常使用准确率.。同样也有很多的其他评价标准,我们将在日后的学习笔记中逐渐补充

 

  距离选择:计算向量间的距离有很多种方法,另一个常用的方法是 L2 距离,从几何学的角度,可以理解为它在计算两个向量间的欧式距离。L2 距离的公式如下: 

d2(I1,I2)=∑p(Ip1−Ip2)2−−−−−−−−−−−√d2(I1,I2)=∑p(I1p−I2p)2


换句话说,我们依旧是在计算像素间的差值,只是先求其平方,然后把这些平方全部加起来,最后对这个和开方。注意这里使用了开平方,但是在实际中可能不用。因为求平方根函数是一个单调函数,它对不同距离的绝对值求平方根虽然改变了数值大小,但依然保持了不同距离大小的顺序。所以用不用它,都能够对像素差异的大小进行正确比较。

 

  L1 和 L2 比较。比较这两个度量方式是挺有意思的。在面对两个向量之间的差异时,L2 比 L1 更加不能容忍这些差异。也就是说,相对于1个巨大的差异,L2 距离更倾向于接受多个中等程度的差异。L1 和 L2 都是在 p-­norm 常用的特殊形式。更多的衡量距离的标准将在之后的笔记中进行讨论。

2.2 K-Nearest Neighbor分类器

  它的思想很简单:与其只找最相近的那 1 个图片的标签,我们找最相似的 k 个图片的标签,然后让他们针对测试图片进行投票,最后把票数最高的标签作为对测试图片的预测。所以当 k=1 的时候,k­Nearest Neighbor 分类器就是 Nearest Neighbor 分类器。从图 3 直观感受上就可以看到,更高的 k 值可以让分类的效果更平滑,使得分类器对于异常值更有抵抗力。 


图 3 .NN与KNN的对比结果

 

需要注意的是,在 NN 分类器中,异常的数据点(比如:在蓝色区域中的绿点)制造出一个不正确预测的孤岛。5­NN 分类器将这些不规则都平滑了,使得它针对测试数据的泛化(generalization)能力更好(例子中未展示)。注意,5­NN 中也存在一些灰色区域,这些区域是因为近邻标签的最高票数相同导致的(比如:2个邻居是红色,2 个邻居是蓝色,还有 1 个是绿色)。

3. 模型的超参数选择(以K-NN为例)

  在模型的实际使用过程中,K-NN分类器中的 K 选取多少较为合适,计算距离使用 L1 范数还是 L2 范数都是需要我们进行选择的,并且称这些参数为超参数。 在超参数调优的过程中决不能使用测试集来进行调优,因为这样会使模型对测试集过拟合,降低模型的泛化能力。所以测试数据集只使用一次,即在训练完成后评价最终的模型时使用。

  把训练集按照50%­-90%的比例分成训练集和验证集,使用训练集训练模型,使用验证集调节超参数。如在 K-NN 中选择超参数 k ,取不同的 k 值用训练集进行训练,之后用检验集进行检验,作图分析出哪个 k 值表现最好,然后用这个 k 值来跑真正的测试集,并作出对算法的评价。

  交叉验证。有时候,训练集数量较小(因此验证集的数量更小),人们会使用一种被称为交叉验证的方法,这种方法更加复杂些。还是用刚才的例子,如果是交叉验证集,我们就不是取 1000 个图像,而是将训练集平均分成 5 份,其中 4 份用来训练,1 份用来验证。然后我们循环着取其中 4 份来训练,其中 1 份来验证,最后取所有 5 次验证结果的平均值作为算法验证结果。 


图 4 .不同的 K 值对应的KNN分类器结果

 

如图 4 是份交叉验证对 k 值调优的例子。针对每个 k 值,得到 5 个准确率结果,取其平均值,然后对 
不同 k 值的平均表现画线连接。本例中,当 k=7 的时算法表现最好(对应图中的准确率峰值)。如果我们将训练集分成更多份数,直线一般会更加平滑(噪音更少)。

  实际应用。在实际情况下,人们不是很喜欢用交叉验证,主要是因为它会耗费较多的计算资源。一般直接把训练集按照50%-­90%的比例分成训练集和验证集。但这也是根据具体情况来定的:如果超参数数量多,你可能就想用更大的验证集,而验证集的数量不够,那么最好还是用交叉验证吧。至于分成几份比较好,一般都是分成3、5和10份。

4. Nearest Neighbor分类器的优劣

4.1 NN的优点

  首先,Nearest Neighbor分类器易于理解,实现简单。

  其次,算法的训练不需要花时间,因为其训练过程只是将训练集数据存储起来。

4.2 NN的缺点

  首先,因为每个测试图像需要和所有存储的训练图像进行比较,所以占用大量存储空间,耗费大量计算资源,测试要花费大量时间计算。因为在实际应用中,我们关注测试效率远远高于训练效率。其实,我们后续要学习的卷积神经网络在这个权衡上走到了另一个极端:虽然训练花费很多时间,但是一旦训练完成,对新的测试数据进行分类非常快。这样的模式就符合实际使用需求。

  其次,在实际的图像分类工作中,很少使用 NN。因为图像都是高维度数据(他们通常包含很多像素),而高维度向量之间的距离通常是反直觉的。下面的图片展示了基于像素的相似和基于感官的相似是有很大不同的: 


图 5 .L2值相同的不同图片

 

在高维度数据上,基于像素的的距离和感官上的非常不同。上图中,右边 3 张图片和左边第 1 张原始图片的L2距离是一样的。很显然,基于像素比较的相似和感官上以及语义上的相似是不同的。

  这里还有个视觉化证据,可以证明使用像素差异来比较图像是不够的。z这是一个叫做t-SNE的可视化技术,它将CIFAR-10中的图片按照二维方式排布,这样能很好展示图片之间的像素差异值。在这张图片中,排列相邻的图片L2距离就小。 


图 6 .将图片进行降维显示

 

上图使用t-SNE的可视化技术将CIFAR-10的图片进行了二维排列。排列相近的图片L2距离小。可以看出,图片的排列是被背景主导而不是图片语义内容本身主导。具体说来,这些图片的排布更像是一种颜色分布函数,或者说是基于背景的,而不是图片的语义主体。比如,狗的图片可能和青蛙的图片非常接近,这是因为两张图片都是白色背景。从理想效果上来说,我们肯定是希望同类的图片能够聚集在一起,而不被背景或其他不相关因素干扰。为了达到这个目的,我们不能止步于原始像素比较,得继续前进。

参考文献

[1]杨金鑫,杨辉华,李灵巧,潘细朋,刘振丙,周洁茜.结合卷积神经网络和超像素聚类的细胞图像分割方法[J/OL].计算机应用研究,2018,(05):1-2(2017-06-14).http://kns.cnki.net/kcms/detail/51.1196.TP.20170614.1318.098.html.

  • 1
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 好的,我们需要做一些准备工作,首先我们要准备好cifar10数据集并导入相关的库。 ```python import numpy as np from sklearn import datasets from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsClassifier # 导入数据 cifar10 = datasets.load_cifar10() X = cifar10.data y = cifar10.target # 将数据集分为训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 创建k-NN分类器 knn = KNeighborsClassifier(n_neighbors=5) # 训练模型 knn.fit(X_train, y_train) # 评估模型 accuracy = knn.score(X_test, y_test) print('Accuracy:', accuracy) ``` 上面的代码展示了如何使用k-NN算法进行分类的基本流程。首先,我们导入了需要使用的库,包括`numpy`和`sklearn`中的`datasets`和`model_selection`模块。然后,我们使用`load_cifar10`函数导入了cifar10数据集,并将数据和标签存储在`X`和`y`变量中。接着,我们使用`train_test_split`函数将数据集分为训练集和测试集。然后,我们创建了一个k-NN分类器,并使用`fit`方法训练模型。最后,我们使用`score`方法来评估模型的准确率。 希望这个代码能帮到你! ### 回答2: CIFAR-10 数据集是一个常用的计算机视觉数据集,包含了来自10个不同类别的60000张32x32彩色图像。每个类别有6000张图像。其中50000张用于训练集,另外10000张用于测试集。 KNN(K-Nearest Neighbors)算法是一种简单而有效的分类算法。它通过计算该样本与训练集中的每个样本之间的距离,然后选取距离最近的k个训练样本中出现频率最高的类别作为预测结果。 要使用KNN算法完成对CIFAR-10数据集的分类,可以按照以下步骤进行: 1. 加载数据集: 首先,需要将CIFAR-10数据集导入到代码中。可以使用现有的库(如TensorFlow)来加载和处理数据集。 2. 数据预处理: 对于KNN算法,需要将图像数据转换为一维向量。可以将每个图像的RGB通道连接在一起,并将像素值归一化到0到1之间。 3. 计算距离: 在KNN算法中,常用的距离度量方式是欧氏距离。对于测试样本,需要计算它与训练集中每个样本的距离。 4. 选择最近的k个邻居: 根据计算的距离,选择与测试样本距离最近的k个训练样本。 5. 进行分类: 统计这k个最近邻居中每个类别的出现次数,并选择出现频率最高的类别作为预测结果。 6. 评估分类性能: 使用测试集对分类器进行评估,计算准确率或其他性能指标。 需要注意的是,KNN算法在处理大规模数据集时可能会比较缓慢,尤其是当特征维度较高时。因此,在实际应用中,可能需要采用一些优化措施,如使用KD树等数据结构来加速计算。 以上是使用KNN算法完成对CIFAR-10数据集的分类代码的基本思路。根据具体的编程语言和库的选择,实际的代码实现可能会有所不同。 ### 回答3: K最近邻算法(K-Nearest Neighbors,KNN)是一种常用的监督学习算法,它根据样本间的距离来进行分类。下面是使用KNN算法对CIFAR-10数据集进行分类的代码。 首先,我们需要导入所需的库和模块。我们可以使用Python的机器学习库sklearn来实现KNN算法。代码如下所示: ```python import numpy as np from sklearn.neighbors import KNeighborsClassifier from sklearn.metrics import accuracy_score from sklearn.datasets import load_breast_cancer from sklearn.model_selection import train_test_split # 载入CIFAR-10数据集 cifar = load_cifar() # 拆分数据集为训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(cifar.data, cifar.target, test_size=0.2, random_state=42) # 创建并训练KNN模型 k = 5 knn = KNeighborsClassifier(n_neighbors=k) knn.fit(X_train, y_train) # 在测试集上进行预测 y_pred = knn.predict(X_test) # 计算准确率 accuracy = accuracy_score(y_test, y_pred) print("准确率: ", accuracy) ``` 在代码中,我们首先导入了所需的库和模块,包括numpy、sklearn中的KNeighborsClassifier类和accuracy_score函数,以及load_cifar函数和train_test_split函数。 接下来,我们使用load_cifar函数加载CIFAR-10数据集。然后,我们使用train_test_split函数将数据集划分为训练集和测试集,其中测试集占总样本的20%。 然后,我们创建了一个KNN模型,其中k=5表示我们选择的邻居数。接着,我们使用fit函数对训练集进行训练。 在训练完成后,我们使用predict函数对测试集进行预测,得到预测结果y_pred。 最后,我们使用accuracy_score函数计算准确率,将预测的结果y_pred与实际标签y_test进行比较。准确率越高,说明模型的分类效果越好。 以上就是使用KNN算法对CIFAR-10数据集进行分类的代码汇总。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值