Rのkmeansによる教師なし分類


10

衛星画像(5バンド)の時系列があり、Rのkmeansでそれらを分類したいと思います。私のスクリプトは正常に動作しています(画像をループして、画像をdata.frameに変換し、クラスター化して、元の画像に戻します。ラスター):

for (n in files) {
image <- stack(n)    
image <- clip(image,subset)

###classify raster
image.df <- as.data.frame(image)  
cluster.image <- kmeans(na.omit(image.df), 10, iter.max = 10, nstart = 25) ### kmeans, with 10 clusters

#add back NAs using the NAs in band 1 (identic NA positions in all bands), see http://stackoverflow.com/questions/12006366/add-back-nas-after-removing-them/12006502#12006502
image.df.factor <- rep(NA, length(image.df[,1]))
image.df.factor[!is.na(image.df[,1])] <- cluster.image$cluster

#create raster output
clusters <- raster(image)   ## create an empty raster with same extent than "image"  
clusters <- setValues(clusters, image.df.factor) ## fill the empty raster with the class results  
plot(clusters)
}

私の問題は、クラスターの割り当てが画像ごとに異なるため、分類結果を互いに比較できないことです。たとえば、「水」は最初の画像クラスター番号1、次の2、3番目の10にあり、日付間の水の結果を比較することはできません。

クラスタの割り当てを修正するにはどうすればよいですか?

すべての画像の固定開始点を指定できますか(水が常に最初に検出され、したがって1として分類されることを期待して)。

そして、もしそうなら、どうやって?

回答:


6

できないと思います...最初に各クラスにラベルを付けて、それらを比較する必要があります。Kmeanは教師なしで分類するため、事前の情報がないため、いかなる種類のクラスも定義できません。

参照レイヤーがある場合は、過半数の投票でラベリングを作成できます。ここでは、「ラスター」パッケージ関数を使用するよりも、多数決のための非常に効率的なコードを示しますzonal

require (data.table)
fun <- match.fun(modal)
vals <- getValues(ref) 
zones <- round(getValues(class_file), digits = 0) 
rDT <- data.table(vals, z=zones) 
setkey(rDT, z) 
zr<-rDT[, lapply(.SD, modal,na.rm=T), by=z]

どこrefラスタクラス参照ファイルがある、class_fileあなたの関数kmeansは結果です。

zr 最初の列には「ゾーン」番号、2番目の列にはクラスのラベルを指定します。


それは不可能だと思いました。多数決のためのコードをありがとう!
アイリス14

4

イメージスタックにクラスタリングを実装するには、バンドバイバンドではなく、イメージスタック全体で同時に実行します。そうでなければ、@ nmattonが指摘するように、統計はあまり意味がありません。

ただし、これは不可能であり、メモリを大量に消費するだけであることに同意しません。実際の衛星データでは、これは大きな問題であり、高解像度データではおそらく不可能ですが、クラスタリング関数に渡すことができる単一のオブジェクトにラスタを強制することにより、メモリで処理できます。クラスタリング中に削除されるため、ラスタ値全体を追跡する必要があります。また、クラスタ値を正しいセルに割り当てるには、ラスタの位置を知る必要があります。

ここでは、1つのアプローチについて説明します。必要なライブラリといくつかのサンプルデータ(3つのバンドを使用できるようにするためのRGB Rロゴ)を追加してみましょう。

library(raster)
library(cluster)
r <- stack(system.file("external/rlogo.grd", package="raster")) 
  plot(r)

まず、getValuesを使用して、マルチバンドラスタスタックオブジェクトをdata.frameに強制変換できます。行1、列3にNA値を追加しているので、データを処理しない方法を説明できることに注意してください。

r.vals <- getValues(r[[1:3]])
  r.vals[1,][3] <- NA

ここでは、ビジネスに取り掛かり、クラスター結果の割り当てに使用される非NA値のセルインデックスを作成できます。

idx <- 1:ncell(r)
idx <- idx[-unique(which(is.na(r.vals), arr.ind=TRUE)[,1])]  

次に、k = 4の3つのバンドRGB値からクラスターオブジェクトを作成します。クララK-Medoidsメソッドを使用しています。これは、データが大きい場合に適し、分布が奇数の場合に適しているためです。K-Meansとよく似ています。

clus <- cluster::clara(na.omit(scale(r.vals)), k=4)

簡単にするために、元のラスタースタックオブジェクトからラスターバンドの1つを引き出してNA値を割り当てることにより、空のラスターを作成できます。

r.clust <- r[[1]]
r.clust[] <- NA

最後に、インデックスを使用して、クラスター値を空のラスターの適切なセルに割り当て、結果をプロットします。

r.clust[idx] <- clus$clustering
plot(r.clust) 

巨大なラスターの場合、マトリックスをディスクに書き込み、ブロックを操作するbigmemoryパッケージを調べたい場合があります。k-means関数を使用できます。また、これはRが設計された目的とは厳密に一致せず、画像処理またはGISソフトウェアの方が適している場合があることに注意してください。SAGAとOrfeoツールボックスはどちらも、画像スタックで使用できるk-meansクラスタリングを備えた無料のソフトウェアであることを知っています。ソフトウェアをRから呼び出せるようにするRSAGAライブラリもあります。


すべての画像を一度に積み上げてクラスター化すると、結果は1つのクラスター化画像になりますよね?
アイリス

@アイリス、はい、これがこのタイプの画像クラスタリングのしくみであり、リモートセンシングソフトウェアの実装に従います。クリアと関連例は、ArcGIS(中isocluster実装であろうdesktop.arcgis.com/en/arcmap/10.3/tools/spatial-analyst-toolbox/...
ジェフリー・エバンス

次に、この回答はまったく役に立ちません。私の問題は、いくつかの監視されていない画像分類に基づいて、時間の経過とともに変化の検出を行おうとしたことですが、クラスの割り当てが異なるため、異なる結果を比較できました。
アイリス

教師なし分類は、変更検出を実行するための実行可能な方法ではありません。特定の画像にわずかな変化があっても、ピクセルが別のクラスに割り当てられる可能性があります。これは、K-Meansにクラスターセンターを提供した場合でも当てはまります。変更の検出に役立つSpatialEcoパッケージにエントロピー関数があります。NxNウィンドウ内でエントロピーを計算し、各タイムステップでデルタを導出します。負のエントロピーは損失を表し、正のエントロピーは最大エントロピーの下で特定の大きさ内の景観コンポーネントのゲインです。
ジェフリーエヴァンス

それは古い質問であり、私は以前にk-meansを使用するという考えを明らかにしました。しかし、次回の
Iris
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.