Klasifikasi tanpa pengawasan dengan kman di R

10

Saya memiliki serangkaian gambar satelit (5 band) dan ingin mengklasifikasikannya berdasarkan kmeans dalam R. Skrip saya berfungsi dengan baik (loop melalui gambar saya, mengonversi gambar ke data.frame, mengelompokkannya, dan mengubahnya kembali menjadi raster):

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)
}

Masalah saya adalah: Saya tidak dapat membandingkan hasil klasifikasi satu sama lain karena cluster assignents berbeda dari gambar ke gambar. Misalnya, "air" ada di cluster gambar pertama nomor 1, di 2 berikutnya dan di 10 ketiga, sehingga tidak mungkin untuk membandingkan hasil air antara tanggal.

Bagaimana saya bisa memperbaiki tugas cluster?

Dapatkah saya menentukan titik awal yang tetap untuk semua gambar (berharap bahwa air selalu terdeteksi pertama dan dengan demikian diklasifikasikan sebagai 1)?

Dan jika ya, bagaimana?

Iris
sumber

Jawaban:

6

Saya pikir Anda tidak bisa ... Anda harus memberi label pada masing-masing kelas untuk membandingkannya. Saya mengklasifikasikan tanpa pengawasan tanpa informasi sebelumnya dan karenanya tidak dapat mendefinisikan jenis kelas apa pun.

Jika Anda memiliki lapisan referensi, Anda dapat membuat pelabelan dengan voting mayoritas. Berikut adalah kode yang cukup efisien untuk voting mayoritas daripada menggunakan fungsi paket 'raster' 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]

di mana reffile referensi kelas raster Anda, class_fileadalah hasil kmeans Anda.

zr memberi Anda di col pertama nomor 'zona' dan di col kedua, label untuk kelas.

nmatton
sumber
Saya takut itu tidak mungkin. Terima kasih untuk kode pemungutan suara mayoritas!
Iris
4

Untuk menerapkan pengelompokan pada tumpukan gambar, Anda tidak melakukannya satu per satu melainkan pada seluruh tumpukan gambar secara bersamaan. Kalau tidak, seperti yang ditunjukkan oleh @nmatton, statistiknya tidak masuk akal.

Namun, saya tidak setuju bahwa ini tidak mungkin, hanya memori intensif. Pada data satelit nyata ini akan menjadi masalah besar, dan mungkin tidak mungkin pada data resolusi tinggi, tetapi Anda dapat memproses dalam memori dengan memaksa raster Anda menjadi satu objek tunggal yang dapat diteruskan ke fungsi clustering. Anda perlu melacak nilai-nilai NA di seluruh raster karena mereka akan dihapus selama pengelompokan dan Anda akan perlu mengetahui posisi dalam raster sehingga Anda dapat menetapkan nilai-nilai cluster ke sel yang benar.

Kita dapat melangkah melalui satu pendekatan di sini. Mari kita tambahkan perpustakaan yang diperlukan dan beberapa contoh data (logo RGB R untuk memberi kita 3 band untuk bekerja dengan).

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

Pertama, Kita bisa memaksa objek tumpukan raster multi-band ke data.frame menggunakan getValues. Perhatikan bahwa saya menambahkan nilai NA di baris 1, kolom 3 sehingga saya bisa menggambarkan cara menangani tanpa data.

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

Di sini, kita bisa turun ke bisnis dan membuat indeks sel dari nilai-nilai non-NA yang akan digunakan untuk menetapkan hasil cluster.

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

Sekarang, kita membuat objek cluster dari nilai-nilai RGB 3 band dengan k = 4. Saya menggunakan metode clara K-Medoid karena bagus dengan data besar dan lebih baik dengan distribusi ganjil. Ini sangat mirip dengan K-Means.

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

Demi kesederhanaan, kita dapat membuat raster kosong dengan menarik salah satu band raster dari objek tumpukan raster asli kita dan menetapkannya nilai-nilai NA.

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

Akhirnya, menggunakan indeks, kami menetapkan nilai cluster ke sel yang sesuai di raster kosong dan plot hasilnya.

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

Untuk raster besar Anda mungkin ingin melihat ke dalam paket memori besar yang menulis matriks ke disk dan beroperasi pada blok dan ada fungsi k-means yang tersedia. Juga, perlu diingat bahwa ini bukan apa R dirancang untuk dan bahwa pemrosesan gambar atau perangkat lunak GIS mungkin lebih tepat. Saya tahu bahwa SAGA dan kotak alat Orfeo keduanya adalah perangkat lunak gratis yang memiliki pengelompokan k-means yang tersedia untuk tumpukan gambar. Bahkan ada perpustakaan RSAGA yang memungkinkan perangkat lunak dipanggil dari R.

Jeffrey Evans
sumber
Jika semua gambar ditumpuk dan dikelompokkan sekaligus, maka hasilnya adalah satu gambar yang dikelompokkan, bukan?
Iris
@ Iris, ya ini adalah cara kerja pengelompokan gambar jenis ini dan mengikuti implementasi dalam perangkat lunak penginderaan jauh. Contoh yang jelas dan relevan adalah implementasi isocluster di ArcGIS ( desktop.arcgis.com/en/arcmap/10.3/tools/spatial-analyst-toolbox/… )
Jeffrey Evans
Maka jawaban ini tidak membantu sama sekali. Masalah saya adalah bahwa saya mencoba melakukan deteksi perubahan dari waktu ke waktu berdasarkan beberapa klasifikasi gambar yang tidak didukung, tetapi saya dapat membandingkan hasil yang berbeda karena kelas-kelas tersebut diberikan secara berbeda.
Iris
Klasifikasi tanpa pengawasan bukanlah cara yang layak untuk melakukan deteksi perubahan. Bahkan sedikit variasi dalam gambar yang diberikan dapat berakhir dengan piksel yang ditugaskan ke kelas yang berbeda. Ini akan menjadi kasus bahkan jika Anda menyediakan pusat cluster untuk K-Means. Saya memiliki fungsi entropi dalam paket spatialEco yang berguna untuk deteksi perubahan. Anda menghitung entropi dalam jendela NxN dan kemudian mendapatkan delta pada setiap langkah waktu. Entropi negatif merupakan kerugian dan positif adalah perolehan komponen lanskap dalam besaran tertentu di bawah entropi maksimum.
Jeffrey Evans
Itu adalah pertanyaan lama dan saya menolak ide untuk menggunakan k-means sejak lama. Tapi senang mengetahui paket spatialEco untuk waktu berikutnya;)
Iris