MLflow 模型注册表

MLflow 模型注册组件是一个集中的模型存储库、一组 API 和 UI,用于协作管理 MLflow 模型的整个生命周期。它提供了模型血统(哪个 MLflow 实验和运行生成了模型)、模型版本控制、模型别名、模型标记和注释。

概念

模型注册中心引入了一些概念,这些概念描述并促进了MLflow模型的整个生命周期。

模型

MLflow 模型是从实验或运行中创建的,该实验或运行通过模型风格之一的 mlflow.<model_flavor>.log_model() 方法记录。一旦记录,该模型就可以在模型注册表中注册。

注册模型

一个 MLflow 模型可以注册到模型注册表中。一个已注册的模型具有唯一的名称,包含版本、别名、标签和其他元数据。

模型版本

每个注册的模型可以有一个或多个版本。当一个新的模型被添加到模型注册表时,它被添加为版本1。每个新注册到相同模型名称的模型都会增加版本号。模型版本有标签,这对于跟踪模型版本的属性(例如 pre_deploy_checks: “PASSED”)非常有用。

模型别名

模型别名允许你为注册模型的特定版本分配一个可变的命名引用。通过将别名分配给特定的模型版本,你可以使用该别名通过模型URI或模型注册API来引用该模型版本。例如,你可以创建一个名为 champion 的别名,指向名为 MyModel 的模型的版本1。然后,你可以通过使用URI models:/MyModel@champion 来引用 MyModel 的版本1。

别名在部署模型时特别有用。例如,你可以将 champion 别名分配给用于生产流量的模型版本,并在生产工作负载中针对此别名。然后,你可以通过将 champion 别名重新分配给不同的模型版本来更新提供生产流量的模型。

标签

标签是键值对,您可以将其与注册的模型和模型版本关联,从而通过功能或状态对其进行标记和分类。例如,您可以对用于问答任务的注册模型应用一个键为 "task" 值为 "question-answering" 的标签(在UI中显示为 task:question-answering)。在模型版本级别,您可以用 validation_status:pending 标记正在进行预部署验证的版本,并用 validation_status:approved 标记已批准部署的版本。

注释与描述

你可以使用 Markdown 对顶级模型和每个版本进行注释,包括描述和任何对团队有用的相关信息,例如算法描述、使用的数据集或方法。

模型注册工作流程

如果运行自己的 MLflow 服务器,必须使用数据库支持的后端存储,以便通过 UI 或 API 访问模型注册表。参见此处 了解更多信息。

在将模型添加到模型注册表之前,您必须使用相应模型口味的 log_model 方法记录它。一旦模型被记录,您可以通过UI或API在模型注册表中添加、修改、更新或删除模型。

UI 工作流程

本节演示如何使用 MLflow 模型注册表 UI 来管理您的 MLflow 模型。

注册一个模型

按照以下步骤在模型注册表中注册您的 MLflow 模型。

  1. 打开包含您想要注册的已记录MLflow模型的MLflow运行的详细信息页面。在**Artifacts**部分选择包含目标MLflow模型的模型文件夹。

../_images/oss_registry_1_register.png
  1. 点击 注册模型 按钮,这将触发一个表单弹出。

  2. 在表单的 模型 下拉菜单中,你可以选择“创建新模型”,这将创建一个新的注册模型,并将你的 MLflow 模型作为其初始版本,或者选择一个现有的注册模型,将其作为新版本注册在你的模型下。下面的截图演示了将 MLflow 模型注册到一个名为 "iris_model_testing" 的新注册模型中。

../_images/oss_registry_2_dialog.png

查找已注册的模型

在模型注册表中注册您的模型后,您可以通过以下方式导航到它们。

  • 导航到 已注册模型 页面,该页面链接到您已注册的模型及其对应的模型版本。

    ../_images/oss_registry_3_overview.png
  • 转到 MLflow 运行详情页的 Artifacts 部分,点击模型文件夹,然后在右上角点击模型版本以查看从该模型创建的版本。

    ../_images/oss_registry_3b_version.png

部署和组织模型

您可以使用模型别名和标签在模型注册表中部署和组织您的模型。要为注册模型中的模型版本设置别名和标签,请导航到您的注册模型的概览页面,例如下面的页面。

../_images/oss_registry_4_model.png

您可以通过点击模型版本表中相应的 添加 链接或铅笔图标来添加或编辑特定模型版本的别名和标签。

../_images/oss_registry_4b_model_alias.png

