sklearn.metrics 实战:遥感影像分类 5 大指标混淆矩阵一键计算与可视化
遥感影像分类评估全流程从混淆矩阵到Kappa系数的Python实战指南当你在深夜盯着屏幕上的遥感影像分类结果时是否曾困惑于如何全面评估模型表现那些闪烁的像素背后隐藏着怎样的精度故事本文将带你用Python的sklearn.metrics模块揭开遥感影像分类评估的神秘面纱。1. 环境准备与数据加载首先确保你的Python环境已安装以下库pip install numpy scikit-learn matplotlib seaborn pandas假设我们有一组遥感影像的真实标签和预测结果这里用NumPy数组模拟一个多分类场景import numpy as np from sklearn.metrics import confusion_matrix, classification_report from sklearn.metrics import cohen_kappa_score, accuracy_score # 模拟数据6类地物分类结果 y_true np.array([2, 0, 2, 2, 0, 1, 3, 4, 5, 1, 0, 2]) y_pred np.array([1, 0, 2, 1, 0, 2, 3, 3, 5, 1, 1, 2]) class_names [水体, 林地, 耕地, 建筑, 道路, 裸地]2. 核心指标计算与解读2.1 混淆矩阵分类结果的显微镜混淆矩阵是理解模型表现的基础工具它能直观展示各类别的分类情况def plot_confusion_matrix(cm, classes): import seaborn as sns import matplotlib.pyplot as plt plt.figure(figsize(10,8)) sns.heatmap(cm, annotTrue, fmtd, xticklabelsclasses, yticklabelsclasses) plt.ylabel(真实标签) plt.xlabel(预测标签) plt.title(混淆矩阵热力图) plt.show() cm confusion_matrix(y_true, y_pred) plot_confusion_matrix(cm, class_names)混淆矩阵对角线表示正确分类的样本数其他位置则显示误分类情况。例如第一行第二列的数字表示实际为水体但被误判为林地的样本数。2.2 精确率、召回率与F1分数这三个指标提供了更细致的分类性能评估from sklearn.metrics import precision_score, recall_score, f1_score # 宏平均各类别平等权重 precision precision_score(y_true, y_pred, averagemacro) recall recall_score(y_true, y_pred, averagemacro) f1 f1_score(y_true, y_pred, averagemacro) print(f宏平均精确率: {precision:.3f}) print(f宏平均召回率: {recall:.3f}) print(f宏平均F1分数: {f1:.3f}) # 获取各类别的详细指标 report classification_report(y_true, y_pred, target_namesclass_names) print(report)指标解读精确率预测为某类的样本中确实属于该类的比例查得准召回率实际为某类的样本中被正确预测的比例查得全F1分数精确率和召回率的调和平均数综合衡量模型表现2.3 Kappa系数超越随机猜测的精度Kappa系数衡量分类结果与随机分类的一致性差异kappa cohen_kappa_score(y_true, y_pred) print(fKappa系数: {kappa:.3f}) # Kappa系数解读指南 kappa_ranges { 极低一致性: (0.0, 0.2), 一般一致性: (0.2, 0.4), 中等一致性: (0.4, 0.6), 高度一致性: (0.6, 0.8), 极强一致性: (0.8, 1.0) }Kappa值在0-1之间值越大表示分类结果越可靠。通常认为0.4一致性较差0.4-0.75中等至良好一致性0.75优秀一致性2.4 总体精度与类别平衡考量总体精度是最直观的评估指标oa accuracy_score(y_true, y_pred) print(f总体精度: {oa:.3f})但需注意当类别不平衡时总体精度可能产生误导。例如若90%的影像是水体一个总是预测水体的模型也能达到90%的总体精度这显然不合理。3. 高级评估技巧3.1 多指标综合评估函数将常用评估指标封装成函数方便重复使用def evaluate_classification(y_true, y_pred, class_names): 一站式分类评估函数 from collections import OrderedDict metrics OrderedDict() # 基础指标 metrics[总体精度] accuracy_score(y_true, y_pred) metrics[Kappa系数] cohen_kappa_score(y_true, y_pred) # 分类报告 report classification_report(y_true, y_pred, target_namesclass_names, output_dictTrue) # 按类别整理指标 class_metrics {} for i, name in enumerate(class_names): class_metrics[name] { 精确率: report[name][precision], 召回率: report[name][recall], F1分数: report[name][f1-score], 支持数: report[name][support] } # 宏平均 metrics[宏平均精确率] report[macro avg][precision] metrics[宏平均召回率] report[macro avg][recall] metrics[宏平均F1] report[macro avg][f1-score] # 加权平均 metrics[加权平均精确率] report[weighted avg][precision] metrics[加权平均召回率] report[weighted avg][recall] metrics[加权平均F1] report[weighted avg][f1-score] return metrics, class_metrics metrics, class_metrics evaluate_classification(y_true, y_pred, class_names)3.2 可视化分析工具创建雷达图直观比较各类别表现def plot_class_performance(metrics, class_names): import matplotlib.pyplot as plt from math import pi # 准备数据 categories [精确率, 召回率, F1分数] N len(categories) angles [n / float(N) * 2 * pi for n in range(N)] angles angles[:1] plt.figure(figsize(8, 8)) ax plt.subplot(111, polarTrue) ax.set_theta_offset(pi / 2) ax.set_theta_direction(-1) plt.xticks(angles[:-1], categories) ax.set_rlabel_position(0) plt.yticks([0.25, 0.5, 0.75, 1], [0.25, 0.5, 0.75, 1.0], colorgrey, size7) plt.ylim(0, 1) # 绘制每个类别的数据 for name in class_names: values [ class_metrics[name][精确率], class_metrics[name][召回率], class_metrics[name][F1分数] ] values values[:1] ax.plot(angles, values, linewidth1, linestylesolid, labelname) ax.fill(angles, values, alpha0.1) plt.legend(locupper right, bbox_to_anchor(1.3, 1.1)) plt.title(各类别性能比较雷达图) plt.show() plot_class_performance(metrics, class_names)4. 实战案例完整评估流程让我们模拟一个更真实的遥感分类评估场景# 生成更大规模的模拟数据 np.random.seed(42) num_samples 1000 y_true np.random.randint(0, 6, sizenum_samples) # 模拟有偏见的预测某些类别更容易混淆 bias_matrix np.array([ [0.7, 0.1, 0.05, 0.05, 0.05, 0.05], # 水体 [0.1, 0.6, 0.1, 0.1, 0.05, 0.05], # 林地 [0.05, 0.1, 0.65, 0.1, 0.05, 0.05], # 耕地 [0.03, 0.07, 0.1, 0.7, 0.05, 0.05], # 建筑 [0.05, 0.05, 0.1, 0.1, 0.6, 0.1], # 道路 [0.05, 0.05, 0.1, 0.1, 0.1, 0.6] # 裸地 ]) y_pred np.array([np.random.choice(6, pbias_matrix[i]) for i in y_true]) # 完整评估 metrics, class_metrics evaluate_classification(y_true, y_pred, class_names) # 打印关键指标 print(\n关键评估指标) print(-*40) print(f总体精度: {metrics[总体精度]:.3f}) print(fKappa系数: {metrics[Kappa系数]:.3f}) print(f宏平均F1: {metrics[宏平均F1]:.3f}) print(-*40) # 可视化 plot_confusion_matrix(confusion_matrix(y_true, y_pred), class_names) plot_class_performance(metrics, class_names)在这个案例中我们模拟了1000个样本的遥感分类结果设置了类别间的混淆概率如林地有10%概率被误判为耕地执行了完整的评估流程生成了可视化图表帮助分析5. 评估结果解读与模型优化建议通过上述分析你可能会发现混淆矩阵揭示了特定类别间的混淆模式如建筑与道路容易相互误判雷达图显示了某些类别如裸地的召回率明显低于其他指标Kappa系数帮助判断模型是否显著优于随机猜测基于这些发现可以采取以下优化措施对于相互混淆的类别考虑增加训练样本引入更多区分性特征调整分类阈值对于表现较差的类别检查样本数量是否充足特征提取是否有效是否存在标注噪声# 示例计算各类别样本分布 import pandas as pd class_dist pd.Series(y_true).value_counts().sort_index() class_dist.index class_names print(\n类别分布情况) print(class_dist)类别不平衡是遥感分类常见问题。如果发现某些类别样本过少可以考虑过采样、欠采样或使用类别权重调整方法# 在模型训练中设置类别权重 from sklearn.linear_model import LogisticRegression # 计算类别权重 class_weights {i: len(y_true)/sum(y_truei) for i in range(len(class_names))} model LogisticRegression(class_weightclass_weights, max_iter1000) # 后续训练流程...