Dela via


Använda automatiserad ML i en Azure Machine Learning-pipeline i Python

GÄLLER FÖR: Python SDK azureml v1

Med Azure Mašinsko učenje automatiserad ML-funktion kan du identifiera högpresterande modeller utan att du implementerar alla möjliga metoder på nytt. I kombination med Azure Mašinsko učenje pipelines kan du skapa distribuerade arbetsflöden som snabbt kan identifiera algoritmen som fungerar bäst för dina data. Den här artikeln visar hur du effektivt ansluter ett steg för förberedelse av data till ett automatiserat ML-steg. Automatiserad ML kan snabbt identifiera algoritmen som fungerar bäst för dina data, samtidigt som du är på väg till MLOps och modelllivscykelns operationalisering med pipelines.

Förutsättningar

Granska automatiserade ML:s centrala klasser

Automatiserad ML i en pipeline representeras av ett AutoMLStep objekt. Klassen AutoMLStep är en underklass av PipelineStep. Ett diagram med PipelineStep objekt definierar en Pipeline.

Det finns flera underklasser av PipelineStep. Förutom visar den AutoMLStephär artikeln en PythonScriptStep för förberedelse av data och en annan för att registrera modellen.

Det bästa sättet att först flytta data till en ML-pipeline är med Dataset objekt. Om du vill flytta data mellan steg och eventuellt spara datautdata från körningar är det bästa sättet med OutputFileDatasetConfig och OutputTabularDatasetConfig objekt. För att kunna användas med AutoMLStepPipelineData måste objektet omvandlas till ett PipelineOutputTabularDataset objekt. Mer information finns i Indata och utdata från ML-pipelines.

AutoMLStep Konfigureras via ett AutoMLConfig objekt. AutoMLConfig är en flexibel klass, enligt beskrivningen i Konfigurera automatiserade ML-experiment i Python.

En Pipeline körs i en Experiment. Pipelinen Run har för varje steg ett underordnat StepRun. Utdata från den automatiserade ML StepRun :en är träningsmåtten och modellen med högst prestanda.

För att göra saker konkreta skapar den här artikeln en enkel pipeline för en klassificeringsuppgift. Uppgiften förutsäger Titanics överlevnad, men vi kommer inte att diskutera data eller uppgift förutom i förbigående.

Kom igång

Hämta den första datamängden

Ofta börjar ett ML-arbetsflöde med befintliga baslinjedata. Det här är ett bra scenario för en registrerad datauppsättning. Datauppsättningar visas på arbetsytan, stöder versionshantering och kan utforskas interaktivt. Det finns många sätt att skapa och fylla i en datauppsättning, enligt beskrivningen i Skapa Azure Mašinsko učenje datauppsättningar. Eftersom vi använder Python SDK för att skapa vår pipeline använder du SDK:et för att ladda ned baslinjedata och registrera dem med namnet "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')

Koden loggar först in på Den Azure Mašinsko učenje-arbetsyta som definierats i config.json (en förklaring finns i Skapa en arbetsytekonfigurationsfil. Om det inte redan finns en datauppsättning med namnet 'titanic_ds' registrerad skapar den en. Koden laddar ned CSV-data från webben, använder dem för att instansiera en TabularDataset och registrerar sedan datauppsättningen med arbetsytan. Slutligen tilldelar Dataset funktionen Dataset.get_by_name() till titanic_ds.

Konfigurera ditt lagrings- och beräkningsmål

Ytterligare resurser som pipelinen behöver är lagring och vanligtvis Azure Mašinsko učenje beräkningsresurser.

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]

Mellanliggande data mellan dataförberedelsen och det automatiserade ML-steget kan lagras i arbetsytans standarddatalager, så vi behöver inte göra mer än att anropa get_default_datastore() Workspace objektet.

Därefter kontrollerar koden om Azure Mašinsko učenje beräkningsmål 'cpu-cluster' redan finns. Annars anger vi att vi vill ha ett litet CPU-baserat beräkningsmål. Om du planerar att använda automatiserade ML:s djupinlärningsfunktioner (till exempel textbedrift med DNN-stöd) bör du välja en beräkning med starkt GPU-stöd enligt beskrivningen i GPU-optimerade storlekar för virtuella datorer.

