2

rgdalパッケージを使用してRの画像分類スクリプトに取り組んでいます。問題のラスターは、トレーニングデータチャネル、検証データチャネル、および26のスペクトルデータチャネルの28のチャネルを持つPCIDSKファイルです。目的は、トレーニングデータチャネルでゼロではない各ピクセルの値と、26バンドの関連するスペクトル値を含むデータフレームにデータを入力することです。

Python / Numpyでは、画像全体のすべてのバンドを多次元配列に簡単にインポートできますが、メモリの制限により、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パッケージ)を作成することです。これは私の2番目の問題につながります。それは、トレーニングデータによってすでに占有されているメモリの量を考えると、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)

したがって、これははるかに高速です(そして必要なコードは少なくなります)が、分類子を作成するのに十分な空きメモリがないという問題は解決されません...これを達成できる「ラスター」パッケージ関数は見つかりませんでしたか? ?ありがとう...

4

2 に答える 2

3

Rasterパッケージを確認してください。Rasterパッケージは、Rgdalをメモリにロードせずに便利なラッパーを提供します。

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

うまくいけば、この助け。

'raster'パッケージは、基本的な空間ラスター(グリッド)データのアクセスと操作を処理します。ラスタークラスを定義します。非常に大きなファイル(ディスクに保存されている)を処理できます。オーバーレイ、集計、マージなどの標準のラスター関数が含まれています。

'raster'パッケージの目的は、ラスターの操作と分析のための使いやすい関数を提供することです。これらには、オーバーレイ、マージ、集約、投影、リサンプル、距離、ポリゴンからラスターへの変換などの高レベルの機能が含まれます。これらの関数はすべて、メモリにロードできない非常に大きなラスターデータセットに対して機能します。さらに、このパッケージは、他の関数を構築するための、行ごとの読み取りおよび書き込み(rgdalを介した多くの形式への)などの低レベルの関数を提供します。

Rasterパッケージを使用すると、randomForestを使用する前にメモリがいっぱいになるのを防ぐことができます。

[編集]randomForestでメモリの問題を解決するには、ブートストラップサンプル(サイズn)ではなく、サブサンプル(サイズ<< n)でランダムフォレスト内の個々のツリーを学習できると便利です。

于 2010-11-15T16:57:57.010 に答える
0

ここで重要なのは、「トレーニングデータチャネルでゼロではない各ピクセルの値を含むデータフレーム」だと思います。結果のdata.frameがメモリに保持するのに十分小さい場合は、そのバンドだけを読み取り、ゼロ以外の値のみにトリミングしてから、その数の行と合計数のdata.frameを作成してみてください。あなたが望む列。

これを実行できますか?

 training_band = 2 

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

次に、各バンドを個別に読み取り、トレーニングバンドの場合と同様にトリミングすることで、data.frameの列を1つずつ入力できます。

そのdata.frameが大きすぎると、行き詰まります。randomForestがメモリマップされたデータオブジェクトを「ff」で使用できるかどうかはわかりませんが、試してみる価値があるかもしれません。

編集:いくつかのサンプルコード。ラスターはメモリマップされたアクセスを提供しますが、問題はrandomForestがメモリマップされたデータ構造を使用できるかどうかです。必要なデータのみを一度に1バンドずつ読み込むことができる可能性があります。列を追加するのではなく、最初に完全なdata.frameを構築してみてください。

また、最初から完全なdata.frameを生成できる場合は、それが機能するかどうかがわかります。コードのようにrbind()を実行することにより、連続するメモリのチャンクがますます大きくなる必要があり、それは回避できる可能性があります。

于 2010-11-15T22:23:47.983 に答える