在sklearn.cross_validation中,使用train_test_split和cross_val_score的区别

14

我有一个包含20列的矩阵,其中最后一列是0/1标签。

这是数据的链接:这里

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

  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总是高于第二个AUC;它通常是0.70和0.58之类的数值。

感谢您的帮助!


你的数据最开始是否经过随机处理?如果我没记错的话,两种方法中可能有一种或者都默认将数据分割而不进行随机处理。这可能可以解释你所提到的“模式”,但可能无法解释第一种方法整体结果较差的情况(或许会有解释)。 - KCzar
不,数据最初并没有随机化。这似乎是为什么交叉验证得分结果呈现相同模式的一个很好的解释。我猜在我的情况下,cross_val_score中唯一随机的部分就是randomForestClassifier在选择其树中的特征时具有某种随机性的算法。除此之外,如果只是根据初始排序将数据分成n个折叠,那么可能就是问题所在。我会在几个小时后检查它,因为现在已经是半夜了! - evianpring
所以,是的,这个有效: p = np.random.permutation(len(y))Result = cross_val_score(ensemble.RandomForestClassifier(n_estimators=1000, max_depth=5, max_features=3, oob_score=False), X[p], y[p], scoring='roc_auc', cv=2) - evianpring
2个回答

14
使用 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 迭代器有一个 random state 参数: 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'的事实。 是吗? 谢谢您的帮助。 - Anonymous Person

1
答案就是@KCzar指出的。我想注意到我发现随机化数据(Xy具有相同的索引洗牌)最简单的方法如下:
p = np.random.permutation(len(X))
X, y = X[p], y[p]

来源:更好的方法同时打乱两个numpy数组


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接