การจัดประเภทที่มีการควบคุมดูแล

แพ็กเกจ Classifier จะจัดการการจำแนกที่มีการควบคุมดูแลโดยอัลกอริทึม ML แบบดั้งเดิมที่ทำงานใน 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) เพื่อคาดการณ์คลาสง่ายๆ 3 คลาส ดังนี้

เครื่องมือแก้ไขโค้ด (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 API และการใช้ geemap สําหรับการพัฒนาแบบอินเทอร์แอกทีฟได้ที่หน้า สภาพแวดล้อม Python

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() ในตารางเพื่อเปลี่ยนป้ายกำกับชั้นเรียนเป็นจำนวนเต็มแบบต่อเนื่องที่เริ่มต้นที่ 0 หากจําเป็น) และโปรดสังเกตการใช้ 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 API และการใช้ geemap สําหรับการพัฒนาแบบอินเทอร์แอกทีฟได้ที่หน้า สภาพแวดล้อม Python

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

ตัวอย่างนี้ใช้ตัวแยกประเภท Support Vector Machine (SVM) (Burges 1998) โปรดทราบว่า SVM ได้รับการระบุด้วยชุดพารามิเตอร์ที่กําหนดเอง หากไม่มีข้อมูลเบื้องต้นเกี่ยวกับลักษณะทางกายภาพของปัญหาการคาดการณ์ ก็จะไม่ทราบพารามิเตอร์ที่ดีที่สุด ดูคำแนะนำคร่าวๆ ในการเลือกใช้พารามิเตอร์สำหรับ SVM ได้ที่ Hsu et al. (2003)

โหมดเอาต์พุตของคลาสซิไฟเออร์

เมธอด ee.Classifier.setOutputMode() จะควบคุมรูปแบบของผลการแยกประเภทที่มีการควบคุม ซึ่งช่วยให้เอาต์พุตมีโครงสร้างได้หลายวิธีที่แตกต่างกัน ดังนี้

  • การจัดประเภท (ค่าเริ่มต้น): เอาต์พุตคือหมายเลขชั้น
  • REGRESSION: เอาต์พุตคือผลลัพธ์ของการถดถอยมาตรฐาน
  • ความน่าจะเป็น: เอาต์พุตคือความน่าจะเป็นที่การจัดประเภทจะถูกต้อง
  • MULTIPROBABILITY: เอาต์พุตคืออาร์เรย์ของความน่าจะเป็นที่แต่ละคลาสถูกต้อง โดยจัดเรียงตามคลาสที่พบ
  • RAW: เอาต์พุตคืออาร์เรย์ของการแสดงข้อมูลภายในของกระบวนการจัดประเภท เช่น คะแนนดิบในโมเดลต้นไม้การตัดสินใจหลายรายการ
  • RAW_REGRESSION: ผลลัพธ์คืออาร์เรย์ของการแสดงข้อมูลภายในของกระบวนการหาค่าประมาณเชิงเส้น เช่น การคาดการณ์ดิบของต้นไม้การถดถอยหลายรายการ

การรองรับโหมดเอาต์พุตเหล่านี้จะแตกต่างกันไป ตารางต่อไปนี้สรุปโหมดที่รองรับสำหรับตัวจัดประเภทแต่ละรายการ

ตัวแยกประเภท การจัดประเภท การถดถอย PROBABILITY 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 API และการใช้ geemap สําหรับการพัฒนาแบบอินเทอร์แอกทีฟได้ที่หน้า สภาพแวดล้อม Python

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/006/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 = [
  'aec3d4', // water
  '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
  '6f6f6f'  // tundra
];

// 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: 0, max: 17},
             'classification');

การตั้งค่า Python

ดูข้อมูลเกี่ยวกับ Python API และการใช้ geemap สําหรับการพัฒนาแบบอินเทอร์แอกทีฟได้ที่หน้า สภาพแวดล้อม Python

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/006/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 = [
    'aec3d4',  # water
    '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
    '6f6f6f'   # tundra
]

# 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': 0, 'max': 17},
    'classification',
)
m

ตัวอย่างนี้ใช้ตัวแยกประเภทแบบ Random Forest (Breiman 2001) ที่มีต้นไม้ 10 ต้นเพื่อลดขนาดข้อมูล MODIS ให้เป็นความละเอียดระดับ Landsat เมธอด sample() จะสร้างตัวอย่างแบบสุ่ม 2 รายการจากข้อมูล MODIS โดย 1 รายการสําหรับการฝึกและอีก 1 รายการสําหรับการตรวจสอบ ระบบจะใช้ตัวอย่างการฝึกเพื่อฝึกตัวแยกประเภท คุณดูความแม่นยําของการแทนที่ใหม่ในข้อมูลการฝึกได้จาก classifier.confusionMatrix() จัดประเภทข้อมูลการตรวจสอบเพื่อให้การตรวจสอบแม่นยำ ซึ่งจะเพิ่มพร็อพเพอร์ตี้ classification ลงในการตรวจสอบ FeatureCollection เรียกใช้ errorMatrix() ใน FeatureCollection ที่แยกประเภทแล้วเพื่อดูเมทริกซ์ความสับสนที่แสดงถึงการตรวจสอบ (ความคาดหวัง) ที่แม่นยำ

ตรวจสอบเอาต์พุตเพื่อให้แน่ใจว่าความแม่นยำโดยรวมที่ประมาณจากข้อมูลการฝึกอบรมสูงกว่าข้อมูลที่ใช้ตรวจสอบมาก ความแม่นยำที่ประมาณจากข้อมูลการฝึกจะประเมินสูงกว่าความเป็นจริง เนื่องจาก Random Forest "พอดี" กับข้อมูลการฝึก ความแม่นยำที่คาดไว้ของข้อมูลที่ไม่รู้จักจะต่ำกว่า ตามที่ระบุโดยค่าประมาณจากข้อมูลการยืนยัน

นอกจากนี้ คุณยังสุ่มตัวอย่างรายการเดียวแล้วแบ่งพาร์ติชันด้วยวิธี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 API และการใช้ geemap สําหรับการพัฒนาแบบอินเทอร์แอกทีฟได้ที่หน้า สภาพแวดล้อม Python

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 API และการใช้ geemap สําหรับการพัฒนาแบบอินเทอร์แอกทีฟได้ที่หน้า สภาพแวดล้อม Python

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 การดำเนินการนี้เพื่อหลีกเลี่ยงข้อผิดพลาด "เกินขีดจำกัดหน่วยความจำของผู้ใช้"

บันทึกตัวแยกประเภท

การฝึก Classfier ด้วยข้อมูลอินพุตจํานวนมากอาจทําแบบอินเทอร์แอกทีฟไม่ได้เนื่องจากอินพุตมีขนาดใหญ่เกินไป (>99 MB) หรือการฝึกใช้เวลานานเกินไป (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 API และการใช้ geemap สําหรับการพัฒนาแบบอินเทอร์แอกทีฟได้ที่หน้า สภาพแวดล้อม Python

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: 0, max: 17},
             'classification');

การตั้งค่า Python

ดูข้อมูลเกี่ยวกับ Python API และการใช้ geemap สําหรับการพัฒนาแบบอินเทอร์แอกทีฟได้ที่หน้า สภาพแวดล้อม Python

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': 0, 'max': 17},
    'classification',
)
m