我使用Python sklearn(版本0.17)在数据集上选择理想模型。为此,我按照以下步骤操作:
cross_validation.train_test_split
test_size = 0.2
将数据集拆分。GridSearchCV
在训练集上选择理想的k近邻分类器。GridSearchCV
返回的分类器传递给plot_learning_curve
。 plot_learning_curve
给出了如下所示的情节。GridSearchCV
返回的分类器。从情节中,我们可以看到最高分数。训练规模约为0.43。此分数是sklearn.learning_curve.learning_curve
函数返回的分数。
但是当我在测试集上运行最佳分类器时,我得到的准确度分数为0.61,由sklearn.metrics.accuracy_score
返回(正确预测的标签/标签数量)
链接到图片:
这是我正在使用的代码。我没有包含plot_learning_curve
函数,因为它占用了大量空间。我从here
plot_learning_curve
import pandas as pd
import numpy as np
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
from sklearn.metrics import classification_report
from matplotlib import pyplot as plt
import sys
from sklearn import cross_validation
from sklearn.learning_curve import learning_curve
from sklearn.grid_search import GridSearchCV
from sklearn.cross_validation import train_test_split
filename = sys.argv[1]
data = np.loadtxt(fname = filename, delimiter = ',')
X = data[:, 0:-1]
y = data[:, -1] # last column is the label column
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=2)
params = {'n_neighbors': [2, 3, 5, 7, 10, 20, 30, 40, 50],
'weights': ['uniform', 'distance']}
clf = GridSearchCV(KNeighborsClassifier(), param_grid=params)
clf.fit(X_train, y_train)
y_true, y_pred = y_test, clf.predict(X_test)
acc = accuracy_score(y_pred, y_test)
print 'accuracy on test set =', acc
print clf.best_params_
for params, mean_score, scores in clf.grid_scores_:
print "%0.3f (+/-%0.03f) for %r" % (
mean_score, scores.std() / 2, params)
y_true, y_pred = y_test, clf.predict(X_test)
#pred = clf.predict(np.array(features_test))
acc = accuracy_score(y_pred, y_test)
print classification_report(y_true, y_pred)
print 'accuracy last =', acc
print
plot_learning_curve(clf, "KNeighborsClassifier",
X, y,
train_sizes=np.linspace(.05, 1.0, 5))
这是正常的吗?我可以理解得分可能会有所不同,但这是0.18的差异,转换为百分比时的差异为43%,而61%。 classification_report还提供了平均0.61的召回。
我做错了吗? learning_curve
计算分数的方式有何不同?我还尝试将scoring='accuracy'
传递给learning_curve
函数以查看它是否与准确度得分相符,但它没有任何区别。
任何建议都会有很大帮助。
我使用葡萄酒品质(白色)data set from UCI并在运行代码之前删除了标题。
答案 0 :(得分:8)
当您调用learning_curve
函数时,它会对您的整个数据执行交叉验证。当您将cv
参数留空时,它是一个3倍交叉验证拆分策略。这里有一个棘手的部分,因为正如文档中所述“如果估算器是分类器,或者如果y既不是二元也不是多类,则使用 KFold ”。你的估算器是一个分类器。
那么,KFold和StratifiedKFold之间的区别是什么?
KFold =将数据集拆分为k个连续折叠(默认情况下不进行洗牌)
StratifiedKFold =“折叠是通过保留每个类别的样本百分比来实现的。”
我们举一个简单的例子:
这解释了您的学习曲线的低精度(~0.43%)。当然,这是一个极端的例子来说明情况,但是你的数据是以某种方式构建的,你需要对其进行改组。
但是当你获得~61%的准确度时,你已经按方法train_test_split
分割数据,默认情况下会对数据执行混洗并保持比例。
看看这个,我做了一个简单的测试来支持我的假设:
X_train2, X_test2, y_train2, y_test2 = train_test_split(X, y, test_size=0., random_state=2)
在您的示例中,您为learning_curve
提供了所有数据X,y
。我在这里做了一个小技巧,即分割数据告诉test_size=0.
意味着所有数据都在train
个变量中。这样我仍然保留所有数据,但现在它已经通过train_test_split
函数进行了洗牌。
然后我调用了你的绘图函数,但是使用了混洗数据:
plot_learning_curve(clf, "KNeighborsClassifier",X_train2, y_train2, train_sizes=np.linspace(.05, 1.0, 5))
现在,使用最大数量训练样本而非0.43
的输出为0.59
,这对您的GridSearch结果更有意义。
观察:我认为绘制学习曲线的重点是确定是否将更多样本添加到训练集中我们的估算器能够更好地执行(因此您可以决定例如何时没有必要添加更多示例)。正如在
train_sizes
中您只需提供值np.linspace(.05, 1.0, 5) --> [ 0.05 , 0.2875, 0.525 , 0.7625, 1. ]
一样,我并不完全确定这是您在此类测试中所使用的用法。