教學課程:使用 AutoML 和 Python (v1) 定型物件偵測模型 (預覽)

適用於:Python SDK azureml v1

重要

本文所提供的功能目前為預覽狀態。 這些功能應視為是可能隨時變更的實驗性預覽功能。

在本教學課程中,您將學習如何使用 Azure Machine Learning 自動化 ML,以運用 Azure Machine Learning Python SDK 來定型物件偵測模型。 此物件偵測模型會識別影像是否包含物件,例如罐頭、貨箱、牛奶瓶或水瓶。

自動化 ML 接受定型資料和組態設定,並自動逐一查看不同功能正規化/標準化方法、模型及超參數設定的組合,以獲得最佳模型。

您將在本教學課程中使用 Python SDK 來撰寫程式碼,並瞭解下列工作:

  • 下載與轉換資料
  • 將自動化機器學習物件偵測模型定型
  • 指定模型的超參數值
  • 執行超參數整理
  • 部署模型
  • 將偵測視覺化

必要條件

若您想在自己的本機環境中執行此教學課程,也可以在 GitHub 上的 azureml-examples 存放庫中取得。 若要取得必要套件:

計算目標設定

您必須先設定要用於自動化 ML 模型定型的計算目標。 映像工作的自動化 ML 模型需要 GPU SKU。

本教學課程使用 NCsv3 系列 (搭配 V100 GPU),因為這種類型的計算目標會有效率的調控多個 GPU 來加速定型。 此外,您可以設定多個節點,以在微調模型的超參數時利用平行處理原則。

下列程式碼會建立大小標準 _NC24s_v3 的 GPU 計算,並將四個節點附加至工作區 ws

警告

確定您的訂閱具有足夠配額,供您想要使用的計算目標運用。

from azureml.core.compute import AmlCompute, ComputeTarget

cluster_name = "gpu-nc24sv3"

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_NC24s_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 個標籤類別)。

影像工作的超參數整理

您可對已定義的參數空間執行超參數整理,以找出最佳模型。

下列程式碼會針對每個已定義的演算法、yolov5fasterrcnn_resnet50_fpn,定義準備進行超參數整理的參數空間。 在參數空間中,指定 learning_rateoptimizerlr_scheduler 等的值範圍,好讓 AutoML 可供選擇,因為其會嘗試以最佳的主要度量產生模型。 若未指定超參數值,則會使用每個演算法的預設值。

針對微調設定,請藉由匯入 GridParameterSampling, RandomParameterSamplingBayesianParameterSampling 類別來使用隨機取樣,從這個參數空間挑選範例。 如此一來,系統就會告知自動化 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 嘗試的不同設定會很有用。 您可前往上述主要 automl_image_run (亦即 HyperDrive 父代執行) 的 UI 中的 [子執行] 索引標籤,以瀏覽至此 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 容器執行個體 (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="eastus2")
        # 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 入口網站中,選取最左邊的 [資源群組]
  2. 在清單中,選取您所建立的資源群組。
  3. 選取 [刪除資源群組]
  4. 輸入資源群組名稱。 接著選取刪除

您也可以保留資源群組,但刪除單一工作區。 顯示工作區屬性,然後選取 [刪除]

下一步

在此自動化機器學習教學課程中,您已執行下列工作:

  • 設定工作區和備妥用於實驗的資料。
  • 已定型自動化物件偵測模型
  • 已指定模型的超參數值
  • 已執行超參數整理
  • 已部署您的模型
  • 已將偵測視覺化

注意

您可以透過 MIT 授權下的授權,來使用冰箱物件資料集。