模型上线后,先检查“输入分布是否变了”,才能进一步判断模型是否还工作在熟悉的环境。Evidently 的 DataDriftPreset 可以比较参考数据与当前数据,列出发生漂移的特征;没有真实标签时,这些结果只是模型质量的代理信号。
下面会在本地生成两张人工表格,故意改变一个字段的分布,再导出可打开的 HTML 报告和 JSON。示例没有接入真实线上模型,不会根据一个漂移提示自动触发重训。

准备两份可比较的数据
参考集应来自你认可的稳定时段或训练时的数据分布,当前集来自需要检查的时间窗口。两个窗口要统一特征名、类型、单位和采样口径:把“秒”错当“毫秒”,或把全天数据与夜间数据直接对比,都可能造成没有业务意义的告警。
- request_length:请求长度,数值特征。
- latency_ms:延迟毫秒数,数值特征。
- channel:入口渠道,类别特征。
字段只是教学假设。真正用于模型监控时,应优先选择模型实际使用的输入特征,并将处理前后的数据口径写清。延迟可以作为运行指标另行监测,不应被误称为模型一定使用的特征。
安装并使用当前接口
本文代码在 Windows、Python 3.11.15、Evidently 0.7.23、pandas 3.0.6、NumPy 2.4.6 下运行核验。先建立并激活独立 Python 环境,再安装:
python -m venv .venv
# Windows PowerShell
.\.venv\Scripts\Activate.ps1
python -m pip install "evidently==0.7.23" "pandas==3.0.6" "numpy==2.4.6"
以下代码使用 from evidently import Dataset, DataDefinition, Report。如果你看到旧教程从 evidently.report 导入,不要混用两代接口;先核对安装版本。数据类型映射、Report.run(current, reference) 与报告导出依据 官方数据与模型检查入门。
运行一份有明确变化的教学数据
保存下面代码为 drift_check.py。参考和当前各有 1200 行;当前 request_length 的生成均值由 300 改成 440,另外增加 60 条缺失。这些值是人为设定的演示输入。
from pathlib import Path
import json
import numpy as np
import pandas as pd
from evidently import Dataset, DataDefinition, Report
from evidently.presets import DataDriftPreset, DataSummaryPreset
rng = np.random.default_rng(42)
# 人工生成的教学数据,不是真实线上流量。
reference = pd.DataFrame({
"request_length": rng.normal(300, 40, 1200),
"latency_ms": rng.normal(200, 25, 1200),
"channel": rng.choice(["web", "app"], 1200, p=[0.6, 0.4])})
current = pd.DataFrame({
"request_length": rng.normal(440, 40, 1200),
"latency_ms": rng.normal(200, 25, 1200),
"channel": rng.choice(["web", "app"], 1200, p=[0.6, 0.4])})
# 加入部分缺失,展示分布检查与数据质量检查需要同时看。
current.loc[:59, "request_length"] = np.nan
if list(reference.columns) != list(current.columns):
raise ValueError("参考与当前数据列必须一致")
print("missing fractions:", current.isna().mean().to_dict())
schema = DataDefinition(
numerical_columns=["request_length", "latency_ms"],
categorical_columns=["channel"])
ref = Dataset.from_pandas(reference, data_definition=schema)
cur = Dataset.from_pandas(current, data_definition=schema)
result = Report([DataDriftPreset(), DataSummaryPreset()]).run(cur, ref)
result.save_html("drift_report.html")
Path("drift_report.json").write_text(result.json(), encoding="utf-8")
print("saved:", Path("drift_report.html").resolve())
print("means:", reference.request_length.mean(), current.request_length.mean())
print("metrics:", len(result.dict()["metrics"]))
python drift_check.py
脚本成功后生成 drift_report.html 与 drift_report.json。用浏览器打开本地 HTML;JSON 可留存到自己的监控归档。终端同时打印缺失比例与两份表的实际均值,帮助核对报告正在比较正确的数据。
先看单列,再看整体结论
- 在报告中查看各列的类型、分布和漂移判定,优先展开 request_length;它是本例故意修改的字段。
- 核对 reference 与 current 的方向。新版接口是
run(cur, ref),不要把当前集误传成基线。 - 查看整体漂移比例。官方 Data Drift Preset 文档说明,默认在至少 50% 的列发生漂移时判定整体数据集漂移。一个重要字段漂移,仍可能没有整体漂移标记。
- 继续看 DataSummaryPreset 和打印出的缺失比例。漂移检查比较非空值的分布,不能替代缺失值监测;本例当前 request_length 的缺失比例应为 60/1200,即 5%。
默认方法会按列类型与样本规模选择,所以不同特征的“drift score”不一定具有相同单位,也不能统一理解成一个概率。看分数时同时看方法、阈值和直方图;不要因为某列分数更大就直接判断它更危险。
本次运行的 JSON 显示 3 列中 1 列漂移,比例约为 33.3%;request_length 的参考与当前实际均值分别约为 299.1 和 439.3。当前字段缺失比例为 5%。这些结果来自上述人工数据,展示的是列级变化和整体门槛可以给出不同结论。
发现漂移后,按顺序排查
| 现象 | 先核对 | 可采取的下一步 |
|---|---|---|
| 数值整体偏移 | 单位、预处理版本、采集范围 | 先修复口径,再重跑同一窗口比较 |
| 出现新类别 | 业务是否新增渠道、编码是否变更 | 分群检查模型对新类别的处理和真实标签表现 |
| 缺失突然增加 | 采集链路、字段映射、空值填充 | 修复链路,单独统计缺失,不能靠漂移报告替代 |
| 漂移存在且误差增大 | 代表性标注、分群错误、历史窗口 | 评估补标注、更新数据或重训,并再次独立验证 |
真实项目每次至少保存窗口起止时间、样本量、特征版本、基线版本和报告路径。按固定规则持续比较,才能分清一次异常与长期变化;本文的一次本地报告不会自动提供采集、定时、通知或生产处置流程。
没有漂移,能说明模型没问题吗?
不能。输入的单列分布看起来稳定,标签与特征之间的关系仍可能变化;也可能出现只影响少量关键人群的问题。反过来,出现漂移也不必然意味着准确率下降。拿到真实标签后,应再计算模型质量指标并复核失败样本,漂移结果用来指引调查。
报错时先检查两张表是否为空、列名是否一致、类别是否按字符串而非数值编码错误解释。若 ImportError,核对虚拟环境与 Evidently 版本;如果 HTML 生成但结果不合理,先检查数据与时间窗口,不能只调整统计阈值让告警消失。本文实测为本地合成数据报告生成与结果核对;未验证真实业务漂移、生产告警或自动重训。文档核验日期:2026-10-01。
Ai菜鸟网。发布者:AI小管家,转载请注明出处:https://www.alyyhw.com/30454.html