分层抽样似乎不会改变randomForest结果

时间:2013-11-22 17:08:25

标签: r random-forest

我在R中使用randomForest包来构建几个物种分布模型。我的反应变量是二元(0 - 缺席或1 - 存在),并且非常不平衡 - 对于某些物种,缺席的比例:存在是37:1。这种不平衡(或零膨胀)导致可疑的袋外误差估计 - 缺勤与存在的比率越大,我的袋外(OOB)误差估计越低。

为了弥补这种不平衡,我想实施分层抽样,使得随机森林中的每棵树都包含来自存在和缺席类别的相同(或至少不太平衡)的结果。我很惊讶,分层和非分层模型OOB误差估计似乎没有任何差别。请参阅下面的代码:

没有分层

> set.seed(25)
> HHrf<- randomForest(formula = factor(HH_Pres) ~ SST + Dist2Shr+ DaylightHours + Bathy + Slope + MoonPhase + factor(Region) + Chla , data = bll_HH, ntree = 500, replace = FALSE, importance = TRUE, na.action = na.omit)
> HHrf
Call:
  randomForest(formula = factor(HH_Pres) ~ SST + Dist2Shr + DaylightHours + Bathy + Slope + MoonPhase + factor(Region) + Chla, data = bll_HH, ntree = 500, replace = FALSE, importance = TRUE, na.action = na.omit) 
               Type of random forest: classification
                     Number of trees: 500
No. of variables tried at each split: 2

        OOB estimate of  error rate: 19.1%
Confusion matrix:
    0  1 class.error
0 422 18  0.04090909
1  84 10  0.89361702

分层

> HHrf_strata<- randomForest(formula = factor(HH_Pres) ~ SST + Chla + Dist2Shr+ DaylightHours + Bathy + Slope + MoonPhase + factor(Region), data = bll_HH, ntree = 500, replace = FALSE, importance = TRUE, strata = bll_HH$HH_Pres, sampsize = ceiling(.632*nrow(bll_HH)))
> HHrf

Call:
 randomForest(formula = factor(HH_Pres) ~ SST + Dist2Shr + DaylightHours + Bathy + Slope + MoonPhase + factor(Region) + Chla, data = bll_HH, ntree = 500, replace = FALSE, importance = TRUE, na.action = na.omit) 
               Type of random forest: classification
                     Number of trees: 500
No. of variables tried at each split: 2

        OOB estimate of  error rate: 19.1%
Confusion matrix:
    0  1 class.error
0 422 18  0.04090909
1  84 10  0.89361702

我是否有理由在两种情况下获得相同的结果?对于strata参数,我指定了我的响应变量HH_Pres。对于sampsize参数,我指定它应该只是整个数据集的63.2%。

任何人都知道我做错了什么?或者这是预期的吗?

谢谢,

莉莎

重现此问题:

示例数据:https://docs.google.com/file/d/0B-JMocik79JzY3B4U3NoU3kyNW8/edit

代码:

bll = read.csv("bll_Nov2013_NMV.csv", header=TRUE)
HH_Pres <- bll$HammerHeadALL_Presence

Slope <-bll$Slope
Dist2Shr <-bll$Dist2Shr
Bathy <-bll$Bathy2
Chla <-bll$GSM_Chl_Daily_MF
SST <-bll$SST_PF_daily
Region <- bll$Region
MoonPhase <-bll$MoonPhase
DaylightHours <- bll$DaylightHours
bll_HH <- data.frame(HH_Pres, Slope, Dist2Shr, Bathy, Chla, SST, DaylightHours, MoonPhase, Region)
set.seed(25)

HHrf<- randomForest(formula = factor(HH_Pres) ~ SST + Dist2Shr+ DaylightHours + Bathy + Slope + MoonPhase + factor(Region) + Chla , data = bll_HH, ntree = 500, replace = FALSE, importance = TRUE, na.action = na.omit)
HHrf
set.seed(25)
HHrf_strata<- randomForest(formula = factor(HH_Pres) ~ SST + Chla + Dist2Shr+ DaylightHours + Bathy + Slope + MoonPhase + factor(Region), data = bll_HH, strata = bll_HH$HH_Pres, sampsize = c(100, 50), ntree = 500, replace = FALSE, importance = TRUE)
HHrf

3 个答案:

答案 0 :(得分:5)

据我所知,sampsize参数应该是一个与数据集中类的数量相同的向量。如果在strata参数中指定因子变量,则sampsize应该被赋予一个与strata参数中的因子数长度相同的向量。我不确定它是否像你在你的问题中描述的那样表现,但是因为我使用了randomForest函数已经有一段时间了。

