I am doing a supervised classification using RF classifier in GEE. However, the accuracy that I am getting is not exceeding 0.67, even if I increase the training sample or no. of trees in my classifier.
Can someone have a look and advise me of how I can increase my accuracy (maybe till 80% would be enough)?
Here is the link:
https://code.earthengine.google.com/cf4f47bc398ff2b6cc45d54c7e32dc49
// Define a function that scales and masks Landsat 8 surface reflectance images.
function prepSrL8(image) {
// Develop masks for unwanted pixels (fill, cloud, cloud shadow).
var qaMask = image.select('QA_PIXEL').bitwiseAnd(parseInt('11111', 2)).eq(0);
var saturationMask = image.select('QA_RADSAT').eq(0);
// Apply the scaling factors to the appropriate bands.
var getFactorImg = function(factorNames) {
var factorList = image.toDictionary().select(factorNames).values();
return ee.Image.constant(factorList);
};
var scaleImg = getFactorImg([
'REFLECTANCE_MULT_BAND_.|TEMPERATURE_MULT_BAND_ST_B10']);
var offsetImg = getFactorImg([
'REFLECTANCE_ADD_BAND_.|TEMPERATURE_ADD_BAND_ST_B10']);
var scaled = image.select('SR_B.|ST_B10').multiply(scaleImg).add(offsetImg);
// Replace original bands with scaled bands and apply masks.
return image.addBands(scaled, null, true)
.updateMask(qaMask).updateMask(saturationMask);
}
// Make a cloud-free Landsat 8 surface reflectance composite.
var dates = [
// ee.DateRange('2020-04-01', '2020-04-16'),
ee.DateRange('2020-04-16', '2020-05-01'),
ee.DateRange('2020-05-01', '2020-05-16'),
ee.DateRange('2020-05-16', '2020-06-01'),
ee.DateRange('2020-06-01', '2020-06-16'),
ee.DateRange('2020-06-16', '2020-07-01'),
ee.DateRange('2020-07-01', '2020-07-16'),
ee.DateRange('2020-07-16', '2020-08-01'),
ee.DateRange('2020-08-01', '2020-08-16'),
ee.DateRange('2020-08-16', '2020-09-01'),
ee.DateRange('2020-09-01', '2020-09-16'),
ee.DateRange('2020-09-16', '2020-10-01'),
//ee.DateRange('2020-10-01', '2020-10-16'),
]
//var bands = ['SR_B2', 'SR_B3', 'SR_B4', 'SR_B5',
// 'SR_B6', 'SR_B7']
var addNDVI = function(img) {
var ndvi = img.normalizedDifference(['SR_B5','SR_B4']).rename('NDVI')
return img.addBands(ndvi)
}
var addNDWI = function(img) {
var ndwi = img.normalizedDifference(['SR_B3', 'SR_B5']).rename('NDWI')
return img.addBands(ndwi)
}
// //EVI
var addEVI= function(image){
var evi= image.expression(
'2.5*(NIR-RED)/(NIR+6*RED-7.5*BLUE+10000)',{
NIR:image.select('SR_B5'),
RED:image.select('SR_B4'),
BLUE:image.select('SR_B2'),
}).float().rename('EVI')
return image.addBands(evi)
}
var list = dates.map(function(range) {
return ee.ImageCollection('LANDSAT/LC08/C02/T1_L2')
.filterDate(ee.DateRange(range))
.filterBounds(ROI)
.map(addNDVI)
.map(addNDWI)
.map(addEVI)
.select(['SR_B2', 'SR_B3', 'SR_B4', 'SR_B5', 'SR_B6', 'SR_B7','NDVI', 'NDWI','EVI'])
//.mean()
.median()
.rename(['SR_B2', 'SR_B3', 'SR_B4', 'SR_B5','SR_B6', 'SR_B7','NDVI', 'NDWI','EVI'])
});
// print(list)
// Map.addLayer(ROI, {}, 'ROI', false)
///create a stacked layer///
var stacked = ee.ImageCollection(list).toBands().clip(ROI);
Map.addLayer(stacked, {bands: ["3_NDVI", "5_NDVI", "8_NDVI"]}, 'Stacked', false)
print(stacked,'stacked')
// // //Generate 4000 random pt sample
var random1 = ee.FeatureCollection.randomPoints({
region: rice,
points: 2000,
seed: 0,
maxError: 1
})
var random2 = ee.FeatureCollection.randomPoints({
region: maize,
points: 2000,
seed: 0,
maxError: 1
})
var random3 = ee.FeatureCollection.randomPoints({
region: cotton,
points: 3000,
seed: 0,
maxError: 1
})
var random4 = ee.FeatureCollection.randomPoints({
region: potato,
points: 3000,
seed: 0,
maxError: 1
})
// Paint the reference data into an image so we can sample it.
var referenceData = ee.Image().byte().paint(rice, 0).paint(maize, 1).paint(cotton,2).paint(potato,3).rename("class")
//var merged_sample= random1.merge(random2,random3,random4);
// Place the collections in a new collection.
// var combined = ee.FeatureCollection([random1, random2,random3,random4]);
var combined = ee.FeatureCollection([random1,random2,random3]);
// Flatten the collection to create a new collection with all the features.
var flattened = combined.flatten();
///export the sample to assest to free some space and time for computation///
// Export.table.toAsset({
// collection: flattened,
// description:'exportToTableAsset',
// assetId: 'merged_sample',
// });
// // // Get the values for all pixels in each polygon in the training.
var training = stacked.addBands(referenceData).reduceRegions({
reducer: ee.Reducer.first(),
// Get the sample from the polygons FeatureCollection.
collection: flattened
,
// Set the scale to get Landsat pixels in the polygons.
scale: 30,
//crs: 'EPSG:32636',
tileScale: 2
});
// var training = stacked.addBands(referenceData).reduceRegion({
// reducer: ee.Reducer.frequencyHistogram(),
// geometry:stacked.geometry(),
// maxPixels: 1e14,
// scale: 30
// });
//How balanced are the training data?
print(training.reduceColumns(ee.Reducer.frequencyHistogram(), ["class"]))
Map.addLayer(training,{},'training_sample')
// Filter out the null property values and try again.
var trainingNoNulls = training.filter(
ee.Filter.notNull(stacked.bandNames().add("class"))
)
var sample=trainingNoNulls.randomColumn();
var split=0.7
var training_sample=sample.filter(ee.Filter.lt('random',split));
var validation_sample=sample.filter(ee.Filter.gte('random',split));
var classifier = ee.Classifier.smileRandomForest(150)
.train({
features: training_sample,
//.randomColumn().filter("random < 0.7"),
classProperty: 'class',
inputProperties: stacked.bandNames(),
})
var classified = stacked.classify(classifier, 'Classified')
Map.addLayer(classified,{
min: 0,
max: 3,
// palette: [ 'green','orange']
palette: ['yellow', 'green','orange','brown']
},
'classification', true)
// Get a confusion matrix representing resubstitution accuracy.
var trainAccuracy = classifier.confusionMatrix();
print('Resubstitution error matrix: ', trainAccuracy);
print('Training overall accuracy: ', trainAccuracy.accuracy());
print('Training kappa accuracy: ', trainAccuracy.kappa());
////////////// validation sample//////
// Extract spectral data from the input image for validation points
var validation = stacked.sampleRegions({
// Get the sample from the point FeatureCollection.
collection: validation_sample,
// We'll classify on 'Level_2"
properties: ['class'],
// Set the scale to get Sentinel-2 pixels at the points.
scale: 30,
tileScale: 2
})
// Classify the validation data.
var validated = validation.classify(classifier);
// Get a confusion matrix representing expected accuracy.
var testAccuracy = validated.errorMatrix('class', 'classification');
print('Test overall accuracy: ', testAccuracy.accuracy());
print('Test kappa accuracy: ', testAccuracy.kappa());