教程:使用 AutoML 和 Python 训练物体检测模型(预览版)(v1)

适用于:Azure Machine Learning SDK v1 for Python

重要

本文提供有关使用 Azure Machine Learning SDK v1 的信息。 SDK v1 自 2025 年 3 月 31 日起弃用。 对它的支持将于 2026 年 6 月 30 日结束。 可以在该日期之前安装和使用 SDK v1。 使用 SDK v1 的现有工作流将在支持结束日期后继续运行。 但是,在产品发生体系结构更改时,可能会面临安全风险或中断性变更。

建议在 2026 年 6 月 30 日之前过渡到 SDK v2。 有关 SDK v2 的详细信息,请参阅 什么是 Azure Machine Learning CLI 和 Python SDK v2?SDK v2 参考

重要

本文中介绍的功能处于预览阶段。 请将它们视为实验性预览功能,可能会随时更改。

本教程介绍如何使用 Azure Machine Learning 自动化 ML 和 Azure Machine Learning Python SDK 来训练对象检测模型。 此物体检测模型可识别图像是否包含对象(如罐、纸箱、奶瓶或水瓶)。

自动化 ML 接受训练数据和配置设置。 它自动循环访问不同特征规范化和标准化方法、模型和超参数设置的组合,以查找最佳模型。

在本教程中使用 Python SDK 编写代码并学习以下任务:

  • 下载和转换数据
  • 训练自动化机器学习目标检测模型
  • 为模型指定超参数值
  • 执行超参数扫描
  • 部署模型
  • 直观呈现检测结果

先决条件

  • 如果没有Azure订阅,请在开始前创建试用版。 立即试用 Azure Machine Learning 的 free 或付费版本

  • 此功能支持 Python 3.10 或更高版本。

  • 请完成 Quickstart:Azure Machine Learning 快速入门,如果您还没有 Azure Machine Learning 工作区。

  • 下载并解压缩 odFridgeObjects.zip 数据文件。 数据集以 Pascal VOC 格式批注,其中每个图像对应于 XML 文件。 每个 XML 文件都包含有关其相应图像文件所在位置的信息,还包含有关边界框和对象标签的信息。 若要使用此数据,首先需要将其转换为所需的 JSONL 格式,如将下载的数据转换为笔记本的 JSONL 部分。

您也可以在 GitHub 上的 azureml-examples 存储库 中找到本教程,以便在自己的 本地环境 中运行。 若要获取所需的软件包,

计算目标设置

首先需要设置用于自动化 ML 模型训练的计算目标。 用于图像任务的自动化 ML 模型需要 GPU SKU。

本教程使用 NCasT4_v3 系列(具有 T4 GPU),因为这种类型的计算目标利用多个 GPU 来加快训练速度。 此外,还可以设置多个节点,以在优化模型的超参数时利用并行度。

以下代码将创建一个计算实例,类型为 Standard_NC64as_T4_v3,包含四个节点,并附加到工作区 ws

警告

确保订阅有足够的配额用于要使用的计算目标。

from azureml.core.compute import AmlCompute, ComputeTarget

cluster_name = "gpu-nc64ast4v3"

try:
    compute_target = ComputeTarget(workspace=ws, name=cluster_name)
    print('Found existing compute target.')
except KeyError:
    print('Creating a new compute target...')
    compute_config = AmlCompute.provisioning_configuration(vm_size='Standard_NC64as_T4_v3',
                                                           idle_seconds_before_scaledown=1800,
                                                           min_nodes=0,
                                                           max_nodes=4)

    compute_target = ComputeTarget.create(ws, cluster_name, compute_config)

#If no min_node_count is provided, the scale settings are used for the cluster.
compute_target.wait_for_completion(show_output=True, min_node_count=None, timeout_in_minutes=20)

试验设置

接下来,在工作区中创建一个 Experiment,以跟踪模型训练的运行情况。


from azureml.core import Experiment

experiment_name = 'automl-image-object-detection'
experiment = Experiment(ws, name=experiment_name)

直观呈现输入数据

准备格式为 JSONL (JSON 行) 的输入图像数据后,可以对图像的真实边界框进行可视化。 要进行此可视化,请确保已安装matplotlib

%pip install --upgrade matplotlib

%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import matplotlib.patches as patches
from PIL import Image as pil_image
import numpy as np
import json
import os

