图片分类-K近邻分类器

你可以注意到当我们做预测的时候,如果仅仅用最近的图片的是远远不够的。其实,我们更常用的是k近邻分类器。这个思想非常简单。代替寻找训练集中最近的图片,我们会寻找k个最相近的图片,并且让他们再测试图片上投票。特别的,再k=1的时候,我们已经涵盖了最近邻分类器。只管来说,更高的k值有一个平滑的影响使得分类器对极端值有更好的处理:

knn分类
这张图表达了最近邻分类,和5-最近邻分类之间的差距,用二维的电荷3个类别(红色、蓝色、绿色区域)。标记颜色的区域可以展示出通过过L2距离计算出的决策范围。白色部分展示的是有歧义的点(例如,类别投票至少要有两种类型)。可以看到再一个最近邻分类器中,异常数据点(例如,再蓝色点中的绿色点)创建了一个很小的独立不正确预测区域,然而5-近邻分类器平滑的忽略了这些非法数据,而且提高了测试数据的一般性。我们也可以看到5-近邻的灰色区域图片也被近邻选票所约束(例如,2个近邻是红色,另两个是蓝色,最后一个是绿色)。
实际中,你会经常想要使用k近邻。但是k的值取多少。下面我们将解释这个问题。

验证集的超参数调优

k近邻分类器需要一个k值的设置。但是那个数字是最好的呢?并且,我们看到还有很多不同的距离函数我们使用过:L1norm,L2norm,这里还有许多其他的我们没有考虑的函数(例如,向量点积)。这些都叫超参数并且他们经常出现在机器学习算法的设计中。有时候选择一个什么样的参数并不明显。
你可能想我们应该尝试不同的值看哪个表现的最好。这是一个很好的想法并且这也就是我们要做的。但是这必须很小心的取尝试。特别的,我们不能用测试集来调整超参数。无论你何时设计机器学习算法,你应该考虑测试集作为一个最先考虑的资源。因此,最真实的危险就是你可以调整你的超参数再测试集上运行的很好,但是如果你把你的模型运用到真实场景中去,效果就会大打折扣。实际中,我们都会说你过拟合了你的测试集。另一个方面,当你使用他的时候,如果你把超参数测试运用在测试集上,那么你会再测试集中有很好的效果,并且因此你的测试集准确率会提高。但实际上并没有那么高。但如果你仅仅在最后使用测试集,这里还是存在着测试一个普遍性分类器的参数(在以后的课程中会有)。
仅仅再最后使用一次测试集评估
幸运的是,这里有一个正确的方法去测试你的超参数并且不会接触到测试集。这个想法就是把你的训练集一分为二:一个很小的训练集,我们叫做验证集。使用CIFAR-10做个例子,我们可以使用49000作为训练集,剩下的1000个作为验证集。这个验证集就是用来调超参数的。
这里有一个很像CIFAR-10的例子:

# assume we have Xtr_rows, Ytr, Xte_rows, Yte as before
# recall Xtr_rows is 50,000 x 3072 matrix
Xval_rows = Xtr_rows[:1000, :] # take first 1000 for validation
Yval = Ytr[:1000]
Xtr_rows = Xtr_rows[1000:, :] # keep last 49,000 for train
Ytr = Ytr[1000:]

# find hyperparameters that work best on the validation set
validation_accuracies = []
for k in [1, 3, 5, 10, 20, 50, 100]:

  # use a particular value of k and evaluation on validation data
  nn = NearestNeighbor()
  nn.train(Xtr_rows, Ytr)
  # here we assume a modified NearestNeighbor class that can take a k as input
  Yval_predict = nn.predict(Xval_rows, k = k)
  acc = np.mean(Yval_predict == Yval)
  print 'accuracy: %f' % (acc,)

  # keep track of what works on the validation set
  validation_accuracies.append((k, acc))

在最后一个过程,我们可以画一个图来展示哪个k值可以得到最好的结果。我们会把这个值与真实测试集来评估准确率。
将你的测试集分为训练集和验证集。用验证集来调所有的参数。在最后运行一次测试集并且报告准确率。

交叉验证.

再这些例子中你的训练集的大小会是很小的,人们有时会使用随机调参技术叫做交叉验证。再考虑上一个例子,这个思想就是不再玄奇前一千个点来做验证集,二十你可以获取一个更好的并且更少噪音的评估。例如,再5-个交叉验证中,我们可以把训练集分为5整份,用四个做训练,1个做验证。我们会迭代哪个是验证集,评估性能,并且最终再不同的集合中平均性能。

针对k的验证集
针对k值的5份交叉验证。针对每个k值我们训练四份并且再第五份上评估。对于每一个k我们接受一个再验证集上的准确率(y轴就是准确率,每个结果就是一个点)。趋势线由针对每个k的平均结果并且偏差显示为标准差。在这个特殊的例子中,交叉验证中表示当k=7的时候再这个特殊数据集中表现最好(对应图中最高点)。如果我们把数据集切割成更多份,我们会看到更平滑的曲线。

实际中.

