【问题标题】:Different results between using train_test_split and cross_val_score in sklearn.cross_validation with randomized data在随机数据的 sklearn.cross_validation 中使用 train_test_split 和 cross_val_score 的结果不同
【发布时间】:2015-11-22 23:17:07
【问题描述】:

我正在我的代码中使用 sklearn 进行初步测试。

我正在测试:

1) sklearn.cross_validation.cross_val_score

2) sklearn.cross_validation.train_test_split

喜欢这个question

代码如下:

#X is my data and Y the corresponding binary labels                                                  

#My classifier                                                                     
clf = svm.SVC(class_weight='auto', kernel=kernel, gamma=gamma,                   
    degree=degree, cache_size=cache_size,probability=probability)                   


#1st method: ShuffleSplit and cross validation                                      
cv = cross_validation.ShuffleSplit(X.shape[0], n_iter=5,                            
    test_size=0.4, random_state=0)                                                  
#Scoring                                                                            
scores = cross_validation.cross_val_score(clf, X, Y,                     
    cv=cv, n_jobs=3, scoring="roc_auc")                                             

#2nd method: train_test_split                                                       
X_train, X_test, y_train, y_test = cross_validation.train_test_split(               
    X, Y, test_size=0.4, random_state=42)                                           

clf.fit(X_train, y_train)                                                          
pred_test = clf.predict(X_test)                                                     
#Scoring                                                                            
score = roc_auc_score(y_test, pred_test)

与另一个问题的不同之处在于,我的数据在 1) 和 2) 两种情况下都是随机的。

但是对于案例 1),我得到以下分数:

[ 0.9453893   0.94878745  0.95197478  0.95150763  0.94971746]

对于情况 2):

0.867637

我实际上完全不明白这种不同分数的原因,也无法得到我在这里缺少的东西。

分数不应该相似吗?

感谢您的宝贵时间。

【问题讨论】:

  • 尝试在分类器中设置random_stateclf = svm.SVC(class_weight='auto', kernel=kernel, gamma=gamma, degree=degree, cache_size=cache_size,probability=probability, random_state=0)
  • 谢谢。它给出了完全相同的结果:/
  • 对不起,你说这解决了没有?
  • 不,它并不能解决我似乎遇到的这个问题。

标签: python scikit-learn cross-validation


【解决方案1】:

我知道我迟到了,但我刚刚遇到了类似的问题,碰巧偶然发现了这篇文章。使用 train_test_split 和 cross_val_score 比较答案时,我遇到了完全相同的问题 - 使用 roc_auc_score 指标。

我认为问题出在将分类器的预测二进制输出放入 roc_auc_score 比较中。这意味着该指标只有两个二进制输出数组来计算分数。如果您尝试改用“predict_proba”,这将为您提供一个包含不同样本点的类概率的两列(假设您在这里有两类问题)的数组。

在我的数据集上,我将它的第二列与真实值一起输入到 roc_auc_score 中,这个返回的答案更符合 cross_val_score 的输出。

更新:

了解更多(并阅读文档!) - 这不是解决此问题的最佳方法,因为它需要为 SVC 设置 probability=True,而这在计算上要昂贵得多。不要使用predictpredict_proba,而是使用decision_function,然后将这些值作为预测值输入roc_auc_score

更新:

为了回应对此过程的评论,我还附上了几个图表来解释这个过程。我还将提供一些有助于我了解这方面的背景信息。

当决策边界的阈值从严格变为更宽松时,通过观察真阳性与假阳性的相对数量的变化来绘制接收器操作特征曲线。然而,这种解释似乎有些难以理解,所以这里提供了一个数字。这显示了线性支持向量机在具有 2 个特征的一些生成数据上的决策边界,即“蓝色”类和“红色”类。实线表示通过训练 SVM 找到的二元决策阈值。所有点都代表用于训练模型的数据。任何新数据都可以添加到绘图中;如果它们出现在左下角,它们将被标记为“红色”,而在右上角则被标记为“蓝色”。我们可以将“红色”视为“正”类,因此预测的输出是二进制 {0, 1} 输出(红色 = 1,蓝色 = 0)。

