एम्बेडिंग फ़ील्ड का इस्तेमाल, रिग्रेशन के लिए फ़ीचर इनपुट/पूर्वानुमान लगाने वाले के तौर पर किया जा सकता है. ठीक उसी तरह जैसे इनका इस्तेमाल क्लासिफ़िकेशन के लिए किया जाता है.
इस ट्यूटोरियल में, हम यह जानेंगे कि 64 डाइमेंशन वाले एम्बेडिंग फ़ील्ड लेयर का इस्तेमाल, मल्टीपल रिग्रेशन विश्लेषण के लिए इनपुट के तौर पर कैसे किया जाता है. इससे ज़मीन के ऊपर मौजूद बायोमास (एजीबी) का अनुमान लगाया जा सकता है.
नासा का ग्लोबल इकोसिस्टम डाइनैमिक्स इन्वेस्टिगेशन (GEDI) मिशन, ज़मीन पर 60 मीटर के अंतराल पर 30 मीटर के स्पेशल रिज़ॉल्यूशन के साथ, ग्राउंड ट्रांससेक्ट के साथ लिडार मेज़रमेंट इकट्ठा करता है. हम GEDI L4A Raster Aboveground Biomass Density डेटासेट का इस्तेमाल करेंगे. इसमें ज़मीन के ऊपर मौजूद बायोमास डेंसिटी (एजीबीडी) के पॉइंट अनुमान शामिल हैं. इसका इस्तेमाल रिग्रेशन मॉडल में अनुमानित वैरिएबल के तौर पर किया जाएगा.
देश या इलाका चुनें
आइए, सबसे पहले दिलचस्पी वाला कोई इलाका तय करते हैं. इस ट्यूटोरियल के लिए, हम भारत के पश्चिमी घाट में मौजूद किसी क्षेत्र को चुनेंगे और पॉलीगॉन को ज्यामिति वैरिएबल के तौर पर तय करेंगे. इसके अलावा, कोड एडिटर में मौजूद ड्राइंग टूल का इस्तेमाल करके, दिलचस्पी वाले क्षेत्र के चारों ओर एक पॉलीगॉन बनाया जा सकता है. यह पॉलीगॉन, इंपोर्ट में ज्यामिति वैरिएबल के तौर पर सेव हो जाएगा. हम सैटेलाइट के बुनियादी मैप का भी इस्तेमाल करते हैं. इससे, वनस्पति वाले इलाकों का पता लगाना आसान हो जाता है.
var geometry = ee.Geometry.Polygon([[
[74.322, 14.981],
[74.322, 14.765],
[74.648, 14.765],
[74.648, 14.980]
]]);
// Use the satellite basemap
Map.setOptions('SATELLITE');
आंकड़ा: ज़मीन के ऊपर मौजूद बायोमास का अनुमान लगाने के लिए, दिलचस्पी की जगह चुनना
कोई समयावधि चुनें
वह साल चुनें जिसके लिए हमें रिग्रेशन करना है. ध्यान रखें कि सैटेलाइट एम्बेडिंग को हर साल के हिसाब से एग्रीगेट किया जाता है. इसलिए, हम पूरे साल के लिए अवधि तय करते हैं.
var startDate = ee.Date.fromYMD(2022, 1, 1);
var endDate = startDate.advance(1, 'year');
सैटलाइट एम्बेडिंग डेटासेट तैयार करना
रिग्रेशन के लिए, 64 बैंड वाली सैटलाइट एम्बेडिंग इमेज का इस्तेमाल किया जाएगा. हम सैटेलाइट एम्बेडिंग डेटासेट लोड करते हैं. इसके बाद, चुने गए साल और इलाके की इमेज को फ़िल्टर करते हैं.
var embeddings = ee.ImageCollection('GOOGLE/SATELLITE_EMBEDDING/V1/ANNUAL');
var embeddingsFiltered = embeddings
.filter(ee.Filter.date(startDate, endDate))
.filter(ee.Filter.bounds(geometry));
सैटलाइट से ली गई इमेज को टाइल में बांटा जाता है. इसके बाद, टाइल के लिए यूटीएम ज़ोन के प्रोजेक्शन में दिखाया जाता है. इस वजह से, हमें दिलचस्पी वाले इलाके को कवर करने वाली कई सैटेलाइट एम्बेडिंग टाइल मिलती हैं. एक इमेज पाने के लिए, हमें उन्हें मोज़ेक करना होगा. Earth Engine में, इनपुट इमेज के मोज़ेक को डिफ़ॉल्ट प्रोजेक्शन असाइन किया जाता है. यह WGS84 होता है और इसका स्केल 1 डिग्री होता है. हम इस मोज़ेक को ट्यूटोरियल में बाद में एग्रीगेट और रीप्रोजेक्ट करेंगे. इसलिए, ओरिजनल प्रोजेक्शन को बनाए रखना फ़ायदेमंद होता है. हम setDefaultProjection()
फ़ंक्शन का इस्तेमाल करके, किसी एक टाइल से प्रोजेक्शन की जानकारी निकाल सकते हैं और उसे मोज़ेक पर सेट कर सकते हैं.
// Extract the projection of the first band of the first image
var embeddingsProjection = ee.Image(embeddingsFiltered.first()).select(0).projection();
// Set the projection of the mosaic to the extracted projection
var embeddingsImage = embeddingsFiltered.mosaic()
.setDefaultProjection(embeddingsProjection);
GEDI L4A मोज़ेक तैयार करना
GEDI से मिले बायोमास के अनुमानों का इस्तेमाल, हमारे रिग्रेशन मॉडल को ट्रेनिंग देने के लिए किया जाएगा. इसलिए, GEDI से मिले अमान्य या अविश्वसनीय डेटा को इस्तेमाल करने से पहले फ़िल्टर करना ज़रूरी है. हम संभावित तौर पर गलत मेज़रमेंट को हटाने के लिए, कई मास्क लागू करते हैं.
- क्वालिटी की ज़रूरी शर्तें पूरी न करने वाली सभी मेज़रमेंट हटाएं (l4_quality_flag = 0 और degrade_flag > 0)
- ज़्यादा रिलेटिव गड़बड़ी ('agbd_se' / 'agbd' > 50%) वाले सभी मेज़रमेंट हटाएं
- Copernicus GLO-30 Digital Elevation Mode (DEM) के आधार पर, 30% से ज़्यादा ढलान वाली सभी मेज़रमेंट हटाएं
आखिर में, हम समय अवधि और दिलचस्पी वाले क्षेत्र के लिए, सभी बचे हुए मेज़रमेंट चुनते हैं और एक मोज़ेक बनाते हैं.
var gedi = ee.ImageCollection('LARSE/GEDI/GEDI04_A_002_MONTHLY');
// Function to select the highest quality GEDI data
var qualityMask = function(image) {
return image.updateMask(image.select('l4_quality_flag').eq(1))
.updateMask(image.select('degrade_flag').eq(0));
};
// Function to mask unreliable GEDI measurements
// with a relative standard error > 50%
// agbd_se / agbd > 0.5
var errorMask = function(image) {
var relative_se = image.select('agbd_se')
.divide(image.select('agbd'));
return image.updateMask(relative_se.lte(0.5));
};
// Function to mask GEDI measurements on slopes > 30%
var slopeMask = function(image) {
// Use Copernicus GLO-30 DEM for calculating slope
var glo30 = ee.ImageCollection('COPERNICUS/DEM/GLO30');
var glo30Filtered = glo30
.filter(ee.Filter.bounds(geometry))
.select('DEM');
// Extract the projection
var demProj = glo30Filtered.first().select(0).projection();
// The dataset consists of individual images
// Create a mosaic and set the projection
var elevation = glo30Filtered.mosaic().rename('dem')
.setDefaultProjection(demProj);
// Compute the slope
var slope = ee.Terrain.slope(elevation);
return image.updateMask(slope.lt(30));
};
var gediFiltered = gedi
.filter(ee.Filter.date(startDate, endDate))
.filter(ee.Filter.bounds(geometry));
var gediProjection = ee.Image(gediFiltered.first())
.select('agbd').projection();
var gediProcessed = gediFiltered
.map(qualityMask)
.map(errorMask)
.map(slopeMask);
var gediMosaic = gediProcessed.mosaic()
.select('agbd').setDefaultProjection(gediProjection);
// Visualize the GEDI Mosaic
var gediVis = {
min: 0,
max: 200,
palette: ['#edf8fb','#b2e2e2','#66c2a4','#2ca25f','#006d2c'],
bands: ['agbd']
};
Map.addLayer(gediMosaic, gediVis, 'GEDI L4A (Filtered)', false);
इनपुट को फिर से सैंपल करना और एग्रीगेट करना
रिग्रेशन मॉडल को ट्रेन करने के लिए पिक्सल की सैंपलिंग करने से पहले, हम इनपुट को एक ही पिक्सल ग्रिड में फिर से सैंपल करते हैं और फिर से प्रोजेक्ट करते हैं. GEDI के मेज़रमेंट में, हॉरिज़ॉन्टल तौर पर +/- 9 मीटर तक का अंतर हो सकता है. GEDI AGB की वैल्यू को सैटेलाइट एम्बेडिंग पिक्सल से मैच करते समय, यह समस्या आती है. इस समस्या को हल करने के लिए, हम सभी इनपुट इमेज को फिर से सैंपल करते हैं और उन्हें बड़े पिक्सल ग्रिड में इकट्ठा करते हैं. इसमें ओरिजनल पिक्सल की औसत वैल्यू होती है. इससे डेटा में मौजूद गड़बड़ियों को दूर करने और बेहतर मशीन लर्निंग मॉडल बनाने में भी मदद मिलती है.
// Choose the grid size and projection
var gridScale = 100;
var gridProjection = ee.Projection('EPSG:3857')
.atScale(gridScale);
// Create a stacked image with predictor and predicted variables
var stacked = embeddingsImage.addBands(gediMosaic);
// Set the resampling mode
var stacked = stacked.resample('bilinear');
// Aggregate pixels with 'mean' statistics
var stackedResampled = stacked
.reduceResolution({
reducer: ee.Reducer.mean(),
maxPixels: 1024
})
.reproject({
crs: gridProjection
});
// As larger GEDI pixels contain masked original
// pixels, it has a transparency mask.
// We update the mask to remove the transparency
var stackedResampled = stackedResampled
.updateMask(stackedResampled.mask().gt(0));
पिक्सल को फिर से प्रोजेक्ट करना और उन्हें इकट्ठा करना एक मुश्किल प्रोसेस है. इसलिए, यह सबसे सही तरीका है कि स्टैक की गई इमेज को ऐसेट के तौर पर एक्सपोर्ट किया जाए और अगले चरणों में पहले से प्रोसेस की गई इमेज का इस्तेमाल किया जाए. इससे बड़े क्षेत्रों के साथ काम करते समय, कंप्यूटेशन का समय खत्म हो गया या उपयोगकर्ता की मेमोरी खत्म हो गई गड़बड़ियों को ठीक करने में मदद मिलेगी.
// Replace this with your asset folder
// The folder must exist before exporting
var exportFolder = 'projects/spatialthoughts/assets/satellite_embedding/';
var mosaicExportImage = 'gedi_mosaic';
var mosaicExportImagePath = exportFolder + mosaicExportImage;
Export.image.toAsset({
image: stackedResampled.clip(geometry),
description: 'GEDI_Mosaic_Export',
assetId: mosaicExportImagePath,
region: geometry,
scale: gridScale,
maxPixels: 1e10
});
एक्सपोर्ट करने की प्रोसेस शुरू करें और इसके पूरा होने तक इंतज़ार करें. इसके बाद, हम ऐसेट को इंपोर्ट करते हैं और मॉडल बनाना जारी रखते हैं.
// Use the exported asset
var stackedResampled = ee.Image(mosaicExportImagePath);
ट्रेनिंग की सुविधाओं को एक्सट्रैक्ट करना
हमारे पास ट्रेनिंग की सुविधाओं को निकालने के लिए, इनपुट डेटा तैयार है. हम रिग्रेशन मॉडल में, सैटेलाइट एम्बेडिंग बैंड को डिपेंडेंट वैरिएबल (अनुमान लगाने वाले) और GEDI AGBD वैल्यू को इंडिपेंडेंट वैरिएबल (अनुमानित) के तौर पर इस्तेमाल करते हैं. हम हर पिक्सल पर एक जैसी वैल्यू निकाल सकते हैं और अपना ट्रेनिंग डेटासेट तैयार कर सकते हैं. हमारी GEDI इमेज को ज़्यादातर मास्क किया गया है. इसमें सिर्फ़ पिक्सल के छोटे सबसेट की वैल्यू शामिल हैं. sample()
का इस्तेमाल करने पर, ज़्यादातर वैल्यू खाली दिखेंगी. इस समस्या को हल करने के लिए, हम GEDI मास्क से क्लास बैंड बनाते हैं. साथ ही, यह पक्का करने के लिए कि हम बिना मास्क वाले पिक्सल से सैंपल लें, stratifiedSample()
का इस्तेमाल करते हैं.
var predictors = embeddingsImage.bandNames();
var predicted = gediMosaic.bandNames().get(0);
print('predictors', predictors);
print('predicted', predicted);
var predictorImage = stackedResampled.select(predictors);
var predictedImage = stackedResampled.select([predicted]);
var classMask = predictedImage.mask().toInt().rename('class');
var numSamples = 1000;
// We set classPoints to [0, numSamples]
// This will give us 0 points for class 0 (masked areas)
// and numSample points for class 1 (non-masked areas)
var training = stackedResampled.addBands(classMask)
.stratifiedSample({
numPoints: numSamples,
classBand: 'class',
region: geometry,
scale: gridScale,
classValues: [0, 1],
classPoints: [0, numSamples],
dropNulls: true,
tileScale: 16,
});
print('Number of Features Extracted', training.size());
print('Sample Training Feature', training.first());
रिग्रेशन मॉडल को ट्रेन करना
अब हम मॉडल को ट्रेन करने के लिए तैयार हैं. Earth Engine में मौजूद कई क्लासिफ़ायर का इस्तेमाल, क्लासिफ़िकेशन और रिग्रेशन, दोनों के लिए किया जा सकता है. हमें क्लास के बजाय, संख्या वाली वैल्यू का अनुमान लगाना है. इसलिए, हम क्लासिफ़ायर को REGRESSION
मोड में चलाने के लिए सेट कर सकते हैं. साथ ही, ट्रेनिंग डेटा का इस्तेमाल करके उसे ट्रेन कर सकते हैं. मॉडल को ट्रेनिंग देने के बाद, हम मॉडल के अनुमान की तुलना इनपुट वैल्यू से कर सकते हैं. साथ ही, मॉडल की परफ़ॉर्मेंस की जांच करने के लिए, रूट-मीन स्क्वेयर एरर (rmse
) और कोरिलेशन कोएफ़िशिएंट r^2
का हिसाब लगा सकते हैं.
// Use the RandomForest classifier and set the
// output mode to REGRESSION
var model = ee.Classifier.smileRandomForest(50)
.setOutputMode('REGRESSION')
.train({
features: training,
classProperty: predicted,
inputProperties: predictors
});
// Get model's predictions for training samples
var predicted = training.classify({
classifier: model,
outputName: 'agbd_predicted'
});
// Calculate RMSE
var calculateRmse = function(input) {
var observed = ee.Array(
input.aggregate_array('agbd'));
var predicted = ee.Array(
input.aggregate_array('agbd_predicted'));
var rmse = observed.subtract(predicted).pow(2)
.reduce('mean', [0]).sqrt().get([0]);
return rmse;
};
var rmse = calculateRmse(predicted);
print('RMSE', rmse);
// Create a plot of observed vs. predicted values
var chart = ui.Chart.feature.byFeature({
features: predicted.select(['agbd', 'agbd_predicted']),
xProperty: 'agbd',
yProperties: ['agbd_predicted'],
}).setChartType('ScatterChart')
.setOptions({
title: 'Aboveground Biomass Density (Mg/Ha)',
dataOpacity: 0.8,
hAxis: {'title': 'Observed'},
vAxis: {'title': 'Predicted'},
legend: {position: 'right'},
series: {
0: {
visibleInLegend: false,
color: '#525252',
pointSize: 3,
pointShape: 'triangle',
},
},
trendlines: {
0: {
type: 'linear',
color: 'black',
lineWidth: 1,
pointSize: 0,
labelInLegend: 'Linear Fit',
visibleInLegend: true,
showR2: true
}
},
chartArea: {left: 100, bottom: 100, width: '50%'},
});
print(chart);
आंकड़ा: मॉनिटर की गई और मॉडल से अनुमानित AGBD वैल्यू
अज्ञात वैल्यू के लिए अनुमान जनरेट करना
जब हमें मॉडल से संतुष्टि मिल जाती है, तब हम ट्रेनिंग दिए गए मॉडल का इस्तेमाल करके, उन जगहों के लिए अनुमान जनरेट कर सकते हैं जिनके बारे में हमें जानकारी नहीं है. इसके लिए, हमें ऐसी इमेज का इस्तेमाल करना होगा जिसमें अनुमान लगाने वाले बैंड मौजूद हों.
// We set the band name of the output image as 'agbd'
var predictedImage = stackedResampled.classify({
classifier: model,
outputName: 'agbd'
});
अब हर पिक्सल पर अनुमानित एजीबीडी वैल्यू वाली इमेज एक्सपोर्ट करने के लिए तैयार है. हम इसका इस्तेमाल अगले हिस्से में, नतीजों को विज़ुअलाइज़ करने के लिए करेंगे.
// Replace this with your asset folder
// The folder must exist before exporting
var exportFolder = 'projects/spatialthoughts/assets/satellite_embedding/';
var predictedExportImage = 'predicted_agbd';
var predictedExportImagePath = exportFolder + predictedExportImage;
Export.image.toAsset({
image: predictedImage.clip(geometry),
description: 'Predicted_Image_Export',
assetId: predictedExportImagePath,
region: geometry,
scale: gridScale,
maxPixels: 1e10
});
एक्सपोर्ट करने की प्रोसेस शुरू करें और इसके पूरा होने तक इंतज़ार करें. इसके बाद, हम ऐसेट को इंपोर्ट करते हैं और नतीजों को विज़ुअलाइज़ करते हैं.
var predictedImage = ee.Image(predictedExportImagePath);
// Visualize the image
var gediVis = {
min: 0,
max: 200,
palette: ['#edf8fb','#b2e2e2','#66c2a4','#2ca25f','#006d2c'],
bands: ['agbd']
};
Map.addLayer(predictedImage, gediVis, 'Predicted AGBD');
इमेज: अनुमानित एजीबीडी. गहरे हरे रंग से, बायोमास डेंसिटी के ज़्यादा होने का अनुमान लगाया जाता है
कुल बायोमास का अनुमान लगाना
अब हमारे पास इमेज के हर पिक्सल के लिए, एजीबीडी की अनुमानित वैल्यू हैं. इनका इस्तेमाल करके, किसी इलाके में मौजूद कुल अबवग्राउंड बायोमास (एजीबी) का अनुमान लगाया जा सकता है. हालांकि, हमें पहले उन सभी पिक्सल को हटाना होगा जो बिना वनस्पति वाले इलाकों से जुड़े हैं. हम ESA WorldCover लैंडकवर डेटासेट का इस्तेमाल करके, वनस्पति वाले पिक्सल चुन सकते हैं.
// GEDI data is processed only for certain landcovers
// from Plant Functional Types (PFT) classification
// https://doi.org/10.1029/2022EA002516
// Here we use ESA WorldCover v200 product to
// select landcovers representing vegetated areas
var worldcover = ee.ImageCollection('ESA/WorldCover/v200').first();
// Aggregate pixels to the same grid as other dataset
// with 'mode' value.
// i.e. The landcover with highest occurrence within the grid
var worldcoverResampled = worldcover
.reduceResolution({
reducer: ee.Reducer.mode(),
maxPixels: 1024
})
.reproject({
crs: gridProjection
});
// Select grids for the following classes
// | Class Name | Value |
// | Forests | 10 |
// | Shrubland | 20 |
// | Grassland | 30 |
// | Cropland | 40 |
// | Mangroves | 95 |
var landCoverMask = worldcoverResampled.eq(10)
.or(worldcoverResampled.eq(20))
.or(worldcoverResampled.eq(30))
.or(worldcoverResampled.eq(40))
.or(worldcoverResampled.eq(95));
var predictedImageMasked = predictedImage
.updateMask(landCoverMask);
Map.addLayer(predictedImageMasked, gediVis, 'Predicted AGBD (Masked)');
GEDI AGBD वैल्यू की यूनिट, मेगोग्राम प्रति हेक्टेयर (Mg/ha) होती है. कुल एजीबी पाने के लिए, हम हर पिक्सल को उसके क्षेत्रफल (हेक्टेयर में) से गुणा करते हैं और उनकी वैल्यू जोड़ते हैं.
var pixelAreaHa = ee.Image.pixelArea().divide(10000);
var predictedAgb = predictedImageMasked.multiply(pixelAreaHa);
var stats = predictedAgb.reduceRegion({
reducer: ee.Reducer.sum(),
geometry: geometry,
scale: gridScale,
maxPixels: 1e10,
tileScale: 16
});
// Result is a dictionary with key for each band
var totalAgb = stats.getNumber('agbd');
print('Total AGB (Mg)', totalAgb);
Earth Engine Code Editor में, इस ट्यूटोरियल के लिए पूरी स्क्रिप्ट आज़माएं.