在实际中,人们更喜欢避免交叉验证而是选择用一个单独验证集,由于交叉验证是非常耗时的。分割人们趋向于使用50%-90%的训练集剩下的用验证。然而,这取决于多种因素:例如如果超参数的数字非常大那么你情愿用更大的验证集。如果很小,用交叉验证是更安全的。实际中典型的份额就是3份、5份、和十份交叉验证。
交叉验证集
常规数据分块。一个训练和测试集给了。一个训练集被分为几份(例如五份)。1-4份训练集。一份(例如图中黄色部分)作为验证集并且用来测试超参数。交叉验证会迭代每一份作为验证集,从1到5。这会叫做5份交叉验证。在每个最后验证过后并且所有最好的超参数决定以后,模型会在测试集中评估一次。

近邻分类器的优点和缺点

来评价以下近邻分类器的好坏是值得的。很明显,一个优点就是很容易实现和理解。另外,分类器没有时间训练,由于所有训练数据需要存储和索引。然而,我们在测试时间上花费很多,由于区分一个测试用例需要与每一个训练数据来对比。这点很不好,由于在实际中我们通常会更加关注测试时间而不是训练时间。实际上,这节课后面的深度神经网络把这个权衡弄到了另外一个极限:他们训练起来非常耗时,然而一旦训练好了,就很容易去区分一个样本。这种模式更适合于实际中。
另一方面,近邻分类器的计算复杂度是一个很活跃的领域,并且有很多合适的近邻算法(ANN)和库存在可以加速计算效率(例如,FLANN)。
最近邻算法有时可以在许多地方使用,但是很少在图片识别中使用。一个问题就是图片是高维的对象。并且高维空间的距离是非常不直观的。以下图片就是两个图片的L2相似度:

这里写图片描述
高维数据的基于像素距离非常直观。一个原始图片(左)和三个其他图片都是在L2距离上都是很远的。很明显,像素距离并不能很好的响应抽象的相似度。
这里有一个更加可视化的图片让你相信用像素来对比图片的不同是不够的。我们可以用一个可视化工具叫t-SNE来展示CIFAR-10的图片并且把他们在二维中嵌入这样他们之间的距离就被很好展示出来。图片中,图片旁边的图片被看作是L2距离很近的图片。
这里写图片描述

### K近邻算法在图像分类中的实现与应用 #### 实现原理 K近邻(K-Nearest Neighbors, KNN)是一种基于实例的学习方法,其核心思想是通过计算样本之间的相似度来进行预测。对于图像分类任务,通常会将每张图像表示为一个特征向量,然后使用某种距离度量(如欧氏距离或曼哈顿距离)来衡量不同图像间的差异。 在一个典型的图像分类场景中,假设有一组训练数据 \( \{(x_1, y_1), (x_2, y_2), ..., (x_n, y_n)\} \),其中 \( x_i \) 是图像的特征向量,\( y_i \) 是对应的标签。当给定一个新的输入图像 \( z \) 时,可以通过以下步骤完成分类: 1. **提取特征**:将图像转换为固定长度的数值型特征向量。 2. **计算距离**:针对新图像 \( z \),计算它与所有训练样本的距离。 3. **选取邻居**:找到离 \( z \) 最近的 \( k \) 个样本。 4. **投票决策**:根据这些邻居的标签进行多数表决(分类问题),或者取平均值(回归问题)。 这种简单的机制使得 KNN 成为了许多初学者学习机器学习的第一步[^1]。 #### 应用案例分析 以 MNIST 手写数字数据集为例,在这个经典的任务中,目标是对灰度化的手写数字图片进行分类。具体做法如下: - 将每幅大小为 \( 28 \times 28 \) 的像素矩阵拉直成一维数组; - 使用 L2 距离测量两幅图像之间像素强度上的差距; - 对于待测样本,依据最接近它的若干已知样本来决定最终归属类别[^2]。 然而值得注意的是,并非所有的图像都能很好地适应这种方法论。比如某些情况下由于光照条件的变化或者其他干扰因素的影响,即使两张外观极为相近的照片也可能因内部结构的不同而导致错误判定发生。因此单纯依赖几何意义上的临近程度并不总是可靠的选择[^3]。 另外还有更大规模的数据处理实践表明即便是在相对理想条件下执行标准流程也难免存在误判现象。例如采用 CIFAR-10 数据集合共包含六万个彩色小图标被划分为十个独立种类;尽管只拿出了五千份作为基础素材却依旧面临挑战——即面对海量未知情形下的精确匹配难以达成完全一致的效果[^4]。 以下是 Python 中的一个基本实现例子: ```python from sklearn.neighbors import KNeighborsClassifier import numpy as np # 假设 X_train 和 y_train 已经定义好 X_train = np.random.rand(5000, 32*32*3) # 训练集特征 y_train = np.random.randint(0, 10, size=(5000)) # 训练集标签 # 初始化模型并设置参数k=5 model = KNeighborsClassifier(n_neighbors=5) # 模型拟合 model.fit(X_train, y_train) # 测试阶段 test_image = np.random.rand(1, 32*32*3) # 单张测试图片 predicted_label = model.predict(test_image) print(f"Predicted Label: {predicted_label}") ``` 此代码片段展示了如何构建一个简易版的KNN分类器应用于多类别的图像辨识当中去。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值