MLFlow-机器学习工程-二-

65 阅读1小时+

MLFlow 机器学习工程(二)

原文:annas-archive.org/md5/e98213c48352ec428afb655035096e6f

译者:飞龙

协议:CC BY-NC-SA 4.0

第七章:数据和特征管理

在本章中,我们将向正在构建的机器学习平台添加一个特征管理数据层。我们将利用 MLflow Projects 模块的功能来结构化我们的数据管道。

具体来说,在本章中,我们将查看以下部分:

  • 结构化您的数据管道项目

  • 获取股票数据

  • 检查数据质量

  • 管理特征

在本章中,我们将获取相关数据以提供用于训练的数据集。我们的主要资源将是雅虎财经数据集 BTC。除了这些数据,我们还将获取以下额外数据集。

利用在第六章中介绍的引入 ML 系统架构的生产化架构,如图 7.1 所示,特征和数据组件负责从源获取数据,并使数据以平台不同组件可消费的格式可用:

![图 7.1 – 带数据层引用的高级架构]

![img/image0013.jpg]

图 7.1 – 带数据层引用的高级架构

让我们深入本章,看看我们将如何结构化和填充数据层,以包含用于训练模型和生成特征的相关数据。

技术要求

对于本章,您需要以下先决条件:

在下一节中,我们将描述我们的数据管道结构、数据源以及我们将执行的不同步骤来实现我们的实际示例,利用 MLflow 项目功能来打包项目。

注意

直接从代码片段复制粘贴可能会导致您的编辑器出现问题。请参阅本章在 github.com/PacktPublis… 上的 GitHub 仓库。

结构化您的数据管道项目

从高层次来看,我们的数据管道将每周运行一次,收集前 7 天的数据,并以机器学习作业可运行的方式存储。我们将我们的数据文件夹结构化为三种类型的数据:

  • 原始数据:通过从 Yahoo Finance API 获取过去 90 天的数据生成的数据集。我们将以 CSV 格式存储数据——与从 API 收到的格式相同。我们将在 MLflow 中记录运行并提取收集到的行数。

  • 阶段数据:在原始数据上,我们将运行质量检查、模式验证,并确认数据可用于生产。有关数据质量的信息将记录在 MLflow 跟踪中。

  • 训练数据:训练数据是数据管道的最终产品。它必须在被认为是干净且适合执行模型的数据上执行。数据包含已处理成可以直接用于训练过程的功能数据。

这种文件夹结构最初将在文件系统中实现,并在部署期间转换为相关环境(例如:AWS S3、Kubernetes PersistentVolume 等)。

为了执行我们的数据管道项目,我们将使用 MLflow 项目 模块以与执行环境无关的格式打包数据管道。我们将使用 Docker 格式打包 MLflow 项目。Docker 格式为我们提供了不同的选项,根据可用的基础设施,我们可以将项目部署在云端或本地:

图片

图 7.2 – 具有数据层引用的高级架构

我们的工作流程将执行以下步骤,如图 图 7.2 所示:

  1. data/raw/data.csv 文件夹.

  2. data/staged/data.csv 文件.

  3. data/training/data.csv 位置.

通过这三个不同的阶段,我们确保了训练数据生成过程的可重复性、可见性和过程不同步骤的清晰分离。

我们将首先将我们的 MLflow 项目组织成步骤,并为管道的每个组件创建占位符:

  1. 在您的本地机器上创建一个名为 psytock-data-features 的新文件夹。

  2. 添加 MLProject 文件

    name: pystock_data_features
    conda:
      file: conda.yaml
    entry_points:
      data_acquisition:
        command: "python data_acquisition.py"
      clean_validate_data:
        command: "python clean_validate_data.py "
      feature_set_generation:
        command: "python feature_set_generation.py"
      main:
        command: "python main.py"
    
  3. 添加以下 conda.yaml 文件:

        name: pystock-data-features
    channels:
      - defaults
    dependencies:
      - python=3.8
      - numpy
      - scipy
      - pandas
      - cloudpickle
      - pip:
        - git+git://github.com/mlflow/mlflow
        - pandas_datareader
        - great-expectations==0.13.15
    
    
  4. 您现在可以向文件夹中添加一个示例 main.py 文件,以确保项目的基本结构正在工作:

    import mlflow
    import click
    def _run(entrypoint, parameters={}, source_version=None, use_cache=True):
        #existing_run = _already_ran(entrypoint, parameters, source_version)
        #if use_cache and existing_run:
        #    print("Found existing run for entrypoint=%s and parameters=%s" % (entrypoint, parameters))
         #   return existing_run
        print("Launching new run for entrypoint=%s and parameters=%s" % (entrypoint, parameters))
        submitted_run = mlflow.run(".", entrypoint, parameters=parameters)
        return submitted_run
    @click.command()
    def workflow():
        with mlflow.start_run(run_name ="pystock-data-pipeline") as active_run:
            mlflow.set_tag("mlflow.runName", "pystock-data-pipeline")
            _run("load_raw_data")
            _run("clean_validate_data")
            _run("feature_set_generation")
    
    if __name__=="__main__":
        workflow()
    
  5. 通过运行以下命令测试基本结构:

    mlflow run .
    

    此命令将根据您的 conda.yaml 文件创建的环境构建您的项目,并运行您刚刚创建的基本项目。它应该会出错,因为我们需要添加缺失的文件。文件未找到 错误将如下所示:

    python: can't open file 'check_verify_data.py': [Errno 2] No such file or directory
    

在这个阶段,我们有了将在本章中构建的数据管道 MLflow 项目的基石。我们将在下一节中填写获取数据的 Python 脚本。

获取股票数据

我们获取数据的脚本将基于pandas-datareader Python 包。它提供了一个简单的抽象,我们可以利用它来在管道中利用远程金融 API。这个抽象非常简单。给定一个数据源,例如 Yahoo Finance,您提供股票代码/对和日期范围,数据将以 DataFrame 的形式提供。

我们现在将创建load_raw_data.py文件,该文件将负责加载数据并将其保存到raw文件夹中。您可以在以下存储库中查看文件的详细内容:github.com/PacktPublis…

  1. 我们将首先导入相关包:

    import mlflow
    from datetime import date
    from dateutil.relativedelta import relativedelta
    import pprint
    import pandas
    import pandas_datareader.data as web
    
  2. 接下来,您应该添加一个函数来检索数据:

    if __name__ == "__main__":
    
        with mlflow.start_run(run_name="load_raw_data") as 
    run:
            mlflow.set_tag("mlflow.runName", "load_raw_data")
            end = date.today()
            start = end + relativedelta(months=-3)
    
            df = web.DataReader("BTC-USD", 'yahoo', start, end)
            df.to_csv("./data/raw/data.csv") 
    
    

现在我们已经获取了数据,我们需要应用下一节中将要讨论的最佳实践——检查获取的数据质量的方法。

检查数据质量

将数据质量检查作为您机器学习系统的一部分,对于确保模型训练和推理的完整性和正确性至关重要。应借鉴并使用软件测试和质量原则于机器学习平台的数据层。

从数据质量的角度来看,在数据集中有几个关键的维度可以用来评估和配置我们的数据,即:

  • 模式合规性:确保数据来自预期的类型;确保数值不包含其他类型的数据

  • 有效数据:从数据角度评估数据是否从业务角度有效

  • 缺失数据:评估是否所有运行分析和算法所需的数据都可用

对于数据验证,我们将使用Great Expectations Python 包(可在github.com/great-expectations/great_expectations找到)。它允许使用许多数据兼容的包(如 pandas、Spark 和云环境)对数据进行断言。它提供了一个 JSON DSL,我们可以用它来声明我们希望数据遵守的规则。

对于我们的当前项目,我们希望以下规则/约束是可验证的:

  • 日期值应该是有效的日期,且不能缺失。

  • 检查数值和长值是否正确类型。

  • 数据集中的所有列都存在。

现在我们将创建check_verify_data.py文件,该文件将负责加载数据并将其保存到staging文件夹中,所有数据都有效且准备好用于机器学习训练。您可以在以下存储库中查看文件的详细内容:github.com/PacktPublis…

  1. 为了使前面的规则能够被我们的系统依赖,我们需要导入以下依赖项:

    import mlflow
    from datetime import date
    from dateutil.relativedelta import relativedelta
    import pprint
    import pandas_datareader
    import pandas
    from pandas_profiling import ProfileReport
    import great_expectations as ge
    from great_expectations.profile.basic_dataset_profiler import BasicDatasetProfiler
    
  2. 接下来,我们将实现脚本:

    if __name__ == "__main__":
        with mlflow.start_run(run_name="check_verify_data") as run:
            mlflow.set_tag("mlflow.runName", "check_verify_data")
            df = pandas.read_csv("./data/raw/data.csv")
            describe_to_dict=df.describe().to_dict()
            mlflow.log_dict(describe_to_dict,"describe_data.json")
            pd_df_ge = ge.from_pandas(df)
            assert pd_df_ge.expect_column_values_to_match_
    strftime_format("Date", "%Y-%m-%d").success == True
            assert pd_df_ge.expect_column_values_to_be_of_
    type("High", "float").success == True
            assert pd_df_ge.expect_column_values_to_be_of_type("Low", "float").success == True
            assert pd_df_ge.expect_column_values_to_be_of_type("Open", "float").success == True
            assert pd_df_ge.expect_column_values_to_be_of_type("Close", "float").success == True
            assert pd_df_ge.expect_column_values_to_be_of_type("Volume", "long").success == True
            assert pd_df_ge.expect_column_values_to_be_of_type("Adj Close", "float").success == True
    
  3. 现在我们可以进行一些清理工作:

            #we can do some basic cleaning by dropping the null values
            df.dropna(inplace=True)
            #if data_passes_quality_can_go_to_features:
            df.to_csv("data/staging/data.csv")
    

在验证了数据的质量和暂存用于后,现在可以以高度的信心用于特征生成。

生成特征集和训练数据

我们将重构在本地环境中先前开发的代码,以生成用于训练的特征,并将我们的 MLflow 项目中的数据管道添加到我们的 MLflow 项目中。

