通过插入号和基本randomForest包从randomForest获得不同的结果


14

我有点困惑:经过插入符号训练的模型的结果与原始包装中的模型有什么不同?我阅读了使用带有插入符号包的RandomForest的FinalModel进行预测之前是否需要进行预处理?但我在这里不使用任何预处理。

我通过使用插入符号包并调整了不同的mtry值来训练了不同的随机森林。

> cvCtrl = trainControl(method = "repeatedcv",number = 10, repeats = 3, classProbs = TRUE, summaryFunction = twoClassSummary)
> newGrid = expand.grid(mtry = c(2,4,8,15))
> classifierRandomForest = train(case_success ~ ., data = train_data, trControl = cvCtrl, method = "rf", metric="ROC", tuneGrid = newGrid)
> curClassifier = classifierRandomForest

我发现mtry = 15是training_data上的最佳参数:

> curClassifier
 ...
Resampling results across tuning parameters:

mtry  ROC    Sens   Spec   ROC SD   Sens SD  Spec SD
 4    0.950  0.768  0.957  0.00413  0.0170   0.00285
 5    0.951  0.778  0.957  0.00364  0.0148   0.00306
 8    0.953  0.792  0.956  0.00395  0.0152   0.00389
10    0.954  0.797  0.955  0.00384  0.0146   0.00369
15    0.956  0.803  0.951  0.00369  0.0155   0.00472

ROC was used to select the optimal model using  the largest value.
The final value used for the model was mtry = 15. 

我用ROC曲线和混淆矩阵评估了模型:

##ROC-Curve
predRoc = predict(curClassifier, test_data, type = "prob")
myroc = pROC::roc(test_data$case_success, as.vector(predRoc[,2]))
plot(myroc, print.thres = "best")

##adjust optimal cut-off threshold for class probabilities
threshold = coords(myroc,x="best",best.method = "closest.topleft")[[1]] #get optimal cutoff threshold
predCut = factor( ifelse(predRoc[, "Yes"] > threshold, "Yes", "No") )


##Confusion Matrix (Accuracy, Spec, Sens etc.)
curConfusionMatrix = confusionMatrix(predCut, test_data$case_success, positive = "Yes")

产生的混淆矩阵和准确性:

Confusion Matrix and Statistics
      Reference
Prediction   No  Yes
   No  2757  693
   Yes  375 6684

           Accuracy : 0.8984
 ....

现在,我使用基本的randomForest软件包训练了具有相同参数和相同training_data的Random Rorest:

randomForestManual <- randomForest(case_success ~ ., data=train_data, mtry = 15, ntree=500,keep.forest=TRUE)
curClassifier = randomForestManual

再次,我为与上述完全相同的test_data创建了预测,并使用与上述相同的代码评估了混淆矩阵。但是现在我有了不同的衡量标准:

Confusion Matrix and Statistics

      Reference
Prediction   No  Yes
       No  2702  897
       Yes  430 6480

           Accuracy : 0.8737 
           ....

是什么原因?我想念什么?


3
您是否为两个模型的随机种子使用了相同的值?
mmmmmmmmmm 2015年

我认同。在将数据集拆分为训练和测试数据时,我在代码中设置了种子,然后训练了插入符号模型,然后训练了“原始” rf模型。因此种子一旦开始就应该保持不变,不是吗?
马尔特2015年

我尝试在训练“原始” rf模型之前直接插入另一个set.seed。不幸的是,这并不能解决问题。
Malte 2015年

3
您应该使用seedstrainControl
topepo

Answers:


4

我认为这个问题虽然有些琐碎且“程序性”的,但它首先涉及了两个在现代统计中非常重要的主要问题:

  1. 结果的可重复性
  2. 非确定性算法。

