使用 ZenML Evidently Data Validator 实现数据质量、数据漂移与模型性能监控

使用 ZenML Evidently Data Validator 实现数据质量、数据漂移与模型性能监控 使用 ZenML Evidently Data Validator 实现数据质量、数据漂移与模型性能监控【免费下载链接】zenmlZenML : One AI Platform from Pipelines to Agents. https://zenml.io.项目地址: https://gitcode.com/GitHub_Trending/ze/zenml本文基于 ZenML 仓库中的 Evidently Data Validator 集成文档 及其源码实现系统讲解如何在 ZenML 管道中集成 Evidently完成数据画像Data Profiling、数据质量测试、数据漂移与模型性能分析。读完本文你将掌握四种不同灵活度的使用方式内置 Report/Test Step、Data Validator 方法调用、直接调用 Evidently 库并能在管道中实现自动化质量门禁与可视化报告产出。一、Evidently 是什么何时该用 Evidently Data ValidatorEvidently 是一款开源的机器学习模型监控与调试库它通过强大的数据画像与可视化能力分析模型所使用的数据并运行一系列数据与模型验证报告和测试——从针对单一数据集的数据完整性测试到模型评估测试、数据漂移分析与模型性能对比测试几乎都可以在极少的配置输入下完成也支持为验证测试定制专门的判定条件。Evidently 目前支持pandas.DataFrame或 CSV 格式的表格数据可同时处理回归与分类两类任务。在 ZenML 中Evidently 通过 Data Validator 类型的 Stack 组件暴露能力。当你需要以下数据与模型验证功能时应优先考虑 Evidently Data Validator数据质量Data Quality报告与测试针对单一数据集给出详细的特征统计与特征行为概览也可以对比任意两个数据集例如训练集与测试集、参考数据与当前数据、或同一数据集的两个子群体。数据漂移Data Drift报告与测试通过对比两个 schema 相同的数据集检测并探索输入数据中特征分布的漂移变化。目标漂移Target Drift报告与测试在目标列和/或预测列可用的两个数据集上检测并探索目标函数或模型预测结果的变化。回归/分类性能Regression/Classification Performance报告与测试在同时含目标列与预测列的单一数据集上评估模型性能也可以通过提供第二个数据集与同一模型的过往表现或另一候选模型的表现进行对比。如果这些能力仍不满足需求可参考 Data Validators 总览 中列出的其他 flavor如 Deepchecks、Great Expectations、Whylogs进行横向选型也可用zenml>zenml integration install evidently -y安装完成后即可注册 Data Validator 并加入 Stack。从源码结构看该组件没有任何配置参数——EvidentlyDataValidatorFlavor 继承自BaseDataValidatorFlavor仅定义了 flavor 名称、文档地址、Logo 与实现类因此注册命令非常简洁# 注册 Evidently data validator zenml>from zenml.integrations.evidently.metrics import EvidentlyMetricConfig from zenml.integrations.evidently.steps import ( EvidentlyColumnMapping, evidently_report_step, ) text_data_report evidently_report_step.with_options( parametersdict( column_mappingEvidentlyColumnMapping( targetRating, numerical_features[Age, Positive_Feedback_Count], categorical_features[ Division_Name, Department_Name, Class_Name, ], text_features[Review_Text, Title], ), metrics[ EvidentlyMetricConfig.metric(DataQualityPreset), EvidentlyMetricConfig.metric( TextOverviewPreset, column_nameReview_Text ), EvidentlyMetricConfig.metric_generator( ColumnRegExpMetric, columns[Review_Text, Title], reg_expr[A-Z][A-Za-z0-9 ]*, ), ], # 文本报告需要先下载 NLTK 数据 download_nltk_dataTrue, ), )从 evidently_report_step 源码 可以看到该 Step 的完整签名还额外支持ignored_cols在送入 Evidently 前从参考/对比数据集中剔除指定列并对未命中的列名给出日志警告与report_options透传给Report构造器两个参数。Step 内部通过EvidentlyDataValidator.get_active_data_validator()获取当前激活的 validator最终返回(report.json(), HTMLString(report.get_html()))二元组即同时产出 JSON 与 HTML 两种格式的报告。上述配置等价于在 Step 内部执行如下 Evidently 原生代码from evidently.legacy.metrics import ColumnRegExpMetric from evidently.legacy.metric_preset import DataQualityPreset, TextOverviewPreset from evidently.legacy.pipeline.column_mapping import ColumnMapping from evidently.legacy.report import Report from evidently.legacy.metrics.base_metric import generate_column_metrics import nltk nltk.download(words) nltk.download(wordnet) nltk.download(omw-1.4) column_mapping ColumnMapping( targetRating, numerical_features[Age, Positive_Feedback_Count], categorical_features[ Division_Name, Department_Name, Class_Name, ], text_features[Review_Text, Title], ) report Report( metrics[ DataQualityPreset(), TextOverviewPreset(column_nameReview_Text), generate_column_metrics( ColumnRegExpMetric, columns[Review_Text, Title], parameters{reg_exp: r[A-Z][A-Za-z0-9 ]*} ) ] ) # 数据集即传入 Evidently Step 的输入 artifact report.run( current_datacurrent_dataset, reference_datareference_dataset, column_mappingcolumn_mapping, )3.2 配置字段逐项拆解evidently_report_step的配置项与你平时传给 EvidentlyReport对象来配置并运行报告的参数一一对应包括column_mappingEvidentlyColumnMapping对象与 Evidently 的ColumnMapping完全等价用于描述数据集各列及应如何被对待分类、数值或文本特征。查看 column_mapping.py 可知它是一个 Pydantic 模型字段包括target、prediction默认prediction、datetime、id、numerical_features、categorical_features、datetime_features、target_names、task、pos_label默认1与text_featuresto_evidently_column_mapping()方法将其转换为 Evidently 原生对象并尽量保留 Evidently 的默认值。metricsEvidentlyMetricConfig对象列表以声明式方式配置报告要使用的 metrics等价于 EvidentlyReport中的metrics。download_nltk_data布尔值指示是否提前下载 NLTK 数据。仅当使用处理文本数据的 Evidently 报告如TextOverviewPreset时才需要置为True。关于 NLTK 下载EvidentlyDataValidator 内部通过_set_nltk_data_path()将NLTK_DATA环境变量指向当前工作目录并追加到 NLTK 搜索路径——因为某些 Docker 容器默认下载目录不可写随后_download_nltk_data()下载words、wordnet、omw-1.4三个数据集。若 NLTK 未安装会抛出明确的ImportError。3.3 引用 Evidently Metric 的三种方式配置EvidentlyMetricConfig时引用 metric 的方式有按类名推荐最简便直接使用 Evidently 文档中出现的 metric 或 metric preset 类名例如DataQualityPreset、DatasetDriftMetric。从 metrics.py 的get_metric_class实现可以看到无点号的名称会依次在evidently.legacy.metrics与evidently.legacy.metric_preset命名空间中查找。按完整类路径例如evidently.legacy.metric_preset.DataQualityPreset、evidently.legacy.metrics.DatasetDriftMetric。适用于使用 Evidently 库中未收录的 metric 或 preset 的情况底层通过source_utils.load动态导入。直接传入类本身例如from evidently.legacy.metrics import DatasetDriftMetric evidently_report_step.with_options( parametersdict( metrics[EvidentlyMetricConfig.metric(DatasetDriftMetric)] ), )3.4 添加 metric 的两种方法添加单个 metric 或 preset调用EvidentlyMetricConfig.metric(...)传入类名/类路径/类其余参数与 Evidently metric 或 preset 类的构造参数一致。批量生成多个 column metric调用EvidentlyMetricConfig.metric_generator(...)传入类名/类路径/类及列名列表等价于 Evidently 的generate_column_metrics。columns参数支持字符串快捷方式all全部列含 target/prediction、num数值特征、cat分类特征、text文本特征、features全部特征列不含 target/predictionNone等价于all还可通过skip_id_columnTrue跳过 ID 列。值得一提的实现细节metric()与metric_generator()在构造配置后会立即调用to_evidently_metric()尝试实例化一次以便尽早发现参数错误to_evidently_metric()则根据is_generator标志决定调用generate_column_metrics还是直接metric_class(**parameters)实例化。3.5 在管道中接入 Report Step内置 Report Step 可接收两个数据集并同时输出 JSON 与 HTML 格式的报告例如from zenml import pipeline from zenml.config import DockerSettings # 注docker_settings 在别处定义 # 注data_loader, data_splitter, text_data_report, text_data_test, text_analyzer 为自定义 step 函数 pipeline(enable_cacheFalse, settings{docker: docker_settings}) def text_data_report_test_pipeline(): 将所有步骤串联成一个管道。 data data_loader() reference_dataset, comparison_dataset data_splitter(data) report, _ text_data_report( reference_datasetreference_dataset, comparison_datasetcomparison_dataset, ) test_report, _ text_data_test( reference_datasetreference_dataset, comparison_datasetcomparison_dataset, ) text_analyzer(report) text_data_report_test_pipeline()如果只需处理单个数据集不传对比数据集即可text_data_report(reference_datasetreference_dataset)3.6 透传 Report 选项evidently_report_step还支持把额外的 Report 选项传给Report构造器例如自定义配色。该能力由EvidentlyDataValidator._unpack_options()实现列表中的每一项由两部分组成——选项类基于dataclass的完整类路径字符串以及该选项实例的 kwargs 字典from zenml.integrations.evidently.steps import ( EvidentlyColumnMapping, ) text_data_report evidently_report_step.with_options( parametersdict( report_options [ ( evidently.legacy.options.ColorOptions, { primary_color: #5a86ad, fill_color: #fff4f2, zero_line_color: #016795, current_data_color: #c292a1, reference_data_color: #017b92, } ), ], ) )以上等价于实例化ColorOptions并逐个设置颜色字段。四、数据验证evidently_test_step 内置 Step除数据画像外Evidently 还能配置并运行自动化的数据验证测试。与画像一样也有三种灵活度不同的使用方式内置 Test Step、Data Validator 方法、直接使用 Evidently 库。ZenML 将 Evidently 的数据验证能力封装为标准 Test Step通过evidently_test_step工具函数实例化与配置from zenml.integrations.evidently.steps import ( EvidentlyColumnMapping, evidently_test_step, ) from zenml.integrations.evidently.tests import EvidentlyTestConfig text_data_test evidently_test_step.with_options( parametersdict( column_mappingEvidentlyColumnMapping( targetRating, numerical_features[Age, Positive_Feedback_Count], categorical_features[ Division_Name, Department_Name, Class_Name, ], text_features[Review_Text, Title], ), tests[ EvidentlyTestConfig.test(DataQualityTestPreset), EvidentlyTestConfig.test_generator( TestColumnRegExp, columns[Review_Text, Title], reg_expr[A-Z][A-Za-z0-9 ]*, ), ], # 测试 TestColumnRegExp 需要下载 NLTK 数据 download_nltk_dataTrue, ), )上述配置等价于在 Step 内执行如下 Evidently 原生代码from evidently.legacy.tests import TestColumnRegExp from evidently.legacy.test_preset import DataQualityTestPreset from evidently.legacy.pipeline.column_mapping import ColumnMapping from evidently.legacy.test_suite import TestSuite from evidently.legacy.tests.base_test import generate_column_tests import nltk nltk.download(words) nltk.download(wordnet) nltk.download(omw-1.4) column_mapping ColumnMapping( targetRating, numerical_features[Age, Positive_Feedback_Count], categorical_features[ Division_Name, Department_Name, Class_Name, ], text_features[Review_Text, Title], ) test_suite TestSuite( tests[ DataQualityTestPreset(), generate_column_tests( TestColumnRegExp, columns[Review_Text, Title], parameters{reg_exp: r[A-Z][A-Za-z0-9 ]*} ) ] ) # 数据集即传入 Evidently Step 的输入 artifact test_suite.run( current_datacurrent_dataset, reference_datareference_dataset, column_mappingcolumn_mapping, )4.1 配置字段拆解evidently_test_step的配置与传给 EvidentlyTestSuite对象的参数一致column_mappingEvidentlyColumnMapping对象与画像场景中的含义与用法完全相同。testsEvidentlyTestConfig对象列表以声明式方式配置测试套件要运行的测试等价于 EvidentlyTestSuite中的tests。download_nltk_data布尔值仅在使用处理文本数据的 Evidently 测试或测试 preset 时需要置为True。与画像 Step 类似evidently_test_step 源码 也支持ignored_cols与test_options参数区别在于Test Step 遇到ignored_cols中列不存在于数据集时会直接抛出ValueError而 Report Step 仅记录警告并跳过缺失列返回值同样是(test_json, test_html)二元组。4.2 引用 Evidently Test 的三种方式与 metric 的引用方式一一对应按类名例如DataQualityTestPreset、TestColumnRegExp按完整类路径例如evidently.legacy.test_preset.DataQualityTestPreset、evidently.legacy.tests.TestColumnRegExp直接传入类本身from evidently.legacy.tests import TestColumnRegExp evidently_test_step.with_options( parametersdict( tests[EvidentlyTestConfig.test(TestColumnRegExp)] ), )4.3 添加 test 的两种方法添加单个 test 或 preset调用EvidentlyTestConfig.test(...)其余参数为 test 类的构造参数。批量生成多个 column test调用EvidentlyTestConfig.test_generator(...)等价于 Evidently 的generate_column_testscolumns同样支持all/num/cat/text/features快捷字符串与列名列表。tests.py 的实现与 metrics 模块完全对称get_test_class依次在evidently.legacy.tests与evidently.legacy.test_preset中按名查找to_evidently_test()根据is_generator调用generate_column_tests或直接实例化。4.4 在管道中接入 Test Steppipeline(enable_cacheFalse, settings{docker: docker_settings}) def text_data_test_pipeline(): 将所有步骤串联成一个管道。 data data_loader() reference_dataset, comparison_dataset data_splitter(data) json_report, html_report text_data_test( reference_datasetreference_dataset, comparison_datasetcomparison_dataset, ) text_data_test_pipeline()单数据集版本同样简单——不传对比数据集text_data_test(reference_datasetreference_dataset)4.5 透传 Test 选项与 Report 选项机制相同evidently_test_step支持把额外选项传给TestSuite构造器from zenml.integrations.evidently.steps import ( EvidentlyColumnMapping, ) text_data_test evidently_test_step.with_options( parametersdict( test_options [ ( evidently.legacy.options.ColorOptions, { primary_color: #5a86ad, fill_color: #fff4f2, zero_line_color: #016795, current_data_color: #c292a1, reference_data_color: #017b92, } ), ], ), )五、第三种方式直接调用 Evidently Data Validator如果你希望保留 Data Validator 抽象带来的可移植性未来可平滑切换到其他 Data Validator同时又想对 Step 内部逻辑有更大控制权可以在自定义 Step 中直接调用EvidentlyDataValidator的方法。它以get_active_data_validator()获取当前激活的组件实例提供data_profiling(...)生成Report与data_validation(...)生成TestSuite两个核心方法from typing import Annotated from typing import Tuple import pandas as pd from evidently.legacy.pipeline.column_mapping import ColumnMapping from zenml.integrations.evidently.data_validators import EvidentlyDataValidator from zenml.integrations.evidently.metrics import EvidentlyMetricConfig from zenml.integrations.evidently.tests import EvidentlyTestConfig from zenml.types import HTMLString from zenml import step step def data_profiling( reference_dataset: pd.DataFrame, comparison_dataset: pd.DataFrame, ) - Tuple[ Annotated[str, report_json], Annotated[HTMLString, report_html] ]: 使用 Evidently 的自定义数据画像 step。 Args: reference_dataset: 一个 Pandas DataFrame comparison_dataset: 要与参考数据对比的新数据 DataFrame Returns: 以 JSON 和 HTML 格式渲染的 Evidently 报告。 # 预处理如数据集准备可以在这里进行 data_validator EvidentlyDataValidator.get_active_data_validator() report data_validator.data_profiling( datasetreference_dataset, comparison_datasetcomparison_dataset, profile_list[ EvidentlyMetricConfig.metric(DataQualityPreset), EvidentlyMetricConfig.metric( TextOverviewPreset, column_nameReview_Text ), EvidentlyMetricConfig.metric_generator( ColumnRegExpMetric, columns[Review_Text, Title], reg_expr[A-Z][A-Za-z0-9 ]*, ), ], column_mapping ColumnMapping( targetRating, numerical_features[Age, Positive_Feedback_Count], categorical_features[ Division_Name, Department_Name, Class_Name, ], text_features[Review_Text, Title], ), download_nltk_data True, ) # 后处理如解读结果、采取行动可以在这里进行 return report.json(), HTMLString(report.show(modeinline).data) step def data_validation( reference_dataset: pd.DataFrame, comparison_dataset: pd.DataFrame, ) - Tuple[ Annotated[str, test_json], Annotated[HTMLString, test_html] ]: 使用 Evidently 的自定义数据验证 step。 Args: reference_dataset: 一个 Pandas DataFrame comparison_dataset: 要与参考数据对比的新数据 DataFrame Returns: 以 JSON 和 HTML 格式渲染的 Evidently 测试套件结果。 # 预处理如数据集准备可以在这里进行 data_validator EvidentlyDataValidator.get_active_data_validator() test_suite data_validator.data_validation( datasetreference_dataset, comparison_datasetcomparison_dataset, check_list[ EvidentlyTestConfig.test(DataQualityTestPreset), EvidentlyTestConfig.test_generator( TestColumnRegExp, columns[Review_Text, Title], reg_expr[A-Z][A-Za-z0-9 ]*, ), ], column_mapping ColumnMapping( targetRating, numerical_features[Age, Positive_Feedback_Count], categorical_features[ Division_Name, Department_Name, Class_Name, ], text_features[Review_Text, Title], ), download_nltk_data True, ) # 后处理如解读结果、采取行动可以在这里进行 return test_suite.json(), HTMLString(test_suite.show(modeinline).data)从 evidently_data_validator.py 的实现可以看到data_profiling与data_validation都遵循相同的内部流程先处理 NLTK 数据路径与下载当profile_list/check_list未提供时分别回退到EvidentlyMetricConfig.default_metrics()与EvidentlyTestConfig.default_tests()——前者使用除TextOverviewPreset因默认数据没有文本列外的全部 MetricPreset后者使用全部 TestPreset随后将声明式配置逐个实例化为 Evidently 对象解包选项构造Report/TestSuite并执行run(reference_datadataset, current_datacomparison_dataset, column_mappingcolumn_mapping)。六、第四种方式在自定义 Step 中直接使用 Evidently当内置 Step 与 Data Validator 抽象都不足以满足需求时可以直接在管道 Step 中使用 Evidently 原生库获得完全的自由度from typing import Annotated from typing import Tuple import pandas as pd from evidently.legacy.report import Report from evidently.legacy.metric_preset import DataQualityPreset from evidently.legacy.test_suite import TestSuite from evidently.legacy.test_preset import DataQualityTestPreset from evidently.legacy.pipeline.column_mapping import ColumnMapping from zenml.types import HTMLString from zenml import step step def data_profiler( dataset: pd.DataFrame, ) - Tuple[ Annotated[str, report_json], Annotated[HTMLString, report_html] ]: 使用 Evidently 的自定义数据画像 step。 Args: dataset: 一个 Pandas DataFrame Returns: 以 JSON 和 HTML 格式生成的 Evidently 报告。 # 预处理如数据集准备可以在这里进行 report Report(metrics[DataQualityPreset()]) report.run( current_datadataset, reference_datadataset, ) # 后处理如解读结果、采取行动可以在这里进行 return report.json(), HTMLString(report.show(modeinline).data) step def data_tester( dataset: pd.DataFrame, ) - Tuple[ Annotated[str, test_json], Annotated[HTMLString, test_html] ]: 使用 Evidently 的自定义数据测试 step。 Args: dataset: 一个 Pandas DataFrame Returns: 以 JSON 和 HTML 格式生成的 Evidently 测试结果。 # 预处理如数据集准备可以在这里进行 test_suite TestSuite(tests[DataQualityTestPreset()]) test_suite.run( current_datadataset, reference_datadataset, ) # 后处理如解读结果、采取行动可以在这里进行 return test_suite.json(), HTMLString(test_suite.show(modeinline).data)七、报告与测试结果的可视化你可以直接在 ZenML Dashboard 中查看管道 Step 生成的 Evidently 报告可视化在管道运行 DAG 中点击对应的 artifact 即可。下图展示了报告与测试结果在 Dashboard 中的典型渲染效果如果在 Jupyter notebook 中运行也可以通过artifact.visualize()方法加载并渲染报告from zenml.client import Client def visualize_results(pipeline_name: str, step_name: str) - None: pipeline Client().get_pipeline(pipelinepipeline_name) evidently_step pipeline.last_run.steps[step_name] evidently_step.visualize() if __name__ __main__: visualize_results(text_data_report_pipeline, text_report) visualize_results(text_data_test_pipeline, text_test)由于内置两个 Step 都返回(JSON 字符串, HTMLString)形式的 artifact报告 JSON 可被下游 Step 继续消费做程序化判定例如自动化的质量门禁HTML 则用于人类可视化与存档。八、实战模式将 Evidently 报告接入质量门禁仓库中的 e2e 示例 给出了一个完整的落地模式在批量推理管道中用evidently_report_step对比训练数据参考数据集与当前推理数据然后在后续 Step 中消费返回的 JSON 报告做自动化判定from zenml.integrations.evidently.metrics import EvidentlyMetricConfig from zenml.integrations.evidently.steps import evidently_report_step report, _ evidently_report_step( reference_datasetmodel.get_artifact(dataset_trn), comparison_datasetdf_inference, ignored_cols[target], metrics[ EvidentlyMetricConfig.metric(DataQualityPreset), ], ) drift_quality_gate(report)其中drift_quality_gate是一个典型的质量门禁 Step见 drift_quality_gate.py它解析 Evidently JSON 报告比较参考数据与当前数据缺失值数量的相对偏差超过阈值即抛出RuntimeError中断管道从而实现数据质量不达标即止损的自动化防护。这种报告 门禁的组合正是 Evidently 与 ZenML 协作的最佳实践——前者提供检测能力后者提供管道编排、artifact 版本化存储与失败告警管道可挂载on_failure通知钩子。九、小结ZenML 的 Evidently 集成提供了从数据画像、数据/模型漂移检测到性能评估、再到自动化质量门禁的完整闭环能力。四种使用方式覆盖了从零配置开箱即用到完全自定义的全部灵活度区间内置evidently_report_step与evidently_test_step适合大多数场景EvidentlyDataValidator方法调用兼顾抽象兼容性与灵活性直接调用 Evidently 库则适用于高度定制化需求。无论选择哪种方式JSON 与 HTML 双格式的输出 artifact 都让结果既可被程序消费、又便于人工审阅为你的 ML 管道构建了一道稳固的数据质量防线。需要进一步了解的点关于每个 metric/test 的用途及其要求的数据列请查阅 Evidently 官方文档中的完整指标列表关于 Evidently 集成的全部配置参数与 API可查阅 ZenML SDK 文档中zenml.integrations.evidently的集成代码文档。【免费下载链接】zenmlZenML : One AI Platform from Pipelines to Agents. https://zenml.io.项目地址: https://gitcode.com/GitHub_Trending/ze/zenml创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考