揭示不完美:我们的MLOps课程创作背后的有趣现实

全栈7步MLOps框架

附加课程:一次“不完美”ML项目的幕后故事——经验和见解

Photo by Hassan Pasha on Unsplash

本文是一个由7个课程组成的附加课程,它将逐步指导您如何使用MLOps良好实践 设计、实现和部署ML系统。在课程期间,您将构建一个生产就绪模型,用于预测丹麦多个消费者类型未来24小时的能源消耗水平。

在课程期间,您将学习使用批处理服务架构设计、编码和部署ML系统的所有基础知识。

本课程面向中高级ML或软件工程师,他们想通过构建自己的ML端到端项目来提升自己的技能。

现在,证书无处不在。构建您自己的高级端到端项目,并在以后展示它们,是获得专业工程师认可的最佳方法。

目录:

  • 课程介绍
  • 课程内容
  • 数据源
  • 附加课程:一次“不完美”ML项目的幕后故事——经验和见解
  • 结论
  • 参考文献

课程介绍

在这7个课程中,您将学习如何:

  • 设计批处理服务架构
  • 使用Hopsworks作为特征存储
  • 设计一个特征工程流水线,从API读取数据
  • 构建具有超参数调整的训练流水线
  • 使用W&B作为ML平台,跟踪您的实验、模型和元数据
  • 实现批量预测流水线
  • 使用Poetry构建自己的Python包
  • 部署自己的私有PyPi服务器
  • 使用Airflow编排所有内容
  • 使用预测结果使用FastAPI和Streamlit编写Web应用程序
  • 使用Docker容器化您的代码
  • 使用Great Expectations确保数据验证和完整性
  • 随时间监测预测性能
  • 部署所有ML组件到GCP
  • 使用GitHub Actions构建CI/CD管道

如果您还没有关注这个系列并且它听起来像是您感兴趣的东西,我想让您知道,在完成课程后,您将理解我之前说的一切。最重要的是,您将看到为什么我使用了所有这些工具以及它们如何作为一个系统协同工作。

如果您想从本课程中获得最大的收益, 我建议您访问GitHub存储库 包含所有课程代码。本课程旨在快速阅读并复制文章中的代码。

在课程期间,您将学习如何实现下面的图示。在逐步解释它之后,它听起来不再那么可怕了,对吧?

Diagram of the architecture built during the course [Image by the Author].

在这个最终的附加课程中,我们想谈谈可以针对当前架构进行的潜在改进以及在课程期间所做的设计选择。我们还想强调我们必须做出的权衡,并为您提供未来项目的一些想法。

把它看作是幕后花絮部分👀

课程内容:

  1. 批量服务。特征存储。特征工程流水线。
  2. 训练流水线。ML平台。超参数调整。
  3. 批量预测流水线。使用Poetry打包Python模块。
  4. 私有PyPi服务器。使用Airflow编排所有内容。
  5. 使用GE进行数据验证,以确保数据质量和完整性。模型性能持续监测。
  6. 使用FastAPI和Streamlit消耗和可视化模型的预测结果。Docker化所有内容。
  7. 将所有ML组件部署到GCP。使用Github Actions构建CI/CD管道。
  8. [附加]一次“不完美”ML项目的幕后故事——经验和见解

这个额外课程将公开分享课程的权衡、设计选择和潜在改进。

因此,如果您对构建生产就绪的ML系统感兴趣,我们强烈建议您阅读课程的其余部分👇

构建生产就绪的特征工程流水线框架

第1课:批处理服务。特征存储。特征工程流水线。

towardsdatascience.com

数据来源

我们使用了一个免费且开放的API,该API提供了丹麦所有能源消费类型的每小时能源消费值[1]。

他们提供了一个直观的界面,您可以轻松查询和可视化数据。您可以在这里访问数据[1]。

数据有4个主要属性:

  • UTC时间:数据点被观察到的UTC日期时间。
  • 价格区域:丹麦分为两个价格区域:DK1和DK2 – 被大带分隔。DK1在大带以西,DK2在大带以东。
  • 消费者类型:消费者类型是丹麦能源拥有和维护的工业代码DE35。
  • 总消耗:以千瓦时为单位的总电力消耗。

