共用方式為


在 Python 中的 Azure Machine Learning 管線中使用自動化 ML

適用於:Python SDK azureml 第 1 版

Azure Machine Learning 的自動化 ML 功能可協助您找出高效能的模型,而不需要重新實作每種可能的方法。 結合 Azure Machine Learning 管線後,您可以建立可部署的工作流程,以快速探索最適合您資料的演算法。 本文將說明如何有效率地將資料準備步驟加入自動化 ML 步驟。 自動化 ML 可以快速探索最適合您資料的演算法,同時引導您透過管線完成 MLOps 和模型生命週期運算化。

必要條件

檢閱自動化 ML 的中心類別

管線中的自動化 ML 會以 AutoMLStep 物件表示。 AutoMLStep 類別是 PipelineStep 的子類別。 PipelineStep 物件的圖形會定義 Pipeline

PipelineStep 的子類別有許多個。 除了 AutoMLStep 之外,本文還會說明資料準備的 PythonScriptStep,以及另一個用來註冊模型的步驟。

初次將資料移至 ML 管線的最佳方式是使用 Dataset 物件。 若要在步驟之間移動資料,並從執行中儲存資料輸出,最好的方式是使用 OutputFileDatasetConfigOutputTabularDatasetConfig 物件。 若要搭配使用 AutoMLStepPipelineData 物件必須轉換成 PipelineOutputTabularDataset 物件。 如需詳細資訊,請參閱在 ML 管線中輸入和輸出資料

AutoMLStep 會透過 AutoMLConfig 物件來設定。 AutoMLConfig 是具有彈性的類別,如在 Python 中設定自動化 ML 實驗中所述。

Pipeline 會在 Experiment 中執行。 在每個步驟中,Run 管線都有子系 StepRun。 自動化 ML StepRun 的輸出是訓練計量和最高效能的模型。

為了更具體地說明,本文會建立用於分類工作的簡單管線。 這項工作會預測鐵達尼號的倖存者,但我們不會討論資料或工作 (除非順帶提起)。

開始使用

擷取初始資料集

通常,ML 工作流程會以預先存在的基本資料開始。 這是適合已註冊資料集的案例。 資料集會在工作區中顯示、支援版本設定,並可透過互動方式進行探索。 建立和填入資料集的方式有很多種,如建立 Azure Machine Learning 資料集中所述。 由於我們將使用 Python SDK 來建立管線,所以請使用 SDK 來下載基本資料,並以 'titanic_ds' 作為名稱來進行註冊。

from azureml.core import Workspace, Dataset

ws = Workspace.from_config()
if not 'titanic_ds' in ws.datasets.keys() :
    # create a TabularDataset from Titanic training data
    web_paths = ['https://dprepdata.blob.core.windows.net/demo/Titanic.csv',
                 'https://dprepdata.blob.core.windows.net/demo/Titanic2.csv']
    titanic_ds = Dataset.Tabular.from_delimited_files(path=web_paths)

    titanic_ds.register(workspace = ws,
                                     name = 'titanic_ds',
                                     description = 'Titanic baseline data',
                                     create_new_version = True)

titanic_ds = Dataset.get_by_name(ws, 'titanic_ds')

程式碼會先登入config.json 中定義的 Azure Machine Learning 工作區 (如需說明,請參閱建立工作區設定檔)。 如果其中沒有名為 'titanic_ds' 的已註冊資料集,則會加以建立。 程式碼會從 Web 下載 CSV 資料、使用這些資料來具現化 TabularDataset,然後向工作區註冊資料集。 最後,Dataset.get_by_name() 函式會將 Dataset 指派給 titanic_ds

設定您的儲存體和計算目標

管線需要的額外資源是儲存體,還有通常需要 Azure Machine Learning 計算資源。

from azureml.core import Datastore
from azureml.core.compute import AmlCompute, ComputeTarget

datastore = ws.get_default_datastore()

