MGeo输出结果可视化:Jupyter Notebook绘图示例代码
1. 为什么需要可视化MGeo的输出结果
地址相似度匹配听起来很技术,但它的实际价值藏在细节里——比如两个地址“北京市朝阳区建国路8号”和“北京市朝阳区建国路8号SOHO现代城B座”,系统判断它们是同一实体的概率是0.93还是0.67?这个数字背后,是模型对门牌号、楼栋名、后缀词、省市区层级关系的综合理解。
MGeo是阿里开源的专注中文地址领域的实体对齐模型,它不只返回一个相似度分数,还输出细粒度的匹配证据:哪些字段对上了(如“朝阳区”完全一致)、哪些存在模糊对应(如“SOHO现代城”被识别为“建筑名称”类)、哪些部分未匹配(如缺少楼层信息)。这些结构化输出,才是业务落地的关键依据。
但原始JSON格式的输出对人并不友好。一行行翻看{"score": 0.87, "field_matches": [{"field": "province", "match_type": "exact", "value": "北京市"}]},效率低、易遗漏、难对比。这时候,可视化就不是“锦上添花”,而是“刚需”——把抽象的匹配逻辑变成一眼可读的图表:用柱状图直观比较多组地址对的相似度分布,用热力图呈现字段级匹配强度,用散点图观察分数与编辑距离的关系。本文就带你用Jupyter Notebook,把MGeo的推理结果真正“看见”。
2. 环境准备与数据准备
2.1 镜像部署与环境激活
你已成功在4090D单卡服务器上部署了预置镜像,这是最省心的起点。接下来只需三步进入工作状态:
- 打开浏览器,访问Jupyter Notebook服务地址(通常形如
http://your-server-ip:8888); - 在Notebook界面中,打开终端(
New → Terminal),执行:
这一步确保所有后续Python操作都在MGeo依赖的环境中运行;conda activate py37testmaas - 将推理脚本复制到工作区,方便后续修改和调试:
cp /root/推理.py /root/workspace/
小提示:
/root/workspace/是Jupyter默认的工作目录,所有新建的.ipynb文件都会保存在这里。把推理.py放进来,就能在Notebook里直接导入它的函数,无需路径折腾。
2.2 模拟MGeo输出数据结构
MGeo的典型输出是一个包含多个匹配对的列表,每个匹配对是一个字典。为演示可视化,我们先构造一个符合其格式的模拟数据集——这比等待真实推理更高效,也便于你快速验证绘图逻辑:
# 模拟MGeo推理结果(实际使用时替换为真实输出) mgeo_results = [ { "pair_id": "P001", "address_a": "上海市浦东新区张江路123号", "address_b": "上海市浦东新区张江路123号A栋", "similarity_score": 0.94, "field_matches": [ {"field": "province", "match_type": "exact", "confidence": 1.0}, {"field": "city", "match_type": "exact", "confidence": 1.0}, {"field": "district", "match_type": "exact", "confidence": 1.0}, {"field": "road", "match_type": "exact", "confidence": 0.98}, {"field": "number", "match_type": "fuzzy", "confidence": 0.92}, {"field": "building", "match_type": "partial", "confidence": 0.75} ] }, { "pair_id": "P002", "address_a": "广州市天河区体育西路101号", "address_b": "广州市天河区体育西路103号", "similarity_score": 0.82, "field_matches": [ {"field": "province", "match_type": "exact", "confidence": 1.0}, {"field": "city", "match_type": "exact", "confidence": 1.0}, {"field": "district", "match_type": "exact", "confidence": 1.0}, {"field": "road", "match_type": "exact", "confidence": 0.99}, {"field": "number", "match_type": "fuzzy", "confidence": 0.65} ] }, { "pair_id": "P003", "address_a": "成都市武侯区人民南路四段1号", "address_b": "成都市武侯区人民南路四段1号科分院", "similarity_score": 0.88, "field_matches": [ {"field": "province", "match_type": "exact", "confidence": 1.0}, {"field": "city", "match_type": "exact", "confidence": 1.0}, {"field": "district", "match_type": "exact", "confidence": 1.0}, {"field": "road", "match_type": "exact", "confidence": 0.97}, {"field": "number", "match_type": "exact", "confidence": 0.95}, {"field": "building", "match_type": "partial", "confidence": 0.80} ] } ]这段代码定义了3组地址对的匹配结果,每组都包含similarity_score(总分)和field_matches(字段级匹配详情)。它完全复刻了MGeo的真实输出结构,你可以直接复制粘贴到Notebook的第一个cell中运行。
3. 核心可视化:四种实用图表
3.1 总体相似度分布——水平柱状图
最基础也最重要的图:看清所有匹配对的分数高低。水平柱状图比垂直的更易读长文本标签(如地址对ID),且能清晰展示排序。
import matplotlib.pyplot as plt import pandas as pd # 提取数据 ids = [r["pair_id"] for r in mgeo_results] scores = [r["similarity_score"] for r in mgeo_results] # 创建DataFrame便于操作 df_scores = pd.DataFrame({"Pair ID": ids, "Similarity Score": scores}) # 绘图 plt.figure(figsize=(8, 5)) bars = plt.barh(df_scores["Pair ID"], df_scores["Similarity Score"], color=["#2E86AB", "#A23B72", "#F18F01"], alpha=0.8) plt.xlabel("相似度分数", fontsize=12) plt.title("MGeo地址对相似度得分分布", fontsize=14, fontweight='bold') plt.xlim(0, 1) # 在柱子上添加数值标签 for i, (bar, score) in enumerate(zip(bars, scores)): plt.text(bar.get_width() + 0.01, bar.get_y() + bar.get_height()/2, f'{score:.2f}', va='center', fontsize=11) plt.gca().invert_yaxis() # 让最高分在最上面 plt.tight_layout() plt.show()效果说明:这张图立刻告诉你哪组地址最可能为同一实体(P001,0.94分),哪组需要人工复核(P002,0.82分)。颜色区分让视觉层次更清晰,数值标签免去查表之苦。
3.2 字段级匹配强度——热力图
总分只是结果,字段级匹配才是原因。热力图能一目了然地看到:模型在“省份”“城市”上是否总是100%准确?“楼栋名”的匹配信心为何普遍偏低?
import numpy as np import seaborn as sns # 构建字段匹配矩阵:行是地址对,列是字段类型,值是置信度 all_fields = list(set(f["field"] for r in mgeo_results for f in r["field_matches"])) field_to_idx = {f: i for i, f in enumerate(all_fields)} # 初始化矩阵 matrix_data = np.full((len(mgeo_results), len(all_fields)), np.nan) for i, result in enumerate(mgeo_results): for match in result["field_matches"]: j = field_to_idx[match["field"]] matrix_data[i, j] = match["confidence"] # 创建DataFrame df_heatmap = pd.DataFrame(matrix_data, index=[r["pair_id"] for r in mgeo_results], columns=all_fields) # 绘图 plt.figure(figsize=(9, 5)) sns.heatmap(df_heatmap, annot=True, cmap="YlGnBu", cbar_kws={'label': '匹配置信度'}, linewidths=0.5, linecolor='gray') plt.title("字段级匹配置信度热力图", fontsize=14, fontweight='bold') plt.ylabel("地址对ID") plt.xlabel("地址字段") plt.tight_layout() plt.show()效果说明:图中深蓝色代表高置信度(如所有“province”都是1.0),浅黄色代表中等置信(如“building”在0.75–0.80之间)。你一眼就能发现:模型对行政区划字段极其可靠,而对非结构化楼栋名的识别仍有提升空间——这直接指向了后续优化方向。
3.3 匹配类型分布——环形图
match_type(exact/fuzzy/partial)反映了模型的匹配策略。环形图能直观展示各类匹配方式的占比,帮助你理解模型的“决策风格”。
from collections import Counter # 统计所有匹配类型的出现次数 all_match_types = [match["match_type"] for r in mgeo_results for match in r["field_matches"]] type_counts = Counter(all_match_types) # 绘图 plt.figure(figsize=(6, 6)) colors = ["#2E86AB", "#A23B72", "#F18F01"] plt.pie(type_counts.values(), labels=type_counts.keys(), autopct='%1.1f%%', startangle=90, colors=colors, wedgeprops=dict(width=0.5)) plt.title("匹配类型分布", fontsize=14, fontweight='bold') plt.axis('equal') plt.tight_layout() plt.show()效果说明:如果“exact”占比超过80%,说明模型主要依赖精确字符串匹配;若“fuzzy”比例高,则表明它大量启用了拼音、简繁体、同义词等模糊规则。这个分布是你评估模型是否“按预期工作”的第一道关卡。
3.4 相似度与字段数关系——散点图
一个经验性规律:匹配字段越多,总分往往越高。散点图能验证这一假设,并揭示异常点——比如某对地址只匹配了3个字段却得了0.9分,值得深挖原因。
# 计算每对地址的匹配字段数量 field_counts = [len(r["field_matches"]) for r in mgeo_results] scores = [r["similarity_score"] for r in mgeo_results] plt.figure(figsize=(7, 5)) scatter = plt.scatter(field_counts, scores, s=100, c=scores, cmap="viridis", alpha=0.8, edgecolors='black', linewidth=0.5) plt.xlabel("匹配字段数量", fontsize=12) plt.ylabel("相似度分数", fontsize=12) plt.title("匹配字段数量 vs 相似度分数", fontsize=14, fontweight='bold') plt.xticks(range(min(field_counts), max(field_counts)+1)) plt.grid(True, alpha=0.3) # 添加颜色条 cbar = plt.colorbar(scatter) cbar.set_label("相似度分数", rotation=270, labelpad=15) plt.tight_layout() plt.show()效果说明:图中点的分布趋势若明显向上倾斜,说明字段数量与分数正相关,模型逻辑合理;若出现离群点(如字段数少但分数高),则可能是模型对某个关键字段(如门牌号)赋予了极高权重,或是数据噪声——这正是你需要重点关注的case。
4. 进阶技巧:让可视化更贴近业务
4.1 一键生成完整报告
把上述四个图表封装成一个函数,输入MGeo结果,一键输出PDF报告,适合给业务方汇报:
def generate_mgeo_report(results, output_path="mgeo_visualization_report.pdf"): """生成MGeo可视化分析报告""" from matplotlib.backends.backend_pdf import PdfPages with PdfPages(output_path) as pdf: # 图1:相似度分布 plt.figure(figsize=(8, 5)) ids = [r["pair_id"] for r in results] scores = [r["similarity_score"] for r in results] plt.barh(ids, scores, color=["#2E86AB", "#A23B72", "#F18F01"]) plt.xlabel("相似度分数") plt.title("地址对相似度得分分布") plt.xlim(0, 1) pdf.savefig() plt.close() # 图2:热力图(代码同上,此处省略) # ...(插入3.2节的热力图代码) pdf.savefig() plt.close() # 后续图表同理... print(f"报告已生成:{output_path}") # 使用示例 # generate_mgeo_report(mgeo_results)4.2 交互式探索:用Plotly替代Matplotlib
如果你希望业务同事能自己拖拽、缩放、悬停查看数据,plotly.express是更好的选择:
import plotly.express as px # 散点图升级版 df_scatter = pd.DataFrame({ "Pair ID": ids, "Matched Fields": field_counts, "Similarity Score": scores }) fig = px.scatter(df_scatter, x="Matched Fields", y="Similarity Score", text="Pair ID", size="Similarity Score", color="Similarity Score", color_continuous_scale="Viridis", title="匹配字段数与相似度关系(交互式)") fig.update_traces(textposition="top center") fig.show() # 在Jupyter中直接显示交互图表悬停时会显示具体地址对ID和分数,点击图例可筛选,这才是真正“给人用”的工具。
5. 总结:从数据到洞察,只需一个Notebook
MGeo的强大,不在于它跑得多快,而在于它输出的信息有多丰富。本文没有教你如何调参或重训练,而是聚焦一个最务实的问题:怎么把模型的“黑盒输出”变成你能看懂、能解释、能决策的“白盒洞察”。
我们用Jupyter Notebook完成了四件事:
- 用水平柱状图,一眼锁定高置信匹配对;
- 用热力图,定位模型的强项与短板字段;
- 用环形图,理解模型的匹配策略偏好;
- 用散点图,验证核心假设并发现异常case。
这些图表代码全部基于标准库(matplotlib、seaborn、pandas),无需额外安装,复制即用。更重要的是,它们不是静态图片,而是活的数据视图——你随时可以换上自己的MGeo真实输出,几秒钟内获得全新洞察。
可视化不是终点,而是起点。当你看清了“哪里准、哪里弱、为什么这样”,下一步的模型优化、规则补充、bad case分析,才真正有了方向。
6. 下一步建议
- 替换真实数据:将
mgeo_results变量替换为你运行/root/workspace/推理.py后得到的真实JSON输出; - 扩展字段分析:在热力图中加入
match_type作为第三维度,用不同形状标记exact/fuzzy; - 批量处理:写一个循环,自动为上千组地址对生成相似度分布直方图,快速掌握整体质量水位;
- 集成到Pipeline:把可视化函数嵌入你的地址清洗流水线,每次推理后自动生成质量报告。
真正的工程价值,永远诞生于“看见”之后。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。