python sklearn:accuracy_score和learning_curve得分有什么区别?

时间:2016-02-06 15:30:32

标签: python scikit-learn

我使用Python sklearn(版本0.17)在数据集上选择理想模型。为此,我按照以下步骤操作:

  1. 使用cross_validation.train_test_split test_size = 0.2将数据集拆分。
  2. 使用GridSearchCV在训练集上选择理想的k近邻分类器。
  3. GridSearchCV返回的分类器传递给plot_learning_curveplot_learning_curve给出了如下所示的情节。
  4. 在获得的测试集上运行GridSearchCV返回的分类器。
  5. 从情节中,我们可以看到最高分数。训练规模约为0.43。此分数是sklearn.learning_curve.learning_curve函数返回的分数。

    但是当我在测试集上运行最佳分类器时,我得到的准确度分数为0.61,由sklearn.metrics.accuracy_score返回(正确预测的标签/标签数量)

    链接到图片:graph plot for KNN classifier

    这是我正在使用的代码。我没有包含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并在运行代码之前删除了标题。

1 个答案:

答案 0 :(得分:8)

当您调用learning_curve函数时,它会对您的整个数据执行交叉验证。当您将cv参数留空时,它是一个3倍交叉验证拆分策略。这里有一个棘手的部分,因为正如文档中所述“如果估算器是分类器,或者如果y既不是二元也不是多类,则使用 KFold ”。你的估算器是一个分类器。

那么,KFold和StratifiedKFold之间的区别是什么?

KFold =将数据集拆分为k个连续折叠(默认情况下不进行洗牌

StratifiedKFold =“折叠是通过保留每个类别的样本百分比来实现的。”

我们举一个简单的例子:

  • 您的数据标签是[4.0,4.0,4.0,5.0,5.0,5.0,6.0,6.0,6.0]
  • 由未分层3倍的子集划分:[4.0,4.0,4.0],[5.0,5.0,5.0],[6.0,6.0,6.0]
  • 然后每个折叠使用一次验证集,而k-1(3-2)剩余折叠形成训练集。因此,例如,将在[5.0,5.0,5.0,6.0,6.0,6.0]上进行培训并在[4.0,4.0,4.0]上进行验证

这解释了您的学习曲线的低精度(~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. ]一样,我并不完全确定这是您在此类测试中所使用的用法。