我们现在将创建feature_set_generation.py文件,该文件将负责生成我们的特征并将它们保存在training文件夹中,所有数据都是有效的,并且准备好用于机器学习训练。你可以在仓库 github.com/PacktPublis… 中查看文件内容:

  1. 我们需要导入以下依赖项:

    import mlflow
    from datetime import date
    from dateutil.relativedelta import relativedelta
    import pprint
    import pandas as pd
    import pandas_datareader
    import pandas_datareader.data as web
    import numpy as np
    
  2. 在深入研究代码的主要组件之前,我们现在将实现一个关键函数,通过基本上将每个n个前一天的差异转换为特征,我们将使用这个特征来预测下一天,这与我们在本书的前几章中用于我们的运行用例的方法非常相似:

    def rolling_window(a, window):
        """
            Takes np.array 'a' and size 'window' as parameters
            Outputs an np.array with all the ordered sequences of values of 'a' of size 'window'
            e.g. Input: ( np.array([1, 2, 3, 4, 5, 6]), 4 )
                 Output: 
                         array([[1, 2, 3, 4],
                               [2, 3, 4, 5],
                               [3, 4, 5, 6]])
        """
        shape = a.shape[:-1] + (a.shape[-1] - window + 1, window)
        strides = a.strides + (a.strides[-1],)
        return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)
    
  3. 接下来,我们将继续读取被认为是清洁且准备好由上游流程使用的暂存文件:

        with mlflow.start_run() as run:
            mlflow.set_tag("mlflow.runName", "feature_set_
    generation")
            btc_df = pd.read_csv("data/staging/data.csv")
            btc_df['delta_pct'] = (btc_df['Close'] - btc_df['Open'])/btc_df['Open']
            btc_df['going_up'] = btc_df['delta_pct'].apply(lambda d: 1 if d>0.00001 else 0).to_numpy()
            element=btc_df['going_up'].to_numpy()
            WINDOW_SIZE=15
            training_data = rolling_window(element, WINDOW_SIZE)
            pd.DataFrame(training_data).to_csv("data/training/data.csv", index=False)
    

我们生成特征集和特征。我们现在能够从数据采集到特征生成运行整个端到端管道。

运行你的端到端管道

在本节中,我们将运行完整的示例,你可以从以下地址获取该示例,地址为书的 GitHub 仓库中的/Chapter07/psytock-data-features-main 文件夹。图 7.3展示了你可以在 GitHub 中检查的项目完整文件夹结构,并与你的本地版本进行比较:

图 7.3 – 文件夹结构

图 7.3 – 文件夹结构

要运行端到端管道,你应该在包含代码的目录中执行以下命令:

mlflow run . --experiment-name=psystock_data_pipelines

它将基本执行端到端管道,你可以在 MLflow UI 中直接检查它,按顺序运行管道的每个步骤:

mlflow ui

你可以在 MLflow 中运行和探索跟踪信息,网址为localhost:5000

图 7.4中,你可以看到管道阶段的主项目和子项目的不同运行,以嵌套工作流程格式呈现,你可以浏览以检查细节:

图 7.4 – 带数据层引用的高级架构

图 7.4 – 带数据层引用的高级架构

图 7.5中,你可以看到数据管道的load_raw_data阶段的引用,并检查它何时开始和停止以及使用的参数:

图 7.5 – 包含数据层引用的高级架构

图 7.5 – 包含数据层引用的高级架构

图 7.6中,您可以看到数据管道中check_verify_data阶段的引用,我们记录了数据集的一些基本统计信息:

图 7.6 – 包含数据层引用的高级架构

图 7.6 – 包含数据层引用的高级架构

如果检测到任何数据质量问题,工作流将失败,并明确指出哪个部分失败了,如图 7.7所示:

图 7.7 – 检查错误

图 7.7 – 检查错误

通过本节,我们已完成了使用 MLflow 中的MLProjects模块实现的数据管道中数据管理和特征生成过程的描述。我们现在将探讨如何管理特征存储中的数据。

使用特征存储

特征存储是在您的数据之上的一层软件层,通过为推理系统提供一个接口来检索可用于推理或训练的特征集,从而抽象化所有数据的生成和管理过程。

在本节中,我们将通过使用 Feast(一个特征存储),一个用于管理和为生产中的模型提供机器学习特征的操作性数据系统,来阐述特征存储的概念:

图 7.8 – Feast 架构(来自 https://docs.feast.dev/)

图 7.8 – Feast 架构(来自 docs.feast.dev/)

为了了解 Feast 是如何工作的以及它如何适合您的数据层组件(代码可在 github.com/PacktPublis… 找到,执行以下步骤:

  1. 安装feast

    pip install feast==0.10
    
  2. 初始化特征存储库:

    feast init
    
  3. 通过替换自动生成的yaml文件来创建您的特征定义:

    project: psystock_feature_store
    registry: data/registry.db
    provider: local
    online_store:
        path: data/online_store.db
    
  4. 我们现在将导入特征定义的依赖项:

    from google.protobuf.duration_pb2 import Duration
    from feast import Entity, Feature, FeatureView, ValueType
    from feast.data_source import FileSource
    
  5. 我们现在可以加载特征文件:

    token_features = FileSource(
        path="/data/features.csv",
        event_timestamp_column="create_date",
        created_timestamp_column="event_date",
    )
    token= Entity(name="token", value_type=ValueType.STRING, description="token id",)
    
  6. 我们现在可以添加一个特征视图:

    hourly_view_features_token = FeatureView(
        name="token_hourly_features",
        entities=["token"],
        ttl=Duration(seconds=3600 * 1),
        features=[
            Feature(name="prev_10days", dtype=ValueType.INT64),
            Feature(name="prev_11days", dtype=ValueType.INT64),
            Feature(name="prev_12days", dtype=ValueType.INT64),
            Feature(name="prev_13days", dtype=ValueType.INT64)
        ],
        online=True,
        input=token_features,
        tags={},
    )
    
  7. 要部署带有迄今为止添加的配置的特征存储,我们需要运行以下命令:

    feast apply
    

    在这个阶段,特征存储已部署到您的环境中(在本例中为本地),并且特征存储可供您的 MLflow 作业使用。

  8. 现在所有特征都已存储在特征存储中,我们可以进行特征检索:

    import pandas as pd
    from datetime import datetime
    from feast import FeatureStore
    # entity_df generally comes from upstream systems
    event_data_point = pd.DataFrame.from_dict({
        "token": ["btc","btc"],
        "event_date": [
            datetime(2021, 4, 12, 10, 59, 42),
            datetime(2021, 4, 12, 8,  12, 10),
        ]
    })
    store = FeatureStore(repo_path=".")
    feature_loading_df = store.get_historical_features(
        entity_df=entity_df, 
        feature_refs = [
            'token_hourly_features:prev_3days',
            'token_hourly_features:prev_4days',
            'token_hourly_features:prev_5days'        
        ],
    ).to_df()
    

您现在可以将您的特征存储库集成到您的 MLflow 工作负载中。

通过本节,我们已完成了使用 MLflow 中的MLProjects 模块实现的数据管道中数据管理和特征生成过程的描述。我们现在准备好在后续章节中处理生产环境部署。

摘要

在本章中,我们介绍了 MLflow 及其与参考架构中特征管理数据层的集成。我们利用 MLflow 项目模块的功能来构建我们的数据管道。

介绍了数据与特征管理的重要层级,并明确了特征生成的需求,同时阐述了数据质量、验证和数据准备的概念。

我们将数据管道生产的各个阶段应用于我们的项目。然后我们正式化了数据获取和质量检查。在最后一节,我们介绍了特征存储的概念以及如何创建和使用它。

在本书的下一章节和后续部分,我们将专注于将数据管道和特征应用于生产环境中数据管道的训练和部署过程。

进一步阅读

为了进一步扩展您的知识,您可以参考以下链接中的文档:

github.com/mlflow/mlflow/blob/master/examples/multistep_workflow/MLproject

第八章:使用 MLflow 训练模型

在本章中,您将学习如何使用 MLflow 创建生产就绪的训练作业。在更广泛的范围内,我们将关注如何将我们在早期章节中查看的笔记本环境中的训练作业转换为标准格式和蓝图以创建训练作业。

在本章中,我们将具体查看以下部分:

  • 使用 MLflow 创建您的训练项目。

  • 实现训练作业。

  • 评估模型

  • 在模型注册表中部署模型。

  • 为您的训练作业创建 Docker 镜像。

是时候向 pyStock 机器学习ML)平台训练基础设施添加内容,将第三章中开发的工坊中创建的概念验证模型转移到生产环境。

在本章中,您将开发一个定期运行或由数据集到达触发的训练项目。训练项目的主要输出是一个新模型,作为输出生成并在模型注册表中注册,具有不同的详细信息。

这里是训练工作流程的概述:

图 8.1 – 训练工作流程

图 8.1 – 训练工作流程

图 8.1从高层次描述了一般过程,即训练数据集到达并启动训练作业。训练作业生成一个模型,最终在模型注册表中评估和部署。上游系统现在能够使用新部署的模型部署推理应用程序编程接口API)或批量作业。

技术要求

对于本章,您需要以下先决条件:

  • 在您的机器上安装了最新的 Docker 版本。如果您还没有安装,请按照docs.docker.com/get-docker/中的说明操作。

  • 已安装最新的 Docker Compose 版本——请按照docs.docker.com/compose/install/中的说明操作。

  • 在命令行中访问 Git,并按照git-scm.com/book/en/v2/Getting-Started-Installing-Git中的说明进行安装。

  • 访问 Bash 终端(Linux 或 Windows)。

  • 访问浏览器的权限。

  • 安装了 Python 3.5+。

  • 第四章中所述,您已在本地上安装了最新的 ML 库,MLflow 中的实验管理

使用 MLflow 创建您的训练项目。

您从数据科学家那里收到一份基于XGBoost模型准备从概念验证阶段过渡到生产阶段的规范。

我们可以回顾数据科学家最初注册模型的原版 Jupyter 笔记本,这是开始创建 ML 工程管道的起点。在笔记本中进行初步原型设计和训练后,他们就可以准备将模型投入生产了。

一些公司直接将笔记本自身投入生产,这当然是一种可能性,但以下原因使其变得不可能:

  • 版本控制笔记本很困难。

  • 单元测试代码很困难。

  • 对于长时间运行的测试来说,它不可靠。

通过这三个不同的阶段,我们确保了训练数据生成过程的可重复性,以及过程不同步骤的可见性和清晰的分离。

我们将首先将我们的 MLflow 项目组织成步骤,并为管道的每个组件创建占位符,如下所示:

  1. 在您的本地机器上创建一个新的文件夹,并将其命名为pystock-training。添加MLProject文件,如下所示:

    name: pystock_training
    conda_env: conda.yaml
    entry_points:
      main:
        data_file: path
        command: "python main.py"
      train_model:
        command: "python train_model.py"
      evaluate_model:
        command: "python evaluate_model.py "
      register_model:
        command: "python register_model.py"
    
  2. 添加以下conda.yaml文件:

    name: pystock-training
    channels:
      - defaults
    dependencies:
      - python=3.8
      - numpy
      - scipy
      - pandas
      - cloudpickle
      - pip:
        - git+git://github.com/mlflow/mlflow
        - sklearn
        - pandas_datareader
        - great-expectations==0.13.15
        - pandas-profiling
        - xgboost
    
  3. 您现在可以向文件夹中添加一个示例main.py文件,以确保项目的基本结构正常工作,如下所示:

    import mlflow
    import click
    import os
    def _run(entrypoint, parameters={}, source_version=None, use_cache=True):
        print("Launching new run for entrypoint=%s and parameters=%s" % (entrypoint, parameters))
        submitted_run = mlflow.run(".", entrypoint, parameters=parameters)
        return mlflow.tracking.MlflowClient().get_run(submitted_run.run_id)
    @click.command()
    def workflow():
        with mlflow.start_run(run_name ="pystock-training") as active_run:
            mlflow.set_tag("mlflow.runName", "pystock-training")
            _run("train_model")
            _run("evaluate_model")        
            _run("register_model")
    
    if __name__=="__main__":
        workflow()
    
  4. 通过运行以下命令测试基本结构:

    mlflow run.
    

    此命令将根据您的conda.yaml文件创建的环境构建您的项目,并运行您刚刚创建的基本项目。它应该出错,因为我们需要添加缺失的文件。

在这个阶段,我们已经有了本章将要构建的数据管道 MLflow 项目的基本块。接下来,您将填写用于训练数据的 Python 文件。

实现训练作业

我们将使用上一章生成的训练数据。这里的假设是独立的工作在特定文件夹中填充数据管道。在本书的 GitHub 仓库中,您可以在 github.com/PacktPublis… 查看数据。

现在我们将创建一个train_model.py文件,该文件将负责加载数据以拟合并生成模型。测试预测将被生成并持久化在环境中,以便工作流程的其他步骤可以使用这些数据来评估模型。

本节生成的文件可在以下链接找到:

github.com/PacktPublishing/Machine-Learning-Engineering-with-MLflow/blob/master/Chapter08/psystock-training/train_model.py

  1. 我们将首先导入相关的包。在这种情况下,我们需要pandas来处理数据,xgboost来运行训练算法,显然还需要mlflow来跟踪和记录数据运行。以下是您需要执行的代码:

    import pandas as pd
    import mlflow
    import xgboost as xgb
    import mlflow.xgboost
    from sklearn.model_selection import train_test_split
    
  2. 接下来,您应该添加一个函数来执行数据的分割,该函数依赖于sklearn中的train_test_split。我们选择的分割比例是测试数据和训练数据分别为 33/67%。我们指定random_state参数以确保过程可重复,如下所示:

    def train_test_split_pandas(pandas_df,t_size=0.33,r_state=42):
        X=pandas_df.iloc[:,:-1]
        Y=pandas_df.iloc[:,-1]
        X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=t_size, random_state=r_state)
        return X_train, X_test, y_train, y_test
    
  3. 此函数返回训练和测试数据集以及每个数据集的目标。我们依赖于xgboost矩阵xgb.Dmatrix数据格式来有效地加载训练和测试数据,并馈送给xgboost.train方法。代码如下所示:

    if __name__ == "__main__":
        THRESHOLD = 0.5
        mlflow.xgboost.autolog()
        with mlflow.start_run(run_name="train_model") as run:
            mlflow.set_tag("mlflow.runName", "train_model")
            pandas_df=pd.read_csv("data/training/data.csv")
            pandas_df.reset_index(inplace=True)
            X_train, X_test, y_train, y_test = train_test_split_pandas(pandas_df)
            train_data = xgb.DMatrix(X_train, label=y_train)
            test_data =  xgb.DMatrix(X_test)
            model = xgb.train(dtrain=train_data,params={})        
    
  4. 我们也利用这个时刻使用model.predict方法生成测试预测。一些数据转换被执行以将股票上涨或下跌的概率离散化,并将其转换为0(不会上涨)或1(上涨),如下所示:

            y_probas=model.predict(test_data) 
            y_preds = [1 if  y_proba > THRESHOLD else 0\. for y_proba in y_probas]
    
  5. 作为最后一步,我们将持久化测试预测到result变量中。我们删除索引,以便在运行result.to_csv命令时,保存的pandas DataFrame 不包含索引,如下所示:

            test_prediction_results = pd.DataFrame(data={'y_pred':y_preds,'y_test':y_test})
            result = test_prediction_results.reset_index(drop=True)
    
            result.to_csv("data/predictions/test_predictions.csv")    
    
  6. 您可以通过运行以下命令查看您的 MLflow 用户界面UI)以查看记录的指标:

     mlflow ui
    

