跳到主要内容

模型注册工作流

本指南将引导您通过 UI 和 API 使用 MLflow 模型注册表。 了解如何注册模型、管理版本、应用别名和标签,以及组织您的模型以进行部署。

注意

如果您运行自己的 MLflow 服务器,您必须使用数据库支持的后端存储才能通过 UI 或 API 访问模型注册表。 请参阅此处 获取更多信息。

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

UI 工作流

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

注册模型

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

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

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

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

查找已注册模型

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

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

  • 转到您的 MLflow 运行详细信息页面的工件部分,单击模型文件夹,然后单击右上角的模型版本以查看从该模型创建的版本。

部署和组织模型

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

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

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

在此页面中,您可以检查模型版本详细信息,如模型签名、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,
name="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 身份验证类型的详细信息,请参阅 此文档

通过 Databricks 分片令牌使用 Databricks unity catalog 模型注册表

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 catalog 模型注册表

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>"

使用带有“~/.databrickscfg”配置文件的 Databricks unity catalog 模型注册表

假设您已配置本地“~/.databrickscfg”文件,其中包含如下部分

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

import mlflow
import os

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

OSS Unity Catalog 模型注册表

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

使用 bearer 令牌使用 OSS unity catalog 模型注册表

import mlflow
import os

mlflow.set_registry_uri("uc:https://: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=https://:5000

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

跨环境提升 MLflow 模型

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

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

对于简单的模型部署用例,您可以将您训练的 MLflow 模型注册到 dev 环境已注册模型作为最新模型版本,然后使用 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 模型作为最新版本。

您也可以在 UI 中提升模型版本。 要做到这一点,请导航到模型版本详细信息页面,然后选择提升模型按钮。 这将打开一个模式窗口,您可以在其中选择一个已注册模型,当前模型版本将被复制到该模型。

添加或更新 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 模型

重要

当使用具有较旧模型注册表服务器(< 2.21.0)的 MLflow ≥ 2.21.0 客户端时,搜索 API 行为可能与预期结果不同。 此版本不匹配可能会导致不一致的搜索结果或缺少结果。 为确保行为一致,请通过将您的服务器升级到 MLflow 2.21.0 或更高版本(推荐)或降级您的客户端以匹配您的服务器版本来对齐 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.cn/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

以 pickled 格式保存后,您可以使用 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,
name="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 fluent 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 模型风格支持的机器学习框架。 例如,vaderSentiment 库是用于情感分析的标准自然语言处理 (NLP) 库。 由于它缺少内置的 MLflow 模型风格,因此您无法使用 MLflow 模型 fluent 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_id}"
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(
name=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 模型的生命周期。 用户通过四个固定阶段(从暂存,再到生产,然后到已存档)转换模型版本,因为他们为他们的 ML 用例提出、验证、部署和弃用模型。 通过这样做,模型注册表阶段为模型版本提供了标记和别名功能,通过在 UI 中表示模型版本的状态,并在代码中提供对模型版本的命名引用(例如,模型 URI 中的 /Staging)。 模型注册表阶段也用于表示模型所处的环境,尽管无法为其设置访问控制。

为了替换和改进阶段,我们在 UI 中提升了模型版本标签,并引入了模型版本别名,以提供灵活而强大的方式来标记和别名模型注册表中的 MLflow 模型。 我们还使为您的模型设置单独的环境并为每个环境配置访问控制成为可能。

模型版本标签

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

模型版本别名

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

为模型设置单独的环境

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

从阶段迁移模型

请参阅以下信息,了解如何将新工具用于您的遗留模型阶段用例。

模型环境

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

  • 给定模型用例的基本名称,例如 revenue_forecasting,设置与您的环境对应的各种带有不同前缀的已注册模型。
  • 例如,如果您想要三个单独的 dev、staging 和生产环境,您可以设置 dev.ml_team.revenue_forecastingstaging.ml_team.revenue_forecastingprod.ml_team.revenue_forecasting 已注册模型。
  • 使用 MLflow 身份验证 授予这些模型适当的权限。

跨环境转换模型

一旦您为每个环境设置了已注册模型,您就可以在它们之上构建您的 MLOps 工作流程。

  • 对于简单的模型提升用例,您可以首先在 dev 已注册模型下注册您的 MLflow 模型,然后使用 copy_model_version() 客户端 API 跨环境提升模型。
  • 对于更成熟的生产级设置,我们建议跨环境提升您的 ML 代码(包括模型训练代码、推理代码和 ML 基础设施即代码)。 这消除了跨环境转换模型的需要。 Dev ML 代码是实验性的,并且在 dev 环境中,因此针对 dev 已注册模型。 在将开发的 ML 代码合并到您的源代码存储库之前,您的 CI 将代码暂存在暂存环境中以进行集成测试(针对暂存已注册模型)。 合并后,ML 代码将部署到生产中以进行自动重新训练(针对 prod 已注册模型)。 这样的设置能够安全可靠地对 ML 系统进行 CI/CD - 不仅包括模型训练,还包括特征工程、模型监控和自动重新训练。

模型别名

要指定(通过命名引用)要在环境中部署以为流量提供服务的模型版本(例如,生产),请使用模型别名

  1. 为每个模型注册表阶段决定一个等效的模型别名(例如,Production 阶段的 champion,以指定旨在为大部分流量提供服务的模型)
  2. 将所选别名分配给每个阶段下的最新模型版本。 您可以使用下面的辅助函数来执行此操作。
  3. 更新 ML 工作流程以针对别名而不是阶段。 例如,模型 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 的标签。