التصنيف الإشرافي

تتعامل حزمة Classifier مع التصنيف الخاضع للإشراف من خلال خوارزميات تعلُّم الآلة التقليدية التي تعمل في Earth Engine. وتشمل هذه المصنّفات CART وRandomForest وNaiveBayes وSVM. في ما يلي سير العمل العام للتصنيف:

  1. جمع بيانات التدريب اجمع الميزات التي تحتوي على سمة تخزّن تصنيف الفئة المعروفة والسمات التي تخزّن القيم الرقمية للمتنبّئات.
  2. إنشاء مثيل لمصنِّف اضبط مَعلماته إذا لزم الأمر.
  3. درِّب المصنِّف باستخدام بيانات التدريب.
  4. تصنيف صورة أو مجموعة عناصر
  5. تقدير خطأ التصنيف باستخدام بيانات التحقّق المستقلة

بيانات التدريب هي FeatureCollection مع سمة تخزّن تصنيف الفئة وسمات تخزّن متغيّرات التوقّع. يجب أن تكون تصنيفات الفئات متتالية، وأعدادًا صحيحة تبدأ من 0. إذا لزم الأمر، استخدِم remap() لتحويل قيم الفئات إلى أعداد صحيحة متتالية. يجب أن تكون المتغيّرات المستقلة رقمية.

يمكن أن تأتي بيانات التدريب و/أو التحقّق من مجموعة متنوعة من المصادر. لجمع بيانات التدريب بشكل تفاعلي في Earth Engine، يمكنك استخدام أدوات رسم الأشكال الهندسية (راجِع قسم أدوات الأشكال الهندسية في صفحة "أداة تعديل الرموز"). بدلاً من ذلك، يمكنك استيراد بيانات تدريب محدّدة مسبقًا من مادة عرض جدول في Earth Engine (راجِع صفحة استيراد بيانات الجدول للحصول على التفاصيل). احصل على مصنِّف من إحدى الدوال الإنشائية في ee.Classifier. درِّب المصنِّف باستخدام classifier.train(). تصنيف Image أو FeatureCollection باستخدام classify() يستخدم المثال التالي مصنِّف أشجار التصنيف والانحدار (CART) (Breiman et al. 1984) للتنبؤ بثلاث فئات بسيطة:

أداة تعديل الرموز (JavaScript)

// 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 image = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2')
  .filterDate('2021-03-01', '2021-07-01')
  .map(prepSrL8)
  .median();

// Use these bands for prediction.
var bands = ['SR_B2', 'SR_B3', 'SR_B4', 'SR_B5',
             'SR_B6', 'SR_B7', 'ST_B10'];

// Load training points. The numeric property 'class' stores known labels.
var points = ee.FeatureCollection('GOOGLE/EE/DEMOS/demo_landcover_labels');

// This property stores the land cover labels as consecutive
// integers starting from zero.
var label = 'landcover';

// Overlay the points on the imagery to get training.
var training = image.select(bands).sampleRegions({
  collection: points,
  properties: [label],
  scale: 30
});

// Train a CART classifier with default parameters.
var trained = ee.Classifier.smileCart().train(training, label, bands);

// Classify the image with the same bands used for training.
var classified = image.select(bands).classify(trained);

// Display the inputs and the results.
Map.setCenter(-122.0877, 37.7880, 11);
Map.addLayer(image,
             {bands: ['SR_B4', 'SR_B3', 'SR_B2'], min: 0, max: 0.25},
             'image');
Map.addLayer(classified,
             {min: 0, max: 2, palette: ['orange', 'green', 'blue']},
             'classification');

إعداد Python

يمكنك الاطّلاع على صفحة بيئة Python للحصول على معلومات حول واجهة برمجة التطبيقات Python API واستخدام geemap للتطوير التفاعلي.

import ee
import geemap.core as geemap

Colab (Python)