要了解更多关于特定模型版本的信息,请导航到该模型版本的详细信息页面。

../_images/oss_registry_5_version.png

在本页面中,您可以查看模型版本详细信息,如模型签名、MLflow 源运行和创建时间戳。您还可以查看和配置版本的别名、标签和描述。

API 工作流程

与模型注册表交互的另一种方式是使用 MLflow 模型风格MLflow 客户端跟踪 API 接口。特别是,你可以在 MLflow 实验运行期间或所有实验运行之后注册一个模型。

将 MLflow 模型添加到模型注册表

有三种编程方式可以将模型添加到注册表中。首先,你可以使用 mlflow.<model_flavor>.log_model() 方法。例如,在你的代码中:

from sklearn.datasets import make_regression
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split

import mlflow
import mlflow.sklearn
from mlflow.models import infer_signature

with mlflow.start_run() as run:
    X, y = make_regression(n_features=4, n_informative=2, random_state=0, shuffle=False)
    X_train, X_test, y_train, y_test = train_test_split(
        X, y, test_size=0.2, random_state=42
    )
    params = {"max_depth": 2, "random_state": 42}
    model = RandomForestRegressor(**params)
    model.fit(X_train, y_train)

    # Infer the model signature
    y_pred = model.predict(X_test)
    signature = infer_signature(X_test, y_pred)

    # Log parameters and metrics using the MLflow APIs
    mlflow.log_params(params)
    mlflow.log_metrics({"mse": mean_squared_error(y_test, y_pred)})

    # Log the sklearn model and register as version 1
    mlflow.sklearn.log_model(
        sk_model=model,
        artifact_path="sklearn-model",
        signature=signature,
        registered_model_name="sk-learn-random-forest-reg-model",
    )

在上面的代码片段中,如果名称对应的注册模型不存在,该方法会注册一个新模型并创建版本1。如果名称对应的注册模型存在,该方法会创建一个新模型版本。

第二种方法是使用 mlflow.register_model() 方法,在所有实验运行完成后,并且当你决定哪个模型最适合添加到注册表时。对于这种方法,你需要 run_id 作为 runs:URI 参数的一部分。

result = mlflow.register_model(
    "runs:/d16076a3ec534311817565e6527539c0/sklearn-model", "sk-learn-random-forest-reg"
)

如果名称对应的已注册模型不存在,该方法将注册一个新模型,创建版本1,并返回一个ModelVersion MLflow对象。如果名称对应的已注册模型存在,该方法将创建一个新模型版本并返回该版本对象。

最后,你可以使用 create_registered_model() 来创建一个新的注册模型。如果模型名称已存在,此方法将抛出一个 MlflowException ,因为创建新的注册模型需要一个唯一的名称。

from mlflow import MlflowClient

client = MlflowClient()
client.create_registered_model("sk-learn-random-forest-reg-model")

上述方法创建了一个没有关联版本的空注册模型。你可以使用 create_model_version() 如下所示来创建模型的新版本。

client = MlflowClient()
result = client.create_model_version(
    name="sk-learn-random-forest-reg-model",
    source="mlruns/0/d16076a3ec534311817565e6527539c0/artifacts/sklearn-model",
    run_id="d16076a3ec534311817565e6527539c0",
)

Databricks Unity Catalog 模型注册表

要使用 Databricks unity catalog 模型注册表,请将 MLflow 注册表 URI 设置为 "databricks-uc",并设置两个环境变量 "DATABRICKS_HOST""DATABRICKS_TOKEN"。如果你使用的是 Databricks OAuth 认证,请设置三个环境变量 "DATABRICKS_HOST""DATABRICKS_CLIENT_ID""DATABRICKS_CLIENT_SECRET"。如果你已经在 '~/.databrickscfg' 文件中配置了访问认证,那么你不需要设置上述环境变量。相反,你可以将 MLflow 注册表 URI 设置为 "databricks-uc://{profile}",其中 '{profile}' 部分是你在 '~/.databrickscfg' 配置文件中的配置名称。有关 Databricks 认证类型的详细信息,请参阅 此文档 <https://docs.databricks.com/en/dev-tools/auth/index.html#unified-auth>

使用 Databricks 分片令牌的 Databricks Unity 目录模型注册表

import mlflow
import os

mlflow.set_registry_uri("databricks-uc")
os.environ["DATABRICKS_HOST"] = "<your Databricks shard URI>"
os.environ["DATABRICKS_TOKEN"] = "<your Databricks shard access token>"