compute_name = 'cpu-cluster'
if not compute_name in ws.compute_targets :
    print('creating a new compute target...')
    provisioning_config = AmlCompute.provisioning_configuration(vm_size='STANDARD_D2_V2',
                                                                min_nodes=0,
                                                                max_nodes=1)
    compute_target = ComputeTarget.create(ws, compute_name, provisioning_config)

    compute_target.wait_for_completion(
        show_output=True, min_node_count=None, timeout_in_minutes=20)

    # Show the result
    print(compute_target.get_status().serialize())

compute_target = ws.compute_targets[compute_name]

資料準備和自動化 ML 步驟之間的中繼資料可以儲存在工作區的預設資料存放區中,因此我們只需要在 get_default_datastore() 物件上呼叫 Workspace

之後,該程式碼會檢查 Azure Machine Learning 的計算目標 'cpu-cluster' 是否已存在。 如果不是,我們會指定我們想要以 CPU 為基礎的小型計算目標。 如果您打算使用自動化 ML 的深度學習功能 (例如,具有 DNN 支援的文字特徵化),您應該選擇具有強大 GPU 支援的計算,如 GPU 最佳化的虛擬機器大小中所述。

程式碼會封鎖到目標佈建完成為止,然後再列印一些剛剛建立的計算目標詳細資料。 最後從工作區擷取具名的計算目標,並將其指派給 compute_target

設定訓練執行

您可以藉由建立和設定 RunConfiguration 物件來設定執行階段內容。 我們會在此設定計算目標。

from azureml.core.runconfig import RunConfiguration
from azureml.core.conda_dependencies import CondaDependencies

aml_run_config = RunConfiguration()
# Use just-specified compute target ("cpu-cluster")
aml_run_config.target = compute_target

# Specify CondaDependencies obj, add necessary packages
aml_run_config.environment.python.conda_dependencies = CondaDependencies.create(
    conda_packages=['pandas','scikit-learn'], 
    pip_packages=['azureml-sdk[automl]', 'pyarrow'])

準備自動化機器學習的資料

撰寫資料準備程式碼

基本鐵達尼號資料集是由混合的數值和文字資料所組成,但缺少一些值。 若要為自動化機器學習做好準備,資料準備管線步驟將:

  • 使用隨機資料或對應至「未知」的類別來填滿遺漏的資料
  • 將類別資料轉換成整數
  • 捨棄我們不想使用的資料行
  • 將資料分割成訓練集和測試集
  • 將已轉換的資料寫入至 OutputFileDatasetConfig 輸出路徑
%%writefile dataprep.py
from azureml.core import Run

import pandas as pd 
import numpy as np 
import argparse

RANDOM_SEED=42

def prepare_age(df):
    # Fill in missing Age values from distribution of present Age values 
    mean = df["Age"].mean()
    std = df["Age"].std()
    is_null = df["Age"].isnull().sum()
    # compute enough (== is_null().sum()) random numbers between the mean, std
    rand_age = np.random.randint(mean - std, mean + std, size = is_null)
    # fill NaN values in Age column with random values generated
    age_slice = df["Age"].copy()
    age_slice[np.isnan(age_slice)] = rand_age
    df["Age"] = age_slice
    df["Age"] = df["Age"].astype(int)
    
    # Quantize age into 5 classes
    df['Age_Group'] = pd.qcut(df['Age'],5, labels=False)
    df.drop(['Age'], axis=1, inplace=True)
    return df

def prepare_fare(df):
    df['Fare'].fillna(0, inplace=True)
    df['Fare_Group'] = pd.qcut(df['Fare'],5,labels=False)
    df.drop(['Fare'], axis=1, inplace=True)
    return df 

def prepare_genders(df):
    genders = {"male": 0, "female": 1, "unknown": 2}
    df['Sex'] = df['Sex'].map(genders)
    df['Sex'].fillna(2, inplace=True)
    df['Sex'] = df['Sex'].astype(int)
    return df

def prepare_embarked(df):
    df['Embarked'].replace('', 'U', inplace=True)
    df['Embarked'].fillna('U', inplace=True)
    ports = {"S": 0, "C": 1, "Q": 2, "U": 3}
    df['Embarked'] = df['Embarked'].map(ports)
    return df
    
