您可以查看数据中的历史漂移,以了解您的数据如何变化并选择监控阈值。 这是一个带有 Evidently、Plotly、Mlflow 和一些 Python 代码的示例。
我们经常谈论检测实时数据的漂移。
然后,目标是检查当前分布是否偏离训练或过去某个时期。 当检测到漂移时,您就知道您的模型在相对未知的空间中运行。 是时候做点什么了。
但这里有很多细微差别。 漂移有多大? 如果我的特征只有 10% 漂移,我应该关心吗? 我应该逐周还是逐月查看漂移呢?
细节决定成败。 答案在很大程度上取决于模型、用户场景、重新训练的难易程度以及性能下降的成本。
这是一个可以帮助您思考的过程。
让我们来看看历史数据漂移!
为什么要看过去的数据漂移?
我们的目标是学习漂移动态。 过去我们的数据发生了多大变化?
这很有用,原因有两个:
首先,我们可以了解模型衰减曲线。
关于如何提前检查模型再训练需求,我们分享了一个类似的想法。 在那里,我们研究了模型性能如何随时间变化。
现在,我们看看数据是如何变化的。 如果我们知道我们必须在生产中等待ground truth标签,那么了解数据漂移尤其有用。
假设数据以某种恒定的速度变化,我们可以使用此分析来设定我们的期望。 并准备适当的基础设施。
用例是否高度动态? 我们是否应该为频繁的再训练和建立自动流水线做好准备?
其次,这个分析可以帮助我们定义模型监控触发器。
一旦模型投入生产,我们可能想要检查数据漂移。 我们的触发器应该有多敏感? 我们需要做什么才能对漂移做出反应?
要选择阈值和条件,我们需要了解我们的数据过去是如何变化的。 这是一个微妙的平衡! 我们不希望有太多误报,但我们也希望对有意义的变化做出反应。
我们可以对过去的数据进行多次漂移检查(建模不同的漂移阈值和监控窗口)并探索结果。
下面是如何做到这一点的示例教程。
定义漂移检测逻辑
让我们从 Kaggle 获取一个共享单车数据集。 我们将使用它来探索过去的数据漂移。 您可以在此Jupyter notebook示例中关注它。
在现实生活中,您可以对训练数据进行类似的处理。
为了解决我们的漂移检测逻辑,我们应该做一些假设。
首先,我们应该定义比较窗口。
例如,我们可以逐月查看数据。此选择取决于您对数据的理解。数据是如何产生的?它背后的真实世界过程是什么?你预计它会以多快的速度改变?
这里有一些提示:
- 如果您的数据具有已知的季节性,您可以考虑它。例如,进行逐周比较,而不是逐日比较,以避免对周末模式反应过度。或者比较不同年份的 12 月数据。
- 如果您知道模型恶化的速度有多快,请将其作为起点。我们之前分享过这种方法。如果您知道您的模型会在一个月内退化,您可以查看每周漂移,以了解您可以提前多长时间预测这种下降。
- 您可以构建多个漂移“views”并设置不同的期望。例如,查看每周和每月的漂移并设置不同的阈值。用例定义了它:您可以有多个季节性或者其他的已知模式。
你可以测试一些假设,看看这会如何改变结果。
我们的第二个假设是漂移检测阈值。
我们可以使用统计测试评估单个特征的漂移,并根据 P 值判断结果。
但是要对其采取行动或实施监控触发器,我们通常需要一些“yes”或“no”的决定或整个数据集的总数。为此,我们可以在统计测试的结果之上实现一些自定义逻辑。
例如,我们可以查看漂移特征的份额,并且仅在超过 50% 的特征发生统计显着变化时才发出警报。
我们还可以操纵统计测试的置信度。通常的默认值为 0.95,但您可能有理由将其设置为 0.99 或 0.9。
这里有一些提示:
- 您可以只关注关键特征。您可以根据重要性为特征分配不同的权重,或者仅对最重要的特征运行漂移检测。并非所有的漂移都是平等的。次要特征的变化通常不会影响关键性能指标。
- 如果你有很多弱特征,你可以看看整体漂移。但在这种情况下,您可以增加阈值来定义已经发生漂移(无论是在较高的置信度水平还是特征数量方面)。
在我们的示例中,我们有几个月的数据。
让我们定义我们的假设:
- 我们使用第一个月作为训练数据。
- 我们逐月进行漂移比较。
- 我们将测试单个特征和数据集的漂移。
- 在数据集漂移的情况下,我们将统计测试的置信度设置为 0.95。我们将所有特征视为同等重要,如果超过 50% 的特征漂移,则认为我们的数据集已经发生漂移。
示例代码
要查看所有详细信息,请访问我们的 Jupyter notebook示例。
为了实现这种方法,我们将使用以下库:
- JSON、pandas 和 NumPy 作为处理数据所需的标准库。
- Plotly,可视化我们的数据漂移。
- Evidently,使用统计测试来计算漂移。
- Mlflow,日志和记录结果。
一旦我们导入库,接下来我们加载数据,如下所示:
我们定义列映射来指定特征类型。 这是使用 Evidently 执行正确的统计测试所必需的。
data_columns = {} data_columns['numerical_features'] = ['weather', 'temp', 'atemp', 'humidity', 'windspeed'] 复制代码
我们还定义了我们的参考数据(第一个月)和之后的时间段来评估漂移。 我们将每个月的数据视为一个实验。
reference_dates = ('2011-01-01 00:00:00','2011-01-28 23:00:00') experiment_batches = [ ('2011-02-01 00:00:00','2011-02-28 23:00:00'), ('2011-03-01 00:00:00','2011-03-31 23:00:00'), ('2011-04-01 00:00:00','2011-04-30 23:00:00'), ('2011-05-01 00:00:00','2011-05-31 23:00:00'), ('2011-06-01 00:00:00','2011-06-30 23:00:00'), ('2011-07-01 00:00:00','2011-07-31 23:00:00'), ] 复制代码
接下来,我们实现了两个自定义函数。 他们在 Evidently Profiles 提供的统计测试结果之上引入了逻辑。
第一个有助于检测数据集漂移。 它将在整体漂移上返回一个 TRUE 或 FALSE 响应。 我们可以设置统计测试的置信水平并选择漂移特征的阈值。 我们还可以通过将 get_ratio 设置为 TRUE 来计算漂移特征的份额。
第二个有助于检测特征漂移。 Evidently已经在 JSON Profile输出中返回了各个特征的 P 值。 我们添加这个函数来获得每个特征的是否漂移:1 表示漂移,0 表示没有漂移。 我们可以设置统计测试的置信水平。 而且,我们仍然可以通过将 get_pvalues 设置为 TRUE 来获得每个特征的 P 值。
您可以按照此示例构建自定义逻辑。
可视化特征漂移
让我们从特征漂移开始。
我们调用我们的函数来评估单个特征的漂移。
features_historical_drift = [] for date in experiment_batches: drifts = detect_features_drift(raw_data.loc[reference_dates[0]:reference_dates[1]], raw_data.loc[date[0]:date[1]], column_mapping=data_columns, confidence=0.95, threshold=0.9) features_historical_drift.append([x[1] for x in drifts]) features_historical_drift_frame = pd.DataFrame(features_historical_drift, columns = data_columns['numerical_features']) 复制代码
然后,我们使用 Plotly 在热力图上可视化结果。 我们将检测到漂移的时间段涂成红色。
这是我们得到的:
哎哟! 一点都不稳。
事实是,我们采用了一个季节性很强的用例。 我们的数据实际上是关于天气的。 温度、湿度、风速模式逐月变化很大。
这给了我们一个非常明确的信号,即我们需要考虑最新数据并经常更新模型。
如果我们想以更细化的方式查看它,我们可以绘制我们的 P 值。 我们将 get_pvalues 设置为 TRUE,然后生成一个新图。
如果发生更细微的变化,将 P 值视为梯度会很有帮助,而不仅仅是用于漂移的布尔值 TRUE/FALSE。
可视化数据集漂移
现在让我们调用一个函数来计算数据集漂移。
了解数据的波动性后,我们将阈值设置得很高。 只有当 90% 的特征在分布上有统计变化时,我们才称它为漂移(DRIFT)。
dataset_historical_drift = [] for date in experiment_batches: dataset_historical_drift.append(detect_dataset_drift(raw_data.loc[reference_dates[0]:reference_dates[1]], raw_data.loc[date[0]:date[1]], column_mapping=data_columns, confidence=0.95)) 复制代码
这就是每个月的结果。
您还可以设置更精细的视图并使用每个月内漂移特征的份额进行绘图。
根据用例,您可以选择不同的方式来显示此数据,例如条形图。
记录漂移
当我们的目标是探索或共享信息时,可视化很有帮助。
但我们可能还想在其他地方简单地记录特征和数据集漂移测试的数字结果。 例如,我们想要记录一个漂移值作为实验的结果。
或者,我们想为生产中的模型跟踪它。
一旦我们定义了我们的漂移条件,我们就可以监控它们是否满足。 无论生产中是否发生漂移,我们都希望获得布尔响应,或者根据某个阈值触发警报。
要记录漂移结果,我们可以使用 Mlflow 跟踪。 它是用于管理 ML 生命周期的流行库。 在这种情况下,我们使用 Evidently 和我们的自定义函数来生成输出(数据集漂移指标),然后使用 Mlflow 记录它。
您可以在 Jupyter notebook 中的示例中进行操作。 这是一件容易的事!
这是结果在 Mlflow 中的界面。 我们为每次运行记录了数据集漂移指标。
或者这里是一个展开的视图:
适应您的用户场景
您可以根据您的用例调整此示例。
例如,您可以修改漂移检测逻辑以更好地考虑手头的用例。 您可以测试几种组合并选择适当的窗口和漂移条件。
您还可以使用其他Evidently报表。 例如,除了数据漂移之外,您还可以生成性能报告来记录模型质量指标。 然后,您可以按照类似的步骤使用 Plotly 可视化历史模型性能来分析模型衰减测试的结果。
当然,这种方法也适用于生产环境。 尤其是当您运行批处理模型时。 例如,您定期对您的数据和预测运行漂移检查,并使用 Mlflow 将其记录下来,或者只是将其写入数据库。