# Define a function that scales and masks Landsat 8 surface reflectance images.
def prep_sr_l8(image):
  """Scales and masks Landsat 8 surface reflectance images."""
  # Develop masks for unwanted pixels (fill, cloud, cloud shadow).
  qa_mask = image.select('QA_PIXEL').bitwiseAnd(0b11111).eq(0)
  saturation_mask = image.select('QA_RADSAT').eq(0)

  # Apply the scaling factors to the appropriate bands.
  def _get_factor_img(factor_names):
    factor_list = image.toDictionary().select(factor_names).values()
    return ee.Image.constant(factor_list)

  scale_img = _get_factor_img([
      'REFLECTANCE_MULT_BAND_.|TEMPERATURE_MULT_BAND_ST_B10'])
  offset_img = _get_factor_img([
      'REFLECTANCE_ADD_BAND_.|TEMPERATURE_ADD_BAND_ST_B10'])
  scaled = image.select('SR_B.|ST_B10').multiply(scale_img).add(offset_img)

  # Replace original bands with scaled bands and apply masks.
  return image.addBands(scaled, None, True).updateMask(
      qa_mask).updateMask(saturation_mask)


# Make a cloud-free Landsat 8 surface reflectance composite.
l8_image = (
    ee.ImageCollection('LANDSAT/LC08/C02/T1_L2')
    .filterDate('2021-03-01', '2021-07-01')
    .map(prep_sr_l8)
    .median())

# Use these bands for prediction.
bands = ['SR_B2', 'SR_B3', 'SR_B4', 'SR_B5', 'SR_B6', 'SR_B7', 'ST_B10']

# Load training points. The numeric property 'class' stores known labels.
points = ee.FeatureCollection('GOOGLE/EE/DEMOS/demo_landcover_labels')

# This property stores the land cover labels as consecutive
# integers starting from zero.
label = 'landcover'

# Overlay the points on the imagery to get training.
training = l8_image.select(bands).sampleRegions(
    collection=points, properties=[label], scale=30
)

# Train a CART classifier with default parameters.
trained = ee.Classifier.smileCart().train(training, label, bands)

# Classify the image with the same bands used for training.
classified = l8_image.select(bands).classify(trained)

# Display the inputs and the results.
m = geemap.Map()
m.set_center(-122.0877, 37.7880, 11)
m.add_layer(
    l8_image,
    {'bands': ['SR_B4', 'SR_B3', 'SR_B2'], 'min': 0, 'max': 0.25},
    'image',
)
m.add_layer(
    classified,
    {'min': 0, 'max': 2, 'palette': ['orange', 'green', 'blue']},
    'classification',
)
m

في هذا المثال، تخزّن نقاط التدريب في الجدول تصنيف الفئة فقط. يُرجى العِلم أنّ سمة التدريب ('landcover') تخزّن أعدادًا صحيحة متتالية تبدأ من 0 (استخدِم remap() في جدولك لتحويل تصنيفات الفئات إلى أعداد صحيحة متتالية تبدأ من الصفر إذا لزم الأمر). لاحظ أيضًا استخدام image.sampleRegions() لإدخال المتنبئات في الجدول وإنشاء مجموعة بيانات تدريبية. لتدريب المصنِّف، حدِّد اسم سمة تصنيف الفئة وقائمة بالسمات في جدول التدريب التي يجب أن يستخدمها المصنِّف للمتنبّئات. يجب أن يتطابق عدد النطاقات وترتيبها في الصورة المطلوب تصنيفها تمامًا مع ترتيب قائمة السمات المقدَّمة إلى classifier.train(). استخدِم image.select() للتأكّد من تطابق مخطط المصنِّف مع الصورة.

إذا كانت بيانات التدريب عبارة عن مضلّعات تمثّل مناطق متجانسة، تكون كل بكسل في كل مضلّع نقطة تدريب. يمكنك استخدام المضلّعات للتدريب كما هو موضّح في المثال التالي:

أداة تعديل الرموز (JavaScript)

// 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 image = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2')
  .filterDate('2018-01-01', '2019-01-01')
  .map(prepSrL8)
  .median();

// Use these bands for prediction.
var bands = ['SR_B2', 'SR_B3', 'SR_B4', 'SR_B5',
             'SR_B6', 'SR_B7'];

