您当前的位置: 首页 > 

寒冰屋

暂无认证

  • 6浏览

    0关注

    2286博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

在Azure上大规模部署模型——第1部分:部署XGBoost模型

寒冰屋 发布时间:2022-09-13 22:59:19 ,浏览量:6

目录

入门

注册模型

构建模型推理代码

创建Flask服务代码

使用Python和Flask发布应用服务

授予应用服务应用程序权限

测试服务

检查应用服务日志

使用Azure机器学习和托管终结点

创建在线端点代码

配置在线端点

创建托管在线端点

测试在线端点

删除Azure资源

下一步

这是3部分系列文章的第1部分,演示如何使用各种Python AI框架构建的AI模型,并使用Azure ML托管终结点部署和扩展它们。在本文中,我们发布了一个XGBoost模型,该模型经过训练可以从著名的MNIST数据集中识别手写数字。我们将Azure App Service与Flask一起使用,然后使用机器学习在线端点。

机器学习(ML)、数据科学和Python语言在过去几年中获得了普及和相关性。截至2021年,Python比Java、C#和 C++等成熟的老前辈更受欢迎。它于2021年11月在TIOBE指数中排名第一,比同年 9 月的第二名有所提升。在StackOverflow的2021年开发者调查中,Python也是第三受欢迎的编程语言。

每当您想到机器学习代码时,您很可能会想到Python。您可以在几乎任何东西上运行Python代码:PC、Mac或Raspberry Pi,配备x86、x86-64、AMD64或ARM/ARM64处理器,在Windows、Linux或macOS操作系统上。

机器学习通常需要强大的处理能力,这可能超出您当前计算机的能力。幸运的是,这无关紧要,只要您可以访问Internet和云。Azure是运行几乎任何规模的Python ML工作负载的好地方。

在之前的系列中,我们使用 Python和Azure服务训练了一些机器学习模型。在这个由三部分组成的系列中,我们会将这些模型发布到Azure。稍后我们将部署PyTorch和TensorFlow模型。但在第一篇文章中,我们将演示如何使用托管端点部署XGBoost模型。

我们的目标是为机器学习模型的实时推理创建自定义Rest API服务。我们将使用经过训练的模型,使用众所周知的MNIST数据集来识别手写数字。

我们将首先使用Python、Flask和Azure App Service发布XGBoost模型。然后,我们将使用相同的模型创建一个在线端点,这是一个相对较新的Azure机器学习功能,目前仍处于预览阶段。

我们依靠Azure CLI编写易于理解和可重复的脚本,我们可以存储这些脚本并与其余代码一起进行版本控制。在专用的GitHub存储库中找到本文的示例代码、脚本、模型和一些测试图像。

入门

您需要Visual Studio Code、最新的Python版本(3.7+)和用于Python包管理的Conda来学习本教程。如果您没有其他偏好,请从Miniconda和Python 3.9开始。

安装Conda后,创建并激活一个新环境。

$ conda create -n azureml python=3.9
$ conda activate azureml

除了Python和Conda,我们在2.15.0或更高版本中使用带有机器学习扩展的Azure命令行工具:

$ az extension add -n ml -y

最后但同样重要的是,如果您还没有Azure帐户,请注册一个。您可以获得免费积分并访问许多服务。

准备好所有这些资源后,登录您的订阅。

$ az login

设置以下环境变量以在脚本中使用:

export AZURE_SUBSCRIPTION=""
export RESOURCE_GROUP="azureml-rg"
export AML_WORKSPACE="demo-ws"
export LOCATION="westeurope"

如果您没有遵循上一个系列中的示例,您还需要使用以下命令创建 Azure 机器学习工作区:

$ az ml workspace create --name $AML_WORKSPACE --subscription $AZURE_SUBSCRIPTION 
  --resource-group $RESOURCE_GROUP --location $LOCATION

现在,我们已准备好开始准备我们的模型以进行部署。

注册模型

因为我们的模型很小,我们可以将它与我们的应用程序代码捆绑并部署。不过,这不是最佳做法。现实生活中的模型可能非常大。数兆字节——甚至千兆字节——并不罕见!另外,我们应该独立于我们的代码对模型进行版本控制。

因此,我们使用Azure机器学习工作区中内置的模型注册表。我们已经在上一个系列的第一篇文章中保存了我们的模型。如果你还没有,你可以很容易地做到这一点:

$ az ml model create --name "mnist-xgb-model" --local-path "./mnist.xgb_model" 
  --subscription $AZURE_SUBSCRIPTION --resource-group $RESOURCE_GROUP 
  --workspace-name $AML_WORKSPACE

请注意,我们将模型的名称从“mnist.xgb_model”更改为“mnist-xgb-model”。模型名称不能包含句点。

每次执行此命令时,它都会添加一个新的模型版本,无论您是否上传相同的文件。