需要注意的一点是,数据点不是完全线性可分的,模型中有一个区域靠近决策边界,红色和蓝色点重叠很多。因此,这里的线性模型永远无法获得完美的性能。

虚线表示 SVM 的 边距。 SVM 的训练旨在最大化该边距的宽度,并且非常依赖于提供的超参数 C 值。实际上,较高的 C 值将迫使模型更好地适应训练数据,而较低的值将允许此处的错误分类,目的是对新的和未见过的数据具有更好的普遍性。完整的描述可以在 scikit-learn 文档中看到:http://scikit-learn.org/stable/auto_examples/svm/plot_svm_margin.html#sphx-glr-auto-examples-svm-plot-svm-margin-py。请注意,所有被错误分类或出现在此边缘区域中的点。其他点,我们对正确性非常有信心。

所以,最重要的是,AUC 是如何计算的。我在这张图上添加了两条额外的线,红色和蓝色边界线。这些可以被认为是主决策线从一个高度选择性区域(只有最有信心的红点实际上被归类为红色)到一个非常宽松的边界(每个点都将被归类为红色)的移动归类为红色。请记住,此移动阈值右下角的任何点都将被归类为红色。

最初,没有数据点符合分类为红色的标准,但随着线沿箭头方向移动,它开始舀起这些点。在早期阶段,所有这些都是正确的,因为所有数据点都是红色的,但是当我们走向边缘区域时,我们很快就会开始发现误报(蓝点),同时得到更多的红色。这种以不同速率收集真假阳性的模式会影响 ROC 曲线。展示这一点的最佳方式是使用另一个图:

想象一下,我们从左下角开始绘制曲线,并在每次更改阈值位置时做一个小动作。当我们收集真正的红色阳性时,我们在 y 轴方向上画线,但当我们收集蓝色时,我们在 x 轴方向上画线。目的是使线尽可能靠近左上角,因为最后我们将采用曲线下面积 (AUC) 作为我们的指标。请注意,最后,这条线总是到达右上角(最终,所有数据点都将被归类为红色),在这种情况下,它只是沿着图的顶部行进。这是因为,在这个数据集中,随着阈值靠近蓝线,我们只会得到误报。

现在想象两种截然不同的情况:如果数据是完全线性可分的,因此没有一个训练数据点位于边界的“错误”一侧,那么 ROC 线将始终直接向上 y-axis 直到它到达左上角,沿着图表顶部的头部到右上角,给出 1 的 AUC。但是,如果数据点只是一团噪声,所有混合在中心,你会得到与真阳性相同的误报率,你的线将朝着对角线的方向前进,并给出 0.5 的 AUC。因此,为什么这个值代表了性能的完全机会水平。

我不是 scikit-learn 的贡献者,我也没有检查这里的源代码,但我可以想象 roc_auc_score 使用来自 decision_functionpredict_proba 的值作为自信程度的表示该模型的重点是积极的(在我们的例子中是红色的)类。因此,放宽边界并查看从真到假阳性的变化率的相同逻辑仍然成立。如果这不对,请纠正我。

【讨论】:

  • 嗨,我这里也有类似的问题。如果我们取 predict_proba 的第二列值,您能否解释为什么结果与 cross_val_score 的结果相似?另外,有些分类器没有decision_function(例如决策树)。
  • 嗨,夏洛特,很抱歉回复晚了,但我只是试图在最近的一次编辑中更好地解释这个过程。 predict_proba 的第二列表示数据点属于正类的概率,并表示模型的“自信”程度,这允许正确计算基于阈值的 AUC。这使得输出类似于 cross_val_score。如果您有任何其他问题,请告诉我。
  • @TimVivian-Griffiths 实际上,您可以看到in the code 使用了decision_function。非常感谢您花时间回答
猜你喜欢
  • 1970-01-01
  • 2022-11-03
  • 2017-06-11
  • 2023-03-30
  • 2019-09-27
  • 2018-07-20
  • 1970-01-01
  • 2017-02-02
  • 2017-06-09
相关资源
最近更新 更多