Menjelajahi Piksel di Kedalaman

Ringkasan #30DayMapChallenge 2024

Wahyu Ramadhan
10 min readDec 31, 2024

Halo semuanya,

Memasuki tahun kelima saya menemukan #30DayMapChallenge, sama seperti tahun 2023, lagi-lagi saya belum bisa menyelesaikannya dengan sempurna. Saya tidak akan memberi banyak excuses, karena memang semua ide saya sedang dialihkan pada komitmen yang lain. Tapi yang jelas challenge ini tetap membuat saya antusias tiap bulan November.

Meskipun awalnya pesimis, tapi saya coba sedikit oportunis dengan mengeksekusi beberapa hari sekaligus. Idenya adalah membuat model Geospatial Artificial Intelligence (GeoAI) untuk klasifikasi habitat bentik di laut dangkal. Effort-nya lumayan, terutama di tahap pra-pemrosesan. Walaupun masih tergolong shallow learning, tapi keseluruhan prosesnya bahkan bisa dibagi menjadi beberapa konten.

Sebagai konteks, #30DayMapChallenge diinisiasi oleh Topi Tjukanov pada 2019 dan rutin diselenggarakan tiap tahunnya di bulan November. Tantangannya adalah untuk membuat peta setiap hari dengan tema yang berbeda dalam waktu sebulan. Peta ini tidak dibatasi metode atau bagaimana cara membuatnya asalkan harus dibagikan ke media sosial. Baca lebih lanjut dalam situs resminya di sini.

Tema harian #30DayMapChallenge 2024

Ngomong-ngomong, akun Google saya untuk menyimpan peta/gambar dan video di konten recap tahun-tahun sebelumnya kebetulan di banned tanpa alasan jelas, mungkin perlu waktu untuk mengunggahnya ulang.

Habitat bentik

Habitat bentik adalah lingkungan yang letaknya di dasar perairan (laut dan/atau darat), tempat berbagai organisme beraktivitas dan berinteraksi dengan substrat. Sederhananya, kondisi habitat bentik berbanding lurus dengan biodiversitas yang ada di dalamnya. Kalau konteksnya geosains, habitat bentik yang dapat dipetakan sejauh ini terbatas pada manifestasi objek yang tampak pada perairan dangkal optis (optically shallow water) saja [2] [3]. Jadi, objek seperti terumbu karang, lamun, alga, pasir dsb. yang berada di bawah tubir atau batas antara optically shallow water cenderung susah untuk dideteksi terutama dari citra penginderaan jauh.

Zonasi terumbu karang (kiri) (sumber), serta optically shallow water pada citra penginderaan jauh, warna tubir tampak lebih gelap (kanan)

Pra-pemrosesan

Memperoleh label data

Tahap ini bertujuan untuk memberi label pada dataset yang akan digunakan oleh model GeoAI untuk melakukan prediksi atau klasfikasi habitat bentik pada citra. Jika urutan logis pada klasifikasi Land Use Land Cover (LULC) adalah membuat titik lalu pergi ke lokasi tersebut dan mengambil sampel (beserta variabel-variabel lain yang dibutuhkan), habitat bentik sedikit berbeda.

Ilustrasi line transect (kiri), dan kerja lapangan dalam mengambil sampel habitat bentik (kanan) [1]

Uncertainty dari kondisi perairan menyulitkan kita untuk berada di exact location dari titik acuan yang direncanakan, oleh karena itu approachnya adalah melalui line transect. Teknisnya di lapangan adalah menjadikan garis tersebut sebagai acuan sampling, entah dengan metode photo transect atau spot check [1]. Kalau satu kelas (misalnya lamun) ditemukan dominan pada persentase tertentu di satu titik sampel, maka titik sampel dianggap mewakili kelas tersebut. Atau bahkan kelas campuran apabila komposisi persentasenya memenuhi suatu kondisi [9].

Survei habitat bentik dengan metode photo transect (dokumentasi pribadi)

Dari segi kepraktisan dan efisiensi waktu di lapangan, agaknya photo transect bisa jadi opsi. Dengan kamera dan GPS hanheld, kita ambil foto substrat sepanjang line transect yang sudah dibuat dengan interval jarak misalnya 1 meter. Soal integrasi dokumentasi dengan data GPS (koordinat) dan perhitungan persentase kelas dalam satu titik sampel bisa dilakukan pasca lapangan.

