GEE | 使用CART、RF、SVM进行分类并统计分类结果

文摘   2024-07-31 10:40   中国  

LXX

读完需要

3
分钟

速读仅需 1 分钟

前言:

分类是地学和环境科学领域中的一个重要任务,它有助于我们理解和监测各类地物,如农业、林业、城市发展等方面。本文分享三种分类方法并对分类后的结果进行统计。


希望各位同学点个关注,点个小赞,这将是更新的动力,不胜感激❥(^_-)


1

   

分类方法

1.1

   

决策树分类

CART 是一种决策树算法,可以用于分类和回归任务。CART 分类树的基本思想是通过递归地分割数据集,直到满足某些终止条件为止。具体包括:

(1)树的构建:

从根节点开始,选择一个特征及其分割点,将数据集分成两个子集。分割点的选择基于某种准则,如基尼指数(Gini Index)或信息增益(Information Gain),以最大化子集的纯度。对每个子集重复上述步骤,继续分割,直到达到停止条件,如最小节点大小或最大树深度。

(2)基尼指数:

基尼指数用于衡量节点的纯度,公式如下:

    其中pip_ipi 是类别iii 的概率。分割点选择基于最小化基尼指数的增益。

(3)树的剪枝:

构建完树后,可能会产生过拟合,需要对树进行剪枝。剪枝通过删除某些不重要的节点,减少树的复杂度,提高模型的泛化能力。常见的剪枝方法包括预剪枝(pre-pruning)和后剪枝(post-pruning)。

(4)预测:

对于新的样本,从根节点开始,依次根据样本的特征值进行决策,直到到达叶节点。叶节点的类别标签作为最终的预测结果。

1.2

   

随机森林分类

随机森林(Random Forest)是一种集成学习方法,通过构建多个决策树并结合其预测结果来进行分类。具体包括:

(1)样本和特征随机化:

每棵树使用不同的训练样本,通过自助法(bootstrap)从原始数据集中有放回地抽样。在每个节点的分割过程中,随机选择特征的子集,以增加模型的多样性。

(2)树的构建:

构建每棵树时,使用与 CART 类似的方法,递归地分割数据集。不同于单一决策树,随机森林在每个节点上只考虑随机选择的特征子集。

(3)预测:

对于新的样本,随机森林中的每棵树都会给出一个预测结果。最终的预测结果通过所有树的投票(分类任务)或平均值(回归任务)来确定。优势:

通过集成多个模型,随机森林能够降低单一决策树的过拟合风险,提高预测的准确性和鲁棒性。它还提供了特征重要性评估的能力,帮助识别对预测最重要的特征。

1.3

   

支持向量机分类

支持向量机(Support Vector Machine,SVM)是一种常用的机器学习算法,主要用于分类和回归问题。SVM 的目标是找到一个最优的超平面,将不同类别的样本点分隔开来,使得两个类别的间隔最大化。具体来说,SVM 通过寻找支持向量(即距离超平面最近的样本点),确定决策边界,并根据支持向量的位置进行分类。

具体包括:数据准备,收集并准备用于训练的数据集,确保数据集包含标记好的样本点。特征选择,根据问题的特点选择合适的特征,并对特征进行预处理(如归一化、标准化等)。模型训练,利用训练数据集,通过优化算法找到最优的超平面,使得间隔最大化。模型评估,使用测试数据集评估模型的性能,通常使用准确率、精确率、召回率等指标进行评估。模型调优,根据评估结果,调整模型参数或选择合适的核函数,以提高模型的性能。模型应用,使用训练好的模型对新样本进行分类或回归预测。

2

   

实现代码

