使用SkillMetrics快速绘制泰勒图:模型评估可视化实战指南
发布时间:2026/9/18 3:57:19来源:尧图网络
做气象、水文、空气质量模拟评估的朋友大概率绕不开一张图——泰勒图Taylor Diagram。它能把模型跑出来的结果和观测数据之间的“像不像”拆成三个核心指标塞进一张极坐标图里一眼就能看出哪个模型更靠谱。以前我都是用 matplotlib 手动吭哧吭哧画画一次少说要写上百行坐标轴刻度、标准差的算还要仔细调后来接触到 SkillMetrics 这个专门做模型评估的 Python 库发现泰勒图的绘制直接被封装成了一个类几行代码就能出图真正做到了“5分钟搞定”。这篇文章就把我实际使用 SkillMetrics 的完整流程、关键参数、踩过的坑都写清楚附上可以直接复制运行的完整代码给做数值模拟、机器学习回归评估、环境监测数据对比的朋友一个能直接抄作业的参考。1. 环境准备装好 SkillMetrics避开最容易踩的坑1.1 安装方法与版本选择SkillMetrics 库在 PyPI 上的收录情况比较特殊很多人在pip install skillmetrics这一步就直接卡住了。我实测下来最稳的方式是用 conda 安装conda install -c conda-forge skillmetrics如果 conda 也装不上就去 GitHub 上找 SkillMetrics 的仓库直接下载源码在项目根目录执行python setup.py install也能完成安装。装完之后验证一下import SkillMetrics print(SkillMetrics.__version__)这个库底层依赖 numpy、scipy、matplotlib如果你用的是 Anaconda 发行版这些基础依赖基本都已经具备了不需要额外处理。要注意的是库名的大小写有讲究导入时是import SkillMetrics而不是skillmetrics我在早期版本上踩过这个坑写错大小写会直接 ModuleNotFoundError。1.2 用之前你需要准备什么样的数据SkillMetrics 画泰勒图的核心输入只有两类数据观测值序列和模拟值序列两者必须长度一致。这里“序列”不一定是时间序列只要是同一批采样点上观测和模拟的成对数据就行。实际工作中最常见的几种数据组合气象预报验证某站点 365 天的日平均气温观测值与模式预报值水质模拟不同监测断面某指标的实测浓度与模型计算浓度机器学习回归测试集上的真实标签与模型预测结果数据格式上可以直接传 numpy 数组也可以从 CSV 里读。我习惯先把数据整理成两列一列 obs一列 sim然后分别取出作为一维数组传入。如果数据里有缺失值要先做剔除否则相关系数和标准差的计算结果会失真。1.3 环境验证跑一个最小示例装好库之后先别急着上真实数据我建议你先跑一个最小示例确认环境没问题再往下走import numpy as np import SkillMetrics # 生成两组长度相同的随机序列 np.random.seed(0) obs np.random.randn(100) sim obs * 0.8 np.random.randn(100) * 0.4 taylor SkillMetrics.TaylorDiagram() taylor.AddGrid() taylor.AddMarker(obs, sim) taylor.AddLegend() taylor.figure.show()如果你的环境没问题这个脚本会弹出一个带网格的泰勒图窗口里面有一个红色的标记点和对应的图例。这一步通过之后就可以放心进入正式绘图了。2. 泰勒图到底在画什么原理搞懂图才不会读错2.1 极坐标里的三个核心指标很多人第一次看泰勒图会觉得懵图上只有径向坐标和角度坐标怎么就能代表“模型有多准”关键在于这套坐标系背后对应的统计量。泰勒图的本质是把三个指标映射到一张极坐标图上相关系数 R决定点在极坐标里的角度位置。R 越大点越靠近横轴角度越接近 0°标准差比 σ_sim/σ_obs决定点到原点的径向距离。比值越接近 1点就越落在“观测点”所在的圆弧附近中心化均方根误差RMSD不直接用坐标表示但它的值等于图上点到“观测参考点”的距离观测参考点通常被标记在横轴上、半径等于 1 的位置即 R1、σ_sim/σ_obs1 的点。所以泰勒图的读图逻辑非常直接模拟结果对应的点越靠近观测参考点说明这个模型越好。越靠左下方发散的点说明模型的相位或振幅有明显偏差。2.2 为什么要把标准差比和相关系数放一起早期我做模型评估习惯把相关系数和均方根误差分开列两张表但两张表分开看有一个问题一个模型可能相关系数很高但标准差严重偏大波动幅度比观测值大了两倍这种情况单看相关系数表根本发现不了。泰勒图的价值就在这它强制你把“相关性”和“变率一致性”放在同一个坐标系里看。相关系数高但标准差比偏大的模型点会落在右上角的弧线外侧相关系数一般但标准差比接近 1 的模型点会落在参考点附近偏下的位置。这两种模型哪个更好没有绝对答案取决于你的业务需求但泰勒图能让你一眼看到每个模型的“偏科”情况。2.3 标准化与不标准化两种模式怎么选SkillMetrics 的泰勒图实现里可以通过参数控制是否对数据进行标准化。默认情况下库内部会计算标准差比所以模拟值和观测值的绝对量级不需要一致。但我补充一个实际经验如果观测值和模拟值的量级差很多比如差 10 倍以上建议先在外部把数据标准化或者检查一下是否存在单位错误。因为标准差比虽然对量级不敏感但相关系数对数据的分布形态很敏感如果模拟值整体偏小但变化趋势一致相关系数依然会很高这时候图上的点可能落在 R 很高、σ_ratio0.3 的位置。读图时心里要有数变换趋势一致不代表绝对误差小。3. 完整实操用 SkillMetrics 画一张正经的泰勒图3.1 先造一份可复现的示例数据为了让你能直接用、直接改我用 numpy 生成一份接近真实场景的模拟数据一条带有季节周期的“观测值”序列再生成两个性能不同的“模型模拟值”。import numpy as np import matplotlib.pyplot as plt import SkillMetrics # 固定随机种子保证每次运行结果一致 np.random.seed(42) # 生成120个时间点的观测序列含季节周期和随机噪声 n 120 t np.arange(n) obs 15 8 * np.sin(2 * np.pi * t / 40) np.random.normal(0, 1.2, n) # 模型1与观测有较强相关性但振幅略有压缩 sim_model1 12 6.5 * np.sin(2 * np.pi * t / 40 0.1) np.random.normal(0, 1.5, n) # 模型2相关性较弱振幅严重偏大 sim_model2 18 12 * np.sin(2 * np.pi * t / 40 0.8) np.random.normal(0, 4.0, n)这份数据里model1 应该是相对更好的那个模型。实际工作中你只需要用 pandas 的pd.read_csv()读取自己的数据然后拆出 obs 和 sim 两列一维数组替换掉这组示例数据即可。3.2 核心绘图代码与逐行解读下面是完整的绘图代码# 创建图和泰勒图对象 fig plt.figure(figsize(8, 8)) taylor SkillMetrics.TaylorDiagram() # 绘制基础网格和参考线 taylor.AddGrid() # 添加两个模型的数据标记 taylor.AddMarker( obs, sim_model1, markero, c#d62728, labelModel 1, alpha0.9, ms12 ) taylor.AddMarker( obs, sim_model2, marker^, c#1f77b4, labelModel 2, alpha0.9, ms12 ) # 添加图例 taylor.AddLegend() # 设置标题 plt.title(Taylor Diagram for Model Evaluation, fontsize14, pad20) # 保存高清图 plt.tight_layout() plt.savefig(taylor_diagram.png, dpi200, bbox_inchestight) plt.show()这段代码看起来很短但里面有几个关键点值得展开说。SkillMetrics.TaylorDiagram()这个类创建对象时内部已经帮你配置好了极坐标轴和参考网格线不需要像用 matplotlib 原生态画图那样手动计算角度和半径。AddGrid()会在图上画出标准差圆弧通常包括 0.5、1.0、1.5、2.0 等半径和相关系数射线通常从 0 到 0.9 或到 0.99 的梯度。AddMarker()是核心方法它接收观测序列和模拟序列内部完成相关系数、标准差比、RMSD 的计算然后自动把点画在正确的位置上。参数里marker控制点的形状c控制颜色label用于图例和 matplotlib 的散点图参数风格一致。3.3 图上标记的含义对照跑完上面的代码你会看到图上出现两个标记一个红色圆点、一个蓝色三角。我这边实测的结果是红色圆点落在相关系数约 0.97、标准差比接近 0.85 的位置蓝色三角落在相关系数约 0.5、标准差比接近 1.5 的位置。这两个点的含义可以这样解读Model 1 与观测值高度相关且变率与观测值比较接近是一个可靠的模型Model 2 相关性偏低同时振幅偏大说明它对观测的跟踪能力不足波动过于剧烈如果在实际项目中我会直接淘汰 Model 2或者检查是不是它的参数标定出了问题。3.4 替换成自己的数据完整代码框架为了让你的“5分钟”能够真正落地我再给一个更贴近实际文件的版本import numpy as np import pandas as pd import matplotlib.pyplot as plt import SkillMetrics # 读取数据假设你的CSV有两列obs, sim df pd.read_csv(your_data.csv) obs df[obs].values sim df[sim].values # 剔除缺失值 valid ~(np.isnan(obs) | np.isnan(sim)) obs, sim obs[valid], sim[valid] # 绘图 fig plt.figure(figsize(8, 8)) taylor SkillMetrics.TaylorDiagram() taylor.AddGrid() taylor.AddMarker(obs, sim, markers, c#2ca02c, labelYour Model) taylor.AddLegend() plt.title(Taylor Diagram: Your Model vs Observation) plt.tight_layout() plt.savefig(my_taylor.png, dpi300, bbox_inchestight) plt.show()我建议把数据读取、缺失值剔除和绘图封装成一个函数这样以后换了数据源只需要改文件路径和列名其他代码一行都不用动。4. 进阶玩法多模型对比、样式定制与批量出图4.1 同时对比四五个模型实际项目中很少只比较一个模型更多是同时评估多个模型或不同参数配置方案。SkillMetrics 对多模型的叠加支持得很好只需要连续调用多次AddMarkerfig plt.figure(figsize(9, 8)) taylor SkillMetrics.TaylorDiagram() taylor.AddGrid() models { Model A: (sim_a, o, #d62728), Model B: (sim_b, ^, #1f77b4), Model C: (sim_c, s, #2ca02c), Model D: (sim_d, D, #9467bd), } for name, (sim, marker, color) in models.items(): taylor.AddMarker(obs, sim, markermarker, ccolor, labelname, ms10) taylor.AddLegend() plt.show()这里有一个使用心得当模型数量超过 4 个时默认的小尺寸标记容易重叠建议把ms标记尺寸调大一些同时让颜色在明度和色相上有明显区分。另外图例的位置可能需要手动调整AddLegend()默认放在图外如果模型名字太长记得把图的figsize调宽一点否则图例容易折叠。4.2 图样式与坐标轴的细节定制SkillMetrics 的泰勒图已经封装了大部分美学设置但有时候你需要对齐论文或者报告的风格这时可以拿到内部的 matplotlib 轴对象做微调。例如# 获取内部极坐标轴 ax taylor.ax # 自定义标题 ax.set_title(Seasonal Mean Evaluation, fontsize14, loccenter) # 调整径向刻度标签字体大小 for label in ax.get_yticklabels() ax.get_xticklabels(): label.set_fontsize(11)还有一个很实用的技巧如果你不想显示默认的网格标签或者想换成你自己的阈值例如只看相关系数大于 0.8 的区域可以直接操作坐标轴的范围把图放大到感兴趣的区域细节会更清楚。4.3 批量绘制多站点泰勒图我做过一个项目要对 20 个监测站点的模型结果分别画泰勒图手工一张张来绝对累死人。后来我写了个循环批量出图用subplots网格组合到一张大图里stations [Site_A, Site_B, Site_C, Site_D] fig, axes plt.subplots(2, 2, figsize(14, 12)) for ax, site in zip(axes.flat, stations): obs_site obs_dict[site] sim_site sim_dict[site] taylor SkillMetrics.TaylorDiagram(axax) taylor.AddGrid() taylor.AddMarker(obs_site, sim_site, markero, c#1f77b4, labelsite) taylor.AddLegend() plt.tight_layout() plt.savefig(multi_station_taylor.png, dpi300)注意TaylorDiagram类支持传入已有的ax参数这个特性在做子图组合时特别方便。如果你用的版本不支持传ax可以退一步用plt.figure()创建多个独立图再通过 PIL 拼接不过那样明显麻烦多了。4.4 保存图片的正确姿势保存图片时我强烈建议用bbox_inchestight参数否则图例和边缘标签容易被裁剪掉。此外不同期刊对图片格式有要求一般提交论文用矢量图更好可以将格式改为 pdf 或 svgfig.savefig(taylor.pdf, bbox_inchestight)矢量图的优势是放大后文字和标记不会模糊审稿人和编辑对这种细节很满意。5. 常见问题与排查技巧实录5.1 安装失败pip 和 conda 都装不上SkillMetrics 这个库因为更新维护节奏不快在某些 Python 版本尤其是最新的 Python 3.11、3.12上直接 pip 安装可能会报编译错误或找不到包。我的建议是优先使用 conda-forge 通道安装如果 conda 也没有对应版本就去 GitHub 下载源码安装。装完后如果 import 还是报错检查一下是不是装了同名的其他包把环境里的同名包先卸载干净再重装。另外如果项目对 Python 版本有严格要求可以考虑建一个独立的 Python 3.9 环境专门跑 SkillMetrics我在 3.9 上从来没有遇到过问题。5.2 图上点太多了根本看不清做敏感性分析时可能一次要画几十条模拟结果满屏都是点图就废了。我的解决办法是第一先做一个预筛选只画出相关系数大于某个阈值比如 R 0.7的模型第二对特别关注的模型用大标记和鲜明的颜色其他的用灰色小点表示。比如# 不重要的模型一律小灰点 taylor.AddMarker(obs, sim_other, markero, c#bbbbbb, label_nolegend_, ms5)这个label_nolegend_的技巧是从 matplotlib 里继承来的可以让大量点不进入图例保持图面干净。5.3 图上相关系数和我自己算的不一致之前有读者私信问我为什么程序绘制的相关系数和自己在 Excel 里算的不一样。后来定位到原因他手动计算的是原始观测和模拟的 Pearson 相关系数而 SkillMetrics 在部分版本里默认计算的是“中心化”并做了标准化处理的相关系数。另外如果数据里有缺失值或异常值也会导致统计量偏差。处理办法是绘图前先对数据做清洗剔除 NaN 和明显超出物理范围的异常值同时用自己的脚本先算一遍 Pearson 相关系数和库返回的结果比对确认理解一致后再放心读图。5.4 图片里的中文字体显示成方块SkillMetrics 内部调用的 matplotlib 默认字体不含中文字符如果你的图标题或模型名字里有中文保存出来的图会显示成一个个小方块。解决方式是在绘图前加入 matplotlib 的中文字体配置import matplotlib as mpl mpl.rcParams[font.sans-serif] [SimHei, Microsoft YaHei, PingFang SC] mpl.rcParams[axes.unicode_minus] False注意这个axes.unicode_minus也要设置否则坐标轴上的负号会显示成乱码。5.5 参考线精度和读图范围泰勒图默认会把相关性射线标到 0.9 或 0.95但当你处理的模型精度很高R 大于 0.98时所有点会挤在横轴附近看起来几乎重叠。这时可以放大坐标范围让细节暴露出来。具体做法是手动调整极坐标半径的显示范围或者把图放大到局部区域。AddGrid()生成的网格是参考不影响你把视角拉近。6. 从跑通到用好我的三点实操体会先说实话SkillMetrics 这个库学习成本极低但真正把它用好还是需要一些“业务判断力”的。第一泰勒图不是万能的。它擅长表达“变率相关性”但不擅长表达“绝对偏差”。如果你的模型整体系统性偏低但波形和观测高度一致泰勒图上会显示一个“很优秀”的点这时你必须配合普通的偏差图或时间序列图一起看否则会被误导。第二多模型对比时除了看每个点离参考点的距离还要看它们之间的相对位置。两个点离得很近说明这两个模型的误差结构非常相似即使它们各自离参考点都比较远优化时也很可能属于同一类问题。第三数据预处理比绘图本身更重要。缺失值、异常值、单位不统一都会直接影响统计指标进而让泰勒图给出错误信号。我见过有人用没清洗的数据画出的图特别漂亮但实际上是因为某些离群点把相关系数“抬”起来了。所以画图之前先看看数据的分布和清洗报告永远值得多花这几分钟。这套技能在项目汇报里特别加分。对方问“你这个模型到底行不行”你直接甩出一张泰勒图指着参考点附近的标记说“相关系数 0.95、标准差比接近 1”比贴十行表格都有说服力。而且整个绘制过程真的只要几分钟剩下的时间你可以专心用来解释结论、分析原因而不是和画图代码搏斗。
网站建设高端定制企业官网