鉴于需要将机器学习(ML)工作流进行操作化,机器学习运维(MLOps) 近期应运而生。MLOps旨在促进向易于生产的实际ML系统的更平滑过渡。这一方法整合了若干关键原则,这些原则基于软件工程、机器学习和DevOps的最佳实践。另一方面,时间序列预测 是工业界中最常见的ML问题之一,广泛应用于制造业、零售业、能源和金融等行业。
在我们“ 在Google Cloud Platform上的MLOps端到端系统”系列的第一篇文章中,我们介绍了在开发ML解决方案过程中采用的基于MLOps的方法。MLOps 一瞥(图片来自 Patrik Sharma)
第二篇文章,MLOps 端到端系统在 Google 云平台 (II): 详细解决方案,可以在这里阅读 here。
将MLOps理解为确保高效且可靠的机器学习系统的原理和最佳实践集合,我们在开发过程中一直致力于遵循该范式的所有关键点。
模块化是指基于独立的组件或模块开发系统,每个组件都有其特定的功能或任务。这有助于解决方案的可扩展性和可重用性,同时也便于将这些单一组件灵活地集成以构建更完整的系统。
从一开始我们就有了这个想法,虽然这不仅是MLOps的最佳实践,也是通用软件开发的一部分,但在构建组件(即,训练和推理管道中的步骤)时已经考虑到了这一点。每个步骤都设计有其具体的目的,理想情况下应该是确定性的(相同的输入 = 相同的输出)。通过这种做法,我们在训练和推理管道中重用了相同的步骤(例如,我们的自定义 add_lags 管道步骤)。输入和输出使步骤之间能够进行通信和工件传输。
管道执行图的片段。每个组件在其管道步骤中执行特定任务(由作者提供图片)。
ML 管道代表一系列独立但相互连接的任务(表示为组件),每个任务都有其特定的目的,这些任务被串联起来以构建完整的流程。MLOps 需要对这些复杂的流程进行自动化和编排,这些流程必须协同运行。这些任务主要由 Vertex AI,Google Cloud 的完全托管的 ML 平台来处理。
我们在整个系统开发中的核心工作集中在使用 Vertex AI 和 Kubeflow Pipelines (KFP) 开发 可重用、可扩展 和 一致的ML管道 上。如前所述,尽管这两个管道是分别开发的,并使用模块化组件(每个组件都有自己的独立任务),但它们在完整的ML系统中应 相应地运行。例如,必须遵循相同的特征工程过程(例如,添加某些日期时间或滞后特征),或者在两种情况下(训练/推理)必须配置相同的预测时间范围。
感谢 Vertex AI 平台 中的管道编排和自动化,持续训练(CT) 也得到了保证。这在处理时间序列数据时尤其有意义,因为特征通常会随着时间自然漂移(例如,由于季节性或周期性趋势),并且使用最新记录进行更新有时是严格必要的。此外,我们的系统支持 按需重新训练 ,如果工程师发现模型性能随时间显著下降,可以从我们的 UI 触发重新训练。
我们ML预测系统中的计划管道(作者提供图片)。
CI/CD 管道也是 MLOps 范式的核心。它们支持自动化某些原本需要手动步骤的任务。
通过利用 Cloud Build,GCP 的无服务器 CI/CD 平台,我们构建了多个工作流以增强特定功能并优化频繁流程。
### cloudbuild-trainer-image-workflow.yaml steps: - id: '克隆Cloud Source Repository' name: 'gcr.io/cloud-builders/gcloud' args: ['source', 'repos', 'clone', '${_CLOUD_SOURCE_REPOSITORY}', '--project=${PROJECT_ID}' ] - id: '构建更新的Trainer Docker镜像' name: 'gcr.io/cloud-builders/docker' args: ['build', '-f', '${_DOCKERFILE_NAME}', '-t', '${_ARTIFACT_REGISTRY_REPO_LOCATION}-docker.pkg.dev/${PROJECT_ID}/${_ARTIFACT_REGISTRY_REPO_NAME}/${_TRAINER_IMAGE_NAME}:${_TRAINER_IMAGE_TAG}', '.' ] # 执行此步骤的工作目录 dir: '${_CLOUD_SOURCE_REPOSITORY}/training-pipeline' substitutions: _CLOUD_SOURCE_REPOSITORY: 'poc-mlops-asset' _CLOUD_SOURCE_REPOSITORY_URI: 'workspace/${_CLOUD_SOURCE_REPOSITORY}' _ARTIFACT_REGISTRY_REPO_LOCATION: 'us-central1' _ARTIFACT_REGISTRY_REPO_NAME: 'poc-mlops-asset' _TRAINER_IMAGE_NAME: 'time-series-trainer' _TRAINER_IMAGE_TAG: 'latest' _DOCKERFILE_NAME: 'trainer.Dockerfile' options: dynamicSubstitutions: true logging: CLOUD_LOGGING_ONLY tags: ['training-pipeline'] # 这会自动将构建的镜像推送到Artifact Registry images: ['${_ARTIFACT_REGISTRY_REPO_LOCATION}-docker.pkg.dev/${PROJECT_ID}/${_ARTIFACT_REGISTRY_REPO_NAME}/${_TRAINER_IMAGE_NAME}:${_TRAINER_IMAGE_TAG}']
Cloud Build 构建历史记录(用于 Trainer 图像的 CI/CD 工作流)(由作者提供图像)。
Kubeflow Pipelines 仓库在 GCP Artifact Registry 中(作者提供图片)。
存储管道运行让我们能够跟踪和比较机器学习实验,贯穿整个机器学习系统的生命周期以及随时间的变化。这使得进一步探索不同超参数组合对训练模型性能的影响成为可能。
## task.py 代码片段来自 Trainer 源代码 aiplatform.init(project=PROJECT_ID, experiment=EXPERIMENT_NAME) with aiplatform.start_run(PIPELINE_RUN_NAME): # 记录训练参数 aiplatform.log_params(xgb_params) # ... # 记录训练性能(TensorBoard) for i, rmse in enumerate(val_error): aiplatform.log_time_series_metrics({'rmse': rmse}, step=i) # ... # 记录训练指标 aiplatform.log_metrics({"mse_train": mse_train, "mse_test": mse_test})
我们使用Vertex AI Experiments来跟踪训练管道的运行。训练脚本负责将选定的超参数和生成的训练指标记录到我们特定的实验中,以便在需要时存储所有这些数据以供进一步分析。
Vertex AI 实验训练运行性能比较(作者绘制的图片)。
模型注册表是MLOps中的一个重要概念。它能够使模型管理和版本控制更加容易,作为机器学习模型的存储库,并且代表了我们训练(注册模型)和推理(检索模型)管道之间的连接。
在我们的MLOps系统中,Vertex AI 模型注册表 是我们预测模型的集中存储。此外,我们的训练管道将模型工件(例如,model.joblib,model.pickle)存储在 Google Cloud Storage (GCS) 的指定存储桶目录中。
测试机器学习系统需要采用一种与传统软件略有不同的方法。管道组件应设计为可以使用单元测试进行测试。然而,一些与外部源(例如BigQuery)交互的组件则不受此设计规则的限制。
为此,我们使用了pytest作为我们的测试框架。由于我们的Python基KFP组件是经过装饰的Python函数,关键的想法是测试的不是组件本身,而是内部函数。此外,有时还需要模拟输入和输出的工件。
管理ML工作流消耗和生成的元数据的生命周期至关重要,因此本章涉及存储所有ML管道日志,以便在出现问题时协助调试任务。
GCP 服务在此任务中为我们提供了帮助,因为 Vertex AI 管道 将所有元数据和管道执行工件存储在 Vertex ML 元数据 和 Google Cloud Storage (GCS) 中,日志则集中存储在 Logs Explorer 中。
在机器学习系统设计中,一个最具有挑战性的任务是持续监控数据和概念漂移以及模型性能。特别是在我们这种预测场景中,这尤其具有挑战性,因为实际值通常在模型预测已经误导我们之后才出现。延迟的真实值使得反馈循环变慢,难以发现表现不佳的模型。为此,监控数据和目标漂移对于模型维护至关重要,理解特征或目标的漂移甚至对于调试模型衰退也很重要。有时可能需要重新训练模型,但关键是要充分理解整个环境,以确定这是否能改善预测,或者是否只是可以避免的额外开销。
对于这项任务,我们选择了Evidently.AI,一个开源的ML可观测性平台。它提供了跟踪数据漂移和目标漂移的方法,研究传入数据的分布,检查预期的数据模式,并进行多种验证(例如,具有漂移的特征比例,值范围出乎意料的特征),还可以比较模型性能与训练性能,以检测模型衰减或(可能的)过拟合。
我们的策略是在预定的推断时间之前生成每日监控报告和测试套件,这样所有的真实记录都已经可用,我们可以将推断时间的输入数据与模型训练时的数据进行比较。因此,我们探索 (1) 推断时使用的数据,以研究是否存在数据漂移,以及 (b) 当天预测中的模型性能。
Evidently仪表板:测试套件和监控报告(数据漂移、模型性能)(作者提供图片)。
注意:理想情况下,这些每天生成的测试套件报告可以在认为必要时触发重新训练。
这种做法不仅包括对源代码进行版本控制,还包括对编译的管道、训练的Docker镜像、预测的模型甚至训练的数据集进行版本控制。这使得在整个机器学习生命周期的所有步骤中都能有一个全面的概览,并且在发生意外事件时也有助于调试。
GCP Artifact Registry 中的管道仓库。
在我们的MLOps系统中,管道模板(包括训练和推理)和训练者Docker镜像通过Kubeflow Pipelines仓库和Docker仓库在Artifact Registry中进行版本管理和存储。如前所述,Vertex AI Model Registry用于管理ML模型的版本。另一方面,Vertex AI 数据集负责管理训练数据集的版本(这得益于GCP内置组件‘TimeSeriesDatasetCreateOp’,该组件在数据处理完成后被包含在我们的训练管道中)。
为了总结这次初步阅读,我们整理了一些可能的使用场景,在这些场景中,像我们所提议的端到端预测解决方案可能是一个很好的替代选择:
为了详细了解我们如何开发机器学习解决方案,请参阅我们系列文章中的第二篇:**[MLOps 端到端系统在 Google 云平台 (II): 我们解决方案的详细说明](https://medium.com/gft-engineering/mlops-end-to-end-system-on-google-cloud-platform-ii-our-solution-in-detail-029bcea531eb)。**
有任何问题或建议?随时联系我们!
罗伯托·赫南德兹·鲁伊斯
费兰·阿兰·多明戈
@GFT Technologies, 人工智能服务