// 加载数据var forest = ee.Image("users/geestudy2/forest");Map.centerObject(forest, 20);
// 计算植被指数并将其作为新波段添加到图像中var NDVI = forest.normalizedDifference(['b4', 'b1']).rename('NDVI');var ReCI = forest.expression('(NIR / RED) - 1', { 'NIR': forest.select('b4'), 'RED': forest.select('b1')}).rename('ReCI');var NDRE = forest.normalizedDifference(['b4', 'b5']).rename('NDRE');var MSAVI = forest.expression( '(2 * NIR + 1 - sqrt((2 * NIR + 1) ** 2 - 8 * (NIR - RED))) / 2', { 'NIR': forest.select('b4'), 'RED': forest.select('b1') }).rename('MSAVI');var GNDVI = forest.normalizedDifference(['b4', 'b2']).rename('GNDVI');var SIPI = forest.expression( '(NIR - BLUE) / (NIR - RED)', { 'NIR': forest.select('b4'), 'BLUE': forest.select('b3'), 'RED': forest.select('b1') }).rename('SIPI');
// 创建用于分类的波段栈var stack = forest.addBands([NDVI, ReCI, NDRE, MSAVI, GNDVI, SIPI]);
// 定义可视化的颜色调色板var palette = ['blue', 'white', 'green', 'red', 'yellow', 'purple'];
// 显示RGB复合图像和指数Map.addLayer(forest.select(['b1', 'b2', 'b3']), {min: 0, max: 0.3}, 'RGB');var indicesLayers = { 'NDVI': NDVI, 'ReCI': ReCI, 'NDRE': NDRE, 'MSAVI': MSAVI, 'GNDVI': GNDVI, 'SIPI': SIPI};for (var index in indicesLayers) { Map.addLayer(indicesLayers[index], {min: -1, max: 1, palette: palette}, index);}
// 合并不同土地覆盖类型的样本点到一个 FeatureCollectionvar samplePoints = Road.merge(Land).merge(Good_Forest) .merge(Bad_Forest).merge(Glass).merge(Other);
// 将 'landcover' 从字符串转换为整数var convertedSamplePoints = samplePoints.map(function(feature) { // 获取 landcover 值 var landcover = feature.get('landcover'); // 检查 landcover 是否为非空字符串;如果不是,则设置为默认值(例如 null) var landcoverNumber = ee.Algorithms.If( ee.String(landcover).trim().length().gt(0), ee.Number.parse(landcover), null // 如果无效,则设置为 null ); return feature.set('landcover', landcoverNumber);});
// 在采样前过滤掉无效(null)的 landcover 值var filteredSamplePoints = convertedSamplePoints.filter(ee.Filter.notNull(['landcover']));
// 使用过滤后的样本点对波段栈进行采样var trainingRegions = stack.sampleRegions({ collection: filteredSamplePoints, properties: ['landcover'],});
// 随机化集合并分割为训练和验证数据集trainingRegions = trainingRegions.randomColumn();var training = trainingRegions.filter(ee.Filter.lt('random', 0.7));var validation = trainingRegions.filter(ee.Filter.gte('random', 0.7));
// 训练 CART、随机森林和 SVM 分类器var cartClassifier = ee.Classifier.smileCart().train({ features: training, classProperty: 'landcover', inputProperties: stack.bandNames()});var rfClassifier = ee.Classifier.smileRandomForest(40).train({ features: training, classProperty: 'landcover', inputProperties: stack.bandNames()});var svmClassifier = ee.Classifier.libsvm({ kernelType: 'RBF', gamma: 0.5, cost: 10}).train({ features: training, classProperty: 'landcover', inputProperties: stack.bandNames()});
// 使用训练好的分类器进行分类var classifiedCart = stack.classify(cartClassifier);var classifiedRf = stack.classify(rfClassifier);var classifiedSvm = stack.classify(svmClassifier);
// 评估每个分类器的准确性var validationClassifiedCart = validation.classify(cartClassifier);var cartConfusionMatrix = validationClassifiedCart.errorMatrix('landcover', 'classification');var cartAccuracy = cartConfusionMatrix.accuracy();var validationClassifiedRF = validation.classify(rfClassifier);var rfConfusionMatrix = validationClassifiedRF.errorMatrix('landcover', 'classification');var rfAccuracy = rfConfusionMatrix.accuracy();var validationClassifiedSVM = validation.classify(svmClassifier);var svmConfusionMatrix = validationClassifiedSVM.errorMatrix('landcover', 'classification');var svmAccuracy = svmConfusionMatrix.accuracy();var cartKappa = cartConfusionMatrix.kappa();var rfKappa = rfConfusionMatrix.kappa();var svmKappa = svmConfusionMatrix.kappa();// 打印 CART 分类器的准确性和 Kappa 系数print('CART 混淆矩阵:', cartConfusionMatrix);print('CART 准确性:', cartAccuracy);print('CART Kappa 系数:', cartKappa);
print('随机森林 混淆矩阵:', rfConfusionMatrix);print('随机森林 准确性:', rfAccuracy);print('随机森林 Kappa 系数:', rfKappa);
print('SVM 混淆矩阵:', svmConfusionMatrix);print('SVM 准确性:', svmAccuracy);print('SVM Kappa 系数:', svmKappa);
// 显示分类结果Map.addLayer(classifiedCart, {min: 0, max: 5, palette: palette}, 'CART 分类结果');Map.addLayer(classifiedRf, {min: 0, max: 5, palette: palette}, '随机森林 分类结果');Map.addLayer(classifiedSvm, {min: 0, max: 5, palette: palette}, 'SVM 分类结果');print(classifiedSvm);
// 将地图缩放到森林对象Map.centerObject(forest, 10);// 导出 CART 分类结果Export.image.toDrive({ image: classifiedCart, description: 'CART_Classification', scale: forest.projection().nominalScale(), // 假设 forest 是原始图像 region: forest.geometry(), maxPixels: 1e13});
// 类似地导出随机森林和 SVM 分类结果
// 计算面积并绘制图表// 计算每个像素的面积var classNames = ['Road', 'Land', 'Good_Forest', 'Bad_Forest', 'Glass', 'Other'];var pixelArea = ee.Image.pixelArea();
// 计算每个类别的面积var classValues = ee.List.sequence(0, 5); // 创建一个从 0 到 5 的列表,对应各个类别var classAreas = ee.List(classValues.map(function(classValue) { classValue = ee.Number(classValue); // 将类别值转换为数字 var masked = pixelArea.updateMask(classifiedSvm.eq(classValue)); // 将图像遮罩为该类别 return masked.reduceRegion({ reducer: ee.Reducer.sum(), geometry: forest.geometry(), scale: forest.projection().nominalScale(), // 假设 forest 是原始图像 maxPixels: 1e9 }).getNumber('area');}));
// 将面积结果转换为 FeatureCollection 用于图表var areasList = classAreas.zip(classNames).map(function(info) { var infoList = ee.List(info); var area = ee.Number(infoList.get(0)); var label = ee.String(infoList.get(1)); return ee.Feature(null, {'label': label, 'area': area});});
// 转换为 FeatureCollectionvar chartFeatures = ee.FeatureCollection(areasList);
// 创建图表// 现在这个图表会使用从 classifiedSvm 自动计算得到的面积数据
// 创建条形图var barChart = ui.Chart.feature.byFeature(chartFeatures, 'label', 'area') .setChartType('ColumnChart') .setOptions({ title: '各类别面积', hAxis: {title: '类别'}, vAxis: {title: '面积(平方米)'}, legend: {position: 'none'}, bar: {groupWidth: '60%'} });
// 创建饼状图var pieChart = ui.Chart.feature.byFeature(chartFeatures, 'label', 'area') .setChartType('PieChart') .setOptions({ title: '各类别面积比例', sliceVisibilityThreshold: 0 // 显示所有类别,即使面积非常小 });
// 显示图表print(barChart);print(pieChart);

3

   

结果




后续开始补之前留下的ICESat-2水深反演......

遥感小屋
分享遥感相关文章、代码,大家一起交流,互帮互助
 最新文章