您应该能够查看您的 MLflow UI,如下面的截图所示,您可以在其中看到持久化的模型和刚刚训练的模型的不同模型信息:

![Figure 8.2 – 训练模型

![img/image0025.jpg]

图 8.2 – 训练模型

在这个阶段,我们已经将我们的模型保存并持久化到我们的 MLflow 安装的工件中。接下来,我们将添加一个新的步骤到我们的工作流程中,以生成刚刚生成的模型的指标。

评估模型

我们现在将收集模型的评估指标,以添加到模型的元数据中。

我们将处理evaluate_model.py文件。您可以通过在一个空文件中工作或访问 github.com/PacktPublis… 来跟随操作。按照以下步骤进行:

  1. 导入相关的包—pandasmlflow—分别用于读取和运行步骤。我们将依赖于导入sklearn中可用的模型评估指标,用于分类算法,如下所示:

    import pandas as pd
    import mlflow
    from sklearn.model_selection import train_test_split
    from sklearn.metrics import  \
        classification_report, \
        confusion_matrix, \
        accuracy_score, \
        auc, \
        average_precision_score, \
        balanced_accuracy_score, \
        f1_score, \
        fbeta_score, \
        hamming_loss, \
        jaccard_score, \
        log_loss, \
        matthews_corrcoef, \
        precision_score, \
        recall_score, \
        zero_one_loss
    

    在这个阶段,我们已经导入了我们需要的所有函数,以便在下一节中提取所需的指标。

  2. 接下来,您应该添加一个classification_metrics函数来根据df参数生成指标。假设 DataFrame 有两个列:y_pred,这是训练模型预测的目标,以及y_test,这是训练数据文件中存在的目标。以下是您需要的代码:

    def classification_metrics(df:None):
        metrics={}
        metrics["accuracy_score"]=accuracy_score(df["y_pred"], df["y_test"]  )
        metrics["average_precision_score"]=average_precision_score( df["y_pred"], df["y_test"]  )
        metrics["f1_score"]=f1_score( df["y_pred"], df["y_test"]  )
        metrics["jaccard_score"]=jaccard_score( df["y_pred"], df["y_test"]  )
        metrics["log_loss"]=log_loss( df["y_pred"], df["y_test"]  )
        metrics["matthews_corrcoef"]=matthews_corrcoef( df["y_pred"], df["y_test"]  )
        metrics["precision_score"]=precision_score( df["y_pred"], df["y_test"]  )
        metrics["recall_score"]=recall_score( df["y_pred"], df["y_test"] )
        metrics["zero_one_loss"]=zero_one_loss( df["y_pred"], df["y_test"]  )
        return metrics
    

    前面的函数基于预测值和测试预测值生成一个metrics字典。

  3. 在创建了这个生成指标的函数之后,我们需要使用start_run,基本上是读取预测测试文件并运行指标。我们将所有指标通过mlflow.log_metrics方法以日志字典的形式同时记录。代码在下面的代码片段中展示:

    if __name__ == "__main__":
        with mlflow.start_run(run_name="evaluate_model") as run:
            mlflow.set_tag("mlflow.runName", "evaluate_model")
            df=pd.read_csv("data/predictions/test_predictions.csv")
            metrics = classification_metrics(df)
            mlflow.log_metrics(metrics)    
    
  4. 我们可以再次查看 MLflow UI,在那里我们可以看到刚刚持久化的不同指标。您可以在以下位置查看输出:

图 8.3 – 持久化的训练模型指标

图 8.3 – 持久化的训练模型指标

在这个阶段,我们对训练作业进行了模型评估,为模型实现者/部署者提供了指标和信息。现在我们将继续到训练过程的最后一步,即在 MLflow 模型注册表中注册模型,以便它可以部署到生产环境中。

在模型注册表中部署模型

接下来,您应该将register_model.py函数添加到模型注册表中以注册模型。

这就像执行mlflow.register_model方法,传入模型的统一资源标识符URI)和模型名称。基本上,如果模型不存在,将会创建一个模型。如果它已经在注册表中,将添加一个新的版本,使得部署工具可以查看模型并追踪训练作业和指标。它还允许做出决定,是否将模型推广到生产环境中。所需的代码在下面的代码片段中展示:

import mlflow
if __name__ == "__main__":

    with mlflow.start_run(run_name="register_model") as run:
        mlflow.set_tag("mlflow.runName", "register_model")
        model_uri = "runs:/{}/sklearn-model".format(run.info.run_id)
        result = mlflow.register_model(model_uri, "training-model-psystock")

在以下屏幕截图中,展示了已注册的模型,我们可以根据我们的工作流程更改状态并进入预发布或生产状态:

图 8.4 – 已注册模型

图 8.4 – 已注册模型

在注册了我们的模型之后,我们现在将转向准备一个用于公共云环境或 Kubernetes 集群的训练作业 Docker 镜像。

为您的训练作业创建 Docker 镜像

在许多情况下,Docker 镜像是模型开发者向生产中的更专业系统基础设施团队交付的最关键的成果之一。项目包含在以下存储库的文件夹中:github.com/PacktPublis… Docker 镜像:

  1. 您需要在项目的根目录下设置一个 Docker 文件,如下面的代码片段所示:

    FROM continuumio/miniconda3:4.9.2
    RUN apt-get update && apt-get install build-essential -y
    RUN pip install \
        mlflow==1.18.0 \
        pymysql==1.0.2 \
        boto3
    COPY ./training_project /src
    WORKDIR /src
    
  2. 我们将首先通过运行以下命令来构建和训练镜像:

    docker build -t psystock_docker_training_image .
    
  3. 您可以运行您的镜像,指定您的跟踪服务器$TRACKING_SERVER_URI值以到达host.docker.internal:5000,如下面的代码片段所示:

    docker run -e MLflow_TRACKING_SERVER=$TRACKING_SERVER_URI psystock_docker_training_image
    

在这个阶段,我们已经完成了完整训练工作流程的所有步骤。在下一章中,我们将继续在生产环境中部署平台的各个组件,利用迄今为止创建的所有 MLflow 项目。

摘要

在本章中,我们介绍了使用 MLflow 创建生产训练过程的概念和不同功能。

我们首先设置了 MLflow 训练项目的基本模块,并在本章中依次进行了训练模型、评估训练好的模型和注册训练好的模型。我们还深入探讨了为您的训练任务创建一个现成的图像。

这是我们架构的一个重要组成部分,它将使我们能够为我们的生产 ML 系统构建一个端到端的生产系统。在下一章中,我们将部署不同的组件,并说明模型的部署过程。

进一步阅读

为了进一步扩展您的知识,您可以参考以下链接的官方文档:

www.mlflow.org/docs/latest/projects.html

第九章:使用 MLflow 进行部署和推理

在本章中,您将了解我们机器学习(ML)系统的端到端部署基础设施,包括使用 MLflow 的推理组件。然后我们将转向在云原生 ML 系统(AWS SageMaker)和混合环境中部署我们的模型。接触这些不同环境的主要目标是让您具备在不同项目环境(云原生和本地)约束下部署 ML 模型的能力。

本章的核心是将 PsyStock 模型部署以预测基于您在本书中迄今为止所做的前 14 天市场行为的比特币(BTC/USD)价格。我们将借助工作流在多个环境中部署此模型。

具体来说,我们将在本章中查看以下部分:

  • 启动本地模型注册库

  • 设置批量推理作业

  • 创建推理的 API 流程

  • 在 Kubernetes 中部署模型进行批量评分

  • 使用 AWS SageMaker 进行云部署

技术要求

对于本章,您需要以下先决条件:

  • 在您的机器上安装了最新版本的 Docker。如果您尚未安装,请按照docs.docker.com/get-docker/上的说明进行操作。

  • 安装了最新版本的docker-compose。请按照docs.docker.com/compose/install/上的说明进行操作。

  • 在命令行中访问 Git,其安装方法可参考git-scm.com/book/en/v2/Getting-Started-Installing-Git

  • 访问 Bash 终端(Linux 或 Windows)。

  • 访问浏览器。

  • 安装了 Python 3.5+。

  • 按照第三章**,您的数据科学工作台中所述,在本地安装了最新版本的 ML 平台。

  • 一个配置好的 AWS 账户,用于运行 MLflow 模型。

启动本地模型注册库

在执行本章的以下部分之前,您需要设置一个集中的模型注册库和跟踪服务器。我们不需要整个数据科学工作台,因此可以直接使用内置在以下章节中将要部署的模型中的较轻量级的工作台变体。您应该在代码的根目录中,该目录可在github.com/PacktPublishing/Machine-Learning-Engineering-with-MLflow/tree/master/Chapter09找到。

接下来,切换到gradflow目录,并启动环境的一个轻量级版本以服务于您的模型,操作如下:

$ cd gradflow
$ export MLFLOW_TRACKING_URI=http://localhost:5000 
$ make gradflow-light

在使用 MLflow 从 ML 注册表中检索模型并设置我们的 API 部署基础设施之后,我们将继续处理需要评分的批量输入数据的情况。我们将使用 MLflow 为当前的预测问题准备一个批量推理作业。

设置批量推理作业

本节所需的代码位于 pystock-inference-api 文件夹中。MLflow 基础设施由代码附带的 Docker 镜像提供,如图下所示:

![Figure 9.1 – 批量评分部署布局

![img/image0015.jpg]

图 9.1 – 批量评分部署布局

如果你直接访问到这些工件,你可以执行以下操作。代码位于 pystock-inference-batch 目录下。为了设置一个批量推理作业,我们将遵循以下步骤:

  1. 导入你的批量作业的依赖项;在相关的依赖项中,我们包括 pandasmlflowxgboost

    import pandas as pd
    import mlflow
    import xgboost as xgb
    import mlflow.xgboost
    import mlflow.pyfunc
    
  2. 我们接下来将通过调用 mlflow.start_run 来加载 start_run 并从 input.csv 评分输入文件加载数据:

    if __name__ == "__main__":
        with mlflow.start_run(run_name="batch_scoring") as run:
            data=pd.read_csv("data/input.csv",header=None)
    
  3. 接下来,我们通过指定 model_uri 值从注册表中加载模型,基于模型的详细信息:

            model_name = "training-model-psystock"
            stage = 'Production'
            model = mlflow.pyfunc.load_model(
                    model_uri=f"models:/{model_name}/{stage}"
            )
    
  4. 我们现在可以通过运行 model.predict 来预测我们刚刚读取的数据集:

            y_probas=model.predict(data)
    
  5. 保存批量预测。这基本上涉及到将 y_preds 变量中的市场上涨的概率目标映射到 0 到 1 的值:

        y_preds = [1 if  y_proba > 0.5 else 0 for y_proba in y_probas]
    
        data[len(data.columns)] =y_preds
    
        result = data
        result.to_csv("data/output.csv")
    
  6. 我们现在需要将作业打包成一个 Docker 镜像,这样我们就可以轻松地在生产环境中运行它:

    FROM continuumio/miniconda3
    WORKDIR /batch-scoring/
    RUN pip install mlflow==1.16.0
    RUN pip install pandas==1.2.4
    COPY batch_scoring.py   /batch-scoring/
    COPY MLproject          /batch-scoring/
    ENV MLFLOW_TRACKING_URI=http://localhost:5000
    ENTRYPOINT ["mlflow run . --no-conda"]
    
  7. 构建你的 Docker 镜像并对其进行标记,以便你可以引用它:

    docker build . -t pystock-inference-batch
    
  8. 通过执行以下命令来运行你的 Docker 镜像:

    docker run -i pystock-inference-batch
    

在这种情况下,一个 Docker 镜像为你提供了一个机制,可以在支持 Docker 镜像的任何云或本地计算环境中运行你的批量评分作业。

我们现在将展示如何为 MLflow 生成一个 Docker 化的 API 推理环境。

创建用于推理的 API 进程

本节所需的代码位于 pystock-inference-api 文件夹中。MLflow 基础设施由代码附带的 Docker 镜像提供,如图下所示:

![Figure 9.2 – API 作业的结构

![img/image0026.jpg]

图 9.2 – API 作业的结构

通过依赖 MLflow 内置的 REST API 环境,设置一个 API 系统相当简单。我们将依赖本地文件系统上的工件存储来测试 API。

通过以下命令集,其核心是使用 CLI 中的 models serve 命令,我们可以提供我们的模型服务:

cd /gradflow/
export MLFLOW_TRACKING_URI=http://localhost:5000
mlflow models serve -m "models:/training-model-psystock/Production" -p 6000

我们接下来将前面的命令打包到一个 Docker 镜像中,以便在任何环境中进行部署。实现这一目标的步骤如下:

  1. 生成一个 Docker 镜像,指定工作目录和需要启动的命令作为 entry point

    FROM continuumio/miniconda3
    WORKDIR /batch-scoring/
    RUN pip install mlflow==1.16.0
    ENV MLFLOW_TRACKING_URI=http://localhost:5000
    ENTRYPOINT ["mlflow models serve -m "models:/training-model-psystock/Production" -p 6000"]
    
  2. 构建你的 Docker 镜像:

    docker build . -t pystock-inference-api
    
  3. 运行你的 Docker 镜像:

    docker run -i pystock-inference-api -p 6000:6000
    

在这个阶段,你已经将 API 基础设施 Docker 化,并且可以在你方便的计算环境中部署它。

在深入研究了 MLflow 与 AWS 平台上的云原生部署的交互之后,我们现在将关注一个不依赖于任何提供商的部署。

在 Kubernetes 中部署你的模型进行批量评分

我们将使用 Kubernetes 来部署我们的批量评分作业。我们需要进行一些修改,使其符合 Docker 格式,以便通过 Kubernetes 进行生产中的 MLflow 部署。本节的前提条件是你有权访问 Kubernetes 集群或可以设置一个本地集群。有关指南,请参阅 kind.sigs.k8s.io/docs/user/quick-start/minikube.sigs.k8s.io/docs/start/

你现在需要执行以下步骤,从 Kubernetes 中的注册表中部署你的模型:

  1. 前提条件:部署和配置 kubectl (kubernetes.io/docs/reference/kubectl/overview/) 并将其链接到你的 Kubernetes 集群。

  2. 创建 Kubernetes 后端配置文件:

    {
      "kube-context": "docker-for-desktop",
      "repository-uri": "username/mlflow-kubernetes-example",
      "kube-job-template-path": "/Users/username/path/to/kubernetes_job_template.yaml"
    }
    
  3. 加载输入文件并运行模型:

    mlflow run . --backend kubernetes --backend-config kubernetes_config.json
    

在查看在 Kubernetes 中部署模型之后,我们现在将专注于在云原生 ML 平台上部署我们的模型。

使用 AWS SageMaker 进行云部署

在过去几年中,像 AWS SageMaker 这样的服务作为运行 ML 工作负载的引擎已经逐渐占据了一席之地。MLflow 提供了集成和易于使用的命令,可以将你的模型部署到 SageMaker 基础设施中。由于需要构建大型 Docker 镜像并将其推送到 Docker 仓库,本节的执行将需要几分钟(5 到 10 分钟,具体取决于你的连接速度)。

以下是你需要遵循的一些关键前提条件列表:

  • 本地配置的 AWS CLI 使用默认配置文件(更多详情,请参阅 docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html)。

  • AWS 账户中用于 SageMaker 及其依赖项的访问权限。

  • AWS 账户中用于推送至 Amazon 弹性容器注册ECR)服务的访问权限。

  • 你的 MLflow 服务器需要按照第一部分“启动本地模型注册”中所述运行。

要将你的本地注册表中的模型部署到 AWS SageMaker,请执行以下步骤:

  1. 构建 mlflow-pyfunc 镜像。这是与 SageMaker 兼容的基本镜像。

  2. 构建并推送一个带有 mlflow pyfunc 消息的容器:

    mlflow sagemaker build-and-push-container
    

    此命令将构建 MLflow 默认镜像并将其部署到 Amazon ECR 容器。

    为了确认此命令成功执行,你可以在控制台上检查你的 ECR 实例:

    图 9.3 – SageMaker 部署的镜像

    图 9.3 – SageMaker 部署的镜像

  3. 在本地运行你的模型以测试 SageMaker Docker 镜像并导出跟踪 URI:

    7777.The output should look like the following excerpt and you should be able to test your model locally:
    
    

    安装收集的包:mlflow

    尝试卸载:mlflow

    已找到现有安装:mlflow 1.16.0

    卸载 mlflow-1.16.0:

    成功卸载 mlflow-1.16.0

    成功安装 mlflow-1.15.0

    pip 20.2.4 来自 /miniconda/lib/python3.8/site-packages/pip(python 3.8)

    Python 3.8.5

    1.15.0

    [2021-05-08 14:01:43 +0000] [354] [INFO] Starting gunicorn 20.1.0

    [2021-05-08 14:01:43 +0000] [354] [INFO] Listening at: http://127.0.0.1:8000 (354)

    
    This will basically confirm that the image is working as expected and you should be able to run your API in SageMaker.
    
  4. 通过 AWS cli双重检查你的镜像:

    aws ecr describe-images --repository-name mlflow-pyfunc 
    

    你应该在图像列表中看到你的已部署镜像,并且肯定可以运行。

  5. 你需要在 AWS 中配置一个角色,该角色允许 SageMaker 代表你创建资源(你可以在 docs.databricks.com/administrat… 找到更多详细信息)。

  6. 接下来,你需要使用以下命令将你的区域和角色导出到$REGION$ROLE环境变量中,指定你环境的实际值:

    export $REGION=your-aws-region
    export $ROLE=your sagemaker-enabled-role
    
  7. 要将你的模型部署到 SageMaker,请运行以下命令:

    mlflow sagemaker deploy -a pystock-api -m models:/training-model-psystock/Production –region-name $REGION -- $ROLE
    

    此命令将从你的本地注册表中加载你的模型到 SageMaker 作为内部表示,并使用生成的 Docker 镜像在 AWS SageMaker 基础设施引擎中提供模型。设置所有基础设施将需要几分钟。成功后,你应该会看到以下消息:

    2021/05/08 21:09:12 INFO mlflow.sagemaker: The deployment operation completed successfully with message: "The SageMaker endpoint was created successfully."
    
  8. 验证你的 SageMaker 端点:

    aws sagemaker list-endpoints
    

    你可以查看以下内容,以了解输出消息类型的示例:

    {
        "Endpoints": [
            {
                "EndpointName": "pystock-api",
                "EndpointArn": "arn:aws:sagemaker:eu-west-1:123456789:endpoint/pystock-api",
                "CreationTime": "2021-05-08T21:01:13.130000+02:00",
                "LastModifiedTime": "2021-05-08T21:09:08.947000+02:00",
                "EndpointStatus": "InService"
            }
        ]
    }
    
  9. 接下来,我们需要使用一个简单的脚本来消费我们的 API,该脚本基本上列出功能,使用 Amazon Boto3 客户端调用 SageMaker 端点,并打印出基于特征向量的市场价格的概率:

    import pandas
    import boto3
    features = pd.DataFrame([[1,0,1,1,0,1,0,1,0,1,0,1,0,1]])
    payload = features.to_json(orient="split")
    result  = runtime.invoke_endpoint(
                EndpointName='pystock-api', Body=payload, 
                ContentType='application/json')
    preds = result['Body'].read().decode("ascii")
    print(preds)
    

    运行此之前的脚本后,你应该会看到以下输出:

    '[0.04279635474085808]
    
  10. 探索 SageMaker 端点接口。在其监控组件中,你可以查看与你的部署环境和模型相关的不同指标,如图图 9.4所示:![图 9.4 – SageMaker 推理实例指标 img/image0046.jpg

    图 9.4 – SageMaker 推理实例指标

  11. 现在,你可以轻松地拆除已部署的模型,当需要部署模型或逐步淘汰时。所有相关资源都将被拆除:

    mlflow sagemaker delete -a pystock-api --region-name $REGION
    

    删除后,你应该会看到类似于以下摘录中的消息:

    2021/05/08 23:49:46 INFO mlflow.sagemaker: The deletion operation completed successfully with message: "The SageMaker endpoint was deleted successfully."
    2021/05/08 23:49:46 INFO mlflow.sagemaker: Cleaning up unused resources...
    2021/05/08 23:49:47 INFO mlflow.sagemaker: Deleted associated endpoint configuration with arn: arn:aws:sagemaker:eu-west-1:123456789:endpoint-config/pystock-api-config-v-hznm3ttxwx-g8uavbzia
    2021/05/08 23:49:48 INFO mlflow.sagemaker: Deleted associated model with arn: arn:aws:sagemaker:eu-west-1:123456789:model/pystock-api-model-4nly3634reqomejx1owtdg
    

通过本节,我们完成了在不同环境中使用 MLflow 在生产环境中部署 ML 模型的相关功能描述,包括从本地机器到 Docker 和docker-compose、公共云,以及使用 AWS SageMaker 的非常灵活的方法。

摘要

在本章中,我们专注于 ML 模型的部署,其背后的概念,以及 MLflow 在多个环境中部署时提供的不同功能。

我们解释了如何准备 Docker 镜像以便部署。我们还阐明了如何与 Kubernetes 和 AWS SageMaker 交互以部署模型。

在本书的下一章和接下来的几节中,我们将专注于使用工具来帮助我们扩展 MLflow 工作负载,以提高我们模型基础设施的性能。

进一步阅读

为了进一步扩展您的知识,您可以查阅以下链接中的文档:

第四部分:高级主题

本节涵盖了关于 MLflow 高级使用的各种主题,使您了解如何在大数据环境中扩展 MLflow 以及满足高计算需求。我们将涵盖高级用例,以确保广泛覆盖将要讨论的模型类型和用例,同时也会介绍 MLflow 的内部结构和如何为其做出贡献。

本节包含以下章节:

  • 第十章*,* 扩展您的机器学习工作流程

  • 第十一章*,* 性能监控

  • 第十二章*,* 使用 MLFlow 的高级主题

第十章:扩展您的机器学习工作流程

在本章中,您将了解各种技术和模式,以在不同的可扩展性维度上扩展您的 机器学习ML)工作流程。我们将探讨使用 Databricks 管理环境来扩展您的 MLflow 开发能力,在您有更大的数据集的情况下添加 Apache Spark。我们将探索 NVIDIA RAPIDS 和 图形处理单元GPU)支持,以及 Ray 分布式框架来加速您的 ML 工作负载。本章的格式是一个小的 概念验证,包含一个定义良好的规范数据集,以展示一种技术和工具链。