// Manually created polygons.
var forest1 = ee.Geometry.Rectangle(-63.0187, -9.3958, -62.9793, -9.3443);
var forest2 = ee.Geometry.Rectangle(-62.8145, -9.206, -62.7688, -9.1735);
var nonForest1 = ee.Geometry.Rectangle(-62.8161, -9.5001, -62.7921, -9.4486);
var nonForest2 = ee.Geometry.Rectangle(-62.6788, -9.044, -62.6459, -8.9986);

// Make a FeatureCollection from the hand-made geometries.
var polygons = ee.FeatureCollection([
  ee.Feature(nonForest1, {'class': 0}),
  ee.Feature(nonForest2, {'class': 0}),
  ee.Feature(forest1, {'class': 1}),
  ee.Feature(forest2, {'class': 1}),
]);

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

// Create an SVM classifier with custom parameters.
var classifier = ee.Classifier.libsvm({
  kernelType: 'RBF',
  gamma: 0.5,
  cost: 10
});

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

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

// Display the classification result and the input image.
Map.setCenter(-62.836, -9.2399, 9);
Map.addLayer(image,
             {bands: ['SR_B4', 'SR_B3', 'SR_B2'], min: 0, max: 0.25},
             'image');
Map.addLayer(polygons, {color: 'yellow'}, 'training polygons');
Map.addLayer(classified,
             {min: 0, max: 1, palette: ['orange', 'green']},
             'deforestation');

إعداد Python

يمكنك الاطّلاع على صفحة بيئة Python للحصول على معلومات حول واجهة برمجة التطبيقات Python API واستخدام geemap للتطوير التفاعلي.

import ee
import geemap.core as geemap

Colab (Python)

# Define a function that scales and masks Landsat 8 surface reflectance images.
def prep_sr_l8(image):
  # Develop masks for unwanted pixels (fill, cloud, cloud shadow).
  qa_mask = image.select('QA_PIXEL').bitwiseAnd(0b11111).eq(0)
  saturation_mask = image.select('QA_RADSAT').eq(0)

  # Apply the scaling factors to the appropriate bands.
  def _get_factor_img(factor_names):
    factor_list = image.toDictionary().select(factor_names).values()
    return ee.Image.constant(factor_list)
  scale_img = _get_factor_img([
      'REFLECTANCE_MULT_BAND_.|TEMPERATURE_MULT_BAND_ST_B10'])
  offset_img = _get_factor_img([
      'REFLECTANCE_ADD_BAND_.|TEMPERATURE_ADD_BAND_ST_B10'])
  scaled = image.select('SR_B.|ST_B10').multiply(scale_img).add(offset_img)

  # Replace original bands with scaled bands and apply masks.
  return image.addBands(scaled, None, True).updateMask(
      qa_mask).updateMask(saturation_mask)


# Make a cloud-free Landsat 8 surface reflectance composite.
l8_image = (
    ee.ImageCollection('LANDSAT/LC08/C02/T1_L2')
    .filterDate('2018-01-01', '2019-01-01')
    .map(prep_sr_l8)
    .median())

# Use these bands for prediction.
bands = ['SR_B2', 'SR_B3', 'SR_B4', 'SR_B5', 'SR_B6', 'SR_B7']

# Manually created polygons.
forest1 = ee.Geometry.Rectangle(-63.0187, -9.3958, -62.9793, -9.3443)
forest2 = ee.Geometry.Rectangle(-62.8145, -9.206, -62.7688, -9.1735)
non_forest1 = ee.Geometry.Rectangle(-62.8161, -9.5001, -62.7921, -9.4486)
non_forest2 = ee.Geometry.Rectangle(-62.6788, -9.044, -62.6459, -8.9986)

# Make a FeatureCollection from the hand-made geometries.
polygons = ee.FeatureCollection([
    ee.Feature(non_forest1, {'class': 0}),
    ee.Feature(non_forest1, {'class': 0}),
    ee.Feature(forest1, {'class': 1}),
    ee.Feature(forest2, {'class': 1}),
])

# Get the values for all pixels in each polygon in the training.
training = l8_image.sampleRegions(
    # Get the sample from the polygons FeatureCollection.
    collection=polygons,
    # Keep this list of properties from the polygons.
    properties=['class'],
    # Set the scale to get Landsat pixels in the polygons.
    scale=30,
)

