แพ็กเกจ Classifier
จัดการการแยกประเภทที่มีการควบคุมดูแลโดยอัลกอริทึม ML แบบเดิมที่ทำงานใน Earth Engine โดยตัวแยกประเภทเหล่านี้ ได้แก่ CART, RandomForest,
NaiveBayes และ SVM เวิร์กโฟลว์ทั่วไปสำหรับการแยกประเภทมีดังนี้
- รวบรวมข้อมูลการฝึก รวบรวมฟีเจอร์ที่มีพร็อพเพอร์ตี้ที่จัดเก็บ ป้ายกำกับคลาสที่รู้จักและพร็อพเพอร์ตี้ที่จัดเก็บค่าตัวเลขสำหรับตัวทำนาย
- สร้างอินสแตนซ์ของตัวแยกประเภท ตั้งค่าพารามิเตอร์หากจำเป็น
- ฝึกตัวแยกประเภทโดยใช้ข้อมูลการฝึก
- จัดประเภทคอลเล็กชันรูปภาพหรือฟีเจอร์
- ประมาณข้อผิดพลาดในการแยกประเภทด้วยข้อมูลการตรวจสอบอิสระ
ข้อมูลการฝึกคือ FeatureCollection
ที่มีพร็อพเพอร์ตี้ที่จัดเก็บป้ายกำกับคลาส
และพร็อพเพอร์ตี้ที่จัดเก็บตัวแปรทำนาย ป้ายกำกับคลาสควรเป็นจำนวนเต็มที่ต่อเนื่องกัน
โดยเริ่มจาก 0 หากจำเป็น ให้ใช้ remap()
เพื่อแปลงค่าคลาส
เป็นจำนวนเต็มต่อเนื่อง ตัวทำนายควรเป็นตัวเลข
ข้อมูลการฝึกและ/หรือการตรวจสอบอาจมาจากแหล่งที่มาที่หลากหลาย หากต้องการรวบรวมข้อมูลการฝึกแบบอินเทอร์แอกทีฟใน Earth Engine คุณสามารถใช้เครื่องมือวาดรูปเรขาคณิต (ดูส่วนเครื่องมือเรขาคณิตของหน้า Code Editor)
หรือจะนำเข้าข้อมูลการฝึกที่กำหนดไว้ล่วงหน้าจากตารางของ Earth Engine ก็ได้ (ดูรายละเอียดในหน้านำเข้าข้อมูลตาราง) รับเครื่องมือคัดแยก
จากตัวสร้างอย่างใดอย่างหนึ่งใน ee.Classifier
ฝึกเครื่องมือ
จำแนกโดยใช้ classifier.train()
จัดประเภท Image
หรือ
FeatureCollection
โดยใช้ classify()
ตัวอย่างต่อไปนี้
ใช้เครื่องมือจัดประเภท Classification and Regression Trees (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');
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');
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 จะระบุด้วยชุดพารามิเตอร์ที่กำหนดเอง หากไม่มีข้อมูลa priori เกี่ยวกับลักษณะทางกายภาพของปัญหาการคาดการณ์ เราจะไม่ทราบพารามิเตอร์ที่เหมาะสม ดูคำแนะนำคร่าวๆ ในการเลือกพารามิเตอร์สำหรับ SVM ได้ที่ Hsu et al. (2003)
โหมดเอาต์พุตของตัวแยกประเภท
วิธี
ee.Classifier.setOutputMode()
จะควบคุมรูปแบบของผลลัพธ์การจัดประเภทภายใต้การควบคุมดูแล
ซึ่งช่วยให้จัดโครงสร้างเอาต์พุตได้หลายวิธีที่แตกต่างกัน ดังนี้
- การจัดประเภท (ค่าเริ่มต้น): เอาต์พุตคือหมายเลขคลาส
- การถดถอย: เอาต์พุตคือผลลัพธ์ของการถดถอยมาตรฐาน
- 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);
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');
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
ตัวอย่างนี้ใช้ตัวแยกประเภทแบบสุ่ม
(Breiman 2001)
ที่มี 10 ต้นไม้เพื่อลดขนาดข้อมูล MODIS ให้มีความละเอียดเท่ากับ Landsat
sample()
วิธีนี้จะสร้างตัวอย่างแบบสุ่ม 2 รายการจากข้อมูล 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));
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());
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 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 );
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');
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