特别是,在本章中,我们将查看以下部分:

  • 在 Databricks 社区版环境中开发模型

  • 将 MLflow 与 Apache Spark 集成

  • 将 MLflow 与 NVIDIA RAPIDS (GPU) 集成

  • 将 MLflow 与 Ray 平台集成

本章将需要研究每个框架的适当设置,基于每个案例的标准官方文档。

技术要求

对于本章,您需要以下先决条件:

  • 在您的机器上安装的最新版本的 Docker。如果您尚未安装,请按照docs.docker.com/get-docker/中的说明进行操作。

  • 安装了最新版本的 Docker Compose—请按照docs.docker.com/compose/install/中的说明进行操作。

  • 命令行中访问 Git,并按照git-scm.com/book/en/v2/Getting-Started-Installing-Git中的说明进行安装。

  • 访问 Bash 终端(Linux 或 Windows)。

  • 访问浏览器。

  • 安装了 Python 3.5+。

  • 第三章中所述,本地安装的您机器学习库的最新版本,您的数据科学工作台

  • 配置为运行 MLflow 模型的 Amazon Web ServicesAWS)账户。

在 Databricks 社区版环境中开发模型

在许多小型团队和公司的场景中,启动一个集中的 ML 环境可能是一个成本高昂、资源密集的前期投资。一个能够快速扩展并使团队快速掌握技能的团队对于解锁组织内 ML 的价值至关重要。在这些情况下,使用托管服务非常相关,以开始原型设计和开始了解以较低成本使用 ML 的可行性。

一个非常流行的托管 ML 和数据平台是 Databricks 平台,由开发 MLflow 的同一家公司开发。在本节中,我们将使用针对学生和个人使用的 Databricks 社区版版本和许可证。

为了探索 Databricks 平台以开发和共享模型,您需要执行以下步骤:

  1. community.cloud.databricks.com/上注册 Databricks 社区版,并创建一个账户。

  2. 使用您刚刚创建的凭据登录您的账户。

  3. 将训练数据上传到 Databricks。您可以从上传位于Chapter10/databricks_notebooks/training_data.csv文件夹中的训练数据开始。在以下屏幕截图中,您可以看到左侧的数据标签页,并且应该看到您的文件已上传到平台:Figure 10.1 – Uploading training data to Databricks

    Figure 10.1 – Uploading training data to Databricks

  4. 将训练数据上传到 Databricks。您可以从上传位于Chapter10/databricks_notebooks/input_prediction.csv文件夹中的训练数据开始。

  5. 创建一个用于您工作负载的集群。您可以为您的负载拥有集群,限制为 15 GBGB)的随机存取内存RAM),并且使用期限为定义的时间段。

    您可以在以下屏幕截图中查看集群创建过程的概述:

    img/image0027.jpg

    Figure 10.2 – Creating a cluster in Databricks Community Edition

  6. 通过点击页面右上角的创建空白笔记本按钮,在您的着陆工作空间页面上创建一个新的笔记本,如图所示:Figure 10.3 – Creating a new notebook in Databricks Community Edition

    Figure 10.3 – Creating a new notebook in Databricks Community Edition

  7. 我们现在已准备好在这个托管环境中启动一个笔记本以执行基本的训练作业。您可以从点击创建笔记本开始,如图所示:Figure 10.4 – Creating your new notebook

    Figure 10.4 – Creating your new notebook

  8. 将训练数据上传到 Databricks。您可以从上传位于Chapter10/databricks_notebooks/input_prediction.csv文件夹中的训练数据开始。

  9. 导入所需的库。我们将适配一个用于分类我们正在运行的btc-usd标的价格的业务案例的LogicRegression模型,如下所示:

    import pandas
    import numpy as np
    import mlflow
    from sklearn.linear_model import LogisticRegression
    from sklearn.metrics import f1_score, confusion_matrix
    from sklearn.model_selection import train_test_split
    
  10. 由于平台中使用了 Databricks 文件系统,为了读取数据,更方便的是在 Spark 中读取数据,然后将 DataFrame 转换为pandas。我们通常将数据分为训练集和测试集。以下是您需要的代码:

    df = (spark.read.option("header","true").csv("/FileStore/tables/training_data.csv"))
    pandas_df = df.toPandas()
    X=pandas_df.iloc[:,:-1]
    Y=pandas_df.iloc[:,-1]
    X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.33, random_state=4284, stratify=Y)
    
  11. 我们的下一步将是快速训练我们的分类器,如下所示:

    mlflow.sklearn.autolog()
    model = LogisticRegression()
    with mlflow.start_run(run_name='logistic_regression_model_baseline') as run:
        model.fit(X_train, y_train)
        preds = model.predict(X_test)
    
  12. 在页面右上角,您可以点击实验按钮查看关于您运行的更多详细信息,并且可以进一步点击查看您的模型实验,如图所示,以下屏幕截图所示:Figure 10.5 – Experiment button

    Figure 10.5 – Experiment button

  13. 一个有趣的功能是可以扩展并加速你与他人协作的能力,即能够发布公开可访问的模型笔记本,供与你分享链接的每个人使用,如下面的截图所示:

图 10.6 – 发布笔记本

图 10.6 – 发布笔记本

您还可以将笔记本导出为 dbc 文件,以便您可以在 Databricks 环境中快速启动它,您还可以在存储库中共享它,如章节文件夹中所示,在 /databricks-notebooks/bitpred_poc.dbc

在处理了使用 Databricks 环境扩展运行、开发和分发模型的方法之后,我们将接下来探讨将 Apache Spark 流集成到我们的推理工作流程中,以处理我们有访问权的大型数据集的场景。

集成 MLflow 与 Apache Spark

Apache Spark 是一个非常可扩展且流行的大数据框架,它允许在大规模上进行数据处理。有关更多详细信息和支持文档,请访问 spark.apache.org/。作为一个大数据工具,它可以用来加速您的机器学习推理的部分,因为它可以在训练或推理级别进行设置。

在这个特定案例中,我们将说明如何实现它,以便使用上一节在 Databricks 环境中开发的模型来扩展批量推理作业到更大的数据量。

为了探索 Spark 与 MLflow 的集成,我们将执行以下步骤:

  1. 在 Python 中创建一个名为 inference_job_spark 的新笔记本,并将其链接到刚刚创建 bitpred_poc.ipynb 笔记本的运行集群。

  2. 将您的数据上传到环境中的文件/上传数据链接的 dbfs 上。

  3. 在笔记本的一个单元中执行以下脚本,将 logged_modeldf 文件名更改为您环境中的文件名:

    import mlflow
    logged_model = 'runs:/6815b44128e14df2b356c9db23b7f936/model'
    df = spark.read.format("csv").load("dbfs:/FileStore/shared_uploads/ input.csv")
    # Load model as a Spark UDF.
    loaded_model = mlflow.pyfunc.spark_udf(spark, model_uri=logged_model)
    # Predict on a Spark DataFrame.
    df.withColumn('predictions', loaded_model()).collect()
    

这个示例摘录可以在 Databricks 或您自己的 Spark 集群上运行,并可以扩展到大型数据集,利用 Spark 的分布式计算能力。

从使用 Apache Spark 扩展推理开始,我们现在将探讨在 MLflow 的支持下使用 GPU 来扩展超参数优化作业。

集成 MLflow 与 NVIDIA RAPIDS(GPU)

训练和调整机器学习模型是一个漫长且计算成本高昂的操作,并且是能够从并行处理中受益最大的操作之一。在本节中,我们将探讨将您的 MLflow 训练作业(包括超参数优化)与 NVIDIA RAPIDS 框架集成。

要集成 NVIDIA RAPIDS 库,请按照以下步骤操作:

  1. 根据您的环境,以以下方式安装 RAPIDS:

    a. rapids.ai/start.html 包含有关部署选项的详细信息。

    b. developer.nvidia.com/blog/run-rapids-on-google-colab/ 详细说明了如何在 Google ColaboratoryGoogle Colab)上运行 RAPIDS。

  2. 在你的环境中安装 MLflow。

  3. 按照以下方式导入所需的库:

    import argparse
    from functools import partial
    import mlflow
    import mlflow.sklearn
    from cuml.metrics.accuracy import accuracy_score
    from cuml.preprocessing.model_selection import train_test_split
    from cuml.ensemble import RandomForestClassifier
    from hyperopt import fmin, tpe, hp, Trials, STATUS_OK
    
  4. 实现 load_data 函数,这是一个辅助函数,用于将数据加载到将被 cudf DataFrame(一个用于加载、连接、聚合和过滤的 DataFrame 库,无需了解 计算统一设备架构CUDA)编程的细节)使用。以下是所需的代码:

    def load_data(fpath):
        import cudf
        df = cudf.read_parquet(fpath)
        X = df.drop(["ArrDelayBinary"], axis=1)
        y = df["ArrDelayBinary"].astype("int32")
        return train_test_split(X, y, test_size=0.2)Start the ray server 
    ray.init()
    client = serve.start()
    
  5. 按照以下方式定义训练循环:

    def _train(params, fpath):
        max_depth, max_features, n_estimators = params
        max_depth, max_features, n_estimators = (int(max_
    depth), float(max_features), int(n_estimators))
        X_train, X_test, y_train, y_test = load_data(fpath)
        mod = RandomForestClassifier(
            max_depth=max_depth, max_features=max_features, n_estimators=n_estimators
        )
        mod.fit(X_train, y_train)
        preds = mod.predict(X_test)
        acc = accuracy_score(y_test, preds)
        mlparams = {
            "max_depth": str(max_depth),
            "max_features": str(max_features),
            "n_estimators": str(n_estimators),
        }
        mlflow.log_params(mlparams)
        mlflow.log_metric("accuracy", acc)
        mlflow.sklearn.log_model(mod, "saved_models")
        return {"loss": acc, "status": STATUS_OK}
    
  6. 调用内部训练循环,如下所示:

    def train(params, fpath, hyperopt=False):
    
        with mlflow.start_run(nested=True):
            return _train(params, fpath, hyperopt)
    
  7. 如果你在 Docker 中部署了版本,通过读取参数设置你的主要流程。以下代码片段展示了如何执行此操作:

    if __name__ == "__main__":
        parser = argparse.ArgumentParser()
        parser.add_argument("--algo", default="tpe", 
    choices=["tpe"], type=str)
        parser.add_argument("--conda-env", required=True, type=str)
        parser.add_argument("--fpath", required=True, type=str)
        args = parser.parse_args()
    
  8. 按照以下方式定义你的试验和要优化的参数:

        search_space = [
            hp.uniform("max_depth", 5, 20),
            hp.uniform("max_features", 0.1, 1.0),
            hp.uniform("n_estimators", 150, 1000),
        ]
        trials = Trials()
        algorithm = tpe.suggest if args.algo == "tpe" else None
        fn = partial(train, fpath=args.fpath, hyperopt=True)
        experid = 0
    
  9. 按照以下方式运行你的主要循环:

        artifact_path = "Airline-Demo"
        artifact_uri = None
        with mlflow.start_run(run_name="RAPIDS-Hyperopt"):
            argmin = fmin(fn=fn, space=search_space, algo=algorithm, max_evals=2, trials=trials)
            print("===========")
            fn = partial(train, fpath=args.fpath, hyperopt=False)
            final_model = fn(tuple(argmin.values()))
            mlflow.sklearn.log_model(
                final_model,
                artifact_path=artifact_path,
                registered_model_name="rapids_mlflow_cli",
                conda_env="envs/conda.yaml",
            )
    