# Create an SVM classifier with custom parameters.
classifier = ee.Classifier.libsvm(kernelType='RBF', gamma=0.5, cost=10)

# Train the classifier.
trained = classifier.train(training, 'class', bands)

# Classify the image.
classified = l8_image.classify(trained)

# Display the classification result and the input image.
m = geemap.Map()
m.set_center(-62.836, -9.2399, 9)
m.add_layer(
    l8_image,
    {'bands': ['SR_B4', 'SR_B3', 'SR_B2'], 'min': 0, 'max': 0.25},
    'image',
)
m.add_layer(polygons, {'color': 'yellow'}, 'training polygons')
m.add_layer(
    classified,
    {'min': 0, 'max': 1, 'palette': ['orange', 'green']},
    'deforestation',
)
m

يستخدم هذا المثال مصنِّف آلة متجه الدعم (SVM) (Burges 1998). يُرجى العِلم أنّه يتم تحديد SVM باستخدام مجموعة من المَعلمات المخصّصة. بدون معلومات مسبقة عن الطبيعة المادية لمشكلة التوقّع، لا يمكن معرفة المَعلمات المثلى. يمكنك الاطّلاع على Hsu et al. (2003) للحصول على دليل تقريبي لاختيار مَعلمات لآلة المتجهات الداعمة.

أوضاع مخرجات المصنِّف

تتحكّم طريقة ee.Classifier.setOutputMode() في تنسيق نتائج التصنيف الخاضع للإشراف، ما يتيح تنظيم النتائج بعدة طرق مختلفة:

  • CLASSIFICATION (تلقائي): الناتج هو رقم الفئة.
  • ‫REGRESSION: الناتج هو نتيجة الانحدار العادي.
  • PROBABILITY: الناتج هو احتمالية أن يكون التصنيف صحيحًا.
  • ‫MULTIPROBABILITY: الناتج هو مصفوفة من الاحتمالات بأنّ كل فئة صحيحة، ويتم ترتيبها حسب الفئات التي تم رصدها.
  • ‫RAW: الناتج هو مصفوفة من التمثيل الداخلي لعملية التصنيف. على سبيل المثال، الأصوات الأولية في نماذج شجرة القرارات المتعددة.
  • ‫RAW_REGRESSION: الناتج هو مصفوفة من التمثيل الداخلي لعملية الانحدار. على سبيل المثال، التوقّعات الأولية لأشجار الانحدار المتعدّدة.

يختلف مدى توفّر أوضاع الإخراج هذه. يلخّص الجدول التالي الأوضاع المتوافقة لكل مصنِّف.

المصنِّف التصنيف الانحدار الاحتمالية MULTIPROBABILITY RAW RAW_REGRESSION
ee.Classifier.amnhMaxent
ee.Classifier.minimumDistance
ee.Classifier.smileCart
ee.Classifier.smileGradientTreeBoost
ee.Classifier.smileKNN
ee.Classifier.smileNaiveBayes
ee.Classifier.smileRandomForest
ee.Classifier.libsvm C_SVC
ee.Classifier.libsvm NU_SVC
ee.Classifier.libsvm ONE_CLASS
ee.Classifier.libsvm EPSILON_SVR
ee.Classifier.libsvm NU_SVR

استخدِم setOutputMode() قبل تدريب المصنِّف لتحديد تنسيق الناتج. على سبيل المثال، يمكنك ضبط مصنِّف SVM في مجموعة الرموز البرمجية السابقة لإخراج الاحتمالية بدلاً من تصنيفات الفئات التلقائية:

أداة تعديل الرموز (JavaScript)

var classifier = ee.Classifier.libsvm({
  kernelType: 'RBF',
  gamma: 0.5,
  cost: 10
}).setOutputMode('PROBABILITY');

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

إعداد Python

يمكنك الاطّلاع على صفحة بيئة Python للحصول على معلومات حول واجهة برمجة التطبيقات Python API واستخدام geemap للتطوير التفاعلي.

