แพ็กเกจ Classifier
จะจัดการการจำแนกที่มีการควบคุมดูแลโดยอัลกอริทึม ML แบบดั้งเดิมที่ทำงานใน Earth Engine ซึ่งได้แก่ CART, RandomForest, NaiveBayes และ SVM เวิร์กโฟลว์ทั่วไปสำหรับการแยกประเภทมีดังนี้
- รวบรวมข้อมูลการฝึก รวบรวมฟีเจอร์ที่มีพร็อพเพอร์ตี้ที่จัดเก็บป้ายกำกับคลาสที่รู้จักและพร็อพเพอร์ตี้ที่จัดเก็บค่าตัวเลขสำหรับตัวทำนาย
- สร้างอินสแตนซ์ตัวจัดประเภท ตั้งค่าพารามิเตอร์ หากจําเป็น
- ฝึกตัวแยกประเภทโดยใช้ข้อมูลการฝึก
- จัดประเภทรูปภาพหรือคอลเล็กชันองค์ประกอบ
- ประมาณข้อผิดพลาดในการแยกประเภทด้วยข้อมูลการตรวจสอบอิสระ
ข้อมูลการฝึกคือ 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');
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 ได้รับการระบุด้วยชุดพารามิเตอร์ที่กําหนดเอง หากไม่มีข้อมูลเบื้องต้นเกี่ยวกับลักษณะทางกายภาพของปัญหาการคาดการณ์ ก็จะไม่ทราบพารามิเตอร์ที่ดีที่สุด ดูคำแนะนำคร่าวๆ ในการเลือกใช้พารามิเตอร์สำหรับ 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);
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
ตัวอย่างนี้ใช้ตัวแยกประเภทแบบ 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));
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
การดำเนินการนี้เพื่อหลีกเลี่ยงข้อผิดพลาด "เกินขีดจำกัดหน่วยความจำของผู้ใช้"
บันทึกตัวแยกประเภท
การฝึก 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 );
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