当您登录到Azure Machine Learning Studio时,它应该列出所有版本,如下图所示:

构建模型推理代码

我们的Rest API服务的核心部分是加载模型并对图像数据运行推理的代码。

我们将代码保存在文件inference_model.py中:

import numpy
import xgboost as xgb

from PIL import Image

class InferenceModel():
    def __init__(self, model_path):
        self.model = xgb.XGBRFClassifier()
        self.model.load_model(model_path)

    def _preprocess_image(self, image_bytes):
        image = Image.open(image_bytes)
       
        # Reshape the image and convert it to monochrome
        image = image.resize((28,28)).convert('L')
       
        # Normalize data
        image_np = (255 - numpy.array(image.getdata())) / 255.0

 
        # Return image data reshaped to a vector
        return image_np.reshape(1, -1)

    def predict(self, image_bytes):
        image_data = self._preprocess_image(image_bytes)
        prediction = self.model.predict(image_data)
        return prediction

该文件包含一个使用三种方法:__init__、_preprocess_image和predict——调用的InferenceModel类。该__init__方法从文件中加载模型并将其存储以供以后使用。该_preprocess_image方法调整图像大小并将图像转换为模型期望的格式。在我们的例子中,它是一个0.0到1.0范围内的784个浮点数的向量。

该predict方法对提供的图像数据进行推理。

创建Flask服务代码

现在我们有了处理预测的代码,我们可以在我们的Rest API中使用它。首先,我们将创建一个定制的Flask服务来处理这项工作。

我们从新文件app.py中的import开始:

import json
from flask import Flask, request
from inference_model import InferenceModel

from azureml.core.authentication import MsiAuthentication
from azureml.core import Workspace
from azureml.core.model import Model

在访问我们的Azure机器学习工作区资源时,我们使用MsiAuthentication类进行身份验证。该类MsiAuthentication依赖于Azure Active Directory(AD)中的托管标识。我们将托管标识分配给Azure资源,例如虚拟机(VM)或应用服务。使用托管身份使我们免于维护凭据和机密。

接下来,我们创建一个从Azure机器学习模型注册表加载模型的方法:

def get_inference_model():
    global model
    if model == None:
        auth = MsiAuthentication()
        ws = Workspace(subscription_id="",
                        resource_group="azureml-rg",
                        workspace_name="demo-ws",
                        auth=auth)
 
        aml_model = Model(ws, 'mnist-xgb-model', version=1)
        model_path = aml_model.download(target_dir='.', exist_ok=True)
        model = InferenceModel(model_path)
   
    return model

model = None

我们在这个方法中使用一个global变量来确保模型只加载一次。

为了加载模型,我们使用Azure ML Workspace和Model类。最后,我们将下载的模型文件路径传递给InferenceModel类。

有了所有这些部分,我们可以添加代码来为我们的模型提供Flask服务:

app = Flask(__name__)

@app.route("/score", methods=['POST'])
def score():
    image_data = request.files.get('image')
    model = get_inference_model()
    preds = model.predict(image_data)
   
    return json.dumps({"preds": preds.tolist()})

在我们使用变量app声明我们的Flask应用程序之后,我们定义了score方法的路由。此方法读取提供的图像,获取推理模型并运行预测。最后,它以JSON格式返回预测结果。

使用Python和Flask发布应用服务

我们几乎拥有所有代码,可以使用Python和Flask的App Service在Azure上运行我们的REST API服务。我们需要的最后一个文件是requirements.txt,内容如下:

Flask==1.0.2
gunicorn==19.9.0
xgboost==1.5.0
pillow==8.3.2
numpy==1.19.5
scikit-learn==1.0.1
azureml-core==1.35.0

现在我们可以使用Azure CLI发布我们的应用服务应用程序,使用包含我们文件的文件夹中的以下命令:

$ export APP_SERVICE_PLAN=""
$ export APP_NAME=""

$ az webapp up --name $APP_NAME --plan $APP_SERVICE_PLAN --sku F1 
  --os-type Linux --runtime "python|3.8" --subscription $AZURE_SUBSCRIPTION 
  --resource-group $RESOURCE_GROUP

请注意,该APP_NAME值必须是全局唯一的,因为它将是服务URL的一部分。

此命令创建应用服务计划和应用服务,将我们的本地文件上传到Azure,然后启动应用程序。但是,这可能需要一段时间,有时它可能会无缘无故地失败。在极少数情况下,即使部署似乎成功完成,该服务也无法将您的代码正确识别为Flask应用程序,从而使该服务无法使用。

如有疑问,您可以在应用程序的部署中心选项卡中查看部署进度并登录:

如果出现问题,尤其是与超时相关的问题,只需重试部署步骤。

命令完成后,您应该会得到类似于以下内容的JSON:

{
  "URL": "http://.azurewebsites.net",
  "appserviceplan": "",
  "location": "centralus",
  "name": "",
  "os": "Linux",
  "resourcegroup": "azureml-rg",
  "runtime_version": "python|3.8",
  "runtime_version_detected": "-",
  "sku": "FREE",
  "src_path": ""
}

记住“URL”值。我们很快就会需要它来调用服务。

授予应用服务应用程序权限

我们的服务需要从我们的Azure机器学习工作区下载经过训练的模型。但是,此操作需要授权。我们使用托管身份来避免凭据管理。

为我们的应用程序分配一个新的托管标识很简单。添加以下代码:

$ az webapp identity assign --name $APP_NAME --resource-group $RESOURCE_GROUP

完成后,我们应该期待一个JSON。

{
  "principalId": "",
  "tenantId": "",
  "type": "SystemAssigned",
  "userAssignedIdentities": null
}

当我们有返回的“”值时,我们可以添加所需的权限。

$ az role assignment create --role reader --assignee 
  --scope /subscriptions/$AZURE_SUBSCRIPTION/resourceGroups/$RESOURCE_GROUP/providers/
  Microsoft.MachineLearningServices/workspaces/$AML_WORKSPACE

读者角色应该足以满足我们的目的。如果我们的应用程序需要创建额外的资源,我们应该使用贡献者角色。

测试服务

使用我们已经用于训练模型的任何图像都不会有趣。所以,让我们使用一些新的。您可以在示例代码文件夹中的test-images/d0.png到d9.png文件中找到它们。它们看起来像这样:

这些图像没有严格的要求。我们服务的代码将重新缩放并将它们转换为预期的大小和格式。

我们需要发送POST请求来调用我们的服务。我们可以使用Postman或curl。我们可以使用以下curl命令直接从命令行执行我们的请求:

$ curl -X POST -F 'image=@./test-images/d6.png' https://$APP_NAME.azurewebsites.net/score

如果一切顺利,我们可以期待以下响应:

{"preds": [6]}

很好!在我们简单的XGBoost模型中,答案似乎是正确的。不过,这不会成为常态。

检查应用服务日志

如果您遇到任何问题,您可能需要检查您的服务日志。您可以通过Azure门户 监控 > 日志流选项卡执行此操作:

或者,您可以使用Azure CLI访问日志:

$ az webapp log tail --name $APP_NAME --subscription $AZURE_SUBSCRIPTION 
  --resource-group $RESOURCE_GROUP

使用Azure机器学习和托管终结点

使用托管为Azure应用服务的自定义Flask应用程序发布我们的模型非常简单。通过这样做,我们可以体验所有标准应用服务优势,例如手动或自动扩展,具体取决于定价层。

尽管如此,对于应用服务解决方案,我们需要编写和维护与模型推理相关的代码,以及负责将其作为REST服务、安全性和其他较低级别细节的代码。

Azure机器学习(仍处于预览阶段)中可用的新替代方案之一是托管终结点机制。我们将在以下部分中使用我们的模型创建一个在线端点。

创建在线端点代码

我们将从Flask应用程序中复制相同的InferenceModel类到新文件夹端点代码中的inference_model.py文件中。

与之前的Flask应用程序一样,我们需要一些代码来定义我们的服务。我们将代码放在endpoint-code/aml-score.py文件中。这一次,我们可能会依赖内置的Azure机器学习机制:

import os
import json
from inference_model import InferenceModel

from azureml.contrib.services.aml_request import rawhttp
from azureml.contrib.services.aml_response import AMLResponse

def init():
   global model
   model_path = os.path.join(
        os.getenv("AZUREML_MODEL_DIR"), "mnist.xgb_model"
    )

    model = InferenceModel(model_path)

@rawhttp
def run(request):
    if request.method != 'POST':
        return AMLResponse(f"Unsupported verb: {request.method}", 400)

    image_data = request.files['image']
    preds = model.predict(image_data)
   
    return AMLResponse(json.dumps({"preds": preds.tolist()}), 200)

我们只需要两种方法。init该代码在端点启动时调用第一个, 一次。这是加载我们模型的好地方。我们使用AZUREML_MODEL_DIR环境变量来执行此操作,它指示我们模型文件的位置。

以下run方法非常简单。首先,我们确保只接受POST请求。然后实际逻辑开始:我们从请求中检索图像,然后运行并返回预测。

注意@rawhttp装饰器。我们要求它访问原始请求数据(在我们的例子中是二进制图像内容)。没有它,传递给run方法的request参数将仅限于解析的JSON。

配置在线端点

除了代码,我们还需要三个配置文件。第一个,endpoint-code/aml-env.yml,存储Conda环境定义:

channels:
  - conda-forge
  - defaults
