【问题标题】:Image classification (raster stack) with random forest (package ranger)使用随机森林(包 ranger)进行图像分类(光栅堆栈)
【发布时间】:2018-03-03 09:45:33
【问题描述】:

我正在使用 R 包 ranger 拟合随机森林来对光栅图像进行分类。预测函数会产生错误,下面我提供一个可重现的示例。

library(raster)
library(nnet)
library(ranger)
data(iris)

# put iris data into raster
r<-list()
for(i in 1:4){
  r[[i]]<-raster(nrows=10, ncols=15)
  r[[i]][]<-iris[,i]
}
r<-stack(r)
names(r)<-names(iris)[1:4]

# multinom (an example that works)
nn.model <- multinom(Species ~ ., data=iris, trace=F)
nn.pred<-predict(r,nn.model)

# ranger (doesn't work)
ranger.model<-ranger(Species ~ ., data=iris)   
ranger.pred<-predict(r,ranger.model)

给出的错误是

v[cells, ] 中的错误

虽然我的真实数据的错误是

p[-naind, ]

我唯一想到的是 ranger.prediction 对象除了感兴趣的预测之外还包含几个元素。无论如何,如何使用 ranger 在栅格堆栈上进行预测?

【问题讨论】:

  • 我认为如果您在github repository of the ranger package 中打开问题,您可以获得问题的答案。
  • 游侠的predict 期待数据(见?predict.ranger)作为data.framegwaa.data,也许这就是问题所在?

标签: r raster


【解决方案1】:

编辑,2021-07-15

有一个关于使用clusterR 的问题,我找到了一种比我最初建议的更直接的方法。新代码的功能与原始代码相同,但方式更简单,并带有并行处理选项:

# First train the ranger model

ranger.model <- ranger(Species ~ .
                       , data = iris
                       , probability = TRUE  # This argument is needed for se
                       , keep.inbag = TRUE   # So is this one
                       )


# Create prediction function for clusterR

f_se <- function(model, ...) predict(model, ...)$se


# Predict se using clusterR
  
beginCluster(2)

map_se <- clusterR(r
                   , predict
                   , args = list(ranger.model
                                 , type = 'se'  # Remember to include this argument
                                 , fun = f_se
                                 )
                   )

endCluster()

原答案,2018-05-31

您可以通过在 caret 包的 train 函数中训练模型来在栅格堆栈上运行游侠模型的预测:

library(caret)
ranger.model <- train(Species ~ ., data = iris, method = "ranger")  
ranger.pred <- predict(r, ranger.model)

但是,如果您想预测标准误差,这不起作用,因为火车对象的预测函数不接受type = 'se'。我通过使用本文档为此目的构建一个函数来解决这个问题:

https://cran.r-project.org/web/packages/raster/vignettes/functions.pdf

# Function to predict standard errors on a raster
predfun <- function(x, model, type, filename)
{
  out <- raster(x)
  bs <- blockSize(out)
  out <- writeStart(out, filename, overwrite = TRUE)
  for (i in 1:bs$n) {
    v <- getValues(x, row = bs$row[i], nrows = bs$nrows[i])
    nas <- apply(v, 1, function(x) sum(is.na(x)))
    p <- numeric(length = nrow(v))
    p[nas > 0] <- NA
    p[nas == 0] <- predict(object = model,
                           v[nas == 0,],
                           type = 'se')$se
    out <- writeValues(out, p, bs$row[i])
  }
  out <- writeStop(out)
  return(out)
}

# New ranger model 
ranger.model <- ranger(Species ~ .
                       , data = iris
                       , probability = TRUE
                       , keep.inbag  = TRUE
                       )
# Run predictions
se <- predfun(r
              , model = ranger.model
              , type  = "se"
              , filename = paste0(getwd(), "/se.tif")
              )

【讨论】:

  • 这对我有用!有没有办法并行化 predfun 函数或将其与 clusterR 一起使用以加快大型栅格的处理速度?
  • 嗨@elyssac,我在答案中添加了一段新代码,以展示如何使用clusterR预测se
  • 感谢您的更新。 clusterR 函数产生以下错误:Error in clusterR(predictors, predict, args = list(object = ranger.model, : cluster error 同时具有type = "response"type = "se"。但是,当我使用 predict 函数时它可以工作,例如pred_se_predict &lt;- predict(predictors, ranger.model, type='se', progress='text', fun = f_se). 我应该在新帖子中打开一个可重现的示例吗?我认为在predict 方法中添加num.threads 是可行的,但它的运行速度似乎仍然比clusterR 慢得多(尽管这可能只是rangerrandomForest)。
  • 没关系,@ABMoeller 我已经让它工作了!我不小心包含了object = ranger.modelobject 不应该在那里。感谢您的帮助!
【解决方案2】:

经过一番折腾:

pacman::p_load(raster, nnet, ranger)

data(iris)

# put iris data into raster
r<-list()
for(i in 1:4){
  r[[i]]<-raster(nrows=10, ncols=15)
  r[[i]][]<-iris[,i]
}
r<-stack(r)
names(r)<-names(iris)[1:4]

# multinom (an example that works)
nn.model <- multinom(Species ~ ., data=iris, trace=F)
nn.pred <- predict(r,nn.model)  # predict(object, newdata, type = c("raw","class"), ...)

# ranger (doesn't work)
ranger.model <- ranger(Species ~ ., data=iris)   
ranger.pred <- predict(ranger.model, as.data.frame(as.matrix(r)))

as.data.frame(as.matrix(r))做到了!

免责声明:我没有检查输出的正确性,所以这可能根本不会产生任何结果,但是...

identical(iris$Species, ranger.pred$predictions)

【讨论】:

  • 感谢@m-dz,但输出(即 ranger.pred)并不是应有的栅格。但是,实际上我使用的是这种方法,即(1)将栅格转换为data.frame,(2)对df的条目进行分类,以及(3)转换为栅格。但是,恐怕这不适用于大型栅格?
  • 很遗憾我不知道这里的答案,但可以肯定的是predict.ranger 不能将光栅作为输入......也许它不会那么糟糕?
【解决方案3】:

如果有帮助,它对我有用 randomForest 而不是 ranger

library(randomForest)
rf.model<-randomForest(Species ~ ., data=iris)   
rf.pred<-predict(r,rf.model)

【讨论】:

  • 感谢@Antonis,但是 ranger 函数通过我感兴趣的参数 case.weights 接受案例权重。randomForest 没有。这就是我使用游侠的原因。
【解决方案4】:

可以在这里找到另一个解决方案: https://github.com/imbs-hl/ranger/issues/319

正如那里所解释的,将 raster::predict() 与 ranger 随机森林模型一起使用将不起作用,因为 raster 包不支持 ranger。

用户 mnwright 提到了一种使其正常工作的解决方法。您只需在代码中添加一些内容:

ranger.pred<-predict(r,ranger.model, fun = function(model, ...) predict(model, ...)$predictions)

为我工作,现在对象 ranger.pred 应该是光栅。

【讨论】:

    猜你喜欢
    • 2015-05-04
    • 2016-08-30
    • 2019-09-05
    • 2013-09-22
    • 2018-02-18
    • 2015-09-23
    • 2014-03-08
    • 2018-05-20
    • 2016-05-25
    相关资源
    最近更新 更多