MogFace-large模型效果可视化:使用Matplotlib绘制PR曲线与混淆矩阵

发布时间:2026/5/20 20:51:33

MogFace-large模型效果可视化:使用Matplotlib绘制PR曲线与混淆矩阵 MogFace-large模型效果可视化使用Matplotlib绘制PR曲线与混淆矩阵评估一个目标检测模型的好坏不能只看几个冷冰冰的数字。那些精确率、召回率、mAP的数值对于非专业人士来说理解起来有点门槛。我们更想知道的是模型到底“看”得有多准它容易把什么认错在什么情况下会失效今天我就带你一起用Python里最常用的绘图库Matplotlib把MogFace-large这个人脸检测模型的评估结果“画”出来。我们会画出专业的PR曲线、一目了然的混淆矩阵还有能反映检测框质量的IoU分布图。整个过程就像给模型做一次全面的“体检报告”所有指标都变得直观可见。你不需要是数据可视化专家跟着步骤走就能得到一套可以直接用在论文、报告或者技术博客里的专业图表。让我们开始吧。1. 准备工作与环境搭建在开始画图之前我们得先把“画布”和“颜料”准备好。这里主要就是安装必要的Python库并准备好模型评估后产生的数据。1.1 安装必要的Python库我们需要的库不多基本都是科学计算和可视化的标配。打开你的终端或命令提示符执行下面的安装命令。如果你用的是Anaconda也可以在conda环境中安装。pip install matplotlib numpy scikit-learn简单解释一下这几个库Matplotlib 这次的主角Python里最经典、功能最全的绘图库。我们所有的图表都将由它生成。NumPy Python科学计算的基础用来处理我们的评估数据数组、矩阵运算都靠它。scikit-learn 机器学习常用库这里我们主要用它来快速计算PR曲线所需的数据点。安装过程通常很快如果遇到网络问题可以考虑使用国内的镜像源比如在命令后面加上-i https://pypi.tuna.tsinghua.edu.cn/simple。1.2 理解我们的数据模型评估结果画图得有数据。假设我们已经用MogFace-large模型在一个人脸测试集上跑了一遍并得到了评估结果。这些结果通常保存在一个文件里比如JSON或NPY格式。为了演示我们这里模拟生成一些数据。在实际应用中你需要替换成自己模型输出的真实结果。import numpy as np import json # 模拟生成评估数据 # 1. 预测框的置信度分数和其对应的真实标签是否为人脸 np.random.seed(42) # 固定随机种子确保每次运行结果一致 num_predictions 1000 # 模拟置信度分数范围在0.3到0.99之间 confidence_scores np.random.uniform(low0.3, high0.99, sizenum_predictions) # 模拟真实标签1代表人脸0代表背景。这里假设模型不错高分更可能是人脸。 # 使用一个简单的逻辑让高分预测更有可能是正样本 true_labels (confidence_scores np.random.normal(0, 0.2, num_predictions) 0.7).astype(int) # 2. 模拟混淆矩阵所需的预测类别和真实类别多分类简化版 # 假设任务为区分“人脸”、“猫脸”、“误检背景” categories [人脸, 猫脸, 背景] num_categories len(categories) # 生成真实类别和预测类别 true_cats np.random.choice([0, 1, 2], size200, p[0.7, 0.2, 0.1]) # 真实分布 pred_cats true_cats.copy() # 人为制造一些错误10%的“猫脸”被误认为“人脸”15%的“背景”被误认为“人脸” misclassified_mask np.random.random(size200) 0.1 pred_cats[(true_cats1) misclassified_mask] 0 misclassified_mask np.random.random(size200) 0.15 pred_cats[(true_cats2) misclassified_mask] 0 # 3. 模拟检测框与真实框的重叠度IoU ious np.clip(np.random.beta(a2, b1, size500), 0, 1) # 用Beta分布模拟IoU大部分值较高 # 将模拟数据保存模拟从文件加载的过程 data_to_save { confidence_scores: confidence_scores.tolist(), true_labels: true_labels.tolist(), true_categories: true_cats.tolist(), pred_categories: pred_cats.tolist(), ious: ious.tolist(), categories: categories } with open(simulated_evaluation_data.json, w) as f: json.dump(data_to_save, f) print(模拟评估数据已生成并保存到 simulated_evaluation_data.json)运行上面这段代码我们就在当前目录下生成了一个simulated_evaluation_data.json文件里面包含了我们后续绘图需要的所有模拟数据。你的真实数据格式可能不同但核心内容无非就是这几类每个预测的分数和标签、分类的混淆情况、检测框的质量IoU。2. 绘制精确率-召回率PR曲线PR曲线是衡量模型在不同置信度阈值下精准度和覆盖能力平衡关系的重要工具。一条好的PR曲线应该尽可能靠近右上角。2.1 计算PR曲线的数据点我们不从零开始计算那样太麻烦。利用scikit-learn库我们可以很方便地得到绘制PR曲线所需的精确率、召回率和阈值。import matplotlib.pyplot as plt from sklearn.metrics import precision_recall_curve, average_precision_score import json import numpy as np # 加载我们之前模拟的数据 with open(simulated_evaluation_data.json, r) as f: data json.load(f) confidence_scores np.array(data[confidence_scores]) true_labels np.array(data[true_labels]) # 使用sklearn计算精确率、召回率和阈值 precision, recall, thresholds precision_recall_curve(true_labels, confidence_scores) # 计算平均精度AP这是PR曲线下的面积一个重要的汇总指标 average_precision average_precision_score(true_labels, confidence_scores) print(f计算完成。共得到 {len(thresholds)} 个阈值点。) print(f模型在该测试集上的平均精度AP为{average_precision:.4f})2.2 绘制并美化PR曲线图有了数据画图就是Matplotlib的舞台了。我们不仅要画出来还要画得专业、美观。plt.figure(figsize(10, 8)) # 设置画布大小 # 1. 绘制主PR曲线 plt.plot(recall, precision, lw3, colornavy, labelfPR curve (AP{average_precision:.3f})) # 2. 绘制随机猜测模型的基线对于不平衡数据集这条线不是0.5 # 正样本的比例 pos_ratio np.sum(true_labels) / len(true_labels) plt.axhline(ypos_ratio, colorred, linestyle--, lw2, labelfRandom Guess ({pos_ratio:.3f})) # 3. 标记一个典型的工作点例如选择精确率和召回率相对均衡的阈值点 # 找到最接近“平衡点”precision recall的阈值索引 diff np.abs(precision[:-1] - recall[:-1]) # thresholds比precision/recall少一个 balance_idx np.argmin(diff) balance_threshold thresholds[balance_idx] balance_precision precision[balance_idx] balance_recall recall[balance_idx] # 在曲线上标记这个点 plt.scatter(balance_recall, balance_precision, s100, zorder5, colordarkorange, edgecolorsblack, linewidth1.5) plt.text(balance_recall0.02, balance_precision-0.02, fThreshold{balance_threshold:.2f}\n(P{balance_precision:.2f}, R{balance_recall:.2f}), fontsize10, bboxdict(boxstyleround,pad0.3, facecolorwheat, alpha0.8)) # 4. 设置图表样式 plt.xlim([0.0, 1.05]) plt.ylim([0.0, 1.05]) plt.xlabel(Recall (覆盖率), fontsize14, fontweightbold) plt.ylabel(Precision (精准度), fontsize14, fontweightbold) plt.title(MogFace-large 模型 PR 曲线, fontsize16, fontweightbold, pad20) plt.grid(True, linestyle--, alpha0.7) # 添加网格线更易读 plt.legend(locbest, fontsize12) plt.tight_layout() # 自动调整布局防止标签被截断 # 保存图片 plt.savefig(mogface_pr_curve.png, dpi300, bbox_inchestight) print(PR曲线图已保存为 mogface_pr_curve.png) plt.show()这张图告诉我们什么那条蓝色的曲线越靠近右上角说明模型性能越好。红色的虚线是随机猜测的水平我们的模型曲线远高于它这是好事。图上标记的点给了我们一个具体的阈值选择参考在这个阈值下模型的精确率和召回率达到了一个不错的平衡。3. 绘制混淆矩阵混淆矩阵是理解模型具体“错在哪”的绝佳工具。它用矩阵的形式清晰展示了模型在各个类别上预测对了多少又分别把哪些类别误认成了其他类别。3.1 计算并绘制基础混淆矩阵我们继续使用模拟数据中的多分类结果。from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay true_cats np.array(data[true_categories]) pred_cats np.array(data[pred_categories]) categories data[categories] # 计算混淆矩阵 cm confusion_matrix(true_cats, pred_cats) print(原始混淆矩阵数值) print(cm) # 使用sklearn内置函数快速绘制 fig, ax plt.subplots(figsize(8, 6)) # normalizetrue 会按行真实标签归一化显示的是召回率 disp ConfusionMatrixDisplay(confusion_matrixcm, display_labelscategories) disp.plot(cmapBlues, axax, values_formatd) # d表示显示整数 plt.title(MogFace-large 混淆矩阵样本数, fontsize16, fontweightbold, pad20) plt.tight_layout() plt.savefig(mogface_confusion_matrix_raw.png, dpi300, bbox_inchestight) plt.show()第一张图显示的是原始的样本数量。我们可以清楚地看到对角线上预测正确的数字很大说明模型整体准确。同时我们也能发现一些有趣的错误比如第一行第二列有值说明有部分“猫脸”被模型误判成了“人脸”。3.2 绘制归一化混淆矩阵原始数字有时不够直观特别是当不同类别的样本数量差异很大时。将其归一化百分比显示能更好地反映模型在每个类别上的识别能力。# 计算归一化的混淆矩阵按行归一化即真实标签的视角 cm_normalized cm.astype(float) / cm.sum(axis1)[:, np.newaxis] cm_normalized np.round(cm_normalized, 2) # 保留两位小数 print(\n归一化混淆矩阵行百分比即召回率) print(cm_normalized) fig, ax plt.subplots(figsize(8, 6)) # 这次我们手动绘制以便更精细地控制 im ax.imshow(cm_normalized, interpolationnearest, cmapplt.cm.Blues) ax.figure.colorbar(im, axax) # 添加颜色条 # 设置坐标轴 ax.set(xticksnp.arange(cm.shape[1]), yticksnp.arange(cm.shape[0]), xticklabelscategories, yticklabelscategories, titleMogFace-large 混淆矩阵归一化, ylabel真实类别, xlabel预测类别) # 在格子中填充文本 thresh cm_normalized.max() / 2. for i in range(cm_normalized.shape[0]): for j in range(cm_normalized.shape[1]): ax.text(j, i, f{cm_normalized[i, j]:.2f}, hacenter, vacenter, colorwhite if cm_normalized[i, j] thresh else black, fontweightbold) plt.tight_layout() plt.savefig(mogface_confusion_matrix_normalized.png, dpi300, bbox_inchestight) plt.show()这张归一化的图更有价值。比如看“人脸”那一行第一行对角线上的数字是0.92这意味着模型对人脸的召回率是92%有8%的人脸没有被正确检测出来可能被漏检或误判为其他类别。看“猫脸”那一行有0.1010%被误判为“人脸”这揭示了模型一个具体的混淆模式。4. 绘制检测框重叠度IoU分布图对于目标检测模型预测框和真实框的重叠度IoU直接反映了定位的准确性。一个IoU分布图能让我们直观看到模型“框得有多准”。4.1 绘制IoU直方图与密度图ious np.array(data[ious]) fig, axes plt.subplots(1, 2, figsize(14, 5)) # 创建1行2列的子图 # 子图1直方图 ax1 axes[0] n, bins, patches ax1.hist(ious, bins20, range(0, 1), edgecolorblack, alpha0.7, colorskyblue) ax1.axvline(xious.mean(), colorred, linestyle--, linewidth2, labelfMean IoU {ious.mean():.3f}) # 常用阈值线如0.5和0.7 ax1.axvline(x0.5, colororange, linestyle:, linewidth2, labelThreshold 0.5) ax1.axvline(x0.7, colorgreen, linestyle:, linewidth2, labelThreshold 0.7) ax1.set_xlabel(IoU, fontweightbold) ax1.set_ylabel(Count, fontweightbold) ax1.set_title(IoU Distribution Histogram, fontsize14, fontweightbold) ax1.legend() ax1.grid(True, linestyle--, alpha0.5) # 子图2累积分布函数图CDF和核密度估计图KDE ax2 axes[1] # 绘制KDE from scipy import stats kde stats.gaussian_kde(ious) x_grid np.linspace(0, 1, 200) ax2.plot(x_grid, kde(x_grid), b-, lw3, labelKDE) # 绘制CDF sorted_ious np.sort(ious) cdf np.arange(1, len(sorted_ious)1) / len(sorted_ious) ax2.plot(sorted_ious, cdf, r-, lw2, labelCDF) ax2.set_xlabel(IoU, fontweightbold) ax2.set_ylabel(Density / Cumulative Probability, fontweightbold) ax2.set_title(IoU Density Cumulative Distribution, fontsize14, fontweightbold) ax2.legend() ax2.grid(True, linestyle--, alpha0.5) # 在CDF图上标记几个关键阈值 for threshold in [0.5, 0.7, 0.9]: prop_above np.sum(ious threshold) / len(ious) idx np.searchsorted(sorted_ious, threshold) cdf_val cdf[idx] if idx len(cdf) else 1.0 ax2.scatter(threshold, cdf_val, s80, zorder5, colorpurple) ax2.text(threshold0.02, cdf_val-0.05, fIoU≥{threshold}: {prop_above:.1%}, fontsize9, bboxdict(boxstyleround,pad0.2, facecolorlavender, alpha0.8)) plt.suptitle(MogFace-large 检测框IoU分析, fontsize16, fontweightbold, y1.02) plt.tight_layout() plt.savefig(mogface_iou_analysis.png, dpi300, bbox_inchestight) plt.show() # 输出一些统计信息 print(fIoU统计摘要:) print(f 平均值: {ious.mean():.4f}) print(f 中位数: {np.median(ious):.4f}) print(f 标准差: {ious.std():.4f}) print(f IoU 0.5的比例: {np.sum(ious 0.5) / len(ious):.2%}) print(f IoU 0.7的比例: {np.sum(ious 0.7) / len(ious):.2%}) print(f IoU 0.9的比例: {np.sum(ious 0.9) / len(ious):.2%})左边这张直方图让我们对IoU的整体分布有了一个快速的了解。红线标出了平均值橙线和绿线是常用的评价阈值比如在COCO数据集中AP0.5和AP0.75。可以看到大部分检测框的IoU都集中在较高的区域这是个好现象。右边的图信息量更大。蓝色的KDE曲线展示了IoU的密度分布红色的CDF曲线则告诉我们有多少比例的检测框达到了某个IoU值。我们从图上标记的点可以快速读出超过90%的检测框IoU大于0.5超过70%的检测框IoU大于0.7。这些量化的指标比单纯看平均值更有说服力。5. 总结走完这一趟可视化之旅你应该已经掌握了用Matplotlib为MogFace-large这类目标检测模型制作专业评估图表的方法。从PR曲线里我们看到了模型在精准度和覆盖率之间的权衡并找到了一个实用的置信度阈值点。从混淆矩阵里我们像侦探一样发现了模型具体的“犯错”模式比如它偶尔会把猫脸误认成人脸这为后续的模型优化指明了方向。最后IoU分布图告诉我们模型不仅“认得出”而且“框得准”大部分预测框都和真实目标贴合得很好。这套组合图表比任何文字描述都更有力量。它们把抽象的评估指标变成了直观的图形无论是用于团队内部的技术讨论还是写进项目报告、技术论文都能极大地提升沟通效率和专业度。你可以根据自己模型的实际输出数据替换掉本文中的模拟数据快速生成属于你自己的模型“体检报告”。试试看相信你会有更深的体会。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。

相关新闻