[译]图像分类:数据驱动方法、K-最近邻、train/val/test分离 (2)

来源:互联网 发布:淘宝店铺全套免费模板 编辑:程序博客网 时间:2024/06/13 01:14

原文来自:http://cs231n.github.io/classification/#intro

Validation sets for Hyperparameter tuning (验证集:用于调谐超参数)

k-NN分类器需要确定k,k取什么值最好呢?另外,我们看到有许多不同的距离函数:L1标准、L2标准,还有许多其他的选择我们几乎都没有考虑到(比如点积)。这些选择叫做超参数,在机器学习算法的设计中经常遇到。但是我们常常不能直接看出应该用什么样的值或者方式。
可能你会建议我们应该尝试许多不同的值,然后看哪个工作地最好。这是个好主意,事实上我们也是这么做的,但是过程中我们要谨慎。实际中,我们不能将测试集用于调节超参数中。无论何时你在设计机器学习算法的时候,你应该把测试集当做一个非常宝贵的资源,直到最后一次才能用它。否则,潜在的危险就是你调谐了超参数使之在测试集上表现地很出色,然而如果你用于你的模型的时候,会发现其工作表现骤然变坏。实际中我们称此为过度拟合测试集。也就是说如果你用测试集调谐超参数,实际上你将测试集也变成了训练集的一部分,所以其表现非常好。但是如果你只在最后用一次测试集,它确实是测量你的分类器普适性的一个很好的集合。
最后再评测测试集,并只评测一次。
幸运的是,有一种正确方法可以既调谐超参数又不触碰测试集,就是将我们的训练集分成两部分:一部分是一个较小的训练集,另一部分我们叫做 validation set(验证集)。用CIFAR-10作为一个例子,比如我们用49,000张训练图片进行训练,留下1,000张验证。这个验证集经常被用作一个假测试集,来调谐超参数。
下面是在CIFAR-10中的应用:

# 假设我们像之前一样有 Xtr_rows, Ytr, Xte_rows, Yte# Xtr_rows 是50,000 x 3072 的矩阵Xval_rows = Xtr_rows[:1000, :] # 用前1000个作为验证Yval = Ytr[:1000]Xtr_rows = Xtr_rows[1000:, :] # 用后49000个作为训练Ytr = Ytr[1000:]# 找到在验证集中工作最好的超参数validation_accuracies = []for k in [1, 3, 5, 10, 20, 50, 100]:  # 用一个特定的k值评测验证集的数据  nn = NearestNeighbor()  nn.train(Xtr_rows, Ytr)  # 这里我们假设了一个修改后的NN类,将k作为输入  Yval_predict = nn.predict(Xval_rows, k = k)  acc = np.mean(Yval_predict == Yval)  print 'accuracy: %f' % (acc,)  # 记录在验证集工作最好的是哪个  validation_accuracies.append((k, acc))

过程最后,我们可以绘制一张图表,显示哪个k值工作最好。然后我们会认定这个值,在真正的测试集上评测一次。
将你的训练集分离成一个训练集和一个验证集。用验证集调谐所有的超参数。最后在测试集上运行一个,得到结果。
Cross-validation(交叉验证)。有些情况中你的训练集可能很小(验证集随之也很小),人们会采用一个更复杂的技巧来调谐超参数,叫做交叉验证。结合我们之前的例子,这种方法不再武断地选择前1000个数据点作为验证集,剩下的作为训练集。而是通过迭代不同的验证集,将它们的表现平均,最后得到评估k表现的平均化的值。比如,在一个5-fold的交叉验证中,我们将训练集分成5个大小一样的部分,用其中的4个作为训练,1个作为验证。然后遍历5个部分使它们依次成为验证的那部分,评估其表现,最后将不同验证集的表现平均。
这里写图片描述
上图是一个5-fold交叉验证参数k的例子。对于k的每个值,我们都训练4个部分,评测第5个。因此每个k我们都得到5个验证集的准确率(y轴为准确率,每个点代表一个结果)。趋势图画出了每个k结果的平均,误差条代表标准差。注意在这个案例中,交叉验证显示k=7的时候结果最好(对应图中的峰值)。如果我们用的是大于5 folds,可能会看到一条更加平滑的曲线(噪声更少)。