使用 Databricks OAuth 认证的 Databricks unity 目录模型注册表

import mlflow
import os

mlflow.set_registry_uri("databricks-uc")
os.environ["DATABRICKS_HOST"] = "<your Databricks shard URI>"
os.environ["DATABRICKS_CLIENT_ID"] = "<your Databricks oauth client ID>"
os.environ["DATABRICKS_CLIENT_SECRET"] = "<your Databricks oauth client secret>"

使用 Databricks unity catalog 模型注册表与 ‘~/.databrickscfg’ 配置文件

假设你已经在本地配置了 ‘~/.databrickscfg’ 文件,其中包含如下部分:

[my-databricks-shard1] host = <你的 Databricks 分片 URI> token = <你的 Databricks 分片访问令牌>

import mlflow
import os

mlflow.set_registry_uri("databricks-uc://my-databricks-shard1")

OSS Unity 目录模型注册表

要使用 OSS Unity Catalog 服务器作为您的 MLflow 模型注册表,请在 MLflow 注册表 URI 中以 "uc:http://localhost:8080" 格式指定 UC 服务器地址。如果您的 unity catalog 服务器配置为使用身份验证,请设置环境变量 "MLFLOW_UC_OSS_TOKEN"

使用承载令牌的 OSS 统一目录模型注册表

import mlflow
import os

mlflow.set_registry_uri("uc:http://localhost:8080")
# Set this environment variable for MLflow to use your UC OSS token
os.environ["MLFLOW_UC_OSS_TOKEN"] = "<your OSS UC access token>"

使用别名和标签部署和组织模型

模型别名和标签帮助你在模型注册表中部署和组织你的模型。

在模型上设置和删除别名

要使用 MLflow 客户端 API 设置、更新和删除别名,请参见以下示例:

from mlflow import MlflowClient

client = MlflowClient()

# create "champion" alias for version 1 of model "example-model"
client.set_registered_model_alias("example-model", "champion", 1)

# reassign the "Champion" alias to version 2
client.set_registered_model_alias("example-model", "Champion", 2)

# get a model version by alias
client.get_model_version_by_alias("example-model", "Champion")

# delete the alias
client.delete_registered_model_alias("example-model", "Champion")

在模型上设置和删除标签

要使用 MLflow 客户端 API 设置和删除标签,请参见以下示例:

from mlflow import MlflowClient

client = MlflowClient()

# Set registered model tag
client.set_registered_model_tag("example-model", "task", "classification")

# Delete registered model tag
client.delete_registered_model_tag("example-model", "task")

# Set model version tag
client.set_model_version_tag("example-model", "1", "validation_status", "approved")

# Delete model version tag
client.delete_model_version_tag("example-model", "1", "validation_status")

有关别名和标签客户端API的更多详细信息,请参阅 mlflow.client API 文档。

从模型注册表中获取MLflow模型

在您注册了一个 MLflow 模型之后,您可以使用 mlflow.<model_flavor>.load_model() 或更一般地,load_model() 来获取该模型。您可以使用加载的模型进行一次性预测或在推理工作负载中使用,例如批量推理。

获取特定模型版本

要获取特定模型版本,只需将该版本号作为模型URI的一部分提供。

import mlflow.pyfunc

model_name = "sk-learn-random-forest-reg-model"
model_version = 1

model = mlflow.pyfunc.load_model(model_uri=f"models:/{model_name}/{model_version}")

model.predict(data)

通过别名获取模型版本

要通过别名获取模型版本,请在模型URI中指定模型别名,它将获取当前在该别名下的模型版本。

import mlflow.pyfunc

model_name = "sk-learn-random-forest-reg-model"
alias = "champion"

champion_version = mlflow.pyfunc.load_model(f"models:/{model_name}@{alias}")

champion_version.predict(data)

请注意,模型别名分配可以独立于您的生产代码进行更新。如果在上述代码片段中,champion 别名在模型注册表中被重新分配到一个新的模型版本,此代码片段的下一次执行将自动选择新的模型版本。这使您能够将模型部署与推理工作负载解耦。

从模型注册表中提供MLflow模型

在您注册了一个 MLflow 模型之后,您可以将该模型作为服务在您的主机上提供。

#!/usr/bin/env sh

# Set environment variable for the tracking URL where the Model Registry resides
export MLFLOW_TRACKING_URI=http://localhost:5000

# Serve the production model from the model registry
mlflow models serve -m "models:/sk-learn-random-forest-reg-model@champion"

在不同环境中推广MLflow模型