parser = argparse.ArgumentParser()
parser.add_argument('--output_path', dest='output_path', required=True)
args = parser.parse_args()
    
titanic_ds = Run.get_context().input_datasets['titanic_ds']
df = titanic_ds.to_pandas_dataframe().drop(['PassengerId', 'Name', 'Ticket', 'Cabin'], axis=1)
df = prepare_embarked(prepare_genders(prepare_fare(prepare_age(df))))

df.to_csv(os.path.join(args.output_path,"prepped_data.csv"))

print(f"Wrote prepped data to {args.output_path}/prepped_data.csv")

上述程式碼片段雖完整,但是是鐵達尼號資料的最小資料準備範例。 程式碼片段會以 Jupyter 的「Magic 命令」開頭,將程式碼輸出至檔案。 如果您未使用 Jupyter 筆記本,請移除該行並手動建立檔案。

上述程式碼片段中的各種 prepare_ 函式會修改輸入資料集中的相關資料行。 這些函式會在資料變更為 Pandas DataFrame 物件之後,處理這些資料。 在每個案例中,遺漏的資料將會填入代表性隨機資料或指示「未知」的類別資料。以文字為基礎的類別資料會對應至整數。 不再需要的資料行會遭到覆寫或捨棄。

在程式碼定義資料準備函式之後,程式碼會剖析輸入引數,也就是我們想要寫入資料的路徑。 (這些值將會由下一個步驟中所討論的 OutputFileDatasetConfig 物件來決定。)程式碼會擷取已註冊的 'titanic_cs'Dataset,將其轉換成 Pandas DataFrame,並呼叫各種資料準備函式。

由於 output_path 是目錄,所以呼叫 to_csv() 時會指定檔案名稱 prepped_data.csv

寫入資料準備管線步驟 (PythonScriptStep)

上面所述的資料準備程式碼必須與要搭配管線使用的 PythonScripStep 物件相關聯。 寫入 CSV 輸出的路徑是由 OutputFileDatasetConfig 物件所產生。 先前備妥的資源 (例如 ComputeTargetRunConfig'titanic_ds' Dataset) 會用來完成規格。

from azureml.data import OutputFileDatasetConfig
from azureml.pipeline.steps import PythonScriptStep

prepped_data_path = OutputFileDatasetConfig(name="output_path")

dataprep_step = PythonScriptStep(
    name="dataprep", 
    script_name="dataprep.py", 
    compute_target=compute_target, 
    runconfig=aml_run_config,
    arguments=["--output_path", prepped_data_path],
    inputs=[titanic_ds.as_named_input('titanic_ds')],
    allow_reuse=True
)

prepped_data_path 物件屬於會指向目錄的 OutputFileDatasetConfig 類型。 請注意,這會在 arguments 參數中指定。 如果您檢閱上一個步驟,您將會在資料準備程式碼中看到,'--output_path' 引數的值是寫入 CSV 檔案的目錄路徑。

使用 AutoMLStep 訓練

設定自動化的 ML 管線步驟會透過 AutoMLConfig 類別來完成。 在 Python 中設定自動化 ML 實驗中會敘述此具有彈性的類別。 資料輸入和輸出是必須在 ML 管線中特別注意的唯一設定層面。 以下將詳細討論管線中的 AutoMLConfig 輸入和輸出。 除了資料外,ML 管線的優點是能夠針對不同的步驟使用不同的計算目標。 您可以選擇只針對自動化 ML 程序使用更強大的 ComputeTarget。 這麼做就像為 AutoMLConfig 物件的 run_configuration 參數指派更強大的 RunConfiguration 一樣簡單。

將資料傳送至 AutoMLStep

在 ML 管線中,輸入資料必須是 Dataset 物件。 效能最高的方法是以 OutputTabularDatasetConfig 物件的形式提供輸入資料。 您可以使用 OutputFileDatasetConfig 上的 read_delimited_files() 來建立該類型的物件,例如 prepped_data_pathprepped_data_path 物件。