在处理了使用高度可扩展的计算环境在 Ray 平台上提供模型之后,我们现在将考虑一个不同的问题,我们将探讨从本地机器在集中式云位置跟踪多个运行的选择。

将 MLflow 与 Ray 平台集成

Ray 框架([docs.ray.io/en/master/](docs.ray.io/en/master/)…

使用 Ray,你可以在运行需要以与模型服务相同方式扩展的 ML 平台时添加任意逻辑。它基本上是一个网络框架。

我们预先加载了模型和内容,并将它们放入以下存储库文件夹中:github.com/PacktPublis…

为了将你的模型服务执行到 Ray 中,执行以下步骤:

  1. 通过运行以下命令安装 Ray 包:

    pip install -U ray
    
  2. 在你的环境中安装 MLflow。

  3. 按照以下方式导入所需的库:

    import ray
    from ray import serve
    import mlflow.pyfunc
    
  4. 实现模型后端,这基本上意味着将模型服务函数包装到你的 Ray 服务环境中。以下是所需的代码:

    class MLflowBackend:
        def __init__(self, model_uri):
            self.model = mlflow.pyfunc.load_model(model_
    uri=model_uri)
        async def __call__(self, request):
            return self.model.predict(request.data)
    
  5. 按照以下方式启动 Ray 服务器:

    ray.init()
    client = serve.start()
    
  6. 按照以下方式加载模型并创建后端:

    model_uri = "./tmp/0/31fc9974587243d181fdbebfd4d2b6ad/artifacts/model"
    client.create_backend("mlflow_backend", MLflowBackend, model_uri)
    
  7. 通过运行以下命令测试服务平台:

    ray start --head # Start local Ray cluster.
    serve start # Start Serve on the local Ray cluster.
    

在处理了使用高度可扩展的计算环境在 Ray 平台上提供模型之后,我们将在下一章中查看性能和监控组件。

摘要

在本章中,我们专注于使用 Databricks 环境扩展你运行、开发和分发模型的能力。我们还探讨了将 Apache Spark 流集成到我们的批量推理工作流程中,以处理我们有访问大型数据集的场景。

我们使用 NVIDIA RAPIDS 框架和 Ray 分布式框架,以可扩展性的方式总结了两种扩展超参数优化和 应用程序编程接口API)服务的方法。

在下一章和本书的后续部分,我们将专注于 ML 模型的可观察性和性能监控。

进一步阅读

为了进一步扩展您的知识,您可以查阅以下链接中的文档:

第十一章:性能监控

在本章中,你将了解机器学习(ML)操作的重要和相关性领域,以及如何使用该领域的最佳实践和已知的操作模式来确保到目前为止在此书中开发的系统在生产中的平稳运行。我们将了解机器学习中的操作概念,并查看用于监控机器学习系统中数据质量的指标。

具体来说,我们将在本章中查看以下部分:

  • 机器学习模型性能监控概述

  • 监控数据漂移和模型性能

  • 监控目标漂移

  • 基础设施监控和警报

我们将介绍一些用于监控机器学习系统性能和可靠性的实用参考工具。

技术要求

对于本章,你需要以下先决条件:

  • 在您的机器上安装了最新版本的 Docker。如果您还没有安装,请按照docs.docker.com/get-docker/上的说明操作。

  • 安装了最新版本的docker-compose。为此,请按照docs.docker.com/compose/install/上的说明操作。

  • 在命令行中访问 Git,可以按照git-scm.com/book/en/v2/Getting-Started-Installing-Git中的说明进行安装。

  • 访问 Bash 终端(Linux 或 Windows)。

  • 访问浏览器。

  • Python 3.8+已安装。

  • 按照*第三章**,您的数据科学工作台中描述的,在本地安装了您机器学习的最新版本。

  • 配置了 AWS 账户以运行 MLflow 模型。

机器学习模型性能监控概述

监控是可靠机器学习系统的基石,能够持续释放数据的价值并提供改进的关键反馈。

在机器学习模型的监控方面,有多个利益相关者,我们应该从涉及的不同利益相关者那里获取监控要求。以下是一个典型的利益相关者集的一个例子:

  • 数据科学家:他们在监控方面的重点是评估可能对性能产生负面影响的模型性能和数据漂移。

  • 软件工程师:这些利益相关者希望确保他们有衡量指标,以评估他们的产品是否能够可靠且正确地访问为模型提供服务的 API。

  • 数据工程师:他们希望确保数据管道是可靠的,并且能够可靠地推送数据,以适当的速度,并且符合正确的模式。

  • 业务/产品利益相关者:这些利益相关者对其客户群整体解决方案的核心影响感兴趣。例如,在一个交易平台中,他们可能最关心整体解决方案为公司带来的盈利与风险比率。如果市场在一天内非常波动或处于非典型情况,可能会向算法中添加断路器。

在机器学习行业中,最广泛使用的监控维度如下:

  • 数据漂移:这对应于用于模型训练或推理的输入数据发生的重大变化。这可能表明现实世界中模型假设的变化,这将需要重新训练、重新开发模型,甚至如果不再适用,则存档。这可以通过监控用于训练模型的数据与用于评分或推理的数据随时间变化的分布来轻松检测。

  • 目标漂移:随着输入数据中方案的变化,我们在一段时间内经常看到模型输出分布的相同变化。常见的周期是几个月、几周或几天,可能表明环境发生了重大变化,这将需要模型重新开发和调整。

  • 性能漂移:这涉及到查看性能指标,如分类问题的准确度或均方根误差,是否随着时间的推移逐渐恶化。这是模型存在问题的迹象,需要模型开发人员或维护人员进行调查和采取行动。

  • 平台和基础设施指标:此类指标与建模无直接关系,而是与包围模型的系统基础设施有关。它意味着异常的 CPU、内存、网络或磁盘使用,这肯定会影响模型向业务提供价值的能力。

  • 业务指标:非常关键的业务指标,如模型的盈利能力,在某些情况下应添加到模型运营中,以确保负责模型的团队能够监控模型实现其业务假设的能力。

在下一节中,我们将探讨使用一个可以与MLflow集成的工具来监控数据漂移并检查模型的性能。

监控数据漂移和模型性能

