3

I am trying to do a supervised classification in Google Earth Engine and created around 50 polygons for each of my 5 categories and put them into Feature Collections and merged them into one single feature collection with the property "class".

Now I want to split this feature collection into two random samples - the first sample I will use for training my classifier, and the second for validating the classification afterwards.

I have been trying different strategies. I e.g. tried reducing it to an image (images are able to be split into random samples according to the GEE tutorials), but I could not manage to keep the property "class" (the only relevant property my feature collection has). I also tried inserting a random column in my feature collection and filtering by it, which did NOT work:

//merging feature collections
var fc = water.merge(croplandVEG).merge(croplandBARE).merge(urban).merge(naturalVEG);

var newfc = fc.randomColumn();

print(newfc);

//split the image of the training points into Training & Accuracy samples!

var filterrandom0 = ee.Filter.equals('random',0);
var trainingsample = newfc.filter(filterrandom0);

var filterrandom1 = ee.Filter.equals('random',1);
var accuracysample = newfc.filter(filterrandom1);

// Get the values for all pixels in each polygon in the training.
var training = clipped.sampleRegions({
  // Get the sample from the polygons FeatureCollection.
  collection: trainingsample,
  // Keep this list of properties from the polygons.
  properties: ['class'],
  // Set the scale to get Landsat pixels in the polygons.
  scale: 100
});

// Create a random forest classifier with custom parameters.
var classifier = ee.Classifier.randomForest().train({
  features: training,
  classProperty: 'class',
  inputProperties: bands
});

// Train the classifier.
var trained = classifier.train(training, 'class', bands);

// Classify the image.
var classified = clipped.classify(trained);

// Classify the validation data.
var validated = accuracysample.classify(classifier);

For this I get the error code:

ConfusionMatrix (Error)

No data was found in classifier training input.

Why is this possible for images but not for feature collections on Google Earth Engine? Here is how I tried reducing it to an image, which also did not work so far:

var newimage = fc
  .reduceToImage(['class'],
  ee.Reducer.firstNonNull()).select(['first'], ['class']);

  // Sample the input imagery to get a FeatureCollection of training data.
var trainingsample = newimage.stratifiedSample({
  scale: 100,
  numPoints: 5000,
  seed: 0
});

var accuracysample = newimage.stratifiedSample({
  scale: 100,
  numPoints: 5000,
  seed: 1
});

To which I get the error code:

Unable to transform geometry into requested projection.

2

Okay, I figured it out myself and want to share the answer for anyone else who has the problem.

First, it is possible to split a feature class with the random column. My mistake was however to put "ee.Filter.equals('random',0)", as the random column does not only consist of 0s and 1s, but of ANY number between 0 and 1. So what I instead did was:

var filterrandom0 = ee.Filter.greaterThan('random',0.2);
var trainingsample = newfc.filter(filterrandom0);

var filterrandom1 = ee.Filter.lessThan('random',0.2);
var accuracysample = newfc.filter(filterrandom1);

I chose 80% of my data as training data and 20% as accuracy data. This gives back a Feature Collection.

However, this still does not work to just use it as an accuracysample. To assess the accuracy, you need to classify the image twice - once with training data, once with accuracydata, and then compare the images. So I forgot to introduce the step that actually transforms this trainingsample into the data I need:

// Get the values for all pixels in each polygon in the training.
var training = image.sampleRegions({
  // Get the sample from the polygons FeatureCollection.
  collection: newfc,
  // Keep this list of properties from the polygons.
  properties: ['class'],
  // Set the scale to get Landsat pixels in the polygons.
  scale: 100
});

So, it is much smarter to just split this training data that I made directly, which I did with:

var withRandom = training.randomColumn('random');

var split = 0.7;  // Roughly 70% training, 30% testing.
var trainingPartition = withRandom.filter(ee.Filter.lt('random', split));
var testingPartition = withRandom.filter(ee.Filter.gte('random', split));

// Trained with 70% of our data.
var trainedClassifier = ee.Classifier.randomForest().train({
  features: trainingPartition,
  classProperty: 'class',
  inputProperties: bands
});

// Classify the test FeatureCollection.
var test = testingPartition.classify(trainedClassifier);

// Print the confusion matrix.
var confusionMatrix = test.errorMatrix('class', 'classification');
print('Confusion Matrix', confusionMatrix);
print('Validation overall accuracy: ', confusionMatrix.accuracy());

This should in theory work, however, I always get the error code:

ConfusionMatrix (Error) Computation timed out.

So, new question:

How do I avoid the time out? What causes the time out and how do I stop it?

The link to the whole script is here:

https://code.earthengine.google.com/c8c2701a804d9f025a73e94d2cad63c6

  • 1
    A new question is best suited as just that - ask a new question. Otherwise we would need to answer it in comments to this answer. – Kersten Mar 6 '18 at 13:12
  • 1
    Okay, thanks! I figured it out now, the time-out was just a small mistake in my script. The version I posted actually works fine! – sarap Mar 11 '18 at 13:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.