在成熟的 DevOps 和 MLOps 工作流程中,组织使用独立的环境(通常是开发、暂存和生产)并设置访问控制,以实现快速开发而不影响生产稳定性。在 MLflow 中,您可以使用注册模型和 MLflow 认证 来为您的 MLflow 模型表达访问控制的环境。例如,您可以为每个环境和业务问题的组合创建注册模型(例如 prod.ml_team.revenue_forecastingdev.ml_team.revenue_forecasting)并相应地配置权限。当您为业务问题迭代 MLflow 模型时,您可以将它们通过各个环境进行持续集成和部署。

对于成熟的生产级设置,我们建议设置自动化的工作流程,在每个环境中训练和注册模型。要将最新迭代应用于业务问题,请通过源代码控制和CI/CD系统在环境中推广您的机器学习代码。

对于简单的模型部署用例,您可以将训练好的 MLflow 模型注册为开发环境中的最新模型版本,然后使用 copy_model_version() 将其在注册模型之间进行提升。

from mlflow import MlflowClient

client = MlflowClient()
client.copy_model_version(
    src_model_uri="models:/regression-model-staging@candidate",
    dst_name="regression-model-production",
)

此代码片段将 regression-model-staging 模型中带有 candidate 别名的模型版本复制到 regression-model-production 模型中作为最新版本。

您也可以在用户界面中提升模型版本。为此,导航到模型版本详情页面并选择 提升模型 按钮。这将打开一个模态框,您可以在其中选择一个已注册的模型,当前模型版本将被复制到该模型中。

../_images/oss_registry_6_version.png

添加或更新 MLflow 模型描述

在模型的生命周期开发中的任何时候,您都可以使用 update_model_version() 更新模型版本的描述。

client = MlflowClient()
client.update_model_version(
    name="sk-learn-random-forest-reg-model",
    version=1,
    description="This model version is a scikit-learn random forest containing 100 decision trees",
)

重命名一个 MLflow 模型

除了添加或更新模型特定版本的描述外,您还可以使用 rename_registered_model() 重命名现有的已注册模型。

client = MlflowClient()
client.rename_registered_model(
    name="sk-learn-random-forest-reg-model",
    new_name="sk-learn-random-forest-reg-model-100",
)

列出和搜索 MLflow 模型

你可以通过一个简单的方法从注册表中获取已注册模型的列表。

from pprint import pprint

client = MlflowClient()
for rm in client.search_registered_models():
    pprint(dict(rm), indent=4)

这输出:

{   'creation_timestamp': 1582671933216,
    'description': None,
    'last_updated_timestamp': 1582671960712,
    'latest_versions': [<ModelVersion: creation_timestamp=1582671933246, current_stage='Production', description='A random forest model containing 100 decision trees trained in scikit-learn', last_updated_timestamp=1582671960712, name='sk-learn-random-forest-reg-model', run_id='ae2cc01346de45f79a44a320aab1797b', source='./mlruns/0/ae2cc01346de45f79a44a320aab1797b/artifacts/sklearn-model', status='READY', status_message=None, user_id=None, version=1>,
                        <ModelVersion: creation_timestamp=1582671960628, current_stage='None', description=None, last_updated_timestamp=1582671960628, name='sk-learn-random-forest-reg-model', run_id='d994f18d09c64c148e62a785052e6723', source='./mlruns/0/d994f18d09c64c148e62a785052e6723/artifacts/sklearn-model', status='READY', status_message=None, user_id=None, version=2>],
    'name': 'sk-learn-random-forest-reg-model'}

有数百个模型时,浏览此调用返回的结果可能会很麻烦。一种更有效的方法是搜索特定的模型名称,并使用 search_model_versions() 方法列出其版本详细信息,并提供一个过滤字符串,例如 "name='sk-learn-random-forest-reg-model'"

client = MlflowClient()
for mv in client.search_model_versions("name='sk-learn-random-forest-reg-model'"):
    pprint(dict(mv), indent=4)

这输出:

{
    "creation_timestamp": 1582671933246,
    "current_stage": "Production",
    "description": "A random forest model containing 100 decision trees "
    "trained in scikit-learn",
    "last_updated_timestamp": 1582671960712,
    "name": "sk-learn-random-forest-reg-model",
    "run_id": "ae2cc01346de45f79a44a320aab1797b",
    "source": "./mlruns/0/ae2cc01346de45f79a44a320aab1797b/artifacts/sklearn-model",
    "status": "READY",
    "status_message": None,
    "user_id": None,
    "version": 1,
}