Koden blockerar tills målet har etablerats och skriver sedan ut lite information om det just skapade beräkningsmålet. Slutligen hämtas det namngivna beräkningsmålet från arbetsytan och tilldelas till compute_target.

Konfigurera träningskörningen

Körningskontexten anges genom att skapa och konfigurera ett RunConfiguration objekt. Här anger vi beräkningsmålet.

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'])

Förbereda data för automatiserad maskininlärning

Skriva koden för förberedelse av data

Titanic-baslinjedatauppsättningen består av blandade numeriska data och textdata, där vissa värden saknas. För att förbereda den för automatiserad maskininlärning kommer pipelinesteget för förberedelse av data att:

  • Fyll saknade data med antingen slumpmässiga data eller en kategori som motsvarar "Okänd"
  • Transformera kategoriska data till heltal
  • Ta bort kolumner som vi inte tänker använda
  • Dela upp data i tränings- och testuppsättningar
  • Skriva transformerade data till OutputFileDatasetConfig utdatasökvägarna
%%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")

Kodfragmentet ovan är ett komplett, men minimalt, exempel på dataförberedelse för Titanic-data. Kodfragmentet börjar med ett Jupyter "magiskt kommando" för att mata ut koden till en fil. Om du inte använder en Jupyter-anteckningsbok tar du bort den raden och skapar filen manuellt.

De olika prepare_ funktionerna i ovanstående kodfragment ändrar relevant kolumn i indatauppsättningen. Dessa funktioner fungerar på data när de har ändrats till ett Pandas-objekt DataFrame . I varje fall fylls saknade data antingen med representativa slumpmässiga data eller kategoriska data som anger "Okänd". Textbaserade kategoridata mappas till heltal. Kolumner som inte längre behövs skrivs över eller tas bort.

När koden har definierat funktionerna för förberedelse av data parsar koden indataargumentet, vilket är den sökväg som vi vill skriva våra data till. (Dessa värden bestäms av OutputFileDatasetConfig objekt som kommer att diskuteras i nästa steg.) Koden hämtar den registrerade 'titanic_cs' Dataset, konverterar den till en Pandas DataFrameoch anropar de olika funktionerna för dataförberedelse.

output_path Eftersom är en katalog anger anropet till to_csv() filnamnet prepped_data.csv.

Skriv pipelinesteget för dataförberedelse (PythonScriptStep)

Koden för förberedelse av data som beskrivs ovan måste associeras med ett PythonScripStep objekt som ska användas med en pipeline. Sökvägen till vilken CSV-utdata skrivs genereras av ett OutputFileDatasetConfig objekt. Resurserna som förbereddes tidigare, till exempel ComputeTarget, RunConfigoch 'titanic_ds' Dataset används för att slutföra specifikationen.

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
)

Objektet prepped_data_path är av den typ OutputFileDatasetConfig som pekar på en katalog. Observera att den anges i parametern arguments . Om du granskar föregående steg ser du att värdet för argumentet '--output_path' i koden för förberedelse av data är den katalogsökväg där CSV-filen skrevs.

Träna med AutoMLStep

Du konfigurerar ett automatiserat ML-pipelinesteg med AutoMLConfig klassen. Den här flexibla klassen beskrivs i Konfigurera automatiserade ML-experiment i Python. Indata och utdata är de enda aspekterna av konfigurationen som kräver särskild uppmärksamhet i en ML-pipeline. Indata och utdata för AutoMLConfig i pipelines beskrivs i detalj nedan. Utöver data är en fördel med ML-pipelines möjligheten att använda olika beräkningsmål för olika steg. Du kan välja att använda en mer kraftfull ComputeTarget endast för den automatiserade ML-processen. Det är lika enkelt som att tilldela ett kraftfullare RunConfiguration objekt till AutoMLConfig objektets run_configuration parameter.

Skicka data till AutoMLStep

I en ML-pipeline måste indata vara ett Dataset objekt. Det bästa sättet är att tillhandahålla indata i form av OutputTabularDatasetConfig objekt. Du skapar ett objekt av den read_delimited_files() typen med på , OutputFileDatasetConfigtill exempel prepped_data_path, till exempel prepped_data_path -objektet.

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