# type(prepped_data) == OutputTabularDatasetConfig
prepped_data = prepped_data_path.read_delimited_files()

另一個選項是使用在工作區中註冊的 Dataset 物件:

prepped_data = Dataset.get_by_name(ws, 'Data_prepared')

比較這兩種技術:

技術 優點與缺點
OutputTabularDatasetConfig 較高的效能
來自 OutputFileDatasetConfig 的自然路由
管線執行之後不會保存資料
已註冊 Dataset 效能低
可以透過許多方式產生
資料會持續存在,而且會在整個工作區中顯示
顯示已註冊 Dataset 技術的筆記本

指定自動化 ML 輸出

AutoMLStep 的輸出是高效能模型的最終計量分數和模型本身。 若要在進一步的管線步驟中使用這些輸出,請準備 OutputFileDatasetConfig 物件來接收這些輸出。

from azureml.pipeline.core import TrainingOutput, PipelineData

metrics_data = PipelineData(name='metrics_data',
                            datastore=datastore,
                            pipeline_output_name='metrics_output',
                            training_output=TrainingOutput(type='Metrics'))

model_data = PipelineData(name='best_model_data',
                          datastore=datastore,
                          pipeline_output_name='model_output',
                          training_output=TrainingOutput(type='Model'))

上述程式碼片段會為計量和模型輸出建立兩個 PipelineData 物件。 每個物件都會加以命名、指派給稍早擷取的預設資料存放區,並與 AutoMLStepTrainingOutput 的特定 type 相關聯。 由於我們在這些 PipelineData 物件上指派 pipeline_output_name,因此其值不只可從個別的管線步驟取得,還可以從整個管線中取得,如下一節「檢查管線結果」中所述。

設定及建立自動化 ML 管線步驟

一旦定義輸入和輸出之後,就可以建立 AutoMLConfigAutoMLStep。 設定的詳細資料將視您的工作而定,如在 Python 中設定自動化 ML 實驗中所述。 針對鐵達尼號倖存者分類工作,下列程式碼片段會示範簡單的設定。

from azureml.train.automl import AutoMLConfig
from azureml.pipeline.steps import AutoMLStep

# Change iterations to a reasonable number (50) to get better accuracy
automl_settings = {
    "iteration_timeout_minutes" : 10,
    "iterations" : 2,
    "experiment_timeout_hours" : 0.25,
    "primary_metric" : 'AUC_weighted'
}

automl_config = AutoMLConfig(task = 'classification',
                             path = '.',
                             debug_log = 'automated_ml_errors.log',
                             compute_target = compute_target,
                             run_configuration = aml_run_config,
                             featurization = 'auto',
                             training_data = prepped_data,
                             label_column_name = 'Survived',
                             **automl_settings)

train_step = AutoMLStep(name='AutoML_Classification',
    automl_config=automl_config,
    passthru_automl_config=False,
    outputs=[metrics_data,model_data],
    enable_default_model_output=False,
    enable_default_metrics_output=False,
    allow_reuse=True)

此程式碼片段會顯示常用於 AutoMLConfig 的慣例。 較不固定的引數 (像是超參數) 會在個別的字典中指定,而較不可能變更的值則會直接在 AutoMLConfig 建構函式中指定。 在此案例中,automl_settings 會指定短暫執行:執行將只在 2 次反覆運算或 15 分鐘之後停止 (以先達到者為主)。

automl_settings 字典必須以 kwargs 形式傳遞給 AutoMLConfig 建構函式。 其他參數並不複雜:

  • 在本範例中,task 會設定為 classification。 其他有效值包括 regressionforecasting
  • pathdebug_log會描述專案的路徑,以及將用來寫入偵錯資訊的本機檔案
  • compute_target 是先前定義的 compute_target,在此範例中是以 CPU 為基礎的低成本機器。 如果您要使用 AutoML 的深度學習設備,可以變更為以 GPU 為基礎的計算目標
  • featurization 設定為 auto。 如需更多詳細資料,請參閱自動化 ML 設定文件的資料特徵化一節
  • label_column_name 會指出我們想要預測的資料行
  • training_data 會設定為從資料準備步驟輸出中產生的 OutputTabularDatasetConfig 物件

