【问题标题】:Difference between using train_test_split and cross_val_score in sklearn.cross_validation在 sklearn.cross_validation 中使用 train_test_split 和 cross_val_score 的区别
【发布时间】:2015-05-21 03:51:25
【问题描述】:

我有一个 20 列的矩阵。最后一列是 0/1 标签。

数据的链接是here

我正在尝试使用交叉验证在数据集上运行随机森林。我使用了两种方法:

  1. 使用sklearn.cross_validation.cross_val_score
  2. 使用sklearn.cross_validation.train_test_split

当我做我认为几乎完全相同的事情时,我会得到不同的结果。为了举例说明,我使用上面的两种方法进行了两次交叉验证,如下面的代码所示。

import csv
import numpy as np
import pandas as pd
from sklearn import ensemble
from sklearn.metrics import roc_auc_score
from sklearn.cross_validation import train_test_split
from sklearn.cross_validation import cross_val_score

#read in the data
data = pd.read_csv('data_so.csv', header=None)
X = data.iloc[:,0:18]
y = data.iloc[:,19]

depth = 5
maxFeat = 3 

result = cross_val_score(ensemble.RandomForestClassifier(n_estimators=1000, max_depth=depth, max_features=maxFeat, oob_score=False), X, y, scoring='roc_auc', cv=2)

result
# result is now something like array([ 0.66773295,  0.58824739])

xtrain, xtest, ytrain, ytest = train_test_split(X, y, test_size=0.50)

RFModel = ensemble.RandomForestClassifier(n_estimators=1000, max_depth=depth, max_features=maxFeat, oob_score=False)
RFModel.fit(xtrain,ytrain)
prediction = RFModel.predict_proba(xtest)
auc = roc_auc_score(ytest, prediction[:,1:2])
print auc    #something like 0.83

RFModel.fit(xtest,ytest)
prediction = RFModel.predict_proba(xtrain)
auc = roc_auc_score(ytrain, prediction[:,1:2])
print auc    #also something like 0.83

我的问题是:

为什么我得到不同的结果,即为什么当我使用train_test_split 时 AUC(我正在使用的指标)更高?

注意: 当我使用更多折叠(比如 10 折叠)时,我的结果中似乎存在某种模式,第一次计算总是给我最高的 AUC。

在上面示例中的双重交叉验证的情况下,第一个 AUC 总是高于第二个;它总是类似于 0.70 和 0.58。

感谢您的帮助!

【问题讨论】:

  • 您的数据最初是随机的吗?如果我没记错的话,这两种方法中的一种或两种都默认为拆分数据而不进行随机化。这可能解释了您所指的“模式”,尽管它可能无法解释第一种方法的总体结果较差(但可能)
  • 不,数据最初不是随机的。这似乎很好地解释了为什么结果在 cross_val_score 中表现出相同的模式。我猜在我的例子中,cross_val_score 的唯一随机部分是 randomForestClassifier 在其选择树中特征的算法中具有一些随机性。除此之外,如果它只是根据初始排序将数据切割成 n 折,那么也许这就是问题所在。我会在几个小时后真正醒来时检查一下,这里是半夜!
  • 所以,是的,这行得通:p = np.random.permutation(len(y)) 结果 = cross_val_score(ensemble.RandomForestClassifier(n_estimators=1000, max_depth=5, max_features=3, oob_score= False), X[p], y[p], score='roc_auc', cv=2)

标签: python scikit-learn cross-validation


【解决方案1】:

在使用 cross_val_score 时,您经常需要使用 KFolds 或 StratifiedKFolds 迭代器:

http://scikit-learn.org/0.10/modules/cross_validation.html#computing-cross-validated-metrics

http://scikit-learn.org/0.10/modules/generated/sklearn.cross_validation.KFold.html#sklearn.cross_validation.KFold

默认情况下,cross_val_score 不会随机化您的数据,如果您的数据一开始就不是随机的,这可能会产生类似这样的奇怪结果。

KFolds 迭代器有一个随机状态参数:

http://scikit-learn.org/stable/modules/generated/sklearn.cross_validation.KFold.html

train_test_split 也是如此,默认情况下会随机化:

http://scikit-learn.org/stable/modules/generated/sklearn.cross_validation.train_test_split.html

您所描述的模式通常是由于训练/测试集中缺乏随机性造成的。

【讨论】:

  • 我有一个关于 train_test_split 的问题。在上面的代码xtrain, xtest, ytrain, ytest = train_test_split(X, y, test_size=0.50)中,算法如何知道xtrainxtest等必须输入什么值?它怎么知道xtrain 必须包含训练数据集的自变量 的结果,xtest 也是如此。我不认为变量中包含“train”或“test”是事实。是吗?感谢您的帮助。
【解决方案2】:

答案是@KCzar 指出的。只想注意我发现随机化数据的最简单方法(Xy 具有相同的索引改组)如下:

p = np.random.permutation(len(X))
X, y = X[p], y[p]

来源:Better way to shuffle two numpy arrays in unison

【讨论】:

    猜你喜欢
    • 2015-11-22
    • 2022-11-03
    • 2017-09-22
    • 2021-10-21
    • 2017-06-11
    • 2021-06-19
    • 2014-04-08
    • 2022-01-11
    • 2016-02-12
    相关资源
    最近更新 更多