Ett annat alternativ är att använda Dataset objekt som är registrerade på arbetsytan:

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

Jämföra de två teknikerna:

Teknik Fördelar och nackdelar
OutputTabularDatasetConfig Högre prestanda
Naturlig väg från OutputFileDatasetConfig
Data sparas inte efter pipelinekörning
Registrerad Dataset Lägre prestanda
Kan genereras på många sätt
Data bevaras och visas i hela arbetsytan
Notebook-fil som visar registrerad Dataset teknik

Ange automatiserade ML-utdata

Utdata från AutoMLStep är de slutliga måttpoängen för modellen med högre prestanda och själva modellen. Om du vill använda dessa utdata i ytterligare pipelinesteg förbereder du OutputFileDatasetConfig objekt för att ta emot dem.

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'))

Kodfragmentet ovan skapar de två PipelineData objekten för måtten och modellutdata. Var och en namnges, tilldelas till det standarddatalager som hämtades tidigare och associeras med den specifika type TrainingOutput från AutoMLStep. Eftersom vi tilldelar pipeline_output_name dessa PipelineData objekt är deras värden tillgängliga inte bara från det enskilda pipelinesteget, utan från pipelinen som helhet, vilket beskrivs nedan i avsnittet "Granska pipelineresultat".

Konfigurera och skapa det automatiserade ML-pipelinesteget

När indata och utdata har definierats är det dags att skapa AutoMLConfig och AutoMLStep. Informationen om konfigurationen beror på din uppgift, enligt beskrivningen i Konfigurera automatiserade ML-experiment i Python. För titanics överlevnadsklassificeringsuppgift visar följande kodfragment en enkel konfiguration.

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)

Kodfragmentet visar ett idiom som ofta används med AutoMLConfig. Argument som är mer flytande (hyperparameter-ish) anges i en separat ordlista, medan värdena som är mindre benägna att ändras anges direkt i AutoMLConfig konstruktorn. I det här fallet automl_settings anger du en kort körning: körningen stoppas bara efter 2 iterationer eller 15 minuter, beroende på vilket som kommer först.

Ordlistan automl_settings skickas till AutoMLConfig konstruktorn som kwargs. De andra parametrarna är inte komplexa:

  • task är inställt på classification för det här exemplet. Andra giltiga värden är regression och forecasting
  • path och debug_log beskriva sökvägen till projektet och en lokal fil som felsökningsinformation ska skrivas till
  • compute_target är den tidigare definierade compute_target som i det här exemplet är en billig processorbaserad dator. Om du använder AutoML:s djupinlärningsanläggningar vill du ändra beräkningsmålet till GPU-baserat
  • featurization är inställt på auto. Mer information finns i avsnittet Data featurization i det automatiserade ML-konfigurationsdokumentet
  • label_column_name anger vilken kolumn vi är intresserade av att förutsäga
  • training_data är inställt på de objekt som OutputTabularDatasetConfig skapas från utdata från steget för dataförberedelse

Själva AutoMLStep tar AutoMLConfig och har, som utdata, de PipelineData objekt som skapats för att lagra mått och modelldata.

Viktigt!

Du måste ange enable_default_model_output och enable_default_metrics_output till True endast om du använder AutoMLStepRun.

I det här exemplet utför den automatiserade ML-processen korsvalidering på training_data. Du kan styra antalet korsvalideringar med n_cross_validations argumentet . Om du redan har delat upp dina träningsdata som en del av dina dataförberedelsesteg kan du ange validation_data till egna Dataset.

Ibland kan du se användningen X för datafunktioner och y för dataetiketter. Den här tekniken är inaktuell och du bör använda training_data för indata.

Registrera modellen som genereras av automatiserad ML

Det sista steget i en enkel ML-pipeline är att registrera den skapade modellen. Genom att lägga till modellen i arbetsytans modellregister blir den tillgänglig i portalen och kan versionshanteras. Om du vill registrera modellen skriver du en annan PythonScriptStep som tar model_data utdata från AutoMLStep.

Skriv koden för att registrera modellen