import ee
import geemap.core as geemap

Colab (Python)

classifier = ee.Classifier.libsvm(
    kernelType='RBF', gamma=0.5, cost=10
).setOutputMode('PROBABILITY')

trained = classifier.train(training, 'class', bands)

تقييم الدقة

لتقييم دقة المصنِّف، استخدِم ConfusionMatrix (Stehman 1997). يستخدم المثال التالي sample() لإنشاء بيانات التدريب والتحقّق من الصحة من صورة مرجعية من جهاز MODIS، ويقارن مصفوفات نجاح التوقعات التي تمثّل دقة التدريب والتحقّق من الصحة:

أداة تعديل الرموز (JavaScript)

// Define a region of interest.
var roi = ee.Geometry.BBox(-122.93, 36.99, -121.20, 38.16);

// 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 input = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2')
    .filterBounds(roi)
    .filterDate('2020-03-01', '2020-07-01')
    .map(prepSrL8)
    .median()
    .setDefaultProjection('EPSG:4326', null, 30)
    .select(['SR_B2', 'SR_B3', 'SR_B4', 'SR_B5', 'SR_B6', 'SR_B7']);

// Use MODIS land cover, IGBP classification, for training.
var modis = ee.Image('MODIS/061/MCD12Q1/2020_01_01')
    .select('LC_Type1');

// Sample the input imagery to get a FeatureCollection of training data.
var training = input.addBands(modis).sample({
  region: roi,
  numPixels: 5000,
  seed: 0
});

// Make a Random Forest classifier and train it.
var classifier = ee.Classifier.smileRandomForest(10)
    .train({
      features: training,
      classProperty: 'LC_Type1',
      inputProperties: ['SR_B2', 'SR_B3', 'SR_B4', 'SR_B5', 'SR_B6', 'SR_B7']
    });

// Classify the input imagery.
var classified = input.classify(classifier);

// Get a confusion matrix representing resubstitution accuracy.
var trainAccuracy = classifier.confusionMatrix();
print('Resubstitution error matrix: ', trainAccuracy);
print('Training overall accuracy: ', trainAccuracy.accuracy());

// Sample the input with a different random seed to get validation data.
var validation = input.addBands(modis).sample({
  region: roi,
  numPixels: 5000,
  seed: 1
  // Filter the result to get rid of any null pixels.
}).filter(ee.Filter.notNull(input.bandNames()));

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

// Get a confusion matrix representing expected accuracy.
var testAccuracy = validated.errorMatrix('LC_Type1', 'classification');
print('Validation error matrix: ', testAccuracy);
print('Validation overall accuracy: ', testAccuracy.accuracy());

// Define a palette for the IGBP classification.
var igbpPalette = [
  '152106', '225129', '369b47', '30eb5b', '387242', // forest
  '6a2325', 'c3aa69', 'b76031', 'd9903d', '91af40',  // shrub, grass
  '111149', // wetlands
  'cdb33b', // croplands
  'cc0013', // urban
  '33280d', // crop mosaic
  'd7cdcc', // snow and ice
  'f7e084', // barren
  'aec3d4'  // water
];

// Display the input and the classification.
Map.centerObject(roi, 10);
Map.addLayer(input.clip(roi),
             {bands: ['SR_B4', 'SR_B3', 'SR_B2'], min: 0, max: 0.25},
             'landsat');
Map.addLayer(classified.clip(roi),
             {palette: igbpPalette, min: 1, max: 17},
             'classification');

إعداد Python

يمكنك الاطّلاع على صفحة بيئة Python للحصول على معلومات حول واجهة برمجة التطبيقات Python API واستخدام geemap للتطوير التفاعلي.

import ee
import geemap.core as geemap

Colab (Python)

# Define a region of interest.
roi = ee.Geometry.BBox(-122.93, 36.99, -121.20, 38.16)

