MLflow 模型注册表
MLflow 模型注册表组件是一个集中的模型存储、API 和 UI 集合,用于协作管理 MLflow 模型的完整生命周期。它提供模型沿袭(哪个 MLflow 实验和运行产生了模型)、模型版本控制、模型别名、模型标签和注释。
概念
模型注册表引入了几个概念,用于描述和促进 MLflow 模型的完整生命周期。
模型
MLflow 模型是使用模型风格的
mlflow.<model_flavor>.log_model()
方法从实验或运行中记录创建的。记录后,该模型可以注册到模型注册表。注册模型
MLflow 模型可以注册到模型注册表。注册的模型具有唯一的名称,包含版本、别名、标签和其他元数据。
模型版本
每个注册的模型可以有一个或多个版本。将新模型添加到模型注册表时,它会作为版本 1 添加。注册到相同模型名称的每个新模型都会递增版本号。模型版本有标签,这对于跟踪模型版本属性(例如
pre_deploy_checks: "PASSED"
)非常有用。模型别名
模型别名允许您为注册模型的特定版本分配一个可变的、命名的引用。通过为特定模型版本分配别名,您可以使用别名通过模型 URI 或模型注册表 API 引用该模型版本。例如,您可以创建一个名为
champion
的别名,它指向名为MyModel
的模型版本 1。然后,您可以使用 URImodels:/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 模型。
- 打开包含您要注册的已记录 MLflow 模型的 MLflow Run 的详细信息页面。在 Artifacts(工件)部分选择包含目标 MLflow 模型的模型文件夹。
-
单击 Register Model(注册模型)按钮,这将触发弹出一个表单。
-
在表单上的 Model(模型)下拉菜单中,您可以选择“Create New Model”(创建新模型),这将创建一个新的注册模型,并将您的 MLflow 模型作为其初始版本;或者选择一个现有的注册模型,这将把您的模型作为新版本注册到该模型下。下面的屏幕截图演示了将 MLflow 模型注册到名为
"iris_model_testing"
的新注册模型。
查找注册模型
在模型注册表中注册模型后,可以通过以下方式导航到它们。
-
导航到 Registered Models(注册模型)页面,该页面链接到您的注册模型和相应的模型版本。
-
转到 MLflow Runs 详细信息页面的 Artifacts(工件)部分,单击模型文件夹,然后单击右上角的模型版本以查看由该模型创建的版本。
部署和组织模型
您可以使用模型别名和标签在模型注册表中部署和组织模型。要为注册模型中的模型版本设置别名和标签,请导航到注册模型的概览页面,如下所示。
您可以通过单击模型版本表中对应的 Add
链接或铅笔图标来添加或编辑特定模型版本的别名和标签。
要了解特定模型版本的更多详细信息,请导航到该模型版本的详细信息页面。
在此页面中,您可以查看模型版本详细信息,例如模型签名、MLflow 源运行和创建时间戳。您还可以查看和配置版本的别名、标签和描述。
API 工作流
与模型注册表交互的另一种方式是使用 MLflow 模型风格或 MLflow Client Tracking 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 认证类型的详细信息,请参阅此文档。
使用 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 模型注册表,请在 MLflow 注册表 URI 中以 "uc:https://:8080"
格式指定 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 Client 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 Client 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_forecasting
、dev.ml_team.revenue_forecasting
),并相应地配置权限。当您针对业务问题迭代 MLflow 模型时,可以通过源代码控制和 CI/CD 系统在不同环境中推广它们,以实现持续集成和部署。
对于成熟的生产级设置,我们建议设置自动化工作流,以在每个环境中训练和注册模型。为了将业务问题的最新迭代投入生产,请通过源代码控制和 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 中推广模型版本。为此,导航到模型版本详细信息页面,然后选择 Promote model
(推广模型)按钮。这将打开一个模态框,您可以在其中选择要复制当前模型版本的注册模型。
添加或更新 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 演示了与模型注册表的交互,但有两个特殊情况需要注意。一种是您有现有机器学习模型,它们是在未使用 MLflow 的情况下从训练中保存的。它们以 sklearn 的 pickle 格式序列化并持久化在磁盘上,您想将此模型注册到模型注册表。第二种情况是您使用的机器学习框架没有内置的 MLflow 模型风格支持,例如 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
保存为 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 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 Model 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_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 模型阶段
在模型的生命周期中,模型会不断演进——从开发到暂存再到生产。您可以将注册模型转换到以下阶段之一:暂存 (Staging)、生产 (Production) 或 归档 (Archived)。
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_forecasting
、dev.ml_team.revenue_forecasting
),并相应地配置权限。针对生产注册模型自动化模型再训练,或者对于简单的模型部署用例,使用 copy_model_version()
在注册模型之间推广模型版本。
将模型从阶段迁移出去
请参阅以下信息,了解如何在您的旧模型阶段用例中使用新工具。
模型环境
要为模型版本设置独立的环境和权限,请创建独立的注册模型
- 给定模型用例的基本名称,例如
revenue_forecasting
,可以设置与您的环境对应的各种注册模型,并带有不同的前缀。 - 例如,如果您想要三个独立的 dev、staging 和 production 环境,可以设置
dev.ml_team.revenue_forecasting
、staging.ml_team.revenue_forecasting
和prod.ml_team.revenue_forecasting
注册模型。 - 使用 MLflow 认证授予这些模型适当的权限。
在环境之间迁移模型
为每个环境设置注册模型后,您可以在其之上构建 MLOps 工作流。
- 对于简单的模型推广用例,您可以首先将您的 MLflow 模型注册到 dev 注册模型下,然后使用
copy_model_version()
客户端 API 在环境之间推广模型。 - 对于更成熟的生产级设置,我们建议在环境之间推广您的 ML 代码(包括模型训练代码、推理代码和 ML 基础设施即代码)。这消除了在环境之间转换模型的需要。Dev ML 代码是实验性的,并且位于 dev 环境中,因此以 dev 注册模型为目标。在将开发的 ML 代码合并到源代码仓库之前,您的 CI 会在 staging 环境中暂存代码以进行集成测试(以 staging 注册模型为目标)。合并后,ML 代码将部署到生产环境进行自动化再训练(以 prod 注册模型为目标)。这种设置能够安全可靠地进行 ML 系统(包括模型训练、特征工程、模型监控和自动化再训练)的 CI/CD。
模型别名设置
要指定(通过命名引用)要在环境中(例如,生产环境)部署哪个模型版本来提供流量,请使用模型别名
- 为每个模型注册表阶段确定一个等效的模型别名(例如,将 champion 用于生产阶段,以指定旨在处理大部分流量的模型)
- 将选定的别名分配给每个阶段下的最新模型版本。您可以使用下面的助手函数完成此操作。
- 更新 ML 工作流以目标别名而不是阶段。例如,模型 URI
models:/regression_model/Production
将在生产代码中替换为模型 URImodels:/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
、值为pending
或passed
的标签。