AutoMLStep 本身會採用 AutoMLConfig,並以輸出形式建立用來保存計量和模型資料的 PipelineData 物件。

重要

只有在使用 AutoMLStepRun 時,才必須將 enable_default_model_outputenable_default_metrics_output 設定為 True

在此範例中,自動化 ML 程序會在 training_data 上執行交叉驗證。 您可以使用 n_cross_validations 引數來控制交叉驗證的數目。 如果您已將訓練資料分割為資料準備步驟的一部分,您可以將 validation_data 設定為自己的 Dataset

您可能偶爾會看到使用 X 作為資料特徵和使用 y 作為資料標籤。 這項技術已被取代,您應該使用 training_data 作為輸入。

註冊自動化 ML 所產生的模型

簡單 ML 管線中的最後一個步驟是註冊建立的模型。 將模型新增至工作區的模型註冊後,該模型就可以在入口網站中取得,並可進行版本設定。 若要註冊模型,請撰寫另一個 PythonScriptStep 來採用 AutoMLStepmodel_data 輸出。

撰寫程式碼以註冊模型

模型會註冊在 Workspace 中。 您可能知道如何使用 Workspace.from_config() 來登入本機電腦上的工作區,但還有另一種方式,您可以從執行中的 ML 管線內登入工作區。 Run.get_context() 會擷取作用中的 Run。 此 run 物件可讓您存取許多重要物件,包括此處所用的 Workspace

%%writefile register_model.py
from azureml.core.model import Model, Dataset
from azureml.core.run import Run, _OfflineRun
from azureml.core import Workspace
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--model_name", required=True)
parser.add_argument("--model_path", required=True)
args = parser.parse_args()

print(f"model_name : {args.model_name}")
print(f"model_path: {args.model_path}")

run = Run.get_context()
ws = Workspace.from_config() if type(run) == _OfflineRun else run.experiment.workspace

model = Model.register(workspace=ws,
                       model_path=args.model_path,
                       model_name=args.model_name)

print("Registered version {0} of model {1}".format(model.version, model.name))

撰寫 PythonScriptStep 程式碼

警告

如果您使用 Azure Machine Learning SDK v1,且您的工作區已設定為網路隔離 (VNet),則在執行此步驟時可能會收到錯誤。 如需詳細資訊,請參閱 HyperdriveStep 和 AutoMLStep 因網路隔離而失敗

模型註冊 PythonScriptStep 會使用 PipelineParameter 作為其中一個引數。 管線參數是管線的引數,可在執行提交時輕鬆設定。 引數會在宣告之後,以一般引數的形式進行傳遞。


from azureml.pipeline.core.graph import PipelineParameter

# The model name with which to register the trained model in the workspace.
model_name = PipelineParameter("model_name", default_value="TitanicSurvivalInitial")

register_step = PythonScriptStep(script_name="register_model.py",
                                       name="register_model",
                                       allow_reuse=False,
                                       arguments=["--model_name", model_name, "--model_path", model_data],
                                       inputs=[model_data],
                                       compute_target=compute_target,
                                       runconfig=aml_run_config)

建立並執行自動化 ML 管線

建立和執行包含 AutoMLStep 的管線與一般管線並無不同。

from azureml.pipeline.core import Pipeline
from azureml.core import Experiment

pipeline = Pipeline(ws, [dataprep_step, train_step, register_step])

experiment = Experiment(workspace=ws, name='titanic_automl')

run = experiment.submit(pipeline, show_output=True)
run.wait_for_completion()

上述程式碼會將資料準備、自動化 ML 和模型註冊步驟結合成一個 Pipeline 物件。 然後建立 Experiment 物件。 Experiment 建構函式會擷取已存在的已命名實驗,或視需要建立一個。 並將 Pipeline 提交至 Experiment,建立會以非同步方式執行管線的 Run 物件。 wait_for_completion() 函式會封鎖到執行完成為止。

