为什么 R 和 Python 之间得到不同的 RandomForest 结果?

Y. *_*Xue 7 python r machine-learning random-forest scikit-learn

我正在尝试比较使用 R 和使用 Python 的随机森林模型的结果。我要比较的模型性能的关键衡量标准是 AUC(ROC 曲线下的面积)。原因是 AUC 值代表了预测值(即概率)的分布。我确实发现 R 和 Python 之间的 AUC 值存在一些显着差异。我确实阅读了 Stack Overflow 上有关 R 和 Python 之间差异的一些相关问题和答案。但是,我觉得我的问题应该与那些不同。

我尝试在 R 和 Python 中保持一些关键的超参数相同。他们是:

  1. R 中的设置ntree等于n_estimatorsPython 中的设置
  2. R 中的设置mtry等于 max_featuresPython 中的设置
  3. R 中的设置nodesize等于min_samples_leafPython 中的设置
  4. 将类别权重设置为 R 和 Python 中的默认值。在 R 中,默认值为NULL。在 Python 中,默认值为None.
  5. 将 R 中的样本大小设置为训练数据中的总行数,这是 Python 中的默认设置。
  6. 在 R 中设置replace等于bootstrap在 Python 中,即两者都是True或两者都是False

该问题是一个二分类问题,有 86 个预测变量。每个预测变量都是连续变量或布尔变量。R 中没有使用因子类型预测器。训练数据中有 2008 个观测值,测试数据中有 335 个观测值。两个数据的响应率相同,即 79.7%。

结果如下:

R 中的模型 1 结果
training_auc=0.9249080test_auc=0.6308934

R 中的模型 2 结果
training_auc=0.9245665test_auc=0.6364838

Python 中的模型 1 结果
training_auc=0.80515863test_auc=0.62194316

Python 中的模型 2 结果
training_auc=0.86075733test_auc=0.61522362

您可以发现,R 和 Python 之间的模型 2(非引导采样)中的 AUC 值差异小于模型 1(引导采样)中的 AUC 值,尤其是在训练数据上的 AUC 值。

即使我在 R 和 Python 中设置相同的超参数,为什么训练数据上的 AUC 会有如此巨大的差异?我错过了什么重要参数吗?或者我的 R 或 Python 代码有什么错误吗?

随机森林模型的 R 代码

library(randomForest)
library(glmnet)
setwd("D:/Project Files2/Python Efficiency/test RF using another dataset")

#read in data for training and data for testing
X_train01 <- read.csv("X_train_0.csv",header=FALSE)
y_train01 <- read.csv("y_train_0.csv",header=FALSE)
colnames(y_train01) <- "response"

X_test01 <- read.csv("X_test_0.csv",header=FALSE)
y_test01 <- read.csv("y_test_0.csv", header=FALSE)
colnames(y_test01) <- "response"

#define a function for RF
run_quick_rf4 <- function(X_train01,y_train01, X_test01, y_test01, ntree, mtry, nodesize, maxnodes=NULL, replace=TRUE, classwt=NULL, rnd_seed= 12345){
  
  set.seed(rnd_seed)
  rf_model <- randomForest(x=X_train01,y=as.factor(y_train01[,1]),
                           ntree=ntree,
                           mtry= mtry,
                           nodesize= nodesize,
                           maxnodes= maxnodes,
                           replace = replace,
                           sampsize = nrow(X_train01),
                           classwt = classwt
  )
  train01_pred <- predict(rf_model, X_train01, type='prob')
  train01_auc <- auc(y_train01[,1], train01_pred[,2])
  
  test01_pred <- predict(rf_model, X_test01, type='prob')
  test01_auc <- auc(y_test01[,1],test01_pred[,2])
  auc_outcome<- c(train01_auc, test01_auc)
  names(auc_outcome)<- c("training_auc", "test_auc")
  return(auc_outcome)
}
#>>>>>>>>>>>>>>>>>>>>>>>>>End of this function>>>>>>>>>>>>>>>>>>

#run random forest models with parameters set.

#Model 1
run_quick_rf4(X_train01, y_train01, X_test01, y_test01, 500, 20, 20, maxnodes=NULL, replace=TRUE, classwt=NULL, rnd_seed= 12345)

#Model 2
run_quick_rf4(X_train01, y_train01, X_test01, y_test01, 500, 20, 20, maxnodes=NULL, replace=FALSE, classwt=NULL, rnd_seed= 12345)
Run Code Online (Sandbox Code Playgroud)

随机森林模型的 Python 代码

import numpy as np
from sklearn import cross_validation
from sklearn.metrics import roc_auc_score
from sklearn.ensemble import RandomForestClassifier
import datetime
import os
#change work directory
os.chdir("D:/yxue/Uplift_Gilenya/followup/Data")

# only specify sample weight
def run_quick_RF_final(file_counter, n_estimators, max_features, min_samples_leaf, max_leaf_nodes=None, class_weight={0: 1, 1: 1}, s_wt={0:1, 1:1}, bootstrap=True, random_seed=4568):
    
    x_train_file = 'X_train_%d.csv' %(file_counter)
    y_train_file = 'y_train_%d.csv' %(file_counter)
    x_test_file = 'X_test_%d.csv' %(file_counter)
    y_test_file = 'y_test_%d.csv' %(file_counter)
    
    X_train = np.loadtxt(x_train_file, delimiter=',', skiprows=0)
    y_train = np.loadtxt(y_train_file, delimiter=',', skiprows=0) 
    
    X_test = np.loadtxt(x_test_file, delimiter=',', skiprows=0)
    y_test = np.loadtxt(y_test_file, delimiter=',', skiprows=0) 
 
    rf_model = RandomForestClassifier()
    rf_model.set_params(n_estimators=n_estimators, max_features=max_features, min_samples_leaf=min_samples_leaf, max_leaf_nodes=max_leaf_nodes, class_weight=class_weight, criterion='gini', bootstrap=bootstrap, random_state=random_seed)

    if s_wt != None:
        sample_wt = np.ones((len(y_train),), dtype=np.float64)
        sample_wt[y_train == 0] = float(s_wt[0])
        sample_wt[y_train == 1] = float(s_wt[1])
    else:
        sample_wt = s_wt

    #print np.bincount(sample_wt)
    rf_model.fit(X_train, y_train, sample_weight=sample_wt)
    
    pred_train = rf_model.predict_proba(X_train)
    train_auc = roc_auc_score(y_train,pred_train[:, 1])
    
    pred_test =  rf_model.predict_proba(X_test)
    test_auc = roc_auc_score(y_test, pred_test[:, 1])
    
    auc_outcome = np.array([train_auc, test_auc])
    
    return auc_outcome
    
# run random forest model. the parameter setting is same as in R
# Model 1
run_quick_RF_final(0, 500, 20, 20, max_leaf_nodes=None, class_weight=None, s_wt=None, bootstrap=True, random_seed=4568)

# Model 2
run_quick_RF_final(0, 500, 20, 20, max_leaf_nodes=None, class_weight=None, s_wt=None, bootstrap=False, random_seed=4568)
Run Code Online (Sandbox Code Playgroud)