{
    "creation_timestamp": 1582671960628,
    "current_stage": "None",
    "description": None,
    "last_updated_timestamp": 1582671960628,
    "name": "sk-learn-random-forest-reg-model",
    "run_id": "d994f18d09c64c148e62a785052e6723",
    "source": "./mlruns/0/d994f18d09c64c148e62a785052e6723/artifacts/sklearn-model",
    "status": "READY",
    "status_message": None,
    "user_id": None,
    "version": 2,
}

删除 MLflow 模型

备注

删除已注册的模型或模型版本是不可逆的,因此请谨慎使用。

你可以删除已注册模型的特定版本,或者你可以删除一个已注册模型及其所有版本。

# Delete versions 1,2, and 3 of the model
client = MlflowClient()
versions = [1, 2, 3]
for version in versions:
    client.delete_model_version(
        name="sk-learn-random-forest-reg-model", version=version
    )

# Delete a registered model along with all its versions
client.delete_registered_model(name="sk-learn-random-forest-reg-model")

虽然上述工作流API展示了与模型注册表的交互,但有两种特殊情况需要注意。一种情况是当你有从训练中保存的现有ML模型,但没有使用MLflow。这些模型以sklearn的pickled格式序列化并持久化在磁盘上,你希望将此模型注册到模型注册表中。第二种情况是当你使用一个没有内置MLflow模型风格支持的ML框架时,例如`vaderSentiment`,并且希望注册该模型。

注册一个保存在 MLflow 之外的模型

并非每个人都会从使用 MLflow 开始他们的模型训练。因此,您可能有一些在使用 MLflow 之前训练的模型。您不需要重新训练这些模型,您所需要做的就是将您保存的模型注册到模型注册表中。

此代码片段创建了一个 sklearn 模型,我们假设您已经创建并将其保存为本地 pickle 格式。

备注

保存模型时使用的sklearn库和pickle版本应与当前MLflow支持的内置sklearn模型风格兼容。

import numpy as np
import pickle

from sklearn import datasets, linear_model
from sklearn.metrics import mean_squared_error, r2_score

# source: https://scikit-learn.org/stable/auto_examples/linear_model/plot_ols.html

# Load the diabetes dataset
diabetes_X, diabetes_y = datasets.load_diabetes(return_X_y=True)

# Use only one feature
diabetes_X = diabetes_X[:, np.newaxis, 2]

# Split the data into training/testing sets
diabetes_X_train = diabetes_X[:-20]
diabetes_X_test = diabetes_X[-20:]

# Split the targets into training/testing sets
diabetes_y_train = diabetes_y[:-20]
diabetes_y_test = diabetes_y[-20:]


def print_predictions(m, y_pred):
    # The coefficients
    print("Coefficients: \n", m.coef_)
    # The mean squared error
    print("Mean squared error: %.2f" % mean_squared_error(diabetes_y_test, y_pred))
    # The coefficient of determination: 1 is perfect prediction
    print("Coefficient of determination: %.2f" % r2_score(diabetes_y_test, y_pred))


# Create linear regression object
lr_model = linear_model.LinearRegression()

# Train the model using the training sets
lr_model.fit(diabetes_X_train, diabetes_y_train)

# Make predictions using the testing set
diabetes_y_pred = lr_model.predict(diabetes_X_test)
print_predictions(lr_model, diabetes_y_pred)

# save the model in the native sklearn format
filename = "lr_model.pkl"
pickle.dump(lr_model, open(filename, "wb"))
Coefficients:
[938.23786125]
Mean squared error: 2548.07
Coefficient of determination: 0.47

一旦以pickle格式保存,你可以使用pickle API将sklearn模型加载到内存中,并将加载的模型注册到模型注册表中。

import mlflow
from mlflow.models import infer_signature
import numpy as np
from sklearn import datasets

# load the model into memory
loaded_model = pickle.load(open(filename, "rb"))

# create a signature for the model based on the input and output data
diabetes_X, diabetes_y = datasets.load_diabetes(return_X_y=True)
diabetes_X = diabetes_X[:, np.newaxis, 2]
signature = infer_signature(diabetes_X, diabetes_y)

