为什么我们要在测试集上执行 Kfold 交叉验证?

Why should we perform a Kfold cross validation on test set??

我正在研究最近邻问题集。我不明白他们为什么要在测试集上执行 K fold cross validation?我们不能直接测试我们最好的参数 K 在整个测试数据上的表现如何吗?而不是进行交叉验证?

iris = sklearn.datasets.load_iris()

X = iris.data  
Y = iris.target

X_train, X_test, Y_train, Y_test = sklearn.cross_validation.train_test_split(
    X, Y, test_size=0.33, random_state=42)

k = np.arange(20)+1

parameters = {'n_neighbors': k}
knn = sklearn.neighbors.KNeighborsClassifier()
clf = sklearn.grid_search.GridSearchCV(knn, parameters, cv=10)
clf.fit(X_train, Y_train)

def computeTestScores(test_x, test_y, clf, cv):
    kFolds = sklearn.cross_validation.KFold(test_x.shape[0], n_folds=cv)

    scores = []
    for _, test_index in kFolds:
        test_data = test_x[test_index]
        test_labels = test_y[test_index]
        scores.append(sklearn.metrics.accuracy_score(test_labels, clf.predict(test_data)))
    return scores

scores = computeTestScores(test_x = X_test, test_y = Y_test, clf=clf, cv=5)

如果你制作了一个适应输入的程序,那么它对于你适应的输入将是最优的。

这会导致称为过度拟合的问题。

为了查看您制作的模型是好是坏,您需要在其他一些不是您用来制作模型的数据上进行测试。这就是将数据分成两部分的原因。

TL;DR

你有没有一位科学老师说过,'any measurement without error bounds is meaningless?'

您可能担心在您的测试集上使用您的拟合、超参数优化的估计器的分数是侥幸。通过对测试集中随机选择的子样本进行多次测试,您可以获得一系列分数;您可以报告它们的均值和标准差等。希望这能更好地代表估算器将如何处理来自野外的新数据。


以下概念模型可能不适用于所有估算器,但牢记在心很有用。您最终需要 3 个数据子集。如果编号点是您已经满意的内容,您可以跳到最后一段。

  1. 训练您的估算器将适合一些您永远不需要直接看到的内部参数。您可以通过在训练集上训练来优化这些。
  2. 大多数估算器也有超参数(邻居的数量、Ridge 的 alpha 等)。超参数也需要优化。您需要使它们适应数据的不同子集;称之为验证集。
  3. 最后,当您对估计器的内部参数和超参数的拟合感到满意时,您想要了解拟合估计器对新数据的预测效果如何。您需要数据的最终子集(测试集)来确定训练和超参数优化的效果。

很多 的情况下,将您的数据分成 3 个意味着您在每个子集中没有足够的样本。解决此问题的一种方法是将训练集随机拆分多次,拟合超参数并聚合结果。这也有助于阻止您的超参数过度适合特定的验证集。 K 折交叉验证是一种策略。

这种随机拆分数据集的另一个用途是获得最终估算器的结果范围。通过拆分测试集并计算分数,您可以获得 'how might we do on new data' 的一系列答案。希望这更能代表您可能看到的真实世界的新颖数据性能。您还可以获得最终分数的标准偏差。这似乎是哈佛 cs109 要点正在做的事情。