结果不同的原因是这两个过程是使用不同的随机种子进行训练的。随机森林使用来自完整数据集变量的随机子集作为每个拆分的候选对象(这是自mtry变量,与随机子空间方法有关),并将原始数据集打包(引导聚合)以减小模型的方差。这两种内部随机采样程序在算法的不同运行之间不确定。采样的随机顺序由所使用的随机种子控制。如果使用相同的种子,则在randomForest调用例程的两种情况下都将获得完全相同的结果。都在内部caret::train以及在外部手动安装随机森林时。我附上了一个简单的代码片段来展示这种情况。请注意,ntree为了保持训练的速度,我使用了很少的树木(参数:),所以通常应该大得多。

library(caret)

set.seed(321)
trainData <- twoClassSim(5000, linearVars = 3, noiseVars = 9)
testData  <- twoClassSim(5000, linearVars = 3, noiseVars = 9)

set.seed(432)
mySeeds <- sapply(simplify = FALSE, 1:26, function(u) sample(10^4, 3))
cvCtrl = trainControl(method = "repeatedcv", number = 5, repeats = 5, 
                      classProbs = TRUE, summaryFunction = twoClassSummary, 
                      seeds = mySeeds)

fitRFcaret = train(Class ~ ., data = trainData, trControl = cvCtrl, 
                   ntree = 33, method = "rf", metric="ROC")

set.seed( unlist(tail(mySeeds,1))[1])
fitRFmanual <- randomForest(Class ~ ., data=trainData, 
                            mtry = fitRFcaret$bestTune$mtry, ntree=33) 

在这一点上,caret.train对象fitRFcaret和手动定义的randomForest对象fitRFmanual都使用相同的数据进行了训练,但重要的是在拟合最终模型时使用了相同的随机种子。这样,当我们尝试预测使用这些对象时,由于我们不对数据进行预处理,因此我们将获得相同的准确答案。

all.equal(current =  as.vector(predict(fitRFcaret, testData)), 
          target = as.vector(predict(fitRFmanual, testData)))
# TRUE

只是为了澄清这个以后再点了一下:predict(xx$finalModel, testData)predict(xx, testData),如果一个集将是不同的preProcess使用时的选项train。另一方面,当finalModel直接使用时,它等效于使用predict拟合的模型中的函数(predict.randomForest此处)而不是predict.train;不会进行任何预处理。显然,在原始问题中概述的方案中,如果不进行任何预处理,则使用finalModel,手动装配的randomForest对象或caret.train对象时,结果将相同。

all.equal(current =  as.vector(predict(fitRFcaret$finalModel, testData)), 
          target = as.vector(predict(fitRFmanual, testData)))
 # TRUE

all.equal(current =  as.vector(predict(fitRFcaret$finalModel, testData)),
          target = as.vector(predict(fitRFcaret, testData)))
# TRUE

我强烈建议您始终设置R,MATLAB或任何其他使用的程序使用的随机种子。否则,您将无法检查结果的可重复性(可以,可能还不是世界末日),也不能排除影响建模过程性能的错误或外部因素(是的,有点糟)。许多领先的机器学习算法(例如,梯度增强,随机森林,极限神经网络)在其训练阶段确实采用了某些内部重采样程序,因此在其训练阶段之前(有时甚至在其内部)设置随机种子状态可能很重要。


重要的部分是使用参数“ seeds”在“ trainControl”中明确设置“ seeds”参数
Malte

当然是。我想确保完全澄清有关为什么需要这样做的问题。
usεr11852恢复单胞菌说,

如何运行train,使其完全等同于randomForest?我试过method="none"但不确定如何将种子设置为单个值。谢谢。
西蒙·伍德沃德

抱歉,目前尚不清楚您是否有任何知识preProcess或如何randomForest接受培训。通常,假设我们没有预处理步骤,则需要确保所使用的种子超参数(此处只是mtry)相同。
usεr11852恢复单胞菌说,

0

来自curClassifier的预测与来自curClassifier$finalModel link的预测不同。您已复制finalModel并将其与predict.train对象进行比较。


1
尽管您说的是正确的,但不幸的是,由于OP没有进行任何预处理,因此在当前设置中有些误导。predict在OP探索的情况下,两者都应该(并且实际上)给出相同的预测。我会在帖子中进一步阐明这一点。
usεr11852恢复单胞菌说,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.