CPCe untuk menghitung persentase habitat bentik pada titik sampel, sayangnya tutorial ini tidak menyertakan integrasi dengan data GPS (koordinat) yang digunakan untuk geotagging

Data referensi

Allen Coral Atlas (ACA) v2.0 saya anggap cukup bagus untuk menjadi referensi dalam membuat label dataset berhubung tidak ada data dari lapangan. Jadi saya mengandaikan seolah-olah sedang melakukan survei di lapangan dengan langkah berikut:

  1. Membuat line transect
  2. Mengubah ke points dengan interval 1m
  3. Extract nilai piksel (kode/id kelas habitat bentik)

*Gunakan script GEE ini untuk ketiga langkah diatas.

Line transect sebisa mungkin dibuat secara melintang, baik ke arah laut (vertikal) dan mengikuti garis pantai (horizontal) untuk mendapatkan variasi kelas yang cukup. Selain itu, buat garisnya hingga ke mendekati tubir. Oh ya, saya revisi lagi statement saya tentang sampel harus poligon di sini, mengingat dinamika kondisi lapangan. Tidak ada salahnya sampel berupa point, asalkan memenuhi jumlah piksel minimum tiap kelas sehingga representatif (selengkapnya).

Pengambilan sampel kelas habitat bentik di Google Earth Engine (GEE). Line transect (kiri), konversi line ke points (tengah), dan overlay titik sampel dengan layer habitat bentik ACA (kanan)

Seleksi shallow water

Saat ini sensor penginderaan jauh (spektral) hanya efektif menangkap objek di bawah air pada panjang gelombang visible (400–700nm). Dengan kata lain habitat bentik yang dapat dideteksi terbatas pada kedalaman tertentu, tergantung kejernihan perairan dan reflektansi akibat penetrasi cahaya. Jadi, seleksi wilayah dengan kedalaman yang mostly adalah optically shallow water harus dilakukan supaya lebih efektif.

Lihat kurva pada objek air, cenderung menurun setelah melalui panjang gelombang merah dan ‘habis’ ketika mendekati inframerah-dekat
Kurva pantulan spektral [4]

Saya memakai pendekatan dengan Normalized Difference Water Index (NDWI) untuk segmentasi wilayah shallow water. Raster Calculator di QGIS adalah cara mudah untuk menghitung NDWI dengan formula (Green-NIR)/(Green+NIR). FYI karena data citranya PlanetScope (8 band), jadi Green = B4 dan NIR = B8. Setelah itu, gunakan rule of thumb untuk reclass hasil NDWI yaitu nilai > 0 dianggap sebagai shallow water. Kemudian convert NDWI yang telah di reclass format vektor untuk masking citra PlanetScope.

Tahapan masking shallow water pada citra PlanetScope

Data yang telah dimasking pada shallow water siap digunakan pada tahapan berikutnya dengan Python.

Data yang telah di masking hanya pada optically shallow water

Unduh script Python

Script lengkapnya ada di GitHub repository saya di sini, karena cukup panjang dan akan lebih mudah apabila ingin update daripada melalui medium. Prosesnya terbagi menjadi tiga file Python (.ipynb), yaitu mempersiapkan dataset training dan testing, membuat model GeoAI, dan menerapkan model pada data.

GitHub repository

Mempersiapkan dataset training dan testing

Sebetulnya saya sudah membuat markdown atau catatan pada file .ipynb di repository, tapi saya akan menambahkan beberapa detail yang belum ada dalam file tersebut. Jika di-breakdown, ada empat hal yang dilakukan di tahap ini: memberi deskripsi band pada data PlanetScope, ekstraksi nilai piksel, membuat training dan testing dataset, serta menangani class imbalance.

Khusus pada pemberian deskripsi pada data, secara teknis bisa saja dihapus dari workflow kalau paham betul struktur atau urutan band. Tapi apabila ada tambahan fitur seperti geomorfologi (batimetri), atau bahkan fusi (raster stack) dengan citra lain, maka itu berpotensi menyulitkan. Demi menjaga konsistensi dan mudah diingat, sebaiknya langkah ini tetap diperlukan.

# Retrieve the list of band descriptions from the dataset
desc = dataset.descriptions