# log and register the model using MLflow scikit-learn API
mlflow.set_tracking_uri("sqlite:///mlruns.db")
reg_model_name = "SklearnLinearRegression"
print("--")
mlflow.sklearn.log_model(
    loaded_model,
    "sk_learn",
    serialization_format="cloudpickle",
    signature=signature,
    registered_model_name=reg_model_name,
)
--
Successfully registered model 'SklearnLinearRegression'.
2021/04/02 16:30:57 INFO mlflow.tracking._model_registry.client: Waiting up to 300 seconds for model version to finish creation.
Model name: SklearnLinearRegression, version 1
Created version '1' of model 'SklearnLinearRegression'.

现在,使用 MLflow 流式 API,您从模型注册表中重新加载模型并进行评分。

# load the model from the Model Registry and score
model_uri = f"models:/{reg_model_name}/1"
loaded_model = mlflow.sklearn.load_model(model_uri)
print("--")

# Make predictions using the testing set
diabetes_y_pred = loaded_model.predict(diabetes_X_test)
print_predictions(loaded_model, diabetes_y_pred)
--
Coefficients:
[938.23786125]
Mean squared error: 2548.07
Coefficient of determination: 0.47

注册一个不支持的机器学习模型

在某些情况下,您可能会使用一个没有内置 MLflow Model 风格支持的机器学习框架。例如,vaderSentiment 库是一个用于情感分析的标准自然语言处理(NLP)库。由于它缺乏内置的 MLflow Model 风格,因此您无法使用 MLflow Model 流式 API 记录或注册模型。

要解决这个问题,你可以创建一个 mlflow.pyfunc 模型风格的实例,并将你的 NLP 模型嵌入其中,这样你就可以保存、记录或注册模型。一旦注册,从模型注册表加载模型并使用 predict 函数进行评分。

下面的代码部分展示了如何创建一个嵌入了 vaderSentiment 模型的 PythonFuncModel 类,保存、记录、注册,并从模型注册表中加载和评分。

备注

要使用此示例,您需要 pip install vaderSentiment

from sys import version_info
import cloudpickle
import pandas as pd

import mlflow.pyfunc
from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer

#
# Good and readable paper from the authors of this package
# http://comp.social.gatech.edu/papers/icwsm14.vader.hutto.pdf
#

INPUT_TEXTS = [
    {"text": "This is a bad movie. You don't want to see it! :-)"},
    {"text": "Ricky Gervais is smart, witty, and creative!!!!!! :D"},
    {"text": "LOL, this guy fell off a chair while sleeping and snoring in a meeting"},
    {"text": "Men shoots himself while trying to steal a dog, OMG"},
    {"text": "Yay!! Another good phone interview. I nailed it!!"},
    {
        "text": "This is INSANE! I can't believe it. How could you do such a horrible thing?"
    },
]

PYTHON_VERSION = f"{version_info.major}.{version_info.minor}.{version_info.micro}"


def score_model(model):
    # Use inference to predict output from the customized PyFunc model
    for i, text in enumerate(INPUT_TEXTS):
        text = INPUT_TEXTS[i]["text"]
        m_input = pd.DataFrame([text])
        scores = loaded_model.predict(m_input)
        print(f"<{text}> -- {str(scores[0])}")


# Define a class and extend from PythonModel
class SocialMediaAnalyserModel(mlflow.pyfunc.PythonModel):
    def __init__(self):
        super().__init__()
        # embed your vader model instance
        self._analyser = SentimentIntensityAnalyzer()

    # preprocess the input with prediction from the vader sentiment model
    def _score(self, txt):
        prediction_scores = self._analyser.polarity_scores(txt)
        return prediction_scores

    def predict(self, context, model_input, params=None):
        # Apply the preprocess function from the vader model to score
        model_output = model_input.apply(lambda col: self._score(col))
        return model_output


model_path = "vader"
reg_model_name = "PyFuncVaderSentiments"
vader_model = SocialMediaAnalyserModel()

# Set the tracking URI to use local SQLAlchemy db file and start the run
# Log MLflow entities and save the model
mlflow.set_tracking_uri("sqlite:///mlruns.db")

# Save the conda environment for this model.
conda_env = {
    "channels": ["defaults", "conda-forge"],
    "dependencies": [f"python={PYTHON_VERSION}", "pip"],
    "pip": [
        "mlflow",
        f"cloudpickle=={cloudpickle.__version__}",
        "vaderSentiment==3.3.2",
    ],
    "name": "mlflow-env",
}

# Save the model
with mlflow.start_run(run_name="Vader Sentiment Analysis") as run:
    model_path = f"{model_path}-{run.info.run_uuid}"
    mlflow.log_param("algorithm", "VADER")
    mlflow.log_param("total_sentiments", len(INPUT_TEXTS))
    mlflow.pyfunc.save_model(
        path=model_path, python_model=vader_model, conda_env=conda_env
    )

# Use the saved model path to log and register into the model registry
mlflow.pyfunc.log_model(
    artifact_path=model_path,
    python_model=vader_model,
    registered_model_name=reg_model_name,
    conda_env=conda_env,
)

# Load the model from the model registry and score
model_uri = f"models:/{reg_model_name}/1"
loaded_model = mlflow.pyfunc.load_model(model_uri)
score_model(loaded_model)
Successfully registered model 'PyFuncVaderSentiments'.
2021/04/05 10:34:15 INFO mlflow.tracking._model_registry.client: Waiting up to 300 seconds for model version to finish creation.
Created version '1' of model 'PyFuncVaderSentiments'.

<This is a bad movie. You don't want to see it! :-)> -- {'neg': 0.307, 'neu': 0.552, 'pos': 0.141, 'compound': -0.4047}
<Ricky Gervais is smart, witty, and creative!!!!!! :D> -- {'neg': 0.0, 'neu': 0.316, 'pos': 0.684, 'compound': 0.8957}
<LOL, this guy fell off a chair while sleeping and snoring in a meeting> -- {'neg': 0.0, 'neu': 0.786, 'pos': 0.214, 'compound': 0.5473}
<Men shoots himself while trying to steal a dog, OMG> -- {'neg': 0.262, 'neu': 0.738, 'pos': 0.0, 'compound': -0.4939}
<Yay!! Another good phone interview. I nailed it!!> -- {'neg': 0.0, 'neu': 0.446, 'pos': 0.554, 'compound': 0.816}
<This is INSANE! I can't believe it. How could you do such a horrible thing?> -- {'neg': 0.357, 'neu': 0.643, 'pos': 0.0, 'compound': -0.8034}

已弃用:使用模型阶段

警告

模型阶段已被弃用,并将在未来的主要版本中移除。要了解更多关于此弃用的信息,请参阅下面的 迁移指南

请参阅以下关于在 MLflow 模型注册表中使用模型阶段的章节。

过渡 MLflow 模型的阶段

在模型的生命周期中,模型会从开发阶段演进到暂存阶段,再到生产阶段。您可以将已注册的模型过渡到以下阶段之一:暂存生产**或**归档

client = MlflowClient()
client.transition_model_version_stage(
    name="sk-learn-random-forest-reg-model", version=3, stage="Production"
)

接受的 <stage> 值为:Staging|Archived|Production|None。

获取特定阶段中的最新模型版本

要按阶段获取模型版本,只需在模型URI中提供模型阶段,它将获取该阶段中最新的模型版本。

import mlflow.pyfunc

model_name = "sk-learn-random-forest-reg-model"
stage = "Staging"

model = mlflow.pyfunc.load_model(model_uri=f"models:/{model_name}/{stage}")

model.predict(data)

归档一个 MLflow 模型

你可以将模型版本从 生产 阶段移至 归档 阶段。之后,如果不再需要该归档模型,你可以删除它。

# Archive models version 3 from Production into Archived
client = MlflowClient()
client.transition_model_version_stage(
    name="sk-learn-random-forest-reg-model", version=3, stage="Archived"
)

从阶段迁移

自 MLflow 2.9.0 起,模型阶段已被弃用,并将在未来的主要版本中移除。这是对模型阶段在表达 MLOps 工作流程中缺乏灵活性的广泛反馈的最终结果,从中我们开发并引入了新的工具来管理和部署 MLflow 模型注册表中的模型。了解更多如下。

新模型部署工具

模型阶段用于表示 MLflow 模型在生产化和部署过程中的生命周期。用户通过四个固定阶段(从 none,到 staging,到 production,再到 archived)来过渡模型版本,因为他们提出了、验证了、部署了和废弃了他们的 ML 用例模型。通过这种方式,模型注册阶段为模型版本提供了标签和别名功能,通过在 UI 中表示模型版本的状态,并在代码中提供对模型版本的命名引用(例如,模型 URI 中的 /Staging)。模型注册阶段还用于表示模型所处的环境,尽管无法为它们设置访问控制。

为了替换和改进阶段,我们在用户界面中提升了 模型版本标签 ,并引入了 模型版本别名 ,以提供灵活且强大的方式来标记和别名 Model Registry 中的 MLflow 模型。我们还实现了为您的模型 设置独立环境 ,并为每个环境配置访问控制。

模型版本标签

模型版本标签可以用来标注模型版本的状态。例如,你可以在模型版本正在验证时,为其应用一个键为 validation_status 且值为 pending 的标签,然后在通过冒烟测试和性能测试后,将标签值更新为 passed

模型版本别名

模型版本别名提供了一种灵活的方式来为特定模型版本创建命名引用,这对于识别环境中部署的模型版本非常有用。例如,为模型版本设置一个 champion 别名,使您能够通过 get_model_version_by_alias() 客户端API或模型URI models:/<registered model name>@champion 来获取该模型版本。别名可以通过UI和客户端API重新分配给新的模型版本。与模型注册阶段不同,可以为任何给定的模型版本应用多个别名,从而更容易进行A/B测试和模型发布。

为模型设置独立的环境

在成熟的 DevOps 和 MLOps 工作流程中,组织使用独立的环境(通常是开发、暂存和生产)并结合访问控制,以实现快速开发而不影响生产稳定性。通过 MLflow 认证,您可以使用已注册的模型来表示对 MLflow 模型的访问控制环境。例如,您可以为每个环境和业务问题的组合创建已注册的模型(例如 prod.ml_team.revenue_forecastingdev.ml_team.revenue_forecasting)并相应地配置权限。针对生产中的已注册模型自动重新训练模型,或者对于简单的模型部署用例,使用 copy_model_version() 在已注册的模型之间提升模型版本。

将模型从阶段中迁移出去

请参阅以下信息,了解如何使用新工具来处理您的传统模型阶段用例。

模型环境

要为您的模型版本设置独立的环境和权限,请创建独立的注册模型:

  • 给定模型用例的基本名称,例如 revenue_forecasting ,为不同的环境设置带有不同前缀的各种已注册模型。

  • 例如,如果你想设置三个独立的开发、暂存和生产环境,你可以设置 dev.ml_team.revenue_forecastingstaging.ml_team.revenue_forecastingprod.ml_team.revenue_forecasting 注册模型。

  • 使用 MLflow 认证 来授予这些模型适当的权限。

跨环境过渡模型

一旦你为每个环境设置了注册模型,你就可以在这些模型之上构建你的 MLOps 工作流。

  • 对于简单的模型推广用例,您可以首先在开发注册模型下注册您的 MLflow 模型,然后使用 copy_model_version() 客户端 API 在不同环境中推广模型。

  • 对于更成熟的生产级设置,我们建议在不同环境中推广您的 ML 代码(包括模型训练代码、推理代码和 ML 基础设施代码)。这消除了在不同环境中转换模型的需要。开发 ML 代码是实验性的,位于开发环境中,因此针对开发注册模型。在将开发的 ML 代码合并到您的源代码仓库之前,您的 CI 会在暂存环境中对代码进行集成测试(针对暂存注册模型)。合并后,ML 代码将部署到生产环境中进行自动重新训练(针对生产注册模型)。这种设置能够实现安全且稳健的 ML 系统 CI/CD - 不仅包括模型训练,还包括特征工程、模型监控和自动重新训练。

模型别名

要通过命名引用指定在环境中(例如生产环境)部署哪个模型版本以处理流量,请使用 模型别名

  1. 为每个模型注册阶段确定一个等效的模型别名(例如,champion 用于 Production 阶段,以指定旨在服务于大部分流量的模型)

  2. 将选定的别名分配给每个阶段下的最新模型版本。您可以使用下面的辅助函数来完成此操作。

  3. 更新机器学习工作流以指向别名而不是阶段。例如,模型URI models:/regression_model/Production 将被生产代码中的模型URI models:/prod.ml_team.regression_model@champion 替换。

from mlflow import MlflowClient

# Initialize an MLflow Client
client = MlflowClient()


def assign_alias_to_stage(model_name, stage, alias):
    """
    Assign an alias to the latest version of a registered model within a specified stage.

    :param model_name: The name of the registered model.
    :param stage: The stage of the model version for which the alias is to be assigned. Can be
                "Production", "Staging", "Archived", or "None".
    :param alias: The alias to assign to the model version.
    :return: None
    """
    latest_mv = client.get_latest_versions(model_name, stages=[stage])[0]
    client.set_registered_model_alias(model_name, alias, latest_mv.version)

模型状态

要表示和传达您的模型版本的状态,请使用模型版本标签:

  • 在模型版本上设置标签以指示模型的状态。

  • 例如,要指示模型版本的审核状态,您可以设置一个键为 validation_status 且值为 pendingpassed 的标签。