代码之家  ›  专栏  ›  技术社区  ›  Evan

为什么交叉验证RF分类的性能比没有交叉验证时差?

  •  4
  • Evan  · 技术社区  · 6 年前

    我很困惑,为什么没有交叉验证的随机森林分类模型的平均准确度为。996,但通过5倍交叉验证,模型的平均准确度得分为。687

    共有275956个样本。0级=217891,1级=6073,2级=51992

    我试图预测“TARGET”列,即3个类[0,1,2]:

    data.head()
    bottom_temperature  bottom_humidity top_temperature top_humidity    external_temperature    external_humidity   weight  TARGET  
    26.35   42.94   27.15   40.43   27.19   0.0  0.0    1   
    36.39   82.40   33.39   49.08   29.06   0.0  0.0    1   
    36.32   73.74   33.84   42.41   21.25   0.0  0.0    1   
    

    从文档中,数据分为培训和测试

    # link to docs http://scikit-learn.org/stable/modules/cross_validation.html
    from sklearn.model_selection import train_test_split
    from sklearn import datasets
    from sklearn import svm
    
    # Create a list of the feature column's names
    features = data.columns[:7]
    
    # View features
    features
    Out[]: Index([u'bottom_temperature', u'bottom_humidity', u'top_temperature',
           u'top_humidity', u'external_temperature', u'external_humidity',
           u'weight'],
          dtype='object')
    
    
    #split data
    X_train, X_test, y_train, y_test = train_test_split(data[features], data.TARGET, test_size=0.4, random_state=0)
    
    #build model
    clf = RandomForestClassifier(n_jobs=2, random_state=0)
    clf.fit(X_train, y_train)
    
    #predict
    preds = clf.predict(X_test)
    
    #accuracy of predictions
    accuracy = accuracy_score(y_test, preds)
    print('Mean accuracy score:', accuracy)
    
    ('Mean accuracy score:', 0.96607267423425713)
    
    #verify - its the same
    clf.score(X_test, y_test)
    0.96607267423425713
    

    交叉验证:

    from sklearn.model_selection import cross_val_score
    scores = cross_val_score(clf, data[features], data.TARGET, cv=5)
    print("Accuracy: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2))
    
    Accuracy: 0.69 (+/- 0.07)
    

    它要低得多!

    并验证第二种方法:

    #predict with CV
    # http://scikit-learn.org/stable/modules/generated/sklearn.model_selection.cross_val_predict.html#sklearn.model_selection.cross_val_predict
    from sklearn.model_selection import cross_val_predict
    predicted = cross_val_predict(clf, data[features], data.queen3, cv=5)
    metrics.accuracy_score(data.queen3, predicted) 
    
    Out[]: 0.68741031178883594
    

    根据我的理解,交叉验证不应将预测的准确性降低这么多,但应改进模型的预测,因为模型已看到所有数据的“更好”表示。

    3 回复  |  直到 6 年前
        1
  •  5
  •   Stev    6 年前

    通常我会同意Vivek的观点,并告诉你要相信你的交叉验证。

    然而,随机林中固有一定程度的CV,因为每棵树都是从自举样本中生长出来的,所以在运行交叉验证时,您不应该期望看到准确度会有如此大的降低。我怀疑您的问题是由于数据排序中的某种时间或位置依赖性造成的。

    当您使用 train_test_split ,数据是从数据集中随机抽取的,因此所有80个环境都可能存在于训练和测试数据集中。但是,当您使用CV的默认选项进行拆分时,我认为每个折叠都是按顺序绘制的,因此您的每个环境并不存在于每个折叠中(假设您的数据按环境排序)。这会导致较低的准确性,因为您使用来自另一个环境的数据来预测一个环境。

    简单的解决方案是 cv=ms.StratifiedKFold(n_splits=5, shuffle=True)

    在使用串联数据集时,我曾多次遇到过这个问题,肯定还有数百人已经意识到了问题所在,也没有意识到问题所在。默认行为的思想是维护时间序列中的秩序(从我在GitHub讨论中看到的)。

        2
  •  4
  •   Vivek Kumar    6 年前

    train_test_split ,您将60%的数据用于培训( test_size=0.4 )只有一次。但在 cross_val_score 数据将分成80%序列(cv=5)5次(每次4次将成为序列,剩余1次作为测试)。

    现在,您应该认为80%的训练数据大于60%,因此准确性不应降低。但这里还有一件事需要注意。

    这个 train\u test\u拆分 默认情况下不会对拆分进行分层,但在 cross\u val\u分数 。分层是指在每个层次中保持类(目标)的比例相同。因此,最有可能的情况是,在train\u test\u分割中没有保持目标的比率,这导致分类器的过度拟合,从而导致高分。

    我建议以cross\u val\u分数作为最终分数。

        3
  •  2
  •   Adrian    5 年前

    您的数据可能具有某种固有的顺序。在进行CV时,将“shuffle”更改为true。