# Define a function that scales and masks Landsat 8 surface reflectance images.
def prep_sr_l8(image):
  """Scales and masks Landsat 8 surface reflectance images."""
  # Develop masks for unwanted pixels (fill, cloud, cloud shadow).
  qa_mask = image.select('QA_PIXEL').bitwiseAnd(0b1111).eq(0)
  saturation_mask = image.select('QA_RADSAT').eq(0)

  # Apply the scaling factors to the appropriate bands.
  def _get_factor_img(factor_names):
    factor_list = image.toDictionary().select(factor_names).values()
    return ee.Image.constant(factor_list)

  scale_img = _get_factor_img([
      'REFLECTANCE_MULT_BAND_.|TEMPERATURE_MULT_BAND_ST_B10'])
  offset_img = _get_factor_img([
      'REFLECTANCE_ADD_BAND_.|TEMPERATURE_ADD_BAND_ST_B10'])
  scaled = image.select('SR_B.|ST_B10').multiply(scale_img).add(offset_img)

  # Replace original bands with scaled bands and apply masks.
  return image.addBands(scaled, None, True).updateMask(
      qa_mask).updateMask(saturation_mask)


# Make a cloud-free Landsat 8 surface reflectance composite.
input_image = (
    ee.ImageCollection('LANDSAT/LC08/C02/T1_L2')
    .filterBounds(roi)
    .filterDate('2020-03-01', '2020-07-01')
    .map(prep_sr_l8)
    .median()
    .setDefaultProjection('EPSG:4326', None, 30)
    .select(['SR_B2', 'SR_B3', 'SR_B4', 'SR_B5', 'SR_B6', 'SR_B7'])
)

# Use MODIS land cover, IGBP classification, for training.
modis = ee.Image('MODIS/061/MCD12Q1/2020_01_01').select('LC_Type1')

# Sample the input imagery to get a FeatureCollection of training data.
training = input_image.addBands(modis).sample(
    region=roi, numPixels=5000, seed=0
)

# Make a Random Forest classifier and train it.
classifier = ee.Classifier.smileRandomForest(10).train(
    features=training,
    classProperty='LC_Type1',
    inputProperties=['SR_B2', 'SR_B3', 'SR_B4', 'SR_B5', 'SR_B6', 'SR_B7'],
)

# Classify the input imagery.
classified = input_image.classify(classifier)

# Get a confusion matrix representing resubstitution accuracy.
train_accuracy = classifier.confusionMatrix()
display('Resubstitution error matrix:', train_accuracy)
display('Training overall accuracy:', train_accuracy.accuracy())

# Sample the input with a different random seed to get validation data.
validation = (
    input_image.addBands(modis)
    .sample(
        region=roi,
        numPixels=5000,
        seed=1,
        # Filter the result to get rid of any null pixels.
    )
    .filter(ee.Filter.notNull(input_image.bandNames()))
)

# Classify the validation data.
validated = validation.classify(classifier)

# Get a confusion matrix representing expected accuracy.
test_accuracy = validated.errorMatrix('LC_Type1', 'classification')
display('Validation error matrix:', test_accuracy)
display('Validation overall accuracy:', test_accuracy.accuracy())

# Define a palette for the IGBP classification.
igbp_palette = [
    '152106', '225129', '369b47', '30eb5b', '387242',  # forest
    '6a2325', 'c3aa69', 'b76031', 'd9903d', '91af40',  # shrub, grass
    '111149',  # wetlands
    'cdb33b',  # croplands
    'cc0013',  # urban
    '33280d',  # crop mosaic
    'd7cdcc',  # snow and ice
    'f7e084',  # barren
    'aec3d4'   # water
]

# Display the input and the classification with geemap in a notebook.
m = geemap.Map()
m.center_object(roi, 10)
m.add_layer(
    input_image.clip(roi),
    {'bands': ['SR_B4', 'SR_B3', 'SR_B2'], 'min': 0, 'max': 0.25},
    'landsat',
)
m.add_layer(
    classified.clip(roi),
    {'palette': igbp_palette, 'min': 1, 'max': 17},
    'classification',
)
m

