我在 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
最佳答案
据我所知, sampsize
参数应该是一个长度与数据集中类数相同的向量。如果您在 strata
参数中指定了一个因子变量,那么 sampsize
应该被赋予一个长度与 strata
参数中的因子数相同的向量。我不确定它是否像您在问题中描述的那样执行,但是自从我使用 randomForest
函数以来已经有一段时间了。
从帮助文件中,它说:
例如,由于您的分类有 2 个不同的类,因此您需要为 sampsize
提供一个长度为 2 的向量,该向量指定在训练期间要从每个类中采样的观察值数量。
例如sampsize=c(100,50)
此外,您可以指定组的名称以使其更加清晰。
例如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
参数被赋予一个因子变量!例如尝试
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 错误估计是相同的,即使我们只使用了自举样本中每个类的 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
关于r - 分层抽样似乎不会改变 randomForest 结果,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20150525/