0

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());
2
  • Your model is only as good as your input data
    – GeoMonkey
    Commented Dec 26, 2022 at 1:55
  • Yeah, thanks. I hoped there is maybe something extra I can do for enhancement Commented Dec 26, 2022 at 19:48

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.