يستخدم هذا المثال مصنِّف الغابة العشوائية (Breiman 2001) مع 10 أشجار لتقليل دقة بيانات MODIS إلى دقة Landsat. تُنشئ الطريقة sample() عيّنتَين عشوائيتَين من بيانات MODIS: واحدة للتدريب والأخرى للتحقّق. يتم استخدام عيّنة التدريب لتدريب المصنِّف. يمكنك الحصول على دقة إعادة الاستبدال في بيانات التدريب من classifier.confusionMatrix(). للحصول على دقة التحقّق، صنِّف بيانات التحقّق. يؤدي ذلك إلى إضافة سمة classification إلى عملية التحقّق FeatureCollection. يمكنك استدعاء errorMatrix() على FeatureCollection المصنَّف للحصول على مصفوفة نجاح التوقعات التي تمثّل دقة التحقّق (المتوقّعة).

افحص الناتج للتأكّد من أنّ الدقة الإجمالية المقدَّرة من بيانات التدريب أعلى بكثير من بيانات التحقّق. الدقة المقدَّرة من بيانات التدريب هي تقدير مبالغ فيه لأنّ الغابة العشوائية "تتلاءم" مع بيانات التدريب. أما الدقة المتوقعة في البيانات غير المعروفة، فهي أقل، كما هو موضّح في التقدير من بيانات التحقّق.

يمكنك أيضًا أخذ عيّنة واحدة وتقسيمها باستخدام طريقة randomColumn() على مجموعات العناصر. لنتابع المثال السابق:

أداة تعديل الرموز (JavaScript)

var sample = input.addBands(modis).sample({
  region: roi,
  numPixels: 5000,
  seed: 0
});

// The randomColumn() method will add a column of uniform random
// numbers in a column named 'random' by default.
sample = sample.randomColumn();

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

إعداد Python

يمكنك الاطّلاع على صفحة بيئة Python للحصول على معلومات حول واجهة برمجة التطبيقات Python API واستخدام geemap للتطوير التفاعلي.

import ee
import geemap.core as geemap

Colab (Python)

sample = input_image.addBands(modis).sample(region=roi, numPixels=5000, seed=0)

# The randomColumn() method will add a column of uniform random
# numbers in a column named 'random' by default.
sample = sample.randomColumn()

split = 0.7  # Roughly 70% training, 30% testing.
training = sample.filter(ee.Filter.lt('random', split))
validation = sample.filter(ee.Filter.gte('random', split))

قد تحتاج أيضًا إلى التأكّد من عدم ارتباط عيّنات التدريب بعيّنات التقييم. قد ينتج ذلك عن الارتباط الذاتي المكاني للظاهرة التي يتم توقّعها. تتمثّل إحدى طرق استبعاد العيّنات التي قد تكون مرتبطة بهذه الطريقة في إزالة العيّنات التي تقع ضمن مسافة معيّنة من أي عيّنات أخرى. ويمكن تحقيق ذلك من خلال عملية دمج مكاني:

أداة تعديل الرموز (JavaScript)

// Sample the input imagery to get a FeatureCollection of training data.
var sample = input.addBands(modis).sample({
  region: roi,
  numPixels: 5000,
  seed: 0,
  geometries: true,
  tileScale: 16
});

// The randomColumn() method will add a column of uniform random
// numbers in a column named 'random' by default.
sample = sample.randomColumn();

var split = 0.7;  // Roughly 70% training, 30% testing.
var training = sample.filter(ee.Filter.lt('random', split));
print('Training size:', training.size());
var validation = sample.filter(ee.Filter.gte('random', split));

// Spatial join.
var distFilter = ee.Filter.withinDistance({
  distance: 1000,
  leftField: '.geo',
  rightField: '.geo',
  maxError: 10
});

var join = ee.Join.inverted();

// Apply the join.
training = join.apply(training, validation, distFilter);
print('Training size after spatial filtering:', training.size());

إعداد Python

يمكنك الاطّلاع على صفحة بيئة Python للحصول على معلومات حول واجهة برمجة التطبيقات Python API واستخدام geemap للتطوير التفاعلي.

import ee
import geemap.core as geemap

Colab (Python)

# Sample the input imagery to get a FeatureCollection of training data.
sample = input_image.addBands(modis).sample(
    region=roi, numPixels=5000, seed=0, geometries=True, tileScale=16
)