dependencies:
  - python=3.7.10
  - numpy=1.19.5
  - xgboost=1.5.0
  - scikit-learn=1.0.1
  - pillow=8.3.2
  - pip
  - pip:
    - azureml-defaults==1.35.0
    - inference-schema[numpy-support]==1.3.0

以下两个包含端点及其部署的配置。

端点配置文件aml-endpoint.yml包含:

$schema: https://azuremlschemas.azureedge.net/latest/managedOnlineEndpoint.schema.json
name: mnistxgboep
auth_mode: key

除了端点名称(无论如何我们都可以在脚本中更改)之外,该文件只包含一个有意义的行。它设置auth_mode为key,以便我们在调用端点时使用随机生成的“secret”string作为身份验证令牌。

最后一个文件aml-endpoint-deployment.yml包含以下代码:

$schema: https://azuremlschemas.azureedge.net/latest/managedOnlineDeployment.schema.json
name: blue
endpoint_name: mnistxgboep
model: azureml:mnist-xgb-model:1
code_configuration:
  code:
    local_path: ./endpoint-code
  scoring_script: aml-score.py

environment:
  conda_file: ./endpoint-code/aml-env.yml
  image: mcr.microsoft.com/azureml/minimal-ubuntu18.04-py37-cpu-inference:latest

instance_type: Standard_F2s_v2
instance_count: 1

在部署配置中,我们设置了基本的详细信息,例如模型名称和版本。该code_configuration部分指示我们端点的路径及其主脚本文件。请注意,您需要明确定义模型版本,以便代码自动下载并保存这个确切的模型版本,以便为我们的服务做好准备。

接下来,我们定义Docker镜像、Conda环境配置文件、VM实例大小和实例数。

创建托管在线端点

准备好所有这些文件后,我们就可以开始部署了。我们从端点开始:

$ export ENDPOINT_NAME=""

$ az ml online-endpoint create -n $ENDPOINT_NAME -f aml-endpoint.yml 
  --subscription $AZURE_SUBSCRIPTION --resource-group $RESOURCE_GROUP 
  --workspace-name $AML_WORKSPACE

与之前的应用服务应用程序名称一样,每个Azure区域的终结点名称必须是唯一的。它将成为URL的一部分,格式如下:

https://..inference.ml.azure.com/score

创建端点后,我们终于可以部署我们的推理代码了:

$ az ml online-deployment create -n blue 
  --endpoint $ENDPOINT_NAME -f aml-endpoint-deployment.yml 
  --all-traffic --subscription $AZURE_SUBSCRIPTION 
  --resource-group $RESOURCE_GROUP --workspace-name $AML_WORKSPACE

很长一段时间后,该命令应返回确认部署已完成且端点已准备好使用。现在,我们可以检查它是如何工作的。

测试在线端点

我们需要端点URL、端点密钥和示例图像来调用我们的端点。我们已经使用了示例图像,因此我们只需要端点URL和密钥。获取它们的一种方法是通过Azure Machine Learning Studio ,从端点的“使用”选项卡:

与(几乎)一样,我们也可以使用Azure CLI获取这些值:

$ SCORING_URI=$(az ml online-endpoint show -n $ENDPOINT_NAME -o tsv 
--query scoring_uri --resource-group $RESOURCE_GROUP --workspace $AML_WORKSPACE)

$ ENDPOINT_KEY=$(az ml online-endpoint get-credentials --name $ENDPOINT_NAME 
  --subscription $AZURE_SUBSCRIPTION --resource-group $RESOURCE_GROUP 
  --workspace-name $AML_WORKSPACE -o tsv --query primaryKey)

无论如何,填充SCORING_URI和ENDPOINT_KEY变量后,我们可以调用我们的服务:

$ curl -X POST -F 'image=@./test-images/d6.png' 
  -H "Authorization: Bearer $ENDPOINT_KEY" $SCORING_URI

如果一切顺利,我们应该得到与Flask应用程序相同的答案:

{"preds": [6]}
删除Azure资源

你可以删除不再需要的所有资源以减少Azure费用。请特别记住应用服务计划和托管终结点(尽管我们在此示例中使用了免费的应用服务计划)。

下一步

我们已经成功发布了一个XGBoost模型,该模型经过训练可以识别手写数字,使用Flask和App Service,并管理在线端点。下面的文章与此类似,但我们将使用PyTorch而不是XGBoost,使用FastAPI而不是Flask。 此外,我们将快速浏览FastAPI代码以专注于一些额外的托管在线端点功能。

继续阅读本系列的第二部分,了解如何部署和扩展PyTorch模型。

要了解如何使用在线端点(预览版)部署机器学习模型,请查看使用在线端点部署机器学习模型并对其进行评分。

https://www.codeproject.com/Articles/5328263/Deploying-Models-at-Scale-on-Azure-Part-1-Deployin

关注
打赏
1665926880
查看更多评论
立即登录/注册

微信扫码登录

0.3333s