Menjelajahi Piksel di Kedalaman
Ringkasan #30DayMapChallenge 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.
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.
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.
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].
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.
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:
- Membuat line transect
- Mengubah ke points dengan interval 1m
- 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).
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.
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.
Data yang telah dimasking pada shallow water siap digunakan pada tahapan berikutnya dengan Python.
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.
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.
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.
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.
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.
Karena visualisasi peta di Python kurang intutitif, jadi saya prefer membuat layout peta di tempat lain. Seperti biasanya, saya gunakan QGIS dan Figma.
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 😔
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