檢查管線結果

run 完成之後,您就可以擷取已指派 PipelineDatapipeline_output_name 物件。 您可以將結果下載並載入,以進行進一步的處理。

metrics_output_port = run.get_pipeline_output('metrics_output')
model_output_port = run.get_pipeline_output('model_output')

metrics_output_port.download('.', show_progress=True)
model_output_port.download('.', show_progress=True)

下載的檔案會寫入子目錄 azureml/{run.id}/。 計量檔案是 JSON 格式,而且可以轉換成 Pandas 資料框架來進行檢查。

若是在本機進行處理,您可能需要安裝相關的套件,例如 Pandas、Pickle、Azure Machine Learning SDK 等等。 在此範例中,自動化 ML 找到的最佳模型可能會取決於 XGBoost。

!pip install xgboost==0.90
import pandas as pd
import json

metrics_filename = metrics_output._path_on_datastore
# metrics_filename = path to downloaded file
with open(metrics_filename) as f:
   metrics_output_result = f.read()
   
deserialized_metrics_output = json.loads(metrics_output_result)
df = pd.DataFrame(deserialized_metrics_output)
df

上方的程式碼片段顯示計量檔案從 Azure 資料存放區上的計量檔案所在位置載入。 您也可以從下載的檔案載入,如註解中所示。 當您將其還原序列化,並轉換成 Pandas 資料框架之後,您就可以看到自動化 ML 步驟中每個反覆項目的詳細計量。

您可以將模型檔案還原序列化為 Model 物件,以便用於推斷、進一步的計量分析等等。

import pickle

model_filename = model_output._path_on_datastore
# model_filename = path to downloaded file

with open(model_filename, "rb" ) as f:
    best_model = pickle.load(f)

# ... inferencing code not shown ...

如需載入和使用現有模型的詳細資訊,請參閱搭配 Azure Machine Learning 使用現有的模型

下載自動化 ML 執行的結果

如果您遵循此文章,您將會有已經具現化的 run 物件。 但是您也可以從作為 Experiment 物件的 Workspace 中擷取完成的 Run 物件。

工作區包含所有實驗和執行的完整記錄。 您可以使用入口網站來尋找和下載實驗的輸出,或使用程式碼。 若要從歷程記錄執行中存取記錄,請使用 Azure Machine Learning 來尋找感興趣的執行識別碼。 過該識別碼,您可以選擇作為 runWorkspace 的特定 Experiment

# Retrieved from Azure Machine Learning web UI
run_id = 'aaaaaaaa-bbbb-cccc-dddd-0123456789AB'
experiment = ws.experiments['titanic_automl']
run = next(run for run in ex.get_runs() if run.id == run_id)

您必須將上述程式碼中的字串變更為歷程記錄執行的特定資訊。 上述程式碼片段會假設您已將 ws 指派給具有一般 from_config() 的相關 Workspace。 感興趣的實驗會直接擷取,然後程式碼會藉由比對 run.id 值來尋找感興趣的 Run

有了 Run 物件之後,您就可以下載計量和模型。

automl_run = next(r for r in run.get_children() if r.name == 'AutoML_Classification')
outputs = automl_run.get_outputs()
metrics = outputs['default_metrics_AutoML_Classification']
model = outputs['default_model_AutoML_Classification']

metrics.get_port_data_reference().download('.')
model.get_port_data_reference().download('.')

每個 Run 物件都包含 StepRun 物件,而其中包含個別管線步驟執行的相關資訊。 run 可用來搜尋 AutoMLStepStepRun 物件。 計量和模型會使用預設名稱來擷取,即使您未將 PipelineData 物件傳遞給 AutoMLStepoutputs 參數,也可以擷取。

最後,實際的計量和模型會下載到您的本機電腦,如先前的「檢查管線結果」一節中所述。

後續步驟