En modell är registrerad i en Workspace. Du är förmodligen bekant med att använda Workspace.from_config() för att logga in på din arbetsyta på den lokala datorn, men det finns ett annat sätt att hämta arbetsytan från en ML-pipeline som körs. Run.get_context() Hämtar den aktiva Run. Det här run objektet ger åtkomst till många viktiga objekt, inklusive det Workspace som används här.

%%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))

Skriva PythonScriptStep-koden

Varning

Om du använder Azure Mašinsko učenje SDK v1 och din arbetsyta är konfigurerad för nätverksisolering (VNet) kan du få ett fel när du kör det här steget. Mer information finns i HyperdriveStep och AutoMLStep misslyckas med nätverksisolering.

Modellregistreringen PythonScriptStep använder en PipelineParameter för ett av argumenten. Pipelineparametrar är argument till pipelines som enkelt kan anges vid körningsöverföring. När de har deklarerats skickas de som normala argument.


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)

Skapa och köra din automatiserade ML-pipeline

Att skapa och köra en pipeline som innehåller en AutoMLStep är inte annorlunda än en vanlig pipeline.

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()

Koden ovan kombinerar stegen för dataförberedelse, automatiserad ML och modellregistrering i ett Pipeline objekt. Sedan skapas ett Experiment objekt. Konstruktorn Experiment hämtar det namngivna experimentet om det finns eller skapar det om det behövs. Den skickar Pipeline till och Experimentskapar ett Run objekt som asynkront kör pipelinen. Funktionen wait_for_completion() blockeras tills körningen har slutförts.

Granska pipelineresultat

När det run är klart kan du hämta PipelineData objekt som har tilldelats en pipeline_output_name. Du kan ladda ned resultaten och läsa in dem för vidare bearbetning.

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)

Nedladdade filer skrivs till underkatalogen azureml/{run.id}/. Måttfilen är JSON-formaterad och kan konverteras till en Pandas-dataram för undersökning.

För lokal bearbetning kan du behöva installera relevanta paket, till exempel Pandas, Pickle, Azure Mašinsko učenje SDK och så vidare. I det här exemplet är det troligt att den bästa modellen som hittas av automatiserad ML beror på 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

Kodfragmentet ovan visar måttfilen som läses in från dess plats i Azure-datalagret. Du kan också läsa in den från den nedladdade filen, som du ser i kommentaren. När du har deserialiserat den och konverterat den till en Pandas DataFrame kan du se detaljerade mått för var och en av iterationerna i det automatiserade ML-steget.

Modellfilen kan deserialiseras till ett Model objekt som du kan använda för slutsatsdragning, ytterligare måttanalys och så vidare.

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 ...

Mer information om hur du läser in och arbetar med befintliga modeller finns i Använda en befintlig modell med Azure Mašinsko učenje.

Ladda ned resultatet av en automatiserad ML-körning

Om du har följt med i artikeln har du ett instansierat run objekt. Men du kan också hämta slutförda Run objekt från Workspace via ett Experiment objekt.

Arbetsytan innehåller en fullständig post över alla dina experiment och körningar. Du kan antingen använda portalen för att hitta och ladda ned utdata från experiment eller använda kod. Om du vill komma åt posterna från en historisk körning använder du Azure Mašinsko učenje för att hitta ID:t för den körning som du är intresserad av. Med det ID:t kan du välja det specifika run med hjälp av Workspace och 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)

Du måste ändra strängarna i koden ovan till detaljerna i din historiska körning. Kodfragmentet ovan förutsätter att du har tilldelat ws till relevant Workspace med det normala from_config(). Experimentet av intresse hämtas direkt och sedan hittar Run koden intresse genom att matcha run.id värdet.

När du har ett Run objekt kan du ladda ned måtten och modellen.

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('.')

Varje Run objekt innehåller StepRun objekt som innehåller information om den enskilda pipelinestegkörningen. run söks StepRun efter objektet för AutoMLStep. Måtten och modellen hämtas med hjälp av deras standardnamn, som är tillgängliga även om du inte skickar PipelineData objekt till parametern outputs för AutoMLStep.

Slutligen laddas de faktiska måtten och modellen ned till din lokala dator, enligt beskrivningen i avsnittet "Granska pipelineresultat" ovan.

Nästa steg