# If descriptions are not available, create manual descriptions
if not desc or all(d is None for d in desc):
desc = ["B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8"]

# Create a dictionary to associate band descriptions with their indices after transpose
band_descriptions = {f"Band {i+1}": desc[i] for i in range(len(desc))}

# Display the dimensions and descriptions for each band
print("\nDimensions of the raster data after transpose:", planetscope.shape)
print("Descriptions for each band after transpose:")
for band, description in band_descriptions.items():
print(f'{band}: {description}')

Kebetulan biodiversitas habitat bentik di Kepulauan Gili tidak banyak memperlihatkan kelas Microalgal Mats, jadi jumlah sampel kelas tersebut sangat timpang dibanding lainnya. Dampaknya nanti bisa jadi model GeoAI akan menjadi bias, atau lebih baik dalam memprediksi kelas mayoritas [5]. Jadi saya lakukan random oversampling untuk meningkatkan jumlah sampel dari kelas yang teridentifikasi sebagai minoritas. Saya gunakan modul RandomOverSampler dari library imblearn untuk oversampling pada dataset training.

Kelas Microalgal Mats (kiri) dan oversample terhadap kelas minoritas (kanan) [3]

Pembuatan model GeoAI

Outline dari langkah pembuatan model GeoAI adalah: impor dataset training dan test, hyperparameter tuning, dan evaluasi model. Model GeoAI tersebut dibangun menggunakan algoritma Machine Learning (ML) Extreme Gradient Boosting (XGBoost) dengan function XGBClassifier dari library xgboost. Opsi algoritma lain (berbasis pohon keputusan) yang lebih common untuk klasifikasi habitat bentik adalah Random Forest, tapi klaim bahwa XGBoost lebih efisien [6] sejujurnya membuat saya penasaran.

XGBoost secara singkat bekerja dengan prinsip boosting atau membangun model secara iteratif dengan menggabungkan weak learner [7] [8]. Beda dengan RF yang menggabungkan banyak pohon keputusan yang dilatih secara independen atau paralel (bagging) [6]. Weak learner diasosiasikan sebagai model yang masih memiliki kesalahan (error) lantas diperbaiki hingga error pada output bisa minim.

Alur kerja algoritma algoritma ML berbasis boosting yang memperbaiki weak learner [7]

Hal penting lain di proses pembuatan model GeoAI adalah hyperparameter tuning. Saya pilih metode grid search untuk mencari kombinasi paling optimal dari sekian hyperparameter yang tersedia. Sedangkan Cross-Validation (CV) 5-Folds dipakai selama training dan testing untuk evaluasi model. Model akan dilatih dengan 4 dari 5 folds (data training), diuji pada fold yang tersisa (data testing), diulang 5x sehingga tiap fold jadi data testing 1x. Daftar hyperparameter dari XGBoost secara lengkap ada di sini.

# Define a list of parameters for hyperparameter tuning
# List of the parameters
param_list = {
'n_estimators': [50, 100, 300], # Number of trees to build in the model. Trying 50, 100, and 300 trees.
'max_depth': [3, 6, 9], # Maximum depth of each tree. Trying depths of 3, 6, and 9.
'eta': [0.1, 0.3, 0.5], # Controls the step size of the learning process. Trying values of 0.1, 0.3, and 0.5.
'gamma': [0, 0.1, 0.2], # Minimum loss reduction required for further partitioning a leaf node. Trying values of 0, 0.1, and 0.2.
'subsample': [0.8, 1.0], # Fraction of the training data to use for fitting each tree. Trying 0.8 and 1.0.
'colsample_bytree': [0.8, 1.0], # Fraction of features to use for each tree. Trying 0.8 and 1.0.
}

# 5-fold cross-validation GridSearchCV
grid_search = GridSearchCV(
xgb_model, # The model you want to tune (XGBoost classifier)
param_list, # The grid of hyperparameters to search
cv=5, # Number of folds for cross-validation (5-fold)
scoring='accuracy', # The metric used to evaluate model performance (accuracy)
n_jobs=-1, # Use all available CPU cores for parallel processing
verbose=5 # Display progress and information (higher value gives more details)
)