在本节中,我们将通过一个示例,您可以在GitHub仓库(github.com/PacktPublis… MLflow 的集成来运行整个过程。

监控模型性能领域的一个新兴开源工具被称为 pandas、JSON 和 CSV。它允许我们监控机器学习模型中的多个漂移及其性能。Evidently 的 GitHub 仓库可在 github.com/evidentlyai/evidently/ 找到。

在本节中,我们将探索 Evidently 与 MLflow 的组合,以便在下一节中监控数据漂移和模型性能。

监控数据漂移

在本小节中,我们将在我们的环境中设置 Evidently 并了解如何将其集成。请按照 GitHub 仓库中的这些步骤操作(更多详细信息请参阅 技术要求 部分):

  1. 安装 evidently

    pip install evidently==0.1.17.dev0
    
  2. 导入相关库:

    import pandas as pd
    import numpy as np
    from sklearn import datasets
    from sklearn.model_selection import train_test_split
    from evidently.dashboard import Dashboard
    from evidently.tabs import DataDriftTab, NumTargetDriftTab,CatTargetDriftTab
    
  3. 获取一个参考数据集,基本上是一个训练数据集。我们将向 pandas DataFrame 添加一组特征,以便 evidently 能够在漂移报告中使用特征名称:

    reference_data = \
    pd.read_csv("training_data.csv", header=None,
                names=[ "day{}".format(i) for i in \
                        range(0,14) ]+["target"] )
    

    以下 图 11.1 代表我们将用作参考数据集的训练数据的数据结构:

    图 11.1 – 要使用的数据集样本

    图 11.1 – 要使用的数据集样本

  4. 在此步骤中,我们加载 to_score_input_data.csv 文件。这是要评分的文件。我们在此练习中的目的是计算参考训练集中的数据与要评分的数据之间的分布差异:

    latest_input_data = \
    pd.read_csv("to_score_input_data.csv", header=None,
                 names=[ "day{}".format(i) for i in \
                         range(0,14) ] )
    
  5. 执行数据漂移报告生成并记录到 MLflow 运行中。基本上,以下代码片段所发生的是生成一个包含参考数据和最新输入数据的 Evidently 仪表板。计算漂移报告并将其加载到 MLflow 运行中,以便在后续步骤中采取行动和审查:

    EXPERIMENT_NAME="./reports_data_drift"
    mlflow.set_experiment(EXPERIMENT_NAME)
    with mlflow.start_run():
        drift_dashboard = Dashboard(tabs=[DataDriftTab])
        drift_dashboard.calculate(reference_data,
                                  latest_input_data)
        drift_dashboard.save(EXPERIMENT_NAME+"/input_data_drift.html")
        drift_dashboard._save_to_json(EXPERIMENT_NAME+"/input_data_drift.json")
        mlflow.log_artifacts(EXPERIMENT_NAME)
    
  6. 您现在可以运行前几行中的笔记本代码(在 monitoring_data_drift_performance.ipynb 文件中),并在 MLflow 运行的“工件”组件中探索您的数据漂移报告。图 11.2 显示,该工具在 14 个特征中没有检测到任何漂移,并相应地展示了分布:

图 11.2 – 要使用的数据集样本

图 11.2 – 要使用的数据集样本

与数据漂移类似,我们现在将在下一小节中查看目标漂移,以揭示模型中可能的其他问题。

监控目标漂移

我们现在将比较评分输出与参考训练输出,以寻找可能的目标漂移:

  1. 获取最近评分的数据集:

    production_scored_data = \
    pd.read_csv("scored_data.csv", header=None,
                names=[ "day{}".format(i) for i in \
                        range(0,14) ]+["target"] )
    bcancer_data_and_target_drift = \
    Dashboard(reference_data, production_scored_data,
              tabs=[ CatTargetDriftTab])
    bcancer_data_and_target_drift.save('reports/target_drift.html')
    
  2. 执行数据漂移报告生成并将结果记录在 MLflow 中:

    EXPERIMENT_NAME="./reports_target_drift"
    mlflow.set_experiment(EXPERIMENT_NAME)
    with mlflow.start_run():
        model_target_drift = \
        Dashboard(reference_data, production_scored_data,
                  tabs=[CatTargetDriftTab])
        model_target_drift.save(EXPERIMENT_NAME+"/target_drift.html")
        drift_dashboard._save_to_json(EXPERIMENT_NAME+"/target_drift.json")
        mlflow.log_artifacts(EXPERIMENT_NAME)
    
  3. 探索您的目标漂移报告。如图 11.3所示,在此次运行中未发现对目标漂移有统计学意义的数值。在检测漂移时,Evidently 使用数据来自不同分布的概率(由p 值表示)进行统计测试(更多详情请见en.wikipedia.org/wiki/P-value)。它比较了参考数据和当前数据的结果!

    图 11.3 – 目标数据漂移

  4. 图 11.4所示,您可以进一步深入到特定特征的目标漂移;在这种情况下,预测股票价格的特定前8 天

图 11.4 – 我们目标的数据漂移

图 11.4 – 我们目标的数据漂移

在学习了如何检测输入数据中的漂移之后,我们现在将探讨如何使用 Evidently 来监控模型中的漂移。

监控模型漂移

监控模型漂移对于确保您的模型仍然以最佳性能水平运行至关重要。通过这次分析,您可以决定是否重新训练您的模型,甚至从头开始开发一个新模型。

我们现在将监控模型漂移。为此,您需要执行以下步骤:

  1. 导入相关库:

    import xgboost as xgb
    import mlflow
    from evidently.tabs import ClassificationPerformanceTab
    
  2. 获取参考数据集:

    X=reference_data.iloc[:,:-1]
    Y=reference_data.iloc[:,-1]
    reference, production, y_train, y_test = \
    train_test_split(X, Y, test_size=0.33,
                     random_state=4284, stratify=Y)
    reference_train = xgb.DMatrix(reference,label=y_train)
    dproduction= xgb.DMatrix(production)
    dreference=xgb.DMatrix(reference)
    
  3. 训练您的模型:

    mlflow.xgboost.autolog()
    EXPERIMENT_NAME="reports_model_performance"
    mlflow.set_experiment(EXPERIMENT_NAME)
    with mlflow.start_run() as run:
        model=xgb.train(dtrain=reference_train,params={})
    
  4. 创建参考预测和训练预测:

        train_proba_predict = model.predict(dreference)
        test_proba_predict = model.predict(dproduction)
        test_predictions = [1\. if y_cont > threshold else 0\. for y_cont in test_proba_predict]
        train_predictions = [1\. if y_cont > threshold else 0\. for y_cont in train_proba_predict]
        reference['target'] = y_train
        reference['prediction'] = train_predictions
        production['target'] = y_test
        production['prediction'] = test_predictions
    
  5. 生成并附加性能报告到您的执行中:

        classification_performance = Dashboard( 
                      tabs=[ClassificationPerformanceTab])
        classification_performance.calculate(reference,
                                             production)
        classification_performance.save('.reports/'+EXPERIMENT_NAME+'.html')
        mlflow.log_artifact('.reports/'+EXPERIMENT_NAME+'.html')
    
  6. 探索您的 MLflow 性能指标报告。通过查看生成的报告,您可以检查参考指标,包括准确率精确度召回率F1 指标,这些是基于训练数据的参考指标,其最大值为1。当我们测试测试数据集的子集时,下面一行当前状态肯定已经退化。这可以帮助您判断是否在当前的F1值下,模型仍然在生产中运行是有意义的:

图 11.5 – 目标数据漂移

图 11.5 – 目标数据漂移

在深入了解数据漂移、目标漂移和模型性能监控的细节,以及如何将这些功能与 MLflow 集成之后,我们现在将探讨监控基础设施的基本原则,包括监控和警报。

基础设施监控和警报

从基础设施的角度来看,ML 系统监控的主要维度与传统软件系统没有区别。

为了说明这个问题,我们将利用 AWS CloudWatchSageMaker 中可用的监控和警报工具来展示设置监控和警报基础设施的示例。这个相同的机制可以使用 Grafana/Prometheus 等工具在本地和云部署中设置。这些监控工具实现类似的目标,并提供类似的功能,因此您应该根据您的环境和云提供商选择最合适的工具。

AWS CloudWatch 提供了一种监控和可观察性解决方案。它允许您监控您的应用程序,响应系统级性能变化,优化资源使用,并获得操作健康性的单一视图。

在更高层次上,我们可以将基础设施监控和警报组件分为以下三个部分:

  • 资源指标:这指的是系统部署的硬件基础设施的指标。在这种情况下,主要的指标包括以下内容:

    a. CPU 利用率:这基本上是处理器利用率的百分比单位。这是一个通用的指标,应该被监控。

    b. 内存利用率:您的计算系统当前使用的内存百分比。

    c. 网络数据传输:网络数据传输是指特定计算节点进出流量的大小。它通常以 Mb/s 为单位。异常可能意味着您需要向系统中添加更多节点或增加容量。

    d. 磁盘 I/O:这是通过磁盘的读写吞吐量来衡量的;它可能表明系统处于压力之下,需要扩展或调查其性能:

图 11.6 – SageMaker 基础设施指标示例

图 11.6 – SageMaker 基础设施指标示例

图 11.6 – SageMaker 基础设施指标示例

  • 系统指标:基础设施监控和警报组件的第二支柱是指系统基础设施的指标,系统部署在其中。在这种情况下,主要的指标包括以下内容:

    a. 请求吞吐量:每秒处理的预测数量

    b. 错误率:每个预测的错误数量

    c. 请求延迟:服务预测的端到端时间

    d. 验证指标:请求输入数据的错误指标

    一个生产系统,如 SageMaker,会将系统指标推送到 AWS CloudWatch 以提供实时系统指标监控。AWS CloudWatch 拥有一套完整的特性集,用于管理、存储和监控指标和仪表板:

图 11.7 – 在 AWS CloudWatch 中指定警报

图 11.7 – 在 AWS CloudWatch 中指定警报

  • 警报:对于警报,我们使用上一节计算出的任何指标,并设置一个我们认为可接受的阈值。AWS CloudWatch 界面允许您轻松设置默认服务指标和自定义指标的警报。负责可靠性的团队将通过 CloudWatch 发送消息到公司聊天/Slack、电子邮件地址或手机来接收警报,以便团队处理或减轻事件:

图 11.8 – 在 AWS CloudWatch 中指定一个警报

图 11.8 – 在 AWS CloudWatch 中指定一个警报

您可以使用相同的监控工具记录和监控与您的 ML 系统相关联的所有其他指标。例如,为 ML 模型的周利润设置警报是一个应该与系统核心系统指标一起部署的业务指标。

在本书的最后一章,我们将探讨 MLflow 的高级概念,作为对 AWS CloudWatch 作为实现生产中 ML 系统指标监控和警报工具的概述。

摘要

在本章中,我们介绍了数据漂移和目标漂移的概念,并探讨了 ML 系统中性能监控的不同方法。

我们首先介绍了性能和监控领域的重要概念,不同类型的漂移和需要监控的业务指标,以及使用 AWS CloudWatch 作为实时系统中实现监控和警报的工具。

性能和监控是我们架构的重要组成部分,它将使我们能够完成我们 ML 系统架构的重要一层。现在让我们深入了解 MLflow 的高级主题。

进一步阅读

为了进一步扩展您的知识,您可以查阅以下链接中的文档:

第十二章:MLflow 的高级主题

在本章中,我们将涵盖高级主题,以解决常见的情境和用例,通过使用本书其他部分未公开的不同类型的模型,利用你的 MLflow 知识,确保广泛的功能覆盖和接触各种主题。

具体来说,在本章中,我们将查看以下部分:

  • 使用 AutoML 探索 MLflow 用例

  • 将 MLflow 与其他语言集成

  • 理解 MLflow 插件

我们将以模式格式(即问题背景和解决方案方法)简要描述每个案例的问题和解决方案。

本章的不同部分不呈现连续性,因为它们解决不同的问题。

技术要求

对于本章,您需要以下先决条件:

  • 在您的机器上安装 Docker 的最新版本。如果您还没有安装,请按照docs.docker.com/get-docker/中的说明进行操作。

  • 请安装 Docker Compose 的最新版本——请按照docs.docker.com/compose/install/中的说明进行操作。

  • 在命令行中访问 Git,并按照git-scm.com/book/en/v2/Getting-Started-Installing-Git中描述的方式进行安装。

  • 访问 Bash 终端(Linux 或 Windows)。

  • 访问浏览器。

  • 安装 Python 3.5+。

  • 按照第 4 章 中描述的,在本地安装你 ML 库的最新版本,MLflow 中的实验管理

使用 AutoML 探索 MLflow 用例

执行 ML 项目需要多个领域的广泛知识,并且在很多情况下,需要深入的技术专业知识。一种缓解采用并加速项目上市时间TTM)的突发技术是使用自动化机器学习AutoML),其中模型开发者的某些活动被自动化。它基本上包括通过以下两种方式在 ML 中自动化步骤:

  • 特征选择:使用优化技术(例如,贝叶斯技术)选择最佳特征作为模型的输入

  • 建模:通过使用超参数优化技术测试多个算法,自动识别要使用的模型集

我们将探索将 MLflow 与一个名为 PyCaret 的 ML 库(pycaret.org/)集成,该库允许我们利用其 AutoML 技术并在 MLflow 中记录过程,以便您可以自动获得您问题的最佳性能。

我们将接下来查看本书中 pyStock 的用例,并基于我们的训练数据自动建模。

AutoML pyStock 分类用例