# The randomColumn() method will add a column of uniform random
# numbers in a column named 'random' by default.
sample = sample.randomColumn()

split = 0.7  # Roughly 70% training, 30% testing.
training = sample.filter(ee.Filter.lt('random', split))
display('Training size:', training.size())
validation = sample.filter(ee.Filter.gte('random', split))

# Spatial join.
dist_filter = ee.Filter.withinDistance(
    distance=1000, leftField='.geo', rightField='.geo', maxError=10
)

join = ee.Join.inverted()

# Apply the join.
training = join.apply(training, validation, dist_filter)
display('Training size after spatial filtering:', training.size())

في المقتطف السابق، يُرجى ملاحظة أنّه تم ضبط geometries على true في sample(). يتم ذلك للاحتفاظ بالمعلومات المكانية لنقاط العيّنات اللازمة لعملية الربط المكاني. يُرجى العِلم أيضًا أنّه تم ضبط السمة tileScale على 16. يساعد ذلك في تجنُّب ظهور الخطأ "تم تجاوز الحدّ الأقصى لذاكرة المستخدم".

جارٍ حفظ المصنِّفات

قد لا يكون من الممكن تدريب المصنِّف على كمية كبيرة من بيانات الإدخال بشكل تفاعلي لأنّ حجم الإدخال كبير جدًا (أكثر من 99 ميغابايت) أو لأنّ التدريب يستغرق وقتًا طويلاً (5 دقائق). استخدِم Export.classifier.toAsset لتشغيل تدريب المصنِّف كمهمة مجمّعة، حيث يمكن تشغيله لفترة أطول مع ذاكرة أكبر. يمكن تصدير المصنّفات التي يتطلّب تدريبها تكلفة عالية وإعادة تحميلها لتجنّب الحاجة إلى إعادة التدريب.

أداة تعديل الرموز (JavaScript)

// Using the random forest classifier defined earlier, export the random
// forest classifier as an Earth Engine asset.
var classifierAssetId = 'projects/<PROJECT-ID>/assets/upscaled_MCD12Q1_random_forest';
Export.classifier.toAsset(
  classifier,
  'Saved-random-forest-IGBP-classification',
  classifierAssetId
);

إعداد Python

يمكنك الاطّلاع على صفحة بيئة Python للحصول على معلومات حول واجهة برمجة التطبيقات Python API واستخدام geemap للتطوير التفاعلي.

import ee
import geemap.core as geemap

Colab (Python)

# Using the random forest classifier defined earlier, export the random
# forest classifier as an Earth Engine asset.
classifier_asset_id = (
    'projects/<PROJECT-ID>/assets/upscaled_MCD12Q1_random_forest'
)
task = ee.batch.Export.classifier.toAsset(
    classifier, 'Saved-random-forest-IGBP-classification', classifier_asset_id
)
task.start()

لتحميل المصنِّف المحفوظ، استخدِم الخوارزمية ee.Classifier.load()، وحدِّد رقم تعريف المصنِّف الذي تم تصديره واستخدِمه مثل أي مصنِّف مدرَّب آخر.

أداة تعديل الرموز (JavaScript)

// Once the classifier export finishes, we can load our saved classifier.
var savedClassifier = ee.Classifier.load(classifierAssetId);
// We can perform classification just as before with the saved classifier now.
var classified = input.classify(savedClassifier);
Map.addLayer(classified.clip(roi),
             {palette: igbpPalette, min: 1, max: 17},
             'classification');

إعداد Python

يمكنك الاطّلاع على صفحة بيئة Python للحصول على معلومات حول واجهة برمجة التطبيقات Python API واستخدام geemap للتطوير التفاعلي.

import ee
import geemap.core as geemap

Colab (Python)

# Once the classifier export finishes, we can load our saved classifier.
saved_classifier = ee.Classifier.load(classifier_asset_id)
# We can perform classification just as before with the saved classifier now.
classified = input_image.classify(saved_classifier)

m = geemap.Map()
m.center_object(roi, 10)
m.add_layer(
    classified.clip(roi),
    {'palette': igbp_palette, 'min': 1, 'max': 17},
    'classification',
)
m