实际应用. 实际中,人们会偏向于避免使用交叉验证,喜欢用单个验证集,因为交叉验证的计算量非常之大。人们通常采用训练数据中的50%-90%来训练,剩下的来验证。但是这也取决于多种因素:如果超参数的数量很多,呢么可能会倾向于大一点的验证集。如果验证集中的样例太少(可能只有几百个),用交叉验证会更安全些。实际中folds的经典取值可能是3-fold, 5-fold 或者10-fold的交叉验证。
这里写图片描述
通常的数据分割。给定训练集和测试集。测试集被分为不同的部分(比如5个folds)。folds 1-4变成训练集,第5个fold为验证集(黄色),用于调谐超参数。交叉验证进一步地遍历验证集的所有选择,从fold1到fold5。这叫做5-fold交叉验证。最后模型训练好之后,确定了最好的超参数之后,模型被放到测试数据来评测一次(红色)。

Nearest Neighbor classifier的优点和劣势

我们需要考虑NN分类器的优点和劣势。一个明显的优点就是易于实施和理解。另外,这个分类器不需要时间去训练,因为只需要存储和访问训练数据。但是测试的时候需要计算量,因为将一个测试样例分类需要将其与每一个训练样本比较。这就是一个劣势,因为实际中我们关心测试时间,大大多于关系训练时间。事实上,后面我们要探讨的深度神经网络走向了另一个极端:它们在训练上要耗费许多,但是一旦完成训练,进行测试数据的分类会容易得多。这种运行模式更符合实际需要。
顺便一提,NN分类器的计算复杂度也是一个活跃的研究领域,几个Approximate Nearest Neighbor (ANN)算法和库能够加快数据集中最近邻的查找。这些算法在最近邻检索的正确度和计算的空间/时间复杂度之间进行权衡,常依赖于预处理/索引的步骤,建造一个kdtree,运行k-means算法。

NN分类器在某些情况中是一个好的选择(尤其是当数据是低维的时候),但是它很少适用于实际的图像分类。一个问题是图像是高维事物(它们常有大量像素),高维空间中的距离是违反直觉的。下面的图像解释了基于像素的L2相似性是非常不同于感知上的相似性的:
这里写图片描述
高维数据(此指图像)的基于像素的距离非常违背直觉。原始图像(左)和其他三幅图像都同样距离非常远,基于L2像素距离。显然,像素与像素之间的距离并不符合人感知上的相似性。

下面是另一个可视化例子证实用像素差异来比较图像是不充分的。我们用一项叫做t-SNE的可视化技术来处理CIFAR-10图像并将其嵌入到二维空间去,这样它们像素间的差异会最好地保留。在此可视化中,相邻的图像是根据L2距离认定的邻近图像:
这里写图片描述
用t-SNE将CIFAR-10图像嵌入到二维中。注意相比于认知上类的不同,背景有着更大的影响力。

特别地,注意相邻近的图像是由整体的颜色分布,或者说是背景的种类决定的,而不是它们的语意。举个例子,一只狗可能会邻近一只青蛙,因为它们都有白色的背景。理想地,我们想让10个类中的图像分别形成它们自己的聚类群,这样的话同样类的图像会相互邻近,不管它们的一些不相关的特点和变异(比如背景)。但是要达到这种性质,我们需要超越原始像素。

小结

• 我们介绍了图像分类的问题,在此问题中我们被给定了一个图像集,所有的图像都被一个类别所标签。然后要求我们预测新的测试集中图像的类别,然后测量预测的准确率。
• 我们介绍了一个简单的分类器,Nearest Neighbor classifier。我们看到与这个分类器相关的有许多超参数(比如k的值,以及用于比较样例的距离计算方法),我们不能轻易看出应该选择什么样的超参数。
• 我们发现设置这些超参数的正确方法就是将你的训练数据分离成两个部分:一个训练集和一个假的测试集(叫做验证集)。我们尝试了不同的超参数值,保留在验证集上表现最好的超参数。
• 如果考虑到训练数据缺乏的问题,我们讨论了一个叫做交叉验证的过程,可以在评估最佳超参数过程的中,帮助减少干扰。
• 一旦找到最好地超参数,我们将在真实的测试集上作一次评测。
• 我们发现NN可以帮助我们在CIFAR-10上达到40%的正确率。这种方法在训练的过程中容易实施,因为只需要存储训练集,然而在测试图像的时候会耗费很大的计算量。
• 最后我们看到在原始像素上使用L1或L2 distance是不充足的,因为distance与背景有和颜色分布着极大的相关性,而不是它们语意上的内容。

接下来的章节中我们将着手解决这些挑战并且得到能够达90%正确率的途径,一旦学习的过程完成了,我们可以丢弃训练集,瞬间评测一张测试图像。

阅读全文
0 0
原创粉丝点击