欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

图片分类-K近邻分类器

程序员文章站 2022-07-14 14:18:50
...

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

图片分类-K近邻分类器
这张图表达了最近邻分类,和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份、和十份交叉验证。
图片分类-K近邻分类器
常规数据分块。一个训练和测试集给了。一个训练集被分为几份(例如五份)。1-4份训练集。一份(例如图中黄色部分)作为验证集并且用来测试超参数。交叉验证会迭代每一份作为验证集,从1到5。这会叫做5份交叉验证。在每个最后验证过后并且所有最好的超参数决定以后,模型会在测试集中评估一次。

近邻分类器的优点和缺点

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

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

相关标签: 图片 预测