cross_val_score和cross_val_predict之间的区别

时间:2017-04-25 14:25:32

标签: python machine-learning scikit-learn regression cross-validation

我想使用交叉验证来评估使用scikitlearn的回归模型构建并使我感到困惑,我应该使用两个函数cross_val_scorecross_val_predict中的哪一个。 一种选择是:

cvs = DecisionTreeRegressor(max_depth = depth)
scores = cross_val_score(cvs, predictors, target, cv=cvfolds, scoring='r2')
print("R2-Score: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2))

另一个,使用标准r2_score

cvp = DecisionTreeRegressor(max_depth = depth)
predictions = cross_val_predict(cvp, predictors, target, cv=cvfolds)
print ("CV R^2-Score: {}".format(r2_score(df[target], predictions_cv)))

我认为这两种方法都是有效的,并给出类似的结果。但这只是小k倍的情况。虽然r ^ 2对于10倍-cv大致相同,但是对于使用“cross_vall_score”的第一版本的情况,对于更高的k值,它变得越来越低。第二个版本大多不受更改折叠数量的影响。

这种行为是否可以预期,我是否对SKLearn中的CV缺乏了解?

3 个答案:

答案 0 :(得分:13)

cross_val_score返回测试折叠的分数,其中cross_val_predict返回测试折叠的预测y值。

对于cross_val_score(),您使用的是输出的平均值,这会受到折叠次数的影响,因为它可能会有一些折叠,可能会有很高的误差(不合适)。

然而,对于输入中的每个元素,cross_val_predict()返回该元素在测试集中时获得的预测。 [请注意,只能使用将测试集中的所有元素分配一次的交叉验证策略]。因此,增加折叠数量只会增加测试元素的训练数据,因此其结果可能不会受到太大影响。

希望这会有所帮助。随意提出任何疑问。

编辑:回答评论中的问题

请查看cross_val_predict如何运作的以下答案:

我认为cross_val_predict会过度适应,因为随着折叠的增加,更多的数据将用于火车,而更少的数据用于测试。因此,结果标签更依赖于训练数据。同样如上所述,对一个样本的预测仅进行一次,因此可能更容易分裂数据。 这就是为什么大多数地方或教程建议使用cross_val_score进行分析。

答案 1 :(得分:2)

我认为可以通过检查它们的输出来明确区别。请考虑以下代码段:

# Last column is the label
print(X.shape)  # (7040, 133)

clf = MLPClassifier()

scores = cross_val_score(clf, X[:,:-1], X[:,-1], cv=5)
print(scores.shape)  # (5,)

y_pred = cross_val_predict(clf, X[:,:-1], X[:,-1], cv=5)
print(y_pred.shape)  # (7040,)

注意形状:为什么这样? scores.shape的长度为5,因为它是通过5倍交叉验证计算得出的得分(请参见参数cv=5)。因此,对于每个折叠计算单个实数值。该值是分类器的分数:

  

给出正确的标签和预测的标签,在特定的折叠中有多少个预测变量正确?

在这种情况下,输入中使用的y标签被使用了两次:从数据中学习并评估分类器的性能。

另一方面,y_pred.shape的长度为7040,它是数据集的形状。那就是输入数据集的长度。这意味着每个值不是在多个值上计算的分数,而是一个值:分类器的预测:

  

给定输入数据及其标签,在特定示例的特定折叠测试集中,分类器的预测是什么?

请注意,您不知道使用了什么折叠:每个输出都是根据特定折叠的测试数据计算出来的,但是您(至少从此输出中)无法确定是哪个。

在这种情况下,标签仅使用一次:训练分类器。将这些输出与真实输出进行比较以计算分数是您的工作。如果像您一样对它们进行平均,则输出不是分数,而是平均预测。

答案 2 :(得分:0)

所以这个问题也困扰着我,尽管对方提出了自己的观点,但他们并未回答OP的所有方面。

真正的答案是:分数k的增加与k的差异是由于选择的度量R2(确定系数)所致。例如MSE,MSLE或MAE使用cross_val_scorecross_val_predict不会有任何区别。

请参见definition of R2

R ^ 2 = 1-(MSE(基本事实,预测)/ MSE(基本事实,平均值(基本事实))))

粗体部分解释了为什么分数随着k的增加而开始出现差异:我们的拆分次数越多,测试折痕中的样本越少,并且测试折痕均值的方差越大。 相反,对于小k,测试倍数的均值与完全真实的均值相差不大,因为样本量仍然足够大,以至于方差很小。

证明:

import numpy as np
from sklearn.metrics import mean_absolute_error as mae
from sklearn.metrics import mean_squared_log_error as msle, r2_score

predictions = np.random.rand(1000)*100
groundtruth = np.random.rand(1000)*20

def scores_for_increasing_k(score_func):
    skewed_score = score_func(groundtruth, predictions)
    print(f'skewed score (from cross_val_predict): {skewed_score}')
    for k in (2,4,5,10,20,50,100,200,250):
        fold_preds = np.split(predictions, k)
        fold_gtruth = np.split(groundtruth, k)
        correct_score = np.mean([score_func(g, p) for g,p in zip(fold_gtruth, fold_preds)])

        print(f'correct CV for k={k}: {correct_score}')

for name, score in [('MAE', mae), ('MSLE', msle), ('R2', r2_score)]:
    print(name)
    scores_for_increasing_k(score)
    print()

输出将是:

MAE
skewed score (from cross_val_predict): 42.25333901481263
correct CV for k=2: 42.25333901481264
correct CV for k=4: 42.25333901481264
correct CV for k=5: 42.25333901481264
correct CV for k=10: 42.25333901481264
correct CV for k=20: 42.25333901481264
correct CV for k=50: 42.25333901481264
correct CV for k=100: 42.25333901481264
correct CV for k=200: 42.25333901481264
correct CV for k=250: 42.25333901481264

MSLE
skewed score (from cross_val_predict): 3.5252449697327175
correct CV for k=2: 3.525244969732718
correct CV for k=4: 3.525244969732718
correct CV for k=5: 3.525244969732718
correct CV for k=10: 3.525244969732718
correct CV for k=20: 3.525244969732718
correct CV for k=50: 3.5252449697327175
correct CV for k=100: 3.5252449697327175
correct CV for k=200: 3.5252449697327175
correct CV for k=250: 3.5252449697327175

R2
skewed score (from cross_val_predict): -74.5910282783694
correct CV for k=2: -74.63582817089443
correct CV for k=4: -74.73848598638291
correct CV for k=5: -75.06145142821893
correct CV for k=10: -75.38967601572112
correct CV for k=20: -77.20560102267272
correct CV for k=50: -81.28604960074824
correct CV for k=100: -95.1061197684949
correct CV for k=200: -144.90258384605787
correct CV for k=250: -210.13375041871123

当然,这里没有显示其他人提到的另一种效果。 随着k的增加,会有更多的模型在更多的样本上训练并且在更少的样本上进行验证,这将影响最终得分,但这并不是cross_val_scorecross_val_predict之间的选择所引起的。