我在处理一个最近邻问题集时,不明白为什么要对测试集进行K折交叉验证
?我们不能直接测试最佳参数K在整个测试数据上的表现吗?而不是进行交叉验证?
iris = sklearn.datasets.load_iris()X = iris.data Y = iris.targetX_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)+1parameters = {'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 scoresscores = computeTestScores(test_x = X_test, test_y = Y_test, clf=clf, cv=5)
回答:
TL;DR
你是否曾经有一位科学老师说过,’任何没有误差范围的测量都是毫无意义的?’
你可能会担心在测试集上使用你已经拟合并优化了超参数的估计器得到的分数只是一个偶然。通过对测试集的随机子样本进行多次测试,你可以得到一系列分数;你可以报告它们的平均值和标准差等。这希望能更好地代表估计器在新数据上的表现。
以下概念模型可能不适用于所有估计器,但记住它是有用的。你最终需要将数据分成三个子集。如果你对编号点已经满意,可以跳到最后一段。
- 训练你的估计器会拟合一些你不需要直接看到的内部参数。你通过在训练集上训练来优化这些参数。
- 大多数估计器还有超参数(邻居数量,Ridge的alpha等)。超参数也需要优化。你需要在数据的另一个子集上拟合它们;称之为验证集。
- 最后,当你对估计器的内部参数和超参数的拟合满意时,你想看看拟合后的估计器在新数据上的预测效果。你需要数据的最后一个子集(测试集)来评估训练和超参数优化的情况如何。
在很多情况下,将数据分成三部分意味着每个子集中的样本不足。解决这个问题的一种方法是多次随机分割训练集,拟合超参数并聚合结果。这也有助于防止你的超参数过度拟合到特定的验证集。K折交叉验证是一种策略。
随机分割数据集的另一个用途是获得最终估计器表现的一系列结果。通过分割测试集并计算分数,你可以得到一系列关于’我们可能会在新数据上表现如何’的答案。希望这能更代表你在现实世界中对新数据的表现。你还可以得到最终分数的标准差。这似乎是哈佛cs109 gist所做的内容。