R tuneRF 不稳定,如何优化?

R tuneRF unstable, how to optimize?

短片

我正在尝试使用 tuneRF 为我的 randomForest 函数找到最优的 mtry 值,但我发现答案非常不稳定并且随着 运行 run/different 种子。我会 运行 一个循环来查看它在大量 运行 中是如何变化的,但是我无法提取哪个 mtry 具有最低的 OOB 错误。

我有一个 data.frame,它有八个特征,但其中两个特征是包容性的,这意味着一个特征中的所有信息都是另一个特征的子集。例如,一个特征可以是因子 A ~ c("animal', "fish"),而另一个特征可以是因子 B ~c("dog", "cat", "salmon", "trout")。因此,所有的狗和猫都是动物,所有的鲑鱼和鳟鱼都是鱼。这两个变量比其他六个变量中的任何一个都重要得多。因此,如果我 运行 3 个森林,一个使用 A,一个使用 B,一个使用 A 和 B,最后一个似乎是最好的。我怀疑这是因为 A 和/或 B 是如此重要,以至于通过包括两者,我有双倍的机会将它们随机选择为初始特征。我进一步怀疑我不应该允许这种情况发生并且我应该将 A 作为一个因素排除在外,但我找不到任何实际这么说的文献。

总之回到正轨。我有两个数据集 tRFxtRFx2,第一个数据集包含 7 个特征,包括 B 但不包括 A,第二个数据集包含 8 个特征,同时包含 A 和 B。我想看看什么是最佳 mtry 是针对这两个独立的模型,然后是它们相对于彼此的表现。问题是 tuneRF 似乎,至少在这种情况下,非常不稳定。

对于第一个数据集,(包括特征 B 但不包括 A)

> set.seed(1)
> tuneRF(x = tRFx, y = tRFy, nTreeTry = 250, stepFactor = 1.5, improve = 0.01)  
mtry = 2  OOB error = 17.73% 
Searching left ...
Searching right ...
mtry = 3    OOB error = 17.28% 
0.02531646 0.01 
mtry = 4    OOB error = 18.41% 
-0.06493506 0.01 
      mtry  OOBError
2.OOB    2 0.1773288
3.OOB    3 0.1728395
4.OOB    4 0.1840629
> set.seed(3)
> tuneRF(x = tRFx, y = tRFy, nTreeTry = 250, stepFactor = 1.5, improve = 0.01)
mtry = 2  OOB error = 18.07% 
Searching left ...
Searching right ...
mtry = 3    OOB error = 18.18% 
-0.00621118 0.01 
      mtry  OOBError
2.OOB    2 0.1806958
3.OOB    3 0.1818182

即种子 1 mtry=3 但种子=3 mtry=2

对于第二个数据集(包括特征 A 和 B)

> set.seed(1)
> tuneRF(x = tRFx2, y = tRFy, nTreeTry = 250, stepFactor = 1.5, improve = 0.01)
mtry = 3  OOB error = 17.51% 
Searching left ...
mtry = 2    OOB error = 16.61% 
0.05128205 0.01 
Searching right ...
mtry = 4    OOB error = 16.72% 
-0.006756757 0.01 
      mtry  OOBError
2.OOB    2 0.1661055
3.OOB    3 0.1750842
4.OOB    4 0.1672278
> set.seed(3)
> tuneRF(x = tRFx2, y = tRFy, nTreeTry = 250, stepFactor = 1.5, improve = 0.01)
mtry = 3  OOB error = 17.4% 
Searching left ...
mtry = 2    OOB error = 18.74% 
-0.07741935 0.01 
Searching right ...
mtry = 4    OOB error = 17.51% 
-0.006451613 0.01 
      mtry  OOBError
2.OOB    2 0.1874299
3.OOB    3 0.1739618
4.OOB    4 0.1750842

即种子 1 mtry=2 但种子=3 mtry=3

我打算 运行 一个循环,看看哪个 mtry 在大量模拟中是最优的,但不知道如何从每次迭代中捕获最优 mtry .

我知道我可以使用

> set.seed(3)
> min(tuneRF(x = tRFx2, y = tRFy, nTreeTry = 250, stepFactor = 1.5, improve = 0.01))
mtry = 3  OOB error = 17.4% 
Searching left ...
mtry = 2    OOB error = 18.74% 
-0.07741935 0.01 
Searching right ...
mtry = 4    OOB error = 17.51% 
-0.006451613 0.01 
[1] 0.1739618

但我不想捕获 OOB 错误 (0.1739618) 但最佳 mtry (3).

非常感谢任何帮助(甚至是对与 tuneRF 相关的任何内容的一般评论)。对于偶然发现此问题并寻求 tuneRF 帮助的任何其他人,我也发现此 post 很有帮助。 R: unclear behaviour of tuneRF function (randomForest package)

就其价值而言,较小的特征集(具有非包含性特征)的最佳 mtry 似乎是 3,而较大的特征集仅为 2,这最初是违反直觉的,但当您考虑包容性时A 和 B 的性质 does/may 说得通。

  • 在这种情况下(和其他情况下)您选择的 mtry 在性能上没有太大差异。只有当你不想赢得赢家通吃的 kaggle 比赛时,你才可能将许多其他学习算法混合在一个巨大的整体中。在实践中你得到几乎相同的预测。

  • 当您测试如此少的参数组合时,您不需要逐步优化。只需全部尝试并重复多次以找出哪个 mtry 稍微好一点。

  • 我用过tuneRF的那些次,都让我很失望。每次我最终编写自己的逐步优化或只是多次尝试所有组合时。

  • mtry 与 oob-err 不一定是具有单个最小值的平滑曲线,但应观察总体趋势。我很难判断最小值是由于噪声还是一般趋势造成的。

我写了一个做实体mtry筛选的例子。这次放映的结论是没有太大区别。 mtry=2 似乎最好,而且计算起来会稍微快一些。无论如何,默认值一直是 mtry=floor(ncol(X)/3)。

library(mlbench)
library(randomForest)
data(PimaIndiansDiabetes)
y = PimaIndiansDiabetes$diabetes
X = PimaIndiansDiabetes
X = X[,!names(X)%in%"diabetes"]
nvar = ncol(X)
nrep = 25 
rf.list = lapply(1:nvar,function(i.mtry) {
  oob.errs = replicate(nrep,{
    oob.err = tail(randomForest(X,y,mtry=i.mtry,ntree=2000)$err.rate[,1],1)})
})
plot(replicate(nrep,1:nvar),do.call(rbind,rf.list),col="#12345678",
     xlab="mtry",ylab="oob.err",main="tuning mtry by oob.err")
rep.mean = sapply(rf.list,mean)
rep.sd = sapply(rf.list,sd)
points(1:nvar,rep.mean,type="l",col=3)
points(1:nvar,rep.mean+rep.sd,type="l",col=2)
points(1:nvar,rep.mean-rep.sd,type="l",col=2)