def plot_ground_truth_boxes(image_file, ground_truth_boxes):
    # Display the image
    plt.figure()
    img_np = mpimg.imread(image_file)
    img = pil_image.fromarray(img_np.astype("uint8"), "RGB")
    img_w, img_h = img.size

    fig,ax = plt.subplots(figsize=(12, 16))
    ax.imshow(img_np)
    ax.axis("off")

    label_to_color_mapping = {}

    for gt in ground_truth_boxes:
        label = gt["label"]

        xmin, ymin, xmax, ymax =  gt["topX"], gt["topY"], gt["bottomX"], gt["bottomY"]
        topleft_x, topleft_y = img_w * xmin, img_h * ymin
        width, height = img_w * (xmax - xmin), img_h * (ymax - ymin)

        if label in label_to_color_mapping:
            color = label_to_color_mapping[label]
        else:
            # Generate a random color. If you want to use a specific color, you can use something like "red".
            color = np.random.rand(3)
            label_to_color_mapping[label] = color

        # Display bounding box
        rect = patches.Rectangle((topleft_x, topleft_y), width, height,
                                 linewidth=2, edgecolor=color, facecolor="none")
        ax.add_patch(rect)

        # Display label
        ax.text(topleft_x, topleft_y - 10, label, color=color, fontsize=20)

    plt.show()

def plot_ground_truth_boxes_jsonl(image_file, jsonl_file):
    image_base_name = os.path.basename(image_file)
    ground_truth_data_found = False
    with open(jsonl_file) as fp:
        for line in fp.readlines():
            line_json = json.loads(line)
            filename = line_json["image_url"]
            if image_base_name in filename:
                ground_truth_data_found = True
                plot_ground_truth_boxes(image_file, line_json["label"])
                break
    if not ground_truth_data_found:
        print("Unable to find ground truth information for image: {}".format(image_file))

def plot_ground_truth_boxes_dataset(image_file, dataset_pd):
    image_base_name = os.path.basename(image_file)
    image_pd = dataset_pd[dataset_pd['portable_path'].str.contains(image_base_name)]
    if not image_pd.empty:
        ground_truth_boxes = image_pd.iloc[0]["label"]
        plot_ground_truth_boxes(image_file, ground_truth_boxes)
    else:
        print("Unable to find ground truth information for image: {}".format(image_file))

通过使用前面的辅助函数,可以显示任何给定图像的边界框。

image_file = "./odFridgeObjects/images/31.jpg"
jsonl_file = "./odFridgeObjects/train_annotations.jsonl"

plot_ground_truth_boxes_jsonl(image_file, jsonl_file)

上传数据并创建数据集

若要使用数据进行训练,请通过数据存储将其上传到工作区。 数据存储提供了一种用于上传或下载数据以及从远程计算目标与其交互的机制。

ds = ws.get_default_datastore()
ds.upload(src_dir='./odFridgeObjects', target_path='odFridgeObjects')

将数据上传到数据存储后,从数据创建Azure Machine Learning数据集。 数据集将您的数据打包成一个可以用于训练的对象。

以下代码创建用于训练的数据集。 由于未指定验证数据集,默认行为使用 20% 训练数据进行验证。

from azureml.core import Dataset
from azureml.data import DataType

training_dataset_name = 'odFridgeObjectsTrainingDataset'
if training_dataset_name in ws.datasets:
    training_dataset = ws.datasets.get(training_dataset_name)
    print('Found the training dataset', training_dataset_name)
else:
    # create training dataset
        # create training dataset
    training_dataset = Dataset.Tabular.from_json_lines_files(
        path=ds.path('odFridgeObjects/train_annotations.jsonl'),
        set_column_types={"image_url": DataType.to_stream(ds.workspace)},
    )
    training_dataset = training_dataset.register(workspace=ws, name=training_dataset_name)

print("Training dataset name: " + training_dataset.name)

直观呈现数据集

你还可以直观呈现此数据集中图像的地面实况边界框。

将数据集加载到 pandas 的数据帧中。

import azureml.dataprep as dprep

from azureml.dataprep.api.functions import get_portable_path

# Get pandas dataframe from the dataset
dflow = training_dataset._dataflow.add_column(get_portable_path(dprep.col("image_url")),
                                              "portable_path", "image_url")
dataset_pd = dflow.to_pandas_dataframe(extended_types=True)

对于任何给定的图像,请运行以下代码以显示边界框。

image_file = "./odFridgeObjects/images/31.jpg"
plot_ground_truth_boxes_dataset(image_file, dataset_pd)

配置目标检测实验

若要为与图像相关的任务配置自动化 ML 运行,请使用 AutoMLImageConfig 对象。 在 AutoMLImageConfig 中,使用 model_name 参数指定模型算法。 配置设置以对定义的参数空间执行超参数扫描,以查找最佳模型。

