我正在使用RGDAL软件包在R中处理图像分类脚本。所讨论的栅格是一个带有28个通道的PCIDSK文件:训练数据频道,验证数据频道和26个光谱数据通道。目的是填充包含每个像素的值的数据框,该值在训练数据通道中不是零,以及26个频段中的相关光谱值。

在Python/numpy中,我可以轻松地将整个图像的所有频段导入到多维数组中,但是,由于内存限制,R中R中的唯一选项似乎是按块导入此数据块,这非常慢:

library(rgdal)

raster = "image.pix"
training_band = 2
validation_band = 1
BlockWidth = 500
BlockHeight = 500

# Get some metadata about the whole raster
myinfo = GDALinfo(raster)
ysize = myinfo[[1]]
xsize = myinfo[[2]]
numbands = myinfo[[3]]


# Iterate through the image in blocks and retrieve the training data
column = 0
training_data = NULL
while(column < xsize){
 if(column + BlockWidth > xsize){
  BlockWidth = xsize - column
 }
 row = 0
 while(row < ysize){
  if(row + BlockHeight > ysize){
   BlockHeight = ysize - row
  }

  # Do stuff here
  myblock = readGDAL(raster, region.dim = c(BlockHeight,BlockWidth), offset = c(row, column), band = c(training_band,3:numbands), silent = TRUE)
  blockdata = matrix(NA, dim(myblock)[1], dim(myblock)[2])
  for(i in 1:(dim(myblock)[2])){
   bandname = paste("myblock", names(myblock)[i], sep="$")
   blockdata[,i]= as.matrix(eval(parse(text=bandname)))
  }
  blockdata = as.data.frame(blockdata)
  blockdata = subset(blockdata, blockdata[,1] > 0)
  if (dim(blockdata)[1] > 0){
   training_data = rbind(training_data, blockdata)
  }

  row = row + BlockHeight
 }
 column = column + BlockWidth
}
remove(blockdata, myblock, BlockHeight, BlockWidth, row, column)

如果没有记忆力,是否有更快/更好的做同样的事情的方法?

收集此培训数据后的下一步是创建分类器(Randomforest软件包),该分类器也需要大量内存,具体取决于所请求的树木数量。这使我陷入了第二个问题,那就是,鉴于训练数据已经占据了记忆的数量,无法创建500棵树的森林:

myformula = formula(paste("as.factor(V1) ~ V3:V", dim(training_data)[2], sep=""))
r_tree = randomForest(formula = myformula, data = training_data, ntree = 500, keep.forest=TRUE)

有没有办法分配更多内存?我想念什么吗?谢谢...

编辑]正如Jan所建议的那样,使用“栅格”软件包要快得多;但是,据我所知,就收集培训数据而言,它并不能解决内存问题,因为它最终需要在数据范围内,在内存中:

library(raster)
library(randomForest)

# Set some user variables
fn = "image.pix"
training_band = 2
validation_band = 1

# Get the training data
myraster = stack(fn)
training_class = subset(myraster, training_band)
training_class[training_class == 0] = NA
training_class = Which(training_class != 0, cells=TRUE)
training_data = extract(myraster, training_class)
training_data = as.data.frame(training_data)

因此,尽管这要快得多(并且花费更少的代码),但它仍然无法解决没有足够的免费内存来创建分类器的问题...是否有一些“栅格”软件包函数,我找不到可以完成此操作的问题?谢谢...

有帮助吗?

解决方案

查看栅格包。栅格软件包为RGDAL提供了方便的包装器,而无需将其加载到内存中。

http://raster.r-forge.r-project.org/

希望这有所帮助。

“栅格”软件包处理基本的空间栅格(网格)数据访问和操作。它定义了栅格类;可以处理非常大的文件(存储在磁盘上);并包括标准的栅格功能,例如覆盖,聚合和合并。

“栅格”软件包的目的是提供易于使用的功能进行栅格操作和分析。这些包括高级功能,例如覆盖,合并,聚集,投影,重新样本,距离,多边形转换。所有这些功能都适用于无法将其加载到内存中的非常大的栅格数据集。此外,该软件包提供了较低级别的功能,例如通过行读取和写作(通过RGDAL到许多格式)来构建其他功能。

通过使用栅格软件包,您可以在使用RandomForest之前避免填充内存。

编辑]为了用RandomForest解决记忆问题,如果您可以在子样本(大小<< n)而不是Bootstrap样本(大小为n)的子样本上学习随机森林中的单个树,这可能会有所帮助。

其他提示

我认为这里的关键是:“一个包含每个像素的值的数据框架在训练数据渠道中并不为零”。如果生成的data.frame足够小,可以在内存中保存,则可以通过读取该频段来确定这一点,然后将其修剪为那些非零值,然后尝试创建一个数据。你想要的哥伦斯。

你可以运行吗?

 training_band = 2 

 df = readGDAL("image.pix",  band = training_band) 
 df = as.data.frame(df[!df[,1] == 0, ])

然后,您可以通过单独阅读每个频段并修剪训练带来填充数据。

如果data.frame太大,那么您就卡住了 - 我不知道RandomForest是否可以在“ FF”中使用内存映射的数据对象,但可能值得尝试。

编辑:一些示例代码,并注意栅格为您提供内存映射的访问,但问题是RandomForest是否可以使用内存映射的数据结构。您可能只能阅读所需的数据,一次频段 - 您需要尝试构建完整的数据。帧首先,而不是附加列。

另外,如果您可以从一开始就生成完整的数据。通过rbind()通过代码,您需要越来越大的连续内存,这是可以避免的。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top