Sayangnya hasil evaluasi klasifikasinya menunjukkan overall accuracy (OA) yang tidak begitu memuaskan, hanya sebesar 60.19%. Kelas Seagrass punya performa terbaik: Precision/User Accuracy (UA) 76.93%, recall/Producer Accuracy (PA) 77.63%. Sementara performa kelas Micoralgal Mats: UA 16% dan PA 18.18%, tidak memuaskan meski sudah melalui oversampling. Akurasi yang terbatas ini rasanya wajar karena identifikasi karakteristik spektral objek di bawah air memang cukup sulit, apalagi tanpa pre-processing apapun yang mempengaruhi kualitas data citra.

Confusion matrix klasifikasi habitat bentik di Kepulauan Gili

Menerapkan model

Sebenarnya tidak ada catatan khusus untuk tahap yang dimaksudkan untuk menerapkan model XGBoost ke data PlanetScope. Tapi output klasifikasinya selalu menunjukkan perairan dalam dan darat merupakan kelas Rock. Padahal saya sudah beri nilai -9999 pada piksel NoData (null) di dalam function untuk klasifikasi data. Solusi sementara adalah masking dengan poligon shallow water.

Output klasifikasi habitat bentik Kepulauan Gili

Karena visualisasi peta di Python kurang intutitif, jadi saya prefer membuat layout peta di tempat lain. Seperti biasanya, saya gunakan QGIS dan Figma.

Titik sampel, line transect, dan ndwi (shallow water)

Saya baru sadar saat layouting peta ini, ternyata ada ketidaksempurnaan pada shallow water di bagian utara pulau Gili Meno. Yah, mungkin saya kurang teliti saat memilih datanya karena secara visual tutupan awannya sangat tipis 😔

Peta klasifikasi habitat bentik Kepulauan Gili

Referensi

[1] Roelfsema, C. (2010). Integrating field data with high spatial resolution multispectral satellite imagery for calibration and validation of coral reef benthic community maps. Journal of Applied Remote Sensing, 4(1), 043527. https://doi.org/10.1117/1.3430107

[2] Hedley, J. D., Roelfsema, C., Brando, V., Giardino, C., Kutser, T., Phinn, S., Mumby, P. J., Barrilero, O., Laporte, J., & Koetz, B. (2018b). Coral Reef Applications of Sentinel-2: Coverage, characteristics, bathymetry and benthic mapping with comparison to Landsat 8. Remote Sensing of Environment, 216, 598–614. https://doi.org/10.1016/j.rse.2018.07.014

[3] Wicaksono, P., Aryaguna, P. A., & Lazuardi, W. (2019). Benthic habitat mapping model and cross-validation using machine-learning classification algorithms. Remote Sensing, 11(11), 1279. https://doi.org/10.3390/rs11111279

[4] O’Donohue, D. (2024, October 1). Understanding spectral reflectance in remote sensing. mapscaping.com. https://mapscaping.com/understanding-spectral-reflectance-in-remote-sensing/. Diakses pada 24 Desember 2024.

[5] Tang, T. (2023, April 25). Class imbalance strategies — A visual guide with code. Medium. https://towardsdatascience.com/class-imbalance-strategies-a-visual-guide-with-code-8bc8fae71e1a. Diakses pada 24 Desember 2024.

[6] Shao, Z., Ahmad, M. N., & Javed, A. (2024). Comparison of Random Forest and XGBoost Classifiers Using Integrated Optical and SAR Features for Mapping Urban Impervious Surface. Remote Sensing, 16(4), 665. https://doi.org/10.3390/rs16040665

[7] Chen, T., & Guestrin, C. (2016). XGBoost. Proceedings of the 22nd ACM SIGKDD International Conference on Knowledge Discovery and Data Mining, 785–794. https://doi.org/10.1145/2939672.2939785

[8] GeeksforGeeks. (2023, February 6). XGBoost. https://www.geeksforgeeks.org/xgboost/. Diakses pada 24 Desember 2024.

[9] Wicaksono, P., & Harahap, S. D. (2023). Mapping seagrass biodiversity indicators of Pari Island using multiple worldview-2 bands derivatives. Geosfera Indonesia, 8(2), 189. https://doi.org/10.19184/geosi.v8i2.41214

Connect with me on LinkedIn

--

--

Wahyu Ramadhan
Wahyu Ramadhan

Written by Wahyu Ramadhan

Mapping my way through the GIScience universe. Join me on this journey!

No responses yet