适用于:
Azure CLI ml 扩展 v2(当前版本)
了解如何使用 Azure 机器学习 REST API 部署模型以进行批量评分。
REST API 使用标准 HTTP 谓词创建、检索、更新和删除资源。 REST API 适用于可发出 HTTP 请求的任何语言或工具。 REST 具有简单的结构,因此它是适合脚本编写环境和 MLOps 自动化的良好选择。
本文介绍如何使用新的 REST API 执行以下操作:
创建机器学习资产
创建批处理终结点和批处理部署
调用批处理终结点以启动批量评分作业
你对其拥有管理权限的
Azure 订阅
。 如果没有此类订阅,请尝试注册
免费或付费的个人订阅
。
一个
Azure 机器学习工作区
。
工作区中的服务主体。 管理 REST 请求使用
服务主体身份验证
。
一个服务主体身份验证令牌。 请按照
检索服务主体身份验证令牌
中的步骤检索此令牌。
curl
实用工具。 在
适用于 Linux 的 Windows 子系统
或任何 UNIX 分发版中均已提供了
curl
程序。 在 PowerShell 中,
curl
是
Invoke-WebRequest
的别名,并且
curl -d "key=val" -X POST uri
变成了
Invoke-WebRequest -Body "key=val" -Method POST -Uri uri
。
jq
JSON 处理器。
本文中的代码片段假设使用的是 Bash shell。
代码片段摘自
Azure 机器学习示例存储库
中的
/cli/batch-score-rest.sh
文件。
设置终结点名称
批处理终结点名称在 Azure 区域级别需是唯一的。 例如,westus2 中只能有一个名为 mybatchendpoint 的批处理终结点。
export ENDPOINT_NAME=endpt-`echo $RANDOM`
Azure 机器学习批处理终结点
批处理终结点
简化了承载用于批量评分的模型的过程,使你可以将工作重心放在机器学习而不是基础结构上。 在本文中,你将创建一个批处理终结点和部署,并调用它来启动批量评分作业。 但首先必须注册部署所需的资产,包括模型、代码和环境。
可通过多种方式创建 Azure 机器学习批处理终结点,包括 Azure CLI、适用于 Python 的 Azure 机器学习 SDK,以及在工作室中以视觉方式创建。 以下示例使用 REST API 创建批处理终结点和批处理部署。
创建机器学习资产
首先设置 Azure 机器学习资产以配置作业。
在以下 REST API 调用中,我们使用了
SUBSCRIPTION_ID
、
RESOURCE_GROUP
、
LOCATION
和
WORKSPACE
作为占位符。 将占位符替换为自己的值。
管理 REST 请求一个
服务主体身份验证令牌
。 请将
TOKEN
替换为你自己的值。 可使用以下命令检索此令牌:
TOKEN=$(az account get-access-token --query accessToken -o tsv)
服务提供商使用
api-version
参数来确保兼容性。
api-version
参数因服务而异。 将 API 版本设置为变量以适应将来的版本:
API_VERSION="2022-05-01"
批量评分仅在云计算资源上运行,而不在本地运行。 云计算资源是一个可重用的虚拟计算机群集,可在其中运行批量评分工作流。
创建计算群集:
response=$(curl --location --request PUT "https://management.azure.com/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.MachineLearningServices/workspaces/$WORKSPACE/computes/batch-cluster?api-version=$API_VERSION" \
--header "Authorization: Bearer $TOKEN" \
--header "Content-Type: application/json" \
--data-raw "{
\"properties\":{
\"computeType\": \"AmlCompute\",
\"properties\": {
\"osType\": \"Linux\",
\"vmSize\": \"STANDARD_D2_V2\",
\"scaleSettings\": {
\"maxNodeCount\": 5,
\"minNodeCount\": 0
\"remoteLoginPortPublicAccess\": \"NotSpecified\"
\"location\": \"$LOCATION\"
若要改用现有计算,必须在
创建批处理部署
时指定完整的 Azure 资源管理器 ID。 完整 ID 采用
/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.MachineLearningServices/workspaces/$WORKSPACE/computes/<your-compute-name>
格式。
获取存储帐户详细信息
若要注册模型和代码,首先需要将其上传到存储帐户。 数据存储中提供了存储帐户的详细信息。 此示例将获取工作区的默认数据存储和 Azure 存储帐户。 使用 GET 请求查询工作区,以获取包含信息的 JSON 文件。
可以使用工具
jq
分析 JSON 结果并获取所需的值。 也可以使用 Azure 门户找到相同的信息:
# Get values for storage account
response=$(curl --location --request GET "https://management.azure.com/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.MachineLearningServices/workspaces/$WORKSPACE/datastores?api-version=$API_VERSION&isDefault=true" \
--header "Authorization: Bearer $TOKEN")
DATASTORE_PATH=$(echo $response | jq -r '.value[0].id')
BLOB_URI_PROTOCOL=$(echo $response | jq -r '.value[0].properties.protocol')
BLOB_URI_ENDPOINT=$(echo $response | jq -r '.value[0].properties.endpoint')
AZUREML_DEFAULT_DATASTORE=$(echo $response | jq -r '.value[0].name')
AZUREML_DEFAULT_CONTAINER=$(echo $response | jq -r '.value[0].properties.containerName')
AZURE_STORAGE_ACCOUNT=$(echo $response | jq -r '.value[0].properties.accountName')
export AZURE_STORAGE_ACCOUNT $(echo $AZURE_STORAGE_ACCOUNT)
STORAGE_RESPONSE=$(echo az storage account show-connection-string --name $AZURE_STORAGE_ACCOUNT)
AZURE_STORAGE_CONNECTION_STRING=$($STORAGE_RESPONSE | jq -r '.connectionString')
BLOB_URI_ROOT="$BLOB_URI_PROTOCOL://$AZURE_STORAGE_ACCOUNT.blob.$BLOB_URI_ENDPOINT/$AZUREML_DEFAULT_CONTAINER"
上传和注册代码
获取数据存储后,可以上传评分脚本。 有关如何创作评分脚本的详细信息,请参阅
了解评分脚本
。 使用 Azure 存储 CLI 将 Blob 上传到默认容器中:
az storage blob upload-batch -d $AZUREML_DEFAULT_CONTAINER/score -s endpoints/batch/mnist/code/ --connection-string $AZURE_STORAGE_CONNECTION_STRING
也可以使用其他方法来上传,例如 Azure 门户或
Azure 存储资源管理器
。
上传代码后,可以使用 PUT 请求指定代码:
response=$(curl --location --request PUT "https://management.azure.com/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.MachineLearningServices/workspaces/$WORKSPACE/codes/score-mnist/versions/1?api-version=$API_VERSION" \
--header "Authorization: Bearer $TOKEN" \
--header "Content-Type: application/json" \
--data-raw "{
\"properties\": {
\"description\": \"Score code\",
\"codeUri\": \"$BLOB_URI_ROOT/score\"
上传和注册模型
与代码类似,上传模型文件:
az storage blob upload-batch -d $AZUREML_DEFAULT_CONTAINER/model -s endpoints/batch/mnist/model --connection-string $AZURE_STORAGE_CONNECTION_STRING
现在注册模型:
response=$(curl --location --request PUT "https://management.azure.com/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.MachineLearningServices/workspaces/$WORKSPACE/models/mnist/versions/1?api-version=$API_VERSION" \
--header "Authorization: Bearer $TOKEN" \
--header "Content-Type: application/json" \
--data-raw "{
\"properties\": {
\"modelUri\":\"azureml://subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/workspaces/$WORKSPACE/datastores/$AZUREML_DEFAULT_DATASTORE/paths/model\"
部署需要在具有所需依赖关系的环境中运行。 使用 PUT 请求创建环境。 使用 Microsoft Container Registry 中的 Docker 映像。 可以使用
image
配置 Docker 映像,并使用
condaFile
添加 Conda 依赖项。
运行以下代码以读取 json 中定义的
condaFile
。 源文件位于示例存储库中的
/cli/endpoints/batch/mnist/environment/conda.json
:
CONDA_FILE=$(cat endpoints/batch/mnist/environment/conda.json | sed 's/"/\\"/g')
现在,运行以下代码片段来创建环境:
ENV_VERSION=$RANDOM
response=$(curl --location --request PUT "https://management.azure.com/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.MachineLearningServices/workspaces/$WORKSPACE/environments/mnist-env/versions/$ENV_VERSION?api-version=$API_VERSION" \
--header "Authorization: Bearer $TOKEN" \
--header "Content-Type: application/json" \
--data-raw "{
\"properties\":{
\"condaFile\": $(echo \"$CONDA_FILE\"),
\"image\": \"mcr.microsoft.com/azureml/openmpi3.1.2-ubuntu18.04:latest\"
使用批处理终结点进行部署
接下来,创建一个批处理终结点,一个批处理部署,并为该终结点设置默认部署。
创建批处理终结点
创建批处理终结点:
response=$(curl --location --request PUT "https://management.azure.com/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.MachineLearningServices/workspaces/$WORKSPACE/batchEndpoints/$ENDPOINT_NAME?api-version=$API_VERSION" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer $TOKEN" \
--data-raw "{
\"properties\": {
\"authMode\": \"aadToken\"
\"location\": \"$LOCATION\"
创建批处理部署
在终结点下创建批处理部署:
DEPLOYMENT_NAME="nonmlflowedp"
response=$(curl --location --request PUT "https://management.azure.com/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.MachineLearningServices/workspaces/$WORKSPACE/batchEndpoints/$ENDPOINT_NAME/deployments/$DEPLOYMENT_NAME?api-version=$API_VERSION" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer $TOKEN" \
--data-raw "{
\"location\": \"$LOCATION\",
\"properties\": {
\"model\": {
\"referenceType\": \"Id\",
\"assetId\": \"/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.MachineLearningServices/workspaces/$WORKSPACE/models/mnist/versions/1\"
\"codeConfiguration\": {
\"codeId\": \"/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.MachineLearningServices/workspaces/$WORKSPACE/codes/score-mnist/versions/1\",
\"scoringScript\": \"digit_identification.py\"
\"environmentId\": \"/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.MachineLearningServices/workspaces/$WORKSPACE/environments/mnist-env/versions/$ENV_VERSION\",
\"compute\": \"/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.MachineLearningServices/workspaces/$WORKSPACE/computes/batch-cluster\",
\"resources\": {
\"instanceCount\": 1
\"maxConcurrencyPerInstance\": \"4\",
\"retrySettings\": {
\"maxRetries\": 3,
\"timeout\": \"PT30S\"
\"errorThreshold\": \"10\",
\"loggingLevel\": \"info\",
\"miniBatchSize\": \"5\",
在终结点下设置默认批处理部署
一个终结点下只有一个默认的批处理部署,调用运行批量评分作业时将使用该部署。
response=$(curl --location --request PUT "https://management.azure.com/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.MachineLearningServices/workspaces/$WORKSPACE/batchEndpoints/$ENDPOINT_NAME?api-version=$API_VERSION" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer $TOKEN" \
--data-raw "{
\"properties\": {
\"authMode\": \"aadToken\",
\"defaults\": {
\"deploymentName\": \"$DEPLOYMENT_NAME\"
\"location\": \"$LOCATION\"
operation_id=$(echo $response | jq -r '.properties' | jq -r '.properties' | jq -r '.AzureAsyncOperationUri')
wait_for_completion $operation_id $TOKEN
运行批量评分
调用批处理终结点会触发批量评分作业。 响应中会返回作业
id
,该作业可用于跟踪批量评分进度。 在以下代码片段中,
jq
用于获取作业
id
。
调用批处理终结点以启动批量评分作业
获取评分 URI 和访问令牌
获取评分 URI 和访问令牌以调用批处理终结点。 首先获取评分 uri:
response=$(curl --location --request GET "https://management.azure.com/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.MachineLearningServices/workspaces/$WORKSPACE/batchEndpoints/$ENDPOINT_NAME?api-version=$API_VERSION" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer $TOKEN")
SCORING_URI=$(echo $response | jq -r '.properties.scoringUri')
获取批处理终结点访问令牌:
SCORING_TOKEN=$(az account get-access-token --resource https://ml.azure.com --query accessToken -o tsv)
接下来,调用批处理终结点以启动批量评分作业。 如果数据是一个文件夹(可能包含多个文件)并且可通过网络公开访问,则可使用以下代码段:
response=$(curl --location --request POST $SCORING_URI \
--header "Authorization: Bearer $SCORING_TOKEN" \
--header "Content-Type: application/json" \
--data-raw "{
\"properties\": {
\"InputData\": {
\"mnistinput\": {
\"JobInputType\" : \"UriFolder\",
\"Uri\": \"https://pipelinedata.blob.core.windows.net/sampledata/mnist\"
JOB_ID=$(echo $response | jq -r '.id')
JOB_ID_SUFFIX=$(echo ${JOB_ID##/*/})
现在,让我们看看用于调用批处理终结点的其他选项。 当涉及到输入数据时,可选择多种方案,具体取决于输入类型(是指定文件夹还是单个文件)和 URI 类型(是使用 Azure 机器学习已注册的数据存储上的路径(是对 Azure 机器学习已注册的 V2 数据资产的引用)还会使用公共 URI)。
InputData 属性具有 JobInputType 和 Uri 键。 指定单个文件时,可使用 "JobInputType": "UriFile",指定文件夹时,可使用 'JobInputType": "UriFolder"。
当文件或文件夹位于已注册 Azure 机器学习的数据存储上时,Uri 的语法为 azureml://datastores/<datastore-name>/paths/<path-on-datastore>(适用于文件夹)和 azureml://datastores/<datastore-name>/paths/<path-on-datastore>/<file-name>(适用于特定文件)。 还可使用长格式来表示同一路径,例如 azureml://subscriptions/<subscription-id>/resourceGroups/<resource-group-name>/workspaces/<workspace-name>/datastores/<datastore-name>/paths/<path-on-datastore>/。
当文件或文件夹作为 uri_folder 或 uri_file 注册为 V2 数据资产时,Uri 的语法为 \"azureml://locations/<location-name>/workspaces/<workspace-name>/data/<data-name>/versions/<data-version>"(资产 ID 格式)或 \"/subscriptions/<subscription-id>/resourcegroups/<resource-group-name>/providers/Microsoft.MachineLearningServices/workspaces/<workspace-name>/data/<data-name>/versions/<data-version>\"(ARM ID 格式)。
当文件或文件夹位于可公开访问的路径上时,URI 的语法为 https://<public-path>(适用于文件夹)和 https://<public-path>/<file-name>(适用于特定文件)。
有关数据 URI 的详细信息,请参阅 Azure 机器学习数据引用 URI。
下面是使用不同类型的输入数据的一些示例。
如果数据是已注册 Azure 机器学习的数据存储上的文件夹,你则可以:
使用短格式表示 URI:
response=$(curl --location --request POST $SCORING_URI \
--header "Authorization: Bearer $SCORING_TOKEN" \
--header "Content-Type: application/json" \
--data-raw "{
\"properties\": {
\"InputData\": {
\"mnistInput\": {
\"JobInputType\" : \"UriFolder\",
\"Uri": \"azureml://datastores/workspaceblobstore/paths/$ENDPOINT_NAME/mnist\"
JOB_ID=$(echo $response | jq -r '.id')
JOB_ID_SUFFIX=$(echo ${JOB_ID##/*/})
或者对同一 URI 使用长格式:
response=$(curl --location --request POST $SCORING_URI \
--header "Authorization: Bearer $SCORING_TOKEN" \
--header "Content-Type: application/json" \
--data-raw "{
\"properties\": {
\"InputData\": {
\"mnistinput\": {
\"JobInputType\" : \"UriFolder\",
\"Uri\": \"azureml://subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/workspaces/$WORKSPACE/datastores/workspaceblobstore/paths/$ENDPOINT_NAME/mnist\"
JOB_ID=$(echo $response | jq -r '.id')
JOB_ID_SUFFIX=$(echo ${JOB_ID##/*/})
如果要将数据作为已注册 Azure 机器学习的 V2 数据资产进行管理,即 uri_folder,可以按照以下两个步骤操作:
创建 V2 数据资产:
DATA_NAME="mnist"
DATA_VERSION=$RANDOM
response=$(curl --location --request PUT https://management.azure.com/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.MachineLearningServices/workspaces/$WORKSPACE/data/$DATA_NAME/versions/$DATA_VERSION?api-version=$API_VERSION \
--header "Content-Type: application/json" \
--header "Authorization: Bearer $TOKEN" \
--data-raw "{
\"properties\": {
\"dataType\": \"uri_folder\",
\"dataUri\": \"https://pipelinedata.blob.core.windows.net/sampledata/mnist\",
\"description\": \"Mnist data asset\"
引用批处理评分作业中的数据资产:
response=$(curl --location --request POST $SCORING_URI \
--header "Authorization: Bearer $SCORING_TOKEN" \
--header "Content-Type: application/json" \
--data-raw "{
\"properties\": {
\"InputData\": {
\"mnistInput\": {
\"JobInputType\" : \"UriFolder\",
\"Uri": \"azureml://locations/$LOCATION_NAME/workspaces/$WORKSPACE_NAME/data/$DATA_NAME/versions/$DATA_VERSION/\"
JOB_ID=$(echo $response | jq -r '.id')
JOB_ID_SUFFIX=$(echo ${JOB_ID##/*/})
如果数据是可通过 Web 公开访问的单个文件,则可以使用以下代码片段:
response=$(curl --location --request POST $SCORING_URI \
--header "Authorization: Bearer $SCORING_TOKEN" \
--header "Content-Type: application/json" \
--data-raw "{
\"properties\": {
\"InputData\": {
\"mnistInput\": {
\"JobInputType\" : \"UriFile\",
\"Uri": \"https://pipelinedata.blob.core.windows.net/sampledata/mnist/0.png\"
JOB_ID=$(echo $response | jq -r '.id')
JOB_ID_SUFFIX=$(echo ${JOB_ID##/*/})
如果要使用本地数据,可以将其上传到Azure 机器学习已注册的数据存储,并对云数据使用 REST API。
如果对批处理终结点使用现有的 V1 FileDataset,建议将它们迁移到 V2 数据资产,并在调用批处理终结点时直接引用它们。 目前仅支持类型 uri_folder 或 uri_file 的数据资产。 使用 GA CLIv2(2.4.0 及更高版本)或 GA REST API(2022-05-01 及更高版本)创建的批处理终结点不支持 V1 数据集。
还可使用 az ml dataset show 命令和 --query 参数提取从 V1 FileDataset 中提取的数据存储上的 URI 或路径,并将该信息用于调用。
虽然使用早期 API 创建的批处理终结点将继续支持 V1 FileDataset,但我们将使用最新 API 版本添加更多 V2 数据资产支持,以提高可用性和灵活性。 有关 V2 数据资产的详细信息,请参阅使用 SDK v2 处理数据。 有关新的 V2 体验的详细信息,请参阅什么是 v2。
默认情况下,批量评分结果存储在工作区的默认 Blob 存储中按作业名称(系统生成的 GUID)命名的某个文件夹内。 可以配置在调用批处理终结点时用于存储评分输出的位置。 使用 OutputData 在 Azure 机器学习已注册的数据存储上配置输出文件路径。 OutputData 具有 JobOutputType 和 Uri 键。 UriFile 是 JobOutputType 唯一支持的值。 Uri 的语法与 InputData 的语法相同,即都为 azureml://datastores/<datastore-name>/paths/<path-on-datastore>/<file-name>。
下面是用于为批处理评分结果配置输出位置的代码片段示例。
response=$(curl --location --request POST $SCORING_URI \
--header "Authorization: Bearer $SCORING_TOKEN" \
--header "Content-Type: application/json" \
--data-raw "{
\"properties\": {
\"InputData\":
\"mnistInput\": {
\"JobInputType\" : \"UriFolder\",
\"Uri": \"azureml://datastores/workspaceblobstore/paths/$ENDPOINT_NAME/mnist\"
\"OutputData\":
\"mnistOutput\": {
\"JobOutputType\": \"UriFile\",
\"Uri\": \"azureml://datastores/workspaceblobstore/paths/$ENDPOINT_NAME/mnistOutput/$OUTPUT_FILE_NAME\"
JOB_ID=$(echo $response | jq -r '.id')
JOB_ID_SUFFIX=$(echo ${JOB_ID##/*/})
必须使用唯一的输出位置。 如果输出文件已存在,批量评分作业将失败。
检查批量评分作业
批量评分作业通常会花费一段时间来处理整个输入集。 监视作业状态,并在作业完成后检查结果:
该示例调用批处理终结点的默认部署。 若要调用非默认部署,请使用 azureml-model-deployment HTTP 头,并将值设置为部署名称。 例如,在 curl 中使用 --header "azureml-model-deployment: $DEPLOYMENT_NAME" 参数。
wait_for_completion $SCORING_URI/$JOB_ID_SUFFIX $SCORING_TOKEN
检查批量评分结果
有关检查结果的信息,请参阅检查批量评分结果。
删除批处理终结点
如果你将来不再使用该批处理终结点,应使用以下命令将其删除(这会删除该批处理终结点和所有基础部署):
curl --location --request DELETE "https://management.azure.com/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.MachineLearningServices/workspaces/$WORKSPACE/batchEndpoints/$ENDPOINT_NAME?api-version=$API_VERSION" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer $TOKEN" || true
了解如何部署模型进行批评分。
了解如何排查批处理终结点问题