注意:观察有15天的延迟!但对于我们的演示用例,这不是问题,因为我们可以模拟实时相同的步骤。

我们的Web应用程序的屏幕截图,显示我们如何预测区域= 1和consumer_type = 212的能源消耗 [作者的图像]。

数据点具有每小时的分辨率。例如:“2023–04–15 21:00Z”,“2023–04–15 20:00Z”,“2023–04–15 19:00Z”等。

我们将数据建模为多个时间序列。每个唯一的价格区域消费者类型元组代表了其唯一的时间序列。

因此,我们将构建一个模型,独立地为每个时间序列预测未来24小时的能源消耗。

观看下面的视频以更好地了解数据的外观👇

课程和数据源概述[作者的视频]。

额外课程:一个“不完美”的ML项目的幕后故事-教训和见解

不再闲聊。让我们直接跳到幕后🔥

课程期间构建的架构图[作者的图像]。

整体代码

#1. 重复代码

房间里的大象是,我们在不同的Python模块之间有很多重复的代码,这不符合万能的DRY原则。

例如,ML管道的settings.py和utils.py文件或UI的下拉列表+折线图组件。

此代码可以重构为在所有其他模块之间共享的通用模块。

#2. 类,而不是函数!

使用类对代码进行建模是一种好的实践,但我们在课程中仅使用了函数。

我们可以为每个流水线创建一个中央类,例如FeaturesExtractor,Trainer和BatchPredictor。

此外,我们可以创建一个RunResult类,而不是返回包含运行元数据的普通字典,以更好地控制数据的传递。

#3. 没有测试 😟

任何代码库都需要大量的单元测试和集成测试来验证对代码所做的所有更改。

管道设计

#1. DAG 有状态

由于 DAG 具有状态,因此很难并行运行它。我们的问题在于,您需要来自先前运行的预测来计算监视指标。

因此,根据定义,您不能在不同时间点运行相同 DAG 的多个并行实例。

什么时候会出现问题?

当回填时。假设您想要回填最近 2 个月的每个小时。如果您按顺序运行程序,那将花费很长时间。

因此,我们建议将监视组件移动到另一个 DAG。

#2. 避免使用“:latest”作为您的资源版本

如果您使用“:latest”标记访问资源,例如:

  • 模型的工件,
  • 数据(特征存储特征视图或训练数据集),
  • 最佳配置工件等。

… 您会引入 ML 管道的多个运行之间的依赖关系。

这很微妙,但让我解释一下 👇

假设您并行运行 2 个 ML 管道:A & B。管道 A 首先生成新的数据集版本。然后由于任何原因,管道 B 在管道 A 之前启动训练管道,并访问由管道 A 创建的“latest”数据集版本。

这也称为并行计算中的“竞态条件”。

在这种情况下,可以通过在同一管道的任务之间硬编码资源的版本来轻松解决。

例如,不要访问“dataset:latest”,而是访问“dataset:v3”。

如您所见,回填时速度至关重要。因此,长期来看并行运行 DAG 是必不可少的。

Airflow

#1. 使用 Docker 任务

这不一定是一个问题,但我想强调的是,您可以将代码放在 Docker 容器中而不是使用 Python 环境——任务 Docker 装饰器文档 [2]。

主要好处是使系统更具可扩展性。

但好消息是,在课程中学习的过程非常相似。您只需将 Python 包推送到 PyPi 注册表而已,现在您只需将 Docker 映像推送到 Docker 注册表。

#2. 更小的原子任务

在我们的情况下,DAG 中的任务包含大量逻辑。它们基本上运行整个应用程序。

这不一定是坏事,但将其分成更小的片段是一种好的做法。因此,从给定故障点调试、监视和重新启动 DAG 更加容易。

例如,我们可以使用 Airflow 的 GCS 运算符之一而不是在 Python 中读取/写入 GCS 中的数据——GCS Airflow 运算符 [3]。

#3. 从 Airflow 注入超参数调整设置

目前,超参数调整设置硬编码到一个configs/gridsearch.py文件中。

这不是很灵活,因为修改配置的唯一选择是将新版本推送到 git,这不是很实用。

一种解决方案是从 YAML 文件中注入设置,这可以很容易地添加到 Airflow 工作流中。

ML 模型的一个不错的 YAML 配置工具是 Facebook Research 的 Hydra。尝试一下,您会感谢我的。

监控

#1. 不监控系统的健康状况

我们可以通过定期对 API 的 /health 端点进行 ping 操作轻松添加系统健康监控机制。

我们可以在 UI 上用一个绿色/红色面板反映这一点。

#2. 没有警报

基于我们不断监测的 MAPE 指标,我们可以添加一些警报系统,例如:

  • 警告 [threshold_B > MAPE > threshold_A]:通知工程师可能出现问题;
  • 报警器 [MAPE > threshold_B > threshold_A]:通知工程师出现了问题 + 触发超参数调整逻辑。

#3. 丰富UI

我们可以为每个时间序列单独添加MAPE指标。

#4. 不要重复造轮子!

我们实现了一个小型监控工具,只是作为示例。但在真实场景中,您应该利用现有工具,如EvidentlyAI或Arize。

这些工具和软件包已经为您提供了专业解决方案。因此,您可以专注于增加价值。

#5. 监控漂移

作为一个好的补充,监控数据和概念漂移也会很有帮助。但是由于我们几乎拥有实时的GT,所以这只是一个好的补充。

Web应用程序-预测仪表板

#1. 丰富UI

用户界面相当基础。例如,我们可以通过添加文本和警报来丰富用户界面,当数据无效时(未通过验证套件)。

#2. 我们以天真的方式请求数据

我们对API的请求相当天真。通常,这些步骤都受到异常的保护,捕捉300、400和500响应代码上的不同行为。

#3. 设置是硬编码的

我们可以使用 .env 文件注入设置。从而使程序更具可配置性。类似Web应用程序FastAPI代码。

部署和CI/CD流程

#1. 部分CI实现

为了完全完成CI/CD流程,我们可以构建Web应用程序Docker镜像,将它们推送到Docker注册表,并在部署到GCP VM时从那里拉取它们。

构建使用Poetry的Python包相同。

这就是按照书本上的方法完成的。

此外,如果我们有任何测试,我们应该在部署代码之前运行它们。

另一个想法是运行命令,例如 flake8 ,以验证代码是否使用PEP8约定编写。

#2. 在不同的VM上托管PyPi

此外,建议将PyPi服务器托管在不同的VM上,或者至少完全独立于Airflow组件。

这样做,系统将更加模块化和灵活。

#3. 在GCS存储桶中托管.env文件

我们可以将 .env 文件存储在GCS存储桶中,并在CI/CD流程中自动下载它们,而不是手动完成和复制它们。

#4. 自动化基础设施

您已经看到手动设置所需的所有GCP资源是多么无聊……而这只是一个小的基础设施。想象一下当您的基础设施中有100个或1000个组件时会怎样。

这就是为什么建议使用Terraform等IoC工具自动创建您的基础设施。

结论

如果您走到了这一步,我要感谢您,并告诉您我是多么地感激您跟随我的完整堆栈7步MLOps框架课程🙏

在这个奖励课程中,您看到了没有完美的系统,您总是不得不在以下方面做出某些权衡:

  • 时间限制,
  • 资源限制,
  • 糟糕的规划。

现在,您已经看到每个人都在学习,不知道全部,您没有任何借口,而是去构建您的下一个真棒项目🔥

让我们在LinkedIn上联系,让我知道您是否有任何问题或与我分享您的项目。

在此处访问GitHub存储库。

💡我的目标是帮助机器学习工程师提升设计和生产化ML系统的能力。在LinkedIn上关注我或订阅我的每周通讯以获取更多见解!

🔥如果您喜欢阅读此类文章并希望支持我的写作,请考虑成为小猪AI会员。使用我的推荐链接,您可以在不额外花费成本的情况下支持我,同时享受小猪AI丰富的故事收藏。

作为小猪AI会员,您的会费的一部分将用于支付您阅读的作家,并且您可以完全访问每个故事…

pauliusztin.medium.com

谢谢 ✌🏼 !

参考资料

[1] 来自丹麦API的DE35行业代码每个能源消耗,丹麦能源数据服务

[2] 任务Docker装饰器,Airflow文档

[3] GCS Airflow操作员,Airflow文档