对于本节,我们将解决一个你可以跟随的解决方案(github.com/PacktPublis… AutoML:

  1. 让我们从安装 PyCaret 的完整版本开始,如下所示:

    pip install pycaret==2.3.1
    
  2. 首先,我们应该导入必要的库,如下所示:

    import pandas
    import pycaret
    
  3. 然后,我们读取所有训练数据,如下所示:

    data=pandas.read_csv("training_data.csv",header='infer')
    
  4. 接下来,我们设置项目数据和加载输入数据,如下所示:

    from pycaret.classification import *
    s = setup(data, target = 'target',  log_experiment = True, experiment_name = 'psystock')
    

    这里是输出:

    ![图 12.1 – 自动特征推断

    ![img/image0018.jpg]

    图 12.1 – 自动特征推断

  5. 然后,我们执行compare_models(),如下所示:

    best = compare_models()
    

    这里是输出:

    ![图 12.2 – 不同类型的模型

    ![img/image0029.jpg]

    图 12.2 – 不同类型的模型

  6. 通过以下命令选择您最好的模型:

    best = compare_models()
    
  7. 运行 MLflow 来检查所有模型(在以下统一资源定位符URL):http://127.0.0.1:5000/#/experiments/1),然后你应该会看到一个像这样的屏幕:

![img/image0038.jpg]

图 12.3 – 已记录在 MLflow 中的模型

我们将探讨在没有目标的情况下实现 AutoML 的场景。我们需要使用异常检测,这是一种无监督的机器学习技术。

自动机器学习 – 欺诈异常检测

对于本节,我们将解决一个你可以跟随的解决方案(github.com/PacktPublis… AutoML:

  1. 首先,我们应该导入库,如下所示:

    import pandas
    import pycaret
    
  2. 然后,我们读取所有训练数据,如下所示:

    data=pandas.read_csv("credit_card.csv",header='infer')
    

    这里是输出:

    ![图 12.4 – MLflow 中自动可用的模型

    ![img/image0049.jpg]

    图 12.4 – MLflow 中自动可用的模型

  3. 接下来,我们设置项目数据和加载输入数据,如下所示:

    from pycaret.anomaly import *
    s = setup(df,  log_experiment = True, experiment_name = 'psystock_anomaly'))
    
  4. 然后,我们执行compare_models(),如下所示:

    models()
    

    这里是输出:

    ![图 12.5 – 不同类型的模型

    ![img/image0057.jpg]

    图 12.5 – 不同类型的模型

  5. 然后,执行你选择的异常检测模型,如下所示:

    iforest = create_model('iforest', fraction = 0.1)
    iforest_results = assign_model(iforest)
    iforest_results.head()
    
  6. 接下来,运行 MLflow 来检查所有模型(在以下网址:http://127.0.0.1:5000/#/experiments/1),你应该会看到一个像这样的屏幕:

![图 12.6 – MLflow 中自动可用的模型

![img/image0066.jpg]

图 12.6 – MLflow 中自动可用的模型

在这个阶段,你应该能够利用你在整本书中学到的知识来使用本书中识别的生产模型。接下来,我们将探讨如何将 MLflow 与其他语言集成——在这种情况下,是 Java。

将 MLflow 与其他语言集成

MLflow 主要是在机器学习领域的 Python 生态系统中根植的工具。在其核心,MLflow 组件提供了一个 表示状态传输REST)接口。只要创建了 应用程序编程接口API)包装器,底层代码就可以从任何支持 REST 的语言中访问。REST 接口在 www.mlflow.org/docs/latest/rest-api.html 中有广泛的文档;与其他语言的集成大部分是提供访问 API 的简洁、特定语言的库层。

MLflow Java 示例

在机器学习领域,多个团队在多种语言的环境中工作。在大型分布式系统中,最重要的平台之一是 Java 虚拟机JVM)。能够实现可以与基于 Java 的系统交互的系统对于 MLflow 与更广泛的 信息技术IT)基础设施的顺利集成至关重要。

我们将展示如何在 Java 中使用 MLflow 的示例(你可以在以下链接获取代码:github.com/PacktPublis… Java 中使用 MLflow,你必须执行以下步骤:

  1. 按照指示安装 Java 和 Java 构建工具 Maven,链接为 maven.apache.org/install.html

  2. 创建一个包含 MLflow 客户端依赖项的 pom.xml 文件,如下所示:

    <project>
    …
      <dependencies>
        <dependency>
          <groupId>org.mlflow</groupId>
          <artifactId>mlflow-client</artifactId>
          <version>1.17.0</version>..
      </dependency>
    …
    </project>
    
  3. 实现你的主类,如下所示:

    package ai.psystock.jclient;
    import org.mlflow.tracking.MlflowClient;
    import org.mlflow.tracking.MlflowContext;
    import java.io.File;
    import java.io.PrintWriter;
    public class Main {
        public static void main(String[] args) {
            MlflowClient mlflowClient=new MlflowClient();
            String runId="test";
            RunStatus = RunStatus.FINISHED;
    
            MlflowContext = new MlflowContext();
            MlflowClient client = mlflowContext.getClient();
    
            client.logParam("test","alpha", "0.5");
            client.logMetric("test","rmse", 0.786);
            client.setTag("test","origin","HelloWorldFluent Java Example");
             mlflowClient.setTerminated(runId, runStatus, System.currentTimeMillis());
        }
    }
    
  4. 使用以下方式使用 Maven 构建你的项目:

    mvn clean package
    
  5. 执行以下代码以运行你的 Java 项目:

    java -jar ./target/java-maven-command-line-1.0-SNAPSHOT.jar
    

在这个阶段,MLflow 本地集成到 Python 生态系统中。它提供了与其他生态系统类似的链接,就像我们在本章中用 JVM 语言演示的那样。接下来,我们将探索 R 语言的示例。

MLflow R 示例

我们将展示如何在 Databricks 环境中使用 MLflow 的示例(你可以在以下链接获取代码:github.com/PacktPublishing/Machine-Learning-Engineering-with-MLflow/tree/master/Chapter12/mlflow-example-r)。你可以从 Databricks 社区版环境中导入笔记本,并从那里探索代码。

在本节中,我们将在 R 语言的标准数据集上运行随机森林分类器,该数据集作为 R 包 Pima.tf 提供(rdrr.io/cran/MASS/man/Pima.tr.html)。这是一个简单的数据集,包含一组生物医学特征,用于检测特定患者是否患有糖尿病。

为了创建你的 R 示例代码的笔记本,你需要执行以下步骤:

  1. community.cloud.databricks.com/ 上注册 Databricks 社区版,并创建一个账户。

  2. 使用您刚刚创建的凭证登录您的账户。

  3. 创建一个用于您工作负载的集群。您可以为您的负载拥有集群,每个集群的随机存取内存(RAM)限制为 15 GBGB),并且使用期限为定义的时间段。

    您可以在以下屏幕截图中查看集群创建过程的概述:

    图 12.7 – 在 Databricks 社区版中创建集群

    图 12.7 – 在 Databricks 社区版中创建集群

  4. 在您的 Databricks 平台的登录工作空间页面上,通过点击页面右上角的创建空白笔记本按钮来创建一个新的笔记本,如图所示:图 12.8 – 在 Databricks 社区版中创建新的笔记本

    图 12.8 – 在 Databricks 社区版中创建新的笔记本

  5. 我们现在已准备好在这个托管环境中启动一个笔记本来执行基本的训练作业。您可以通过点击工作空间中的新建笔记本来开始。您需要将默认语言设置为R,并将笔记本附加到上一章中创建的集群。

    您可以在以下屏幕截图中查看笔记本创建过程的概述:

    图 12.9 – 添加您的新的 R 笔记本详情

    图 12.9 – 添加您的新的 R 笔记本详情

  6. 您可以从导入 MLflow 依赖项开始您的笔记本,使用install.packages并实例化库,如下所示:

    install.packages("mlflow")
    library(mlflow)
    install_mlflow()
    
  7. 我们现在将使用所需的数据安装额外的包,以便能够执行我们的示例。在这个特定的例子中,我们将使用carrier包来简化远程函数的操作并记录有关它们的信息。我们还将包括MASS包,其中包含我们将在此示例中使用的数据集。el071包和randomforest将用于统计函数和运行预测分类器。以下是您需要的代码:

    install.packages("carrier")
    install.packages("e1071")
    
    library(MASS)
    library(caret)
    library(e1071)
    library(randomForest)
    library(SparkR)
    library(carrier)
    
  8. 接下来,我们将通过以下代码行with(mlflow_start_run(), {)开始一个代码块来启动实验:这将基本上允许我们通过mlflow_log_param函数开始记录模型参数。在以下情况下,我们将在 MLflow 中记录算法每次分割的树的数量(ntree)和随机采样的特征数量(mtry)。代码如下所示:

    with(mlflow_start_run(), {
    
      # Set the model parameters
      ntree <- 100
      mtry <- 3
        # Log the model parameters used for this run
      mlflow_log_param("ntree", ntree)
      mlflow_log_param("mtry", mtry)
    
  9. 在接下来的两行中,我们通过指定Pima.tr训练数据集并添加算法参数来实例化随机森林算法。然后我们使用Pima.te测试数据进行预测。代码如下所示:

      rf <- randomForest(type ~ ., data=Pima.tr, ntree=ntree, mtry=mtry)
    
      pred <- predict(rf, newdata=Pima.te[,1:7])
    
  10. 我们现在可以专注于通过caret包中可用的confusionMatrix方法计算模型性能周围的指标——在这种情况下,特异性和敏感性——如下所示:

    # Define metrics to evaluate the model
      cm <- confusionMatrix(pred, reference = Pima.te[,8])
      sensitivity <- cm[["byClass"]]["Sensitivity"]
      specificity <- cm[["byClass"]]["Specificity"]
    
      # Log the value of the metrics 
      mlflow_log_metric("sensitivity", sensitivity)
      mlflow_log_metric("specificity", specificity)
    
  11. 我们现在可以专注于上传基于先前度量的混淆矩阵图。在 R 中,记录模型的方法是 mlflow_log_artifact。以下是你需要使用的代码:

      # Log the value of the metrics 
        # Create and plot confusion matrix
      png(filename="confusion_matrix_plot.png")
      barplot(as.matrix(cm), main="Results",
             xlab="Observed", ylim=c(0,200), col=c("green","blue"),
             legend=rownames(cm), beside=TRUE)
      dev.off()
    
      # Save the plot and log it as an artifact
      mlflow_log_artifact("confusion_matrix_plot.png")
    
  12. 最后,我们可以使用 carrier 包上可用的 crate 方法将模型函数序列化并记录到 MLflow 中,以便可以从另一个 R 笔记本中重用。我们最终使用 mlflow_log_model 记录模型,并在最后一行代码后关闭括号,如下面的代码片段所示:

      predictor <- crate(function(x) predict(rf,.x))
      mlflow_log_model(predictor, "model")     
    })
    
  13. 现在,你可以自由地探索你环境中的 实验 选项卡,你应该能够访问你的模型日志并探索运行的指标和细节,如下面的屏幕截图所示:

![图 12.10 – MLflow 中自动可用的模型

![img/Image0102.jpg]

图 12.10 – MLflow 中自动可用的模型

在本节中,我们探讨了 Java 和 R 的示例,这两种语言在机器学习生态系统中对工程师和数据科学家都极为相关。现在,我们将深入了解通过插件扩展 MLflow 功能。

理解 MLflow 插件

作为一名机器学习工程师,在你的项目中,你可能会多次达到框架的限制。MLflow 通过其插件功能提供扩展系统。插件架构允许软件系统的可扩展性和适应性。

MLflow 允许创建以下类型的插件:

  • 跟踪存储插件:此类插件控制并调整你用于在特定类型的数据存储中记录实验度量值的存储。

  • log_artifactdownload_artifacts

  • git_tagsrepo_uri,以及你系统环境中的其他相关元素。

  • 模型注册存储:此功能允许你自定义模型存储的位置;例如,如果你只能通过 安全文件传输协议SFTP)系统存储生产基础设施中的模型,你可以使用此功能。在需要适应有限服务集和你的模型注册存储的监管环境中,此功能可能具有优势。

  • MLflow 项目部署:此类插件控制并调整你的部署方式。在部署环境不支持 MLflow 的情况下,你可以使用此功能来专门化你的部署方式。

  • 请求头提供者:使你能够控制并向 MLflow 发出的 REST 请求添加额外值。一个例子是,如果所有 超文本传输协议HTTP)请求都需要一个与你的网络中集成公司 单点登录SSO)的安全令牌相关的头键。

  • 项目后端:这为在不同的执行环境中运行 MLflow 提供了可扩展性。例如,Kubernetes 和 Sagemaker 都是后端,因此 MLflow 和模型将部署的环境之间的集成需要为每种情况编写特定的代码。

要创建一个插件,您必须创建一个 Python 包,该包覆盖 MLflow 中的特定模块。我们将根据官方文档逐步开发一个示例 MLflow 插件。您可以按照以下仓库 URL 跟随:github.com/PacktPublis…

  1. setup.py 文件中定义您的插件。install_requires=["mlflow"] 这行代码将 MLflow 与您的包捆绑在一起,足以安装您的新插件包,并且它将创建一个更改后的 MLflow 实例。代码如下所示:

    setup(
        name="mflow-psystock-deployment-plugin",
        # Require MLflow as a dependency of the plugin, so that plugin users can simply install
        # the plugin and then immediately use it with MLflow
        install_requires=["mlflow"],
        entry_points={
            "mlflow.deployments": " psystock target= psystock. deployment_plugin"
        }
    )
    
  2. 在名为 mlflow-psystock-deployment/_init_.py 的文件夹中创建一个空的包命名空间文件,以表示包的创建。

  3. 下一步涉及通过我们想要在插件中覆盖以覆盖 MLflow 默认行为的方法来覆盖文件的创建。

    在我们的特定情况下,我们将查看覆盖 MLflow 中的 BaseDeploymentClient 类,这基本上意味着我们需要实现所有方法。我们将实现一系列虚拟方法来展示这个过程,从 create_deploymentupdate_deployment 方法开始,如下所示:

    import os
    from mlflow.deployments import BaseDeploymentClient
    p_deployment_name = "pystock"
    class PluginDeploymentClient(BaseDeploymentClient):
        def create_deployment(self, name, model_uri, flavor=None, config=None):
            if config and config.get("raiseError") == "True":
                raise RuntimeError("Error requested")
            return {"name": f_deployment_name, "flavor": flavor}
        def delete_deployment(self, name):
            return None
        def update_deployment(self, name, model_uri=None, flavor=None, config=None):
            return {"flavor": flavor}
    
  4. 我们接着实现了 list_deploymentsget_deployments 方法,如下所示:

        def list_deployments(self):
            if os.environ.get("raiseError") == "True":
                raise RuntimeError("Error requested")
            return [f_deployment_name]
        def get_deployment(self, name):
            return {"key1": "val1", "key2": "val2"}
        def predict(self, deployment_name, df):
            return "1"
    def run_local(name, model_uri, flavor=None, config=None):
        print(
            "Deployed locally at the key {} using the model from {}. ".format(name, model_uri)
            + "It's flavor is {} and config is {}".format(flavor, config)
        )
    

    run_local(name, model_uri, flavor=None, config=None) 方法是当实例化此插件时将被执行的主要方法。

  5. 您现在可以通过运行以下命令在 MLflow 上安装您的插件:

    pip install-e .
    

我们通过本节关于通过新功能扩展 MLflow 的内容来结束本书,这允许您作为机器学习工程师在合理的时候扩展 MLflow。

摘要

在本章中,我们讨论了一些用例,并提供了示例 MLflow 管道。我们探讨了在两种不同场景下实现 AutoML,当我们没有目标时,我们需要使用异常检测作为无监督机器学习技术。我们讨论了非 Python 基础平台的使用,并以如何通过插件扩展 MLflow 作为结论。

在这个阶段,我们已经使用 MLflow 在机器学习工程领域解决了广泛和深入的话题。您的下一步肯定是进一步探索,并在您的项目中利用本书中学到的技术。

进一步阅读

为了进一步扩展您的知识,您可以查阅以下链接中的文档: