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

时间:2015-05-21 03:51:26

标签: python scikit-learn cross-validation

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

数据链接为here

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

  1. 使用sklearn.cross_validation.cross_val_score
  2. 使用sklearn.cross_validation.train_test_split
  3. 当我做我认为完全相同的事情时,我会得到不同的结果。举例来说,我使用上面的两种方法运行双重交叉验证,如下面的代码所示。

    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。

    感谢您的帮助!

2 个答案:

答案 0 :(得分:13)

使用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

您所描述的模式通常是火车/测试集中缺乏随机性的结果。

答案 1 :(得分:0)

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

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

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