从帮助文件中,它说:

  

strata

     

用于分层抽样的(因子)变量。

     

sampsize

     

要抽取的样本的大小。对于分类,如果sampsize是矢量   在分层数量的长度,然后采样分层   strata和sampsize的元素表示要绘制的数字   来自阶层。

例如,由于您的分类有2个不同的类,因此您需要给sampsize一个长度为2的向量,该向量指定您希望在训练期间从每个类中采样的观察数量。

e.g。 sampsize=c(100,50)

此外,您可以指定要清楚的组名称。

e.g。 sampsize=c('0'=100, '1'=50)

使用sampsize参数的帮助文件中的示例,以澄清:

## stratified sampling: draw 20, 30, and 20 of the species to grow each tree.
data(iris)
(iris.rf2 <- randomForest(iris[1:4], iris$Species, sampsize=c(20, 30, 20)))

编辑:在strata中添加了关于randomForest参数的一些注释。

编辑:确保给strata参数一个因子变量!

e.g。试试strata = factor(HH_Pres), sampsize = c(...)其中c(...)是一个与length(levels(factor(bll_HH$HH_Pres)))

长度相同的向量

编辑:

好的,我尝试使用您的数据运行代码,它适用于我。

# Fix up the data set to have HH_Pres and Region as factors
bll_HH$Region <- factor(bll_HH$Region)
bll_HH$HH_Pres <- factor(bll_HH$HH_Pres)

# Original RF code
set.seed(25)
HHrf <- randomForest(formula=HH_Pres ~ SST + Dist2Shr + DaylightHours + Bathy +
                      Slope + MoonPhase + Chla + Region,
                    data=bll_HH, ntree = 500, replace = FALSE, 
                    importance = TRUE, na.action = na.omit)
HHrf

# Output
#         OOB estimate of  error rate: 18.91%
# Confusion matrix:
#     0  1 class.error
# 0 425 15  0.03409091
# 1  86  8  0.91489362

# Take 63.2% from each class
mySampSize <- ceiling(table(bll_HH$HH_Pres) * 0.632)

set.seed(25)
HHrf <- randomForest(formula=HH_Pres ~ SST + Dist2Shr + DaylightHours + Bathy +
                       Slope + MoonPhase + Chla + Region,
                     data=bll_HH, ntree = 500, replace = FALSE, 
                     importance = TRUE, na.action = na.omit,
                     sampsize=mySampSize)
HHrf
# Output
#         OOB estimate of  error rate: 18.91%
# Confusion matrix:
#     0  1 class.error
# 0 424 16  0.03636364
# 1  85  9  0.90425532

请注意,在这种情况下,OOB误差估计是相同的,即使我们仅使用我们的bootstrap样本中每个类的63.2%的数据。这可能是由于使用了与训练数据中的类别分布成比例的样本大小,以及数据集的相对较小的大小。让我们尝试更改mySampSize以确保它真的有效。

# Change mySampSize. Sample 100 from class 0 and 50 from class 1
mySampSize[1] <- 100
mySampSize[2] <- 50

set.seed(25)
HHrf <- randomForest(formula=HH_Pres ~ SST + Dist2Shr + DaylightHours + Bathy +
                       Slope + MoonPhase + Chla + Region,
                     data=bll_HH, ntree = 500, replace = FALSE, 
                     importance = TRUE, na.action = na.omit,
                     sampsize=mySampSize)
HHrf
# Output
#         OOB estimate of  error rate: 21.16%
# Confusion matrix:
#     0  1 class.error
# 0 382 58   0.1318182
# 1  55 39   0.5851064

答案 1 :(得分:0)

这种语法似乎对我的数据工作正常。 OOB为32.21%,类错误:0.32,0.29。我确实将Bootstraps的数量增加到1000.我总是建议使用索引来定义RF模型。在某些情况下,符号语法似乎不稳定。

require(randomForest)
  HHrf <- read.csv("bll_HH.csv")
    set.seed(25)    
( rf.mdl <- randomForest( y=as.factor(HHrf[,"HH_Pres"]), x=HHrf[,2:ncol(HHrf)],
                          strata=as.factor(HHrf[,"HH_Pres"]), sampsize=c(50,50),
                          ntree=1000) ) 

答案 2 :(得分:0)

我也遇到了这个问题。我注意到我在使用 importance = TRUE 时的错误率发生了显着变化。这和我没有选择带抽样分层是不一样的。

对我来说,它最终成为我的分类树没有重要性/准确性分数的权衡。这似乎是此实现中的众多错误之一。