在此示例中,使用 AutoMLImageConfig 来训练对象检测模型,并将 yolov5fasterrcnn_resnet50_fpn(两者均在 COCO 数据集上预训练)用于模型的训练。COCO 是一个大规模的对象检测、分割和标注数据集,包含数千张标记图像和超过80个标签类别。

适用于图像任务的超参数扫描

对定义的参数空间执行超参数扫描,以查找最佳模型。

以下代码定义参数空间,以准备每个定义的算法的超参数扫描, yolov5 以及 fasterrcnn_resnet50_fpn。 在参数空间中,指定 learning_rateoptimizerlr_scheduler 以及其他参数的值范围,供 AutoML 在尝试生成具有最佳主要指标的模型时进行选择。 如果未指定超参数值,则每个算法都使用默认值。

对于调优设置,请通过导入GridParameterSamplingRandomParameterSamplingBayesianParameterSampling类,使用随机采样从此参数空间选取样本。 通过使用这些类,可以告知自动化 ML 使用这些不同的示例尝试总共 20 次迭代,一次在计算目标上运行四次迭代,使用四个节点进行设置。 空间的参数越多,查找最佳模型所需的迭代次数就越多。

还使用 Bandit 提前终止策略。 此策略会终止性能不佳的配置(这些配置不在 20% 最高性能配置的松懈范围内),这可以显著节省计算资源。

from azureml.train.hyperdrive import RandomParameterSampling
from azureml.train.hyperdrive import BanditPolicy, HyperDriveConfig
from azureml.train.hyperdrive import choice, uniform

parameter_space = {
    'model': choice(
        {
            'model_name': choice('yolov5'),
            'learning_rate': uniform(0.0001, 0.01),
            #'model_size': choice('small', 'medium'), # model-specific
            'img_size': choice(640, 704, 768), # model-specific
        },
        {
            'model_name': choice('fasterrcnn_resnet50_fpn'),
            'learning_rate': uniform(0.0001, 0.001),
            #'warmup_cosine_lr_warmup_epochs': choice(0, 3),
            'optimizer': choice('sgd', 'adam', 'adamw'),
            'min_size': choice(600, 800), # model-specific
        }
    )
}

tuning_settings = {
    'iterations': 20,
    'max_concurrent_iterations': 4,
    'hyperparameter_sampling': RandomParameterSampling(parameter_space),
    'policy': BanditPolicy(evaluation_interval=2, slack_factor=0.2, delay_evaluation=6)
}

定义参数空间和优化设置后,将它们传递到对象 AutoMLImageConfig 中。 然后提交试验,以使用训练数据集训练图像模型。

from azureml.train.automl import AutoMLImageConfig
automl_image_config = AutoMLImageConfig(task='image-object-detection',
                                        compute_target=compute_target,
                                        training_data=training_dataset,
                                        validation_data=validation_dataset,
                                        primary_metric='mean_average_precision',
                                        **tuning_settings)

automl_image_run = experiment.submit(automl_image_config)
automl_image_run.wait_for_completion(wait_post_processing=True)

执行超参数扫描时,可视化使用 HyperDrive UI 尝试的不同配置可能很有用。 可以通过转到上面主 UI 中的automl_image_run”选项卡(即 HyperDrive 父运行)导航到此 UI。 然后,您可以转到这个“子运行”选项卡。 或者,以下部分显示了 HyperDrive 父运行,你可以导航到其 子运行 选项卡:

from azureml.core import Run
hyperdrive_run = Run(experiment=experiment, run_id=automl_image_run.id + '_HD')
hyperdrive_run

注册最佳模型

运行完成后,注册最佳运行创建的模型。

best_child_run = automl_image_run.get_best_child()
model_name = best_child_run.properties['model_name']
model = best_child_run.register_model(model_name = model_name, model_path='outputs/model.pt')

将模型部署为 Web 服务

训练模型后,将其部署到Azure。 在Azure Container Instances(ACI)或Azure Kubernetes Service(AKS)上将训练的模型部署为 Web 服务。 ACI 非常适用于测试部署,而 AKS 更适合大规模生产使用。

在本教程中,你将模型部署为 AKS 中的 Web 服务。

  1. 创建 AKS 计算群集。 在此示例中,对部署群集使用 GPU 虚拟机 SKU。

    from azureml.core.compute import ComputeTarget, AksCompute
    from azureml.exceptions import ComputeTargetException
    
    # Choose a name for your cluster
    aks_name = "cluster-aks-gpu"
    
    # Check to see if the cluster already exists
    try:
        aks_target = ComputeTarget(workspace=ws, name=aks_name)
        print('Found existing compute target')
    except ComputeTargetException:
        print('Creating a new compute target...')
        # Provision AKS cluster with GPU machine
        prov_config = AksCompute.provisioning_configuration(vm_size="STANDARD_NC6",
                                                            location="chinanorth3")
        # Create the cluster
        aks_target = ComputeTarget.create(workspace=ws,
                                          name=aks_name,
                                          provisioning_configuration=prov_config)
        aks_target.wait_for_completion(show_output=True)
    
  2. 定义描述如何设置包含模型的 Web 服务的推理配置。 在您的推断配置中,可以使用训练运行中的评分脚本和环境。

    注意事项

    若要更改模型的设置,请在部署模型之前打开下载的评分脚本并修改 model_settings 变量。

    from azureml.core.model import InferenceConfig
    
    best_child_run.download_file('outputs/scoring_file_v_1_0_0.py', output_file_path='score.py')
    environment = best_child_run.get_environment()
    inference_config = InferenceConfig(entry_script='score.py', environment=environment)
    
  3. 将模型部署为 AKS Web 服务。

    
    from azureml.core.webservice import AksWebservice
    from azureml.core.webservice import Webservice
    from azureml.core.model import Model
    from azureml.core.environment import Environment
    
    aks_config = AksWebservice.deploy_configuration(autoscale_enabled=True,
                                                    cpu_cores=1,
                                                    memory_gb=50,
                                                    enable_app_insights=True)
    
    aks_service = Model.deploy(ws,
                               models=[model],
                               inference_config=inference_config,
                               deployment_config=aks_config,
                               deployment_target=aks_target,
                               name='automl-image-test',
                               overwrite=True)
    aks_service.wait_for_deployment(show_output=True)
    print(aks_service.state)
    

测试 Web 服务

测试已部署的 Web 服务以预测新映像。 对于本教程,请将数据集中的随机图像传递到评分 URI。

import requests

# URL for the web service
scoring_uri = aks_service.scoring_uri

# If the service is authenticated, set the key or token
key, _ = aks_service.get_keys()

sample_image = './test_image.jpg'

# Load image data
data = open(sample_image, 'rb').read()

# Set the content type
headers = {'Content-Type': 'application/octet-stream'}

# If authentication is enabled, set the authorization header
headers['Authorization'] = f'Bearer {key}'

# Make the request and display the response
resp = requests.post(scoring_uri, data, headers=headers)
print(resp.text)

直观呈现检测结果

现在,你已为测试图像评分,你可以将该图像的边界框可视化。 为此,请确保已安装 matplotlib。

%pip install --upgrade matplotlib
%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import matplotlib.patches as patches
from PIL import Image
import numpy as np
import json

IMAGE_SIZE = (18,12)
plt.figure(figsize=IMAGE_SIZE)
img_np=mpimg.imread(sample_image)
img = Image.fromarray(img_np.astype('uint8'),'RGB')
x, y = img.size

fig,ax = plt.subplots(1, figsize=(15,15))
# Display the image
ax.imshow(img_np)

# draw box and label for each detection
detections = json.loads(resp.text)
for detect in detections['boxes']:
    label = detect['label']
    box = detect['box']
    conf_score = detect['score']
    if conf_score > 0.6:
        ymin, xmin, ymax, xmax =  box['topY'],box['topX'], box['bottomY'],box['bottomX']
        topleft_x, topleft_y = x * xmin, y * ymin
        width, height = x * (xmax - xmin), y * (ymax - ymin)
        print('{}: [{}, {}, {}, {}], {}'.format(detect['label'], round(topleft_x, 3),
                                                round(topleft_y, 3), round(width, 3),
                                                round(height, 3), round(conf_score, 3)))

        color = np.random.rand(3) #'red'
        rect = patches.Rectangle((topleft_x, topleft_y), width, height,
                                 linewidth=3, edgecolor=color,facecolor='none')

        ax.add_patch(rect)
        plt.text(topleft_x, topleft_y - 10, label, color=color, fontsize=20)

plt.show()

清理资源

如果打算运行其他Azure Machine Learning教程,请不要完成本部分。

如果不打算使用所创建的资源,请将其删除,以免产生任何费用。

  1. 在Azure portal中,选择最左侧的资源组
  2. 从列表中选择已创建的资源组。
  3. 选择“删除资源组”
  4. 输入资源组名称。 然后选择“删除”。

你还可以保留资源组,但删除单个工作区。 显示工作区属性,然后选择“删除”。

后续步骤

在这个自动化机器学习教程中,你已完成以下任务:

  • 配置了工作区并准备了试验数据。
  • 训练了自动化对象检测模型。
  • 为模型指定超参数值。
  • 执行超参数扫描。
  • 部署了模型。
  • 可视化的检测。

注意事项

使用冰箱对象数据集可通过 MIT 许可证的许可证获得。