R randomForest子集无法摆脱因子水平[重复]

Posted

技术标签:

【中文标题】R randomForest子集无法摆脱因子水平[重复]【英文标题】:R randomForest subsetting can't get rid of factor levels [duplicate] 【发布时间】:2012-10-14 20:08:15 【问题描述】:

可能重复:dropping factor levels in a subsetted data frame in R

我正在尝试使用 randomForest 来预测销售额。我有 3 个变量,其中一个是 storeId 的因子变量。我知道测试集中有一些级别不在训练集中。我正在尝试仅对训练集中存在的级别进行预测,但无法让它超越新的因子级别。

这是我迄今为止尝试过的:

require(randomForest)
train <- data.frame(sales = runif(10)*1000, storeId = factor(seq(1,10,1)), dat1 =runif(10), dat2 = runif(10)*10)
test <- data.frame(storeId = factor(seq(2,11,1)), dat1 =runif(10), dat2 = runif(10)*10)


> train 
      sales storeId      dat1     dat2
1  414.7791       1 0.7830092 7.178577
2  719.5965       2 0.9512138 6.153049
3  887.3197       3 0.6879827 5.413556
4  706.5828       4 0.4486214 4.955400
5  326.8189       5 0.0944885 6.900802
6  840.5920       6 0.1917165 8.044636
7  936.2206       7 0.2173074 4.835064
8  244.6947       8 0.6526765 6.516790
9  818.8747       9 0.3317644 9.651675
10 631.6104      10 0.6998037 8.443972
> test 
   storeId      dat1     dat2
1        2 0.7513645 3.442052
2        3 0.2862487 3.196189
3        4 0.4971865 6.074281
4        5 0.8631945 8.766129
5        6 0.3848105 5.001426
6        7 0.9032262 7.018274
7        8 0.1560501 4.523618
8        9 0.3461597 5.551672
9       10 0.1318464 3.092640
10      11 0.6587270 1.348623


> RF1 <- randomForest(train[,c("storeId","dat1","dat2")], train$sales, do.trace=TRUE,
+ importance=TRUE,ntree=5,,forest=TRUE)
     |      Out-of-bag   |
Tree |      MSE  %Var(y) |
   1 | 2.915e+05   544.44 |
   2 | 1.825e+05   340.84 |
   3 |  2.1e+05   392.19 |
   4 | 1.914e+05   357.38 |
   5 | 1.809e+05   337.78 |
> pred <- predict(RF1, test)
Error in predict.randomForest(RF1, test) : 
  New factor levels not present in the training data

这部分是有道理的。

所以我试试这个:

> test2 <- test[test$storeId != 11,]
> pred <- predict(RF1, test2)
Error in predict.randomForest(RF1, test2) : 
  New factor levels not present in the training data

所以我试试这个:

> levels(test2$storeId)
 [1] "2"  "3"  "4"  "5"  "6"  "7"  "8"  "9"  "10" "11"

“11”级还在里面。

接下来我试试这个:

> test2$storeId <- as.numeric(as.character(test2$storeId))
> test2$storeId <- factor(test2$storeId)
> pred <- predict(RF1, test2)
Error in predict.randomForest(RF1, test2) : 
  Type of predictors in new data do not match that of the training data.

尽管这里看起来还不错:

> levels(test2$storeId)
[1] "2"  "3"  "4"  "5"  "6"  "7"  "8"  "9"  "10"

对于让它在没有“11”级别的商店中预测的任何建议?

编辑:

> test2$storeId <- as.factor(as.character(test2$storeId))
> pred <- predict(RF1, test2)
Error in predict.randomForest(RF1, test2) : 
  Type of predictors in new data do not match that of the training data.
> 
> test2$storeId <- drop.levels(test2$storeId)
> pred <- predict(RF1, test2)
Error in predict.randomForest(RF1, test2) : 
  Type of predictors in new data do not match that of the training data.


> str(train)
'data.frame':   10 obs. of  4 variables:
 $ sales  : num  800 679 589 812 384 ...
 $ storeId: Factor w/ 10 levels "1","2","3","4",..: 1 2 3 4 5 6 7 8 9 10
 $ dat1   : num  0.5148 0.5567 0.9871 0.0071 0.736 ...
 $ dat2   : num  8.501 2.994 2.948 0.519 1.746 ...
> str(test)
'data.frame':   10 obs. of  3 variables:
 $ storeId: Factor w/ 10 levels "2","3","4","5",..: 1 2 3 4 5 6 7 8 9 10
 $ dat1   : num  0.0975 0.7435 0.7055 0.2085 0.2944 ...
 $ dat2   : num  5.96 6.84 3.96 8.93 8.62 ...
> str(test2)
'data.frame':   9 obs. of  3 variables:
 $ storeId: Factor w/ 9 levels "2","3","4","5",..: 1 2 3 4 5 6 7 8 9
 $ dat1   : num  0.0975 0.7435 0.7055 0.2085 0.2944 ...
 $ dat2   : num  5.96 6.84 3.96 8.93 8.62 ...

【问题讨论】:

没仔细看,不过……看看?droplevels 看过了,但没有运气。见上面的编辑 【参考方案1】:

这实际上是重复的。您应该使用droplevels,然后在解决该问题后,您忽略了级别仍未对齐的事实。您只需更改级别,使其与训练数据中的相同:

test1 <- droplevels(subset(test,storeId != 11))
levels(test1$storeId) <- as.character(c(2:10,1)
pred <- predict(RF1, test1)
> pred
       1        2        3        4        5        6        7        8        9 
698.9186 703.9761 654.5370 561.3058 491.1836 736.4316 639.8752 586.1755 782.1186 

这里的寓意是,您的训练数据有一个级别为 1,2,...10 的因子,您的测试数据必须具有完全相同的级别集(无论您是否有其中一些级别的数据)级别)。

【讨论】:

您的代码正在修改测试数据。在测试数据集中,因子值为:2-11。在海报示例中,他们正在删除 11 的值,在 test2 中留下 2-10。如果您查看代码“storeId”的结果值,现在的范围是 1-10。根本问题是 test2 缺少模型中存在的级别“1”。 RF 预测函数无法预测缺少级别的新数据。 @JeffreyEvans 很好,但它仍然可行,您只需按正确的顺序重置级别,以便 1 级别在最后。 是的,这行得通。您过去可以通过仅分配原始模型对象的级别来欺骗 RF 预测,从而绕过错误检查。然后 R 将强制添加到修改实际数据的级别函数中。这是一个很好的解决方案,可以提供有效的预测结果。【参考方案2】:

与 rf 模型相比,您无法对缺少因子的新数据运行 randomForest 预测函数。由于 test$storeId 的因子级别范围为“2”-“11”,而 train$storeId 为“1”-“10”,当您在测试数据中删除级别 11 时,您仍然缺少级别“1”,因此 randomForest 预测失败了。

【讨论】:

以上是关于R randomForest子集无法摆脱因子水平[重复]的主要内容,如果未能解决你的问题,请参考以下文章

在 R 的 randomForest 包中,因子是不是必须明确标记为因子?

更改 randomForest R 代码中节点特征子集选择的采样方法

R按因子子集后的空数据框

R函数将多个因子水平定义为缺失

在 R 中使用 randomforest() 进行分类?

H2O randomForest中的多类分类