全栈7步MLOps框架
第6课:使用FastAPI和Streamlit消费和可视化模型预测结果。Docker化一切
本教程是由7个课程中的第6个课程,将为您逐步介绍如何使用MLOps良好实践设计、实现和部署一个ML系统。在本课程期间,您将构建一个可生产的模型,用于预测丹麦多个消费类型未来24小时的能源消耗水平。
通过本课程,您将了解使用批量服务架构设计、编码和部署ML系统的所有基础知识。
本课程面向中级/高级机器学习工程师,希望通过构建自己的端到端项目来提升自己的技能。
现在,证书无处不在,构建高级的端到端项目,并在以后展示出来,是获得专业工程师认可的最佳方式。
目录:
- 课程介绍
- 课程内容
- 数据来源
- 第6课:使用FastAPI和Streamlit消费和可视化模型预测结果。Docker化一切。
- 第6课:代码
- 结论
- 参考文献
课程介绍
在本7课程结束时,您将了解如何:
- 设计批处理服务架构
- 使用Hopsworks作为特征存储
- 设计从API读取数据的特征工程管道
- 构建具有超参数调整的训练管道
- 使用W&B作为ML平台跟踪您的实验、模型和元数据
- 实现批量预测管道
- 使用Poetry构建自己的Python包
- 部署您自己的私有PyPi服务器
- 使用Airflow协调一切
- 使用FastAPI和Streamlit的预测来编写Web应用程序
- 使用Docker将代码容器化
- 使用Great Expectations确保数据验证和完整性
- 随时间监控预测性能
- 将所有内容部署到GCP
- 使用GitHub Actions构建CI/CD管道
如果听起来很多,请不要担心。在学习本课程后,您将了解我之前提到的所有内容。最重要的是,您将知道为什么要使用所有这些工具以及它们如何作为一个系统协同工作。
如果您想从本课程中获得最大收益,我建议您访问包含所有课程代码的GitHub存储库。本课程旨在快速阅读和复制文章中的代码。
在本课程结束时,您将知道如何实现下图。如果有什么不明白的地方,请不要担心,我会详细解释。
到第6课结束时,您将知道如何使用FastAPI和Streamlit在Web应用程序中消费预测和监控指标。
课程内容:
- 批量服务。特征存储。特征工程管道。
- 训练管道。ML平台。超参数调整。
- 批量预测管道。使用Poetry打包Python模块。
- 私有PyPi服务器。使用Airflow协调一切。
- 使用GE进行数据质量和完整性验证。模型性能持续监控。
- 使用FastAPI和Streamlit消费和可视化模型预测结果。Docker化一切。
- 将所有内容部署到GCP。使用GitHub Actions构建CI/CD管道。
查看第三课,了解我们如何计算和存储预测结果在 GCP 存储桶中。
此外,在第五课中,您可以看到我们如何计算监控指标,这些指标也存储在 GCP 存储桶中。
您将从 GCP 存储桶中使用预测结果和监控指标,并使用 FastAPI 和 Streamlit 在友好的仪表板中显示它们。
数据来源
我们使用了一个免费且开放的 API,提供了丹麦所有能源消费类型的每小时能源消费值[1]。
他们提供了一个直观的界面,您可以轻松查询和可视化数据。您可以从这里访问数据[1]。
数据有 4 个主要属性:
- UTC 小时:数据点被观察到的 UTC 日期时间。
- 价格区域:丹麦分为两个价格区域:DK1 和 DK2 — 由大带分隔。DK1 位于大带以西,DK2 位于大带以东。
- 消费类型:消费类型是由丹麦能源拥有和维护的行业代码 DE35。
- 总消耗量:以千瓦时为单位的总电力消耗量
注意:观测值有 15 天的滞后!但对于我们的演示用例来说,这不是问题,因为我们可以模拟与实时相同的步骤。
数据点具有每小时的分辨率。例如:“2023–04–15 21:00Z”,“2023–04–15 20:00Z”,“2023–04–15 19:00Z”等。
我们将把数据建模为多个时间序列。每个唯一的价格区域和消费类型元组都代表其唯一的时间序列。
因此,我们将构建一个模型,独立预测每个时间序列未来 24 小时的能源消耗。
观看下面的视频,以更好地了解数据的外观👇
课程和数据来源概述[作者提供的视频]。
第 6 课:使用 FastAPI 和 Streamlit 消耗和可视化模型的预测结果。 Dockerize 一切。
第 6 课的目标
在第 6 课中,您将构建一个 FastAPI 后端,该后端将消耗 GCS 中的预测结果和监控指标,并通过一组端点将其通过 HTTP(S) 公开。更具体地说,通过一组端点通过 HTTP(S) 公开数据。
此外,您将使用 Streamlit 实现 2 个不同的前端应用程序:
- 显示预测的仪表板(也称为您的应用程序),
- 显示监控指标的仪表板(也称为您的监控仪表板)。
这两个前端应用程序都将通过 HTTP(s) 从 FastAPI RESTful API 请求数据,并使用 Streamlit 将数据呈现为一些美丽的图表。
我想强调的是,您可以在 Python 中使用这两个框架(FastAPI 和 Streamlit)。这对于数据科学家或机器学习工程师非常有用,因为 Python 是他们的终极目标。
请注意,从存储桶中读取预测的过程与 3 管道设计完全解耦。例如,运行 3 个管道:特征工程师、训练和推断需要 ~10 分钟。但是从存储桶中读取预测或监控指标几乎是即时的。
因此,通过将预测结果缓存到GCP中,您可以从客户端的角度在线提供ML模型:预测结果是实时提供的。
这就是批处理架构的魔力。
下一步自然是将您的架构从批处理架构转移到请求-响应或流式架构。
好消息是FE和训练管道几乎相同,您只需要将批处理预测管道(也称为推理步骤)移动到您的Web基础架构中。阅读本文以了解使用Docker以请求-响应方式部署模型的基础知识。
为什么?
因为训练管道将经过训练的模型的权重上传到模型注册表中。从那里,您可以根据您的用例最佳地使用权重。
理论概念和工具
FastAPI:最新和最著名的Python API Web框架之一。我已经尝试过所有顶级Python API Web框架:Django,Flask和FastAPI,我的心归于FastAPI。
为什么?
首先,它是本地异步的,可以通过更少的计算资源提高性能。
其次,它易于使用和直观,这使得它适用于各种规模的应用程序。即使对于庞大的单体,我仍然会选择Django。但这是另一个话题。
Streamlit: Streamlit使编写简单的UI组件(主要是仪表板)变得极其容易,只需使用Python。
Streamlit的范围是让数据科学家和ML工程师使用他们最擅长的东西,即Python,快速构建模型的美观前端。
这正是我们所做的✌️
因此,您将使用FastAPI作为后端,Streamlit作为前端,仅使用Python构建Web应用程序。
课程6:代码
您可以在此处访问GitHub存储库。
注意:所有安装说明都在存储库的README中。在这里,您将直接跳转到代码。
第6课的代码位于以下位置:
- app-api文件夹- FastAPI后端
- app-frontend文件夹-预测仪表板
- app-monitoring文件夹-监控仪表板
使用Docker,您可以快速同时启动所有3个组件:
docker compose -f deploy/app-docker-compose.yml --project-directory . up --build
直接在您的git存储库中存储凭据是巨大的安全风险。这就是为什么您将使用.env文件注入敏感信息的原因。
.env.default是您必须配置的所有变量的示例。对于不敏感的属性(例如项目名称),存储默认值也很有帮助。
准备凭据
对于本课程,您只需要访问GCS服务。在第3课的“准备凭据”部分中,我们已经详细解释了如何做到这一点。此外,您可以在GitHub README中获得更多信息。
为了简洁起见,在本课程中,我想强调,出于安全原因,Web应用程序GCP服务帐户应仅具有读取访问权限。
为什么?
因为FastAPI API仅从GCP存储桶中读取数据,将权限保持到最低限度是一个好习惯。
因此,如果您的Web应用程序被黑客攻击,攻击者只能使用窃取的服务帐户凭据读取数据。他无法删除或覆盖数据,这种情况更加危险。
因此,重复第3课的“准备凭据”部分中的相同步骤,但是选择存储对象查看器角色,而不是选择存储对象管理员角色。
请记住,现在您必须下载一个不同的JSON文件,其中包含您具有只读访问权限的GCP服务帐户密钥。
查看README以了解如何完成 .env 文件。我想强调的是,只有FastAPI后端将需要加载 .env 文件。因此,您必须将 .env 文件放在 app-api 文件夹中。
FastAPI后端
FastAPI后端概述[作者提供的视频]。
作为提醒,FastAPI代码可以在 app-api / api 下找到。
第1步:创建FastAPI应用程序,其中我们配置了文档、CORS中间件和端点根API路由器。
第2步:定义Settings类。这个类的范围是在API代码中持有您需要的所有常量和配置,例如:
- 通用配置:端口、日志级别或版本,
- GCP凭据:bucket名称或JSON服务帐户密钥的路径。
您将使用Settings对象在整个项目中使用 get_settings() 函数。
此外,在 Config 类中,我们编写了FastAPI,以查找当前目录中的 .env 文件,并加载所有以 APP_API_ 为前缀的变量。
如 .env.default 文件中所示,所有变量都以 APP_API_ 开头。
第3步:使用Pydantic定义API数据的模式。这些模式将JSON编码或解码为Python对象或反之亦然。它们还基于您定义的数据模型验证JSON对象的类型和结构。
在定义Pydantic BaseModel时,对于每个变量添加一个类型是至关重要的,这将在验证步骤中使用。
第4步:定义您的端点,在Web术语中称为视图。通常,视图可以访问某些数据存储,并基于查询将数据源的子集返回给请求者。
因此,检索(即GET请求)数据的标准流程如下:
“客户端→请求数据→端点→访问数据存储→编码为Pydantic模式→解码为JSON→响应请求数据”
让我们看看如何定义一个端点以获取所有消费者类型:
我们使用 gcsfs.GCSFileSystem 将GCS存储桶作为标准文件系统进行访问。
我们将端点附加到 api_router 。
使用 api_router.get() Python装饰符,我们将一个基本函数附加到 /consumer_type_values 端点。
在上面的例子中,当调用“ https://<some_ip>:8001/api/v1/consumer_type_values ”时,将触发 consumer_type_values() 函数,并且端点的响应将严格基于函数返回的内容。
另一个重要的事情是要强调,通过在Python装饰符中定义 response_model(即模式),您不必显式创建Pydantic模式。
如果您返回的字典是1:1的,且符合模式结构,FastAPI将自动为您创建Pydantic对象。
就这样。现在我们将重复相同的逻辑来定义其余的端点。FastAPI为您提供了一切如此简单和直观。
现在,让我们看看整个 views.py 文件,我们在其中为以下内容定义了端点:
- /health →健康检查
- /consumer_type_values →获取所有可能的消费者类型
- /area_values →获取所有可能的区域类型
- /predictions/{area}/{consumer_type} →获取给定区域和消费者类型的预测。请注意,使用{<some_variable>}语法,您可以向端点添加参数——FastAPI文档[2]。
- /monitoring/metrics →获取聚合监视指标
- /monitoring/values/{area}/{consumer_type} →获取给定区域和消费者类型的监视值
我想再次强调,FastAPI后端仅读取GCS存储桶的预测结果。推理步骤完全在批处理预测流水线中完成。
您还可以前往“http://<your-ip>:8001/api/v1/docs”访问API的Swagger文档,在那里您可以轻松查看和测试所有端点:
就是这样!现在您知道如何构建FastAPI后端了。当添加数据库层和用户会话时,情况可能会变得更加复杂,但您已经学会了所有的主要概念,这将帮助您入门!
Streamlit预测仪表板
Streamlit预测仪表板概述 [作者提供的视频]。
在app-frontend/frontend下可以访问代码。
使用Streamlit非常简单。整个UI的定义是使用下面的代码完成的,它执行以下操作:
- 定义标题,
- 向后端请求所有可能的区域类型,并基于此创建下拉列表,
- 向后端请求所有可能的消费者类型,并基于此创建下拉列表,
- 根据当前选择的区域和消费者类型,构建并呈现一个plotly图表。
很简单,对吧?
请注意,我们可以对HTTP请求的状态代码进行其他检查。例如,如果请求状态代码与200不同,请显示“服务器已关闭”的文本。但我们想保持简单,并强调仅Streamlit代码 ✌️
我们将所有常量移动到一个不同的文件中,以便在整个代码中轻松访问。下一步,您可以通过一个.env文件使它们可配置,类似于FastAPI的设置。
现在,让我们看看我们如何构建图表🔥
这部分不包含Streamlit代码,只包含一些Pandas和Plotly代码。
build_data_plot()函数执行3个主要步骤:
- 从FastAPI后端请求区域和消费者类型的预测数据。
- 如果响应有效(status_code == 200),则从响应中提取数据并从中构建DataFrame。否则,它将创建一个空的DataFrame以将相同的结构传递给下一个步骤。
- 使用上面计算的DataFrame构建一个线条图-plotly图表。
build_dataframe()函数的作用是将2个列表:
- 用作线条图X轴的日期时间列表;
- 用作线条图Y轴的值列表;
…并将它们转换为DataFrame。如果有一些数据点丢失,我们会将日期时间重新采样为1H的频率,以使数据连续并突出显示缺失的数据点。
很简单,对吧?这就是为什么人们喜欢Streamlit。
Streamlit监控仪表板
Streamlit监控仪表板概述 [作者提供的视频]。
监控代码可以在app-monitoring/monitoring下访问。
您将看到该代码与预测仪表板几乎相同。
在定义Streamlit UI结构时,我们还实现了包含聚合指标的图形和分隔符。
将UI组件的定义与数据访问解耦的好处是,只要您尊重预期数据的接口,就可以向UI注入任何数据而无需修改它。
build_metrics_plot()函数与预测仪表板中的build_data_plot()函数几乎相同,除了我们从API请求的数据。
对于监控仪表板中的build_data_plot()函数,情况也是如此:
如您所见,所有数据访问和操作都由FastAPI后端处理。Streamlit UI的工作是请求和显示数据。
很好,我们仅重用了90%的预测仪表板代码来构建友好的监控仪表板。
用Docker包装全部内容
最后一步是将3个Web应用程序Docker化并在docker-compose文件中包装它们。
因此,我们可以使用单个命令启动整个Web应用程序:
docker compose -f deploy/app-docker-compose.yml --project-directory . up --build
这里是FastAPI Dockerfile:
<p要强调的有趣事情是,我们最初只复制和安装了Poetry依赖项。因此,当您修改代码时,Docker映像将仅从第19行开始重新构建,即从复制代码开始。
这是一种常见的策略,可利用Docker缓存功能构建映像以加快开发过程,因为您很少添加新依赖项,并且安装它们是最耗时的步骤。
此外,在run.sh中,我们调用:
/usr/local/bin/python -m api
但是,命令中没有Python文件😟
好吧,您实际上可以在模块内部定义一个__main__.py文件,使您的模块可执行。
因此,在调用api 模块时,您会调用__main__.py 文件:
在我们的情况下,在__main__.py 文件中,我们使用uvicorn web服务器启动FastAPI后端,并根据正确的IP、端口、日志级别等进行配置。
这里是Streamlit预测仪表板 Dockerfile :
正如您所看到的,这个Dockerfile与用于FastAPI后端的Dockerfile几乎相同,除了最后一个CMD命令,这是启动Streamlit应用程序的标准CLI命令。
Streamlit监控仪表板Dockerfile与预测仪表板Dockerfile相同。因此,将其复制粘贴到此处是多余的。
好消息是,您可以利用我上面展示的Dockerfile模板来Docker化大多数Python应用程序✌️
最后,让我们看看如何使用docker-compose包装全部内容。您可以在deploy/app-docker-compose.yml下访问该文件:
正如您所看到的,前端和监控服务必须等待API打开才能启动。
此外,只有API需要从.env 文件加载凭据。
现在,您可以只使用以下命令运行整个Web应用程序,Docker将负责构建映像并运行容器:
docker compose -f deploy/app-docker-compose.yml --project-directory . up --build
结论
恭喜您完成了Full Stack 7-Steps MLOps Framework课程的第六课。这意味着您现在了解如何利用您的ML系统的预测来构建您的出色应用程序。
在本课程中,您学习了如何:
- 从GCS消费预测和监控指标,
- 构建FastAPI后端以从GCS加载和提供数据,
- 在Streamlit中实现仪表板以显示预测,
- 在Streamlit中创建监控仪表板以可视化模型的性能。
现在,您了解了基于批处理预测架构构建应用程序的灵活性,您可以轻松设计全栈机器学习应用程序。
请查看第7课,了解Full Stack 7-Steps MLOps Framework的最后一步,即将所有内容部署到GCP并使用GitHub Actions构建CI/CD管道。
此外,您可以在此处访问GitHub存储库。
💡我的目标是帮助机器学习工程师在设计和生产化ML系统方面提高水平。关注我的LinkedIn或订阅我的每周简报以获取更多见解!
🔥 如果您喜欢阅读这样的文章并希望支持我的写作,请考虑成为小猪AI会员。使用我的推荐链接,在享受小猪AI丰富故事库的无限访问权的同时,您可以在不增加额外费用的情况下支持我。
使用我的推荐链接加入小猪AI – Paul Iusztin
🤖 加入以获取有关设计和构建生产就绪的ML系统的独家内容 🚀 解锁完整访问权限…
pauliusztin.medium.com
谢谢 ✌🏼!
参考文献
[1] 来自丹麦API的DE35行业代码每单位能耗,丹麦能源数据服务
[2] 路径参数,FastAPI文档