生产型机器学习系统:监控流水线

恭喜!您已部署独角兽模型。您的模型应全天候运行,且不会出现任何问题。为确保系统能够正常运行,您必须监控机器学习 (ML) 流水线。

编写数据架构以验证原始数据

如需监控数据,您应编写数据必须满足的规则,以便持续检查数据是否与预期的统计值相符。这组规则称为数据架构。请按照以下步骤定义数据架构:

  1. 了解特征的范围和分布情况。对于分类特征,了解一组可能值。

  2. 将您的理解编码到数据架构中。以下是规则示例:

    • 确保用户提交的评分始终在 1 到 5 之间。
    • 检查“the”这个词的出现频率是否最高(对于英语文本特征)。
    • 检查每个分类特征是否都设置为固定可能值集合中的值。
  3. 对照数据架构测试您的数据。您的架构应捕获数据错误,例如:

    • 异常
    • 分类变量的值不符合预期
    • 意外的数据分布

编写单元测试以验证特征工程

虽然您的原始数据可能会通过数据架构的验证,但模型不会使用原始数据进行训练。而是使用经过特征工程处理的数据进行训练。例如,您的模型会根据归一化后的数值特征(而非原始数值数据)进行训练。由于经过特征工程处理的数据可能与原始输入数据截然不同,因此您必须将对经过特征工程处理的数据的检查与对原始输入数据的检查分开进行。

根据您对特征工程数据的理解编写单元测试。 例如,您可以编写单元测试来检查是否存在以下情况:

  • 所有数值特征都会进行缩放,例如,介于 0 到 1 之间。
  • 经过独热编码的矢量仅包含 1 个 1 和 N-1 个 0。
  • 转换后的数据分布符合预期。例如,如果您使用 Z 分数进行了标准化,则 Z 分数的平均值应为 0。
  • 处理离群值,例如通过缩放剪裁

查看重要数据片段的指标

成功的整体有时会掩盖失败的子集。换句话说,即使模型的整体指标非常出色,在某些情况下,其预测结果也可能非常糟糕。例如:

您的独角兽模型总体表现良好,但在为撒哈拉沙漠进行预测时表现不佳。

如果您是那种只满足于整体 AUC 较高的工程师,那么您可能不会注意到模型在撒哈拉沙漠中的表现问题。如果为每个区域做出准确的预测非常重要,那么您需要跟踪每个区域的效果。数据子集(例如与撒哈拉沙漠对应的子集)称为数据切片

确定感兴趣的数据片段。然后,将这些数据片段的模型指标与整个数据集的指标进行比较。检查模型在所有数据片段上的表现有助于消除偏差。如需了解详情,请参阅公平性:评估偏差

使用实际指标

模型指标不一定能衡量模型的实际影响。例如,更改超参数可能会提高模型的 AUC,但这种更改对用户体验有何影响?若要衡量实际影响,您需要定义单独的指标。例如,您可以对模型的用户进行调查,以确认在模型预测他们会看到独角兽时,他们确实看到了独角兽。

检查是否存在训练-应用偏差

训练-应用偏差是指训练期间的输入数据与应用中的输入数据不同。下表介绍了两种重要的偏差类型:

类型 定义 示例 解决方案
架构偏差 训练和服务输入数据不符合相同的架构。 服务数据的格式或分布会发生变化,而模型会继续使用旧数据进行训练。 使用相同的架构来验证训练数据和应用数据。 确保单独检查架构未检查的统计信息,例如缺失值的比例
特征偏差 训练数据和应用数据之间的工程化数据不同。 训练和部署阶段的特征工程代码不同,生成的工程化数据也不同。 与架构偏差类似,对训练数据和应用数据采用相同的统计规则。跟踪检测到的偏差特征的数量,以及每个特征的偏差示例比例。

导致训练-应用偏差的原因可能很细微。请始终考虑模型在预测时可用的数据。在训练期间,请仅使用您在服务时可用的特征。

练习:检查您的理解情况

假设您拥有一家网店,并希望预测您在特定日期的收入。您的机器学习目标是使用客户数量作为特征来预测每日收入。

您可能会遇到什么问题?
点击此处查看答案

检查是否存在标签泄露

标签泄露是指您尝试预测的标准答案标签无意中进入了您的训练特征。标签泄露有时很难检测到。

练习:检查您的理解情况

假设您构建了一个二元分类模型,用于预测新入住医院的患者是否患有癌症。您的模型使用以下功能:

  • 患者年龄
  • 患者性别
  • 既往病史
  • 医院名称
  • 生命体征数据
  • 测试结果
  • 遗传

标签如下所示:

  • 布尔值:患者是否患有癌症?

您仔细划分数据,确保训练集与验证集和测试集完全隔离。模型在验证集和测试集上的表现非常出色;指标非常出色。遗憾的是,在现实生活中,该模型对新患者的表现非常糟糕

为什么这个在测试集上表现出色的模型在实际应用中却惨败?
点击此处查看答案

在整个流水线中监控模型年龄

如果服务数据会随时间推移而演变,但您的模型未定期重新训练,那么您会发现模型质量会下降。跟踪模型使用新数据重新训练以来的时间,并为提醒设置阈值年龄。除了监控模型在提供时的年龄外,您还应监控整个流水线中的模型年龄,以便发现流水线停滞。

测试模型权重和输出的数值稳定性

在模型训练期间,权重和层输出不应为 NaN(非数字)或 Inf(无穷大)。编写测试以检查权重和层输出的 NaN 和 Inf 值。 此外,请测试某个层的输出中超过一半的输出不为零。

监控模型性能

您的独角兽外观预测器的受欢迎程度超出预期!您收到大量预测请求,并且训练数据量也越来越大。您会认为这很棒,直到您发现模型的训练需要越来越多的内存和时间。您决定按照以下步骤监控模型的性能:

  • 按代码、模型和数据版本跟踪模型性能。通过此类跟踪,您可以准确找出导致任何性能下降的确切原因。
  • 针对新模型版本,与之前的版本和固定阈值对比测试每秒的训练步骤数。
  • 通过设置内存用量阈值来捕获内存泄漏。
  • 监控 API 响应时间并跟踪其百分位数。虽然 API 响应时间可能超出您的控制范围,但响应缓慢可能会导致实际指标不佳。
  • 监控每秒回答的查询数量。

使用传送的数据测试实时模型的质量

您已验证模型。但是,如果在记录验证数据后,真实场景(例如独角兽行为)发生变化,该怎么办?这样一来,所提供模型的质量就会下降。不过,由于真实数据并不总是带标签,因此很难在投放时测试质量。如果您的投放数据未标记,请考虑进行以下测试:

  • 使用人工评分员生成标签

  • 调查在预测中存在明显统计偏差的模型。请参阅分类:预测偏差

  • 跟踪模型的实际指标。例如,如果您要对垃圾内容进行分类,请将您的预测结果与用户报告的垃圾内容进行比较。

  • 通过对部分查询提供新模型版本,可减少训练数据与应用数据之间的潜在差异。在验证新的分发模型时,请逐渐将所有查询切换到新版本。

使用这些测试时,请务必监控预测质量的突然下降和缓慢下降。

随机

使数据生成流水线可重现。假设您想添加一个特征,以了解它对模型质量有何影响。为了确保实验公平,除了这项新功能外,您的数据集应完全相同。因此,请确保数据生成中的所有随机化操作都可以进行确定性处理:

  • 为随机数生成器 (RNG) 设置种子。设置种子值可确保每次运行 RNG 时,它都会按相同的顺序输出相同的值,从而重新创建数据集。
  • 使用不变的哈希键。 哈希处理是拆分或抽样数据的常用方法。您可以对每个示例进行哈希处理,并使用生成的整数来确定将示例放置在哪个分块中。每次运行数据生成程序时,哈希函数的输入不应发生变化。请勿在哈希中使用当前时间或随机数,例如,如果您想按需重新创建哈希。

上述方法适用于数据采样和拆分。

哈希的注意事项

再假设一下,您正在收集搜索查询,并使用哈希处理来包含或排除查询。如果哈希键仅使用了该查询,那么在多天的数据中,您将始终包含该查询或始终排除该查询。始终包含或始终排除查询是不好的做法,因为:

  • 训练集中的查询会不那么多样化。
  • 评估集将会人为地设置为难度较高,因为它们不会与训练数据重叠。实际上,在投放时,您会在训练数据中看到一些实时流量,因此评估结果应反映这一点。

您可以改为按查询 + 日期进行哈希处理,这样每天的哈希值都会不同。

 

图 7. 动画可视化图表:仅对查询进行哈希处理会导致数据每天都进入同一存储分区,但对查询和查询时间进行哈希处理会导致数据每天都进入不同的存储分区。这三个分桶分别是“训练”“评估”和“忽略”。
图 7. 按查询进行哈希处理与按查询和查询时间进行哈希处理。