Implementare un lavoro AutoML personalizzato utilizzando algoritmi preselezionati in Amazon SageMaker Automatic Model Tuning
Creare un lavoro personalizzato di AutoML utilizzando algoritmi preselezionati in Amazon SageMaker Automatic Model Tuning
AutoML ti consente di ottenere rapidamente informazioni generali dai tuoi dati all’inizio di un progetto di machine learning (ML). Capire in anticipo quali tecniche di pre-elaborazione e tipi di algoritmo offrono i migliori risultati riduce il tempo per sviluppare, addestrare e implementare il modello corretto. Gioca un ruolo cruciale in ogni processo di sviluppo del modello e consente ai data scientist di concentrarsi sulle tecniche di ML più promettenti. Inoltre, AutoML fornisce una prestazione di modello di base che può fungere da punto di riferimento per il team di data science.
Un tool di AutoML applica una combinazione di algoritmi diversi e diverse tecniche di pre-elaborazione ai tuoi dati. Ad esempio, può scalare i dati, eseguire una selezione delle feature univariate, condurre una PCA a diversi livelli di soglia di varianza e applicare il clustering. Tali tecniche di pre-elaborazione potrebbero essere applicate singolarmente o combinate in un flusso di lavoro. Successivamente, un tool di AutoML addestrerà diversi tipi di modello, come la regressione lineare, Elastic-Net o Random Forest, su diverse versioni del tuo dataset pre-elaborato e eseguirà l’ottimizzazione degli iperparametri (HPO). Amazon SageMaker Autopilot elimina il lavoro impegnativo per la creazione di modelli di ML. Dopo aver fornito il dataset, SageMaker Autopilot esplora automaticamente diverse soluzioni per trovare il miglior modello. Ma cosa succede se vuoi implementare la tua versione personalizzata di un flusso di lavoro AutoML?
Questo post mostra come creare un flusso di lavoro AutoML su misura su Amazon SageMaker utilizzando Amazon SageMaker Automatic Model Tuning con il codice di esempio disponibile in un repository GitHub.
Panoramica della soluzione
In questo caso d’uso, supponiamo che tu faccia parte di un team di data science che sviluppa modelli in un dominio specializzato. Hai sviluppato un insieme di tecniche personalizzate di pre-elaborazione e selezionato un numero di algoritmi che ti aspetti tipicamente funzionino bene con il tuo problema di ML. Quando lavori su nuovi casi d’uso di ML, vorresti prima eseguire una fase di AutoML utilizzando le tue tecniche di pre-elaborazione e algoritmi per restringere il campo delle possibili soluzioni.
- Migliori pratiche di promozione per l’utilizzo di Llama 2 Chat LLM tramite Amazon SageMaker JumpStart
- Cosa significa Generazione migliorata tramite recupero?
- Accendendo il futuro il rilascio di TensorRT-LLM accelera le prestazioni di inferenza dell’IA, aggiunge supporto per i nuovi modelli in esecuzione su PC Windows 11 alimentati da RTX
In questo esempio, non utilizzi un dataset specializzato; al contrario, lavori con il dataset California Housing che importerai da Amazon Simple Storage Service (Amazon S3). L’obiettivo è dimostrare l’implementazione tecnica della soluzione utilizzando SageMaker HPO, che in seguito può essere applicato a qualsiasi dataset e dominio.
Il diagramma seguente presenta il flusso di lavoro della soluzione nel complesso.
Prerequisiti
I seguenti sono prerequisiti per completare la guida di questo post:
- Un account AWS
- Familiarità con i concetti di SageMaker, come Estimator, job di addestramento e job di HPO
- Familiarità con l’Amazon SageMaker Python SDK
- Conoscenza della programmazione Python
Implementare la soluzione
Il codice completo è disponibile nel repository GitHub.
I passaggi per implementare la soluzione (come indicato nel diagramma del flusso di lavoro) sono i seguenti:
- Creare una istanza del notebook e specificare quanto segue:
- Per il tipo di istanza del notebook, scegliere ml.t3.medium.
- Per Inferenza elastica, scegliere nessuna.
- Per Indentificatore della piattaforma, scegliere Amazon Linux 2, Jupyter Lab 3.
- Per Ruolo IAM, scegliere il
AmazonSageMaker-ExecutionRole
predefinito. Se non esiste, creare un nuovo Ruolo di accesso e gestione delle identità di AWS (IAM) e allegare la policy IAM AmazonSageMakerFullAccess.
È importante creare un ruolo di esecuzione e una policy minimamente limitati per l’ambiente di produzione.
- Aprire l’interfaccia JupyterLab per la tua istanza del notebook e clonare il repository GitHub.
Puoi farlo avviando una nuova sessione terminale e eseguendo il comando git clone <REPO>
o utilizzando la funzionalità dell’interfaccia utente, come mostrato nell’immagine seguente.
- Aprire il file notebook
automl.ipynb
, selezionare il kernelconda_python3
e seguire le istruzioni per avviare un insieme di job HPO.
Per eseguire il codice senza alcuna modifica, è necessario aumentare la quota di servizio per ml.m5.large per l’utilizzo dei job di training e Numero di istanze per tutti i job di training. AWS consente solo 20 job di training paralleli in contemporanea per entrambe le quote. È necessario richiedere un aumento della quota a 30 per entrambe. Di solito, entrambi i cambiamenti di quota vengono approvati entro pochi minuti. Consultare la guida Richiesta di aumento della quota per ulteriori informazioni.
Se non si desidera modificare la quota, è sufficiente modificare il valore della variabile MAX_PARALLEL_JOBS
nello script (ad esempio, a 5).
- Ogni job HPO completerà un set di job di training prove e indicherà il modello con gli iperparametri ottimali.
- Analizzare i risultati e deployare il modello con le prestazioni migliori.
Questa soluzione comporterà costi sul tuo account AWS. Il costo della soluzione dipenderà dal numero e dalla durata dei job di training HPO. Aumentando questi, aumenteranno anche i costi. È possibile ridurre i costi limitando il tempo di training e configurando TuningJobCompletionCriteriaConfig
secondo le istruzioni discusse in seguito in questo post. Per informazioni sui prezzi, consultare la pagina Prezzi di Amazon SageMaker.
Nelle sezioni seguenti, discutiamo in dettaglio il quaderno con esempi di codice e i passaggi per analizzare i risultati e selezionare il miglior modello.
Impostazione iniziale
Iniziamo eseguendo la sezione Importazioni e configurazioni nel quaderno custom-automl.ipynb
. Vengono installate e importate tutte le dipendenze necessarie, viene istanziata una sessione e un client SageMaker, e viene impostata la regione e l’utilizzo predefinito del bucket S3 per archiviare i dati.
Preparazione dei dati
Scarica il set di dati California Housing e preparalo eseguendo la sezione Scarica dati del quaderno. Il dataset viene diviso in frame di dati di addestramento e di test e caricato nel bucket S3 predefinito della sessione SageMaker.
L’intero set di dati contiene 20.640 record e un totale di 9 colonne, compresa la variabile target. Lo scopo è quello di prevedere il valore mediano di una casa (colonna medianHouseValue
). La seguente schermata mostra le prime righe del set di dati.
Modello di script di addestramento
Il flusso di lavoro AutoML in questo post si basa su scikit-learn pipeline di preprocessing e algoritmi. L’obiettivo è generare una vasta combinazione di diverse pipeline di preprocessing e algoritmi per trovare la migliore configurazione in termini di prestazioni. Iniziamo creando uno script di addestramento generico, che viene salvato localmente nell’istanza del quaderno. In questo script, ci sono due blocchi di commenti vuoti: uno per l’iniezione di iperparametri e l’altro per l’oggetto di pipeline preprocessing-modello. Verranno iniettati dinamicamente per ogni modello di preprocessing candidato. Lo scopo di avere uno script generico è quello di mantenere l’implementazione DRY (don’t repeat yourself).
#crea script base_script = """import argparseimport joblibimport osimport numpy as npimport pandas as pdfrom sklearn.metrics import mean_squared_errorfrom sklearn.pipeline import Pipeline, FeatureUnionfrom sklearn.preprocessing import StandardScalerfrom sklearn.decomposition import PCAfrom sklearn.impute import SimpleImputerfrom sklearn.cluster import KMeansfrom sklearn.linear_model import ElasticNetfrom sklearn.ensemble import RandomForestRegressorfrom sklearn.ensemble import GradientBoostingRegressor############################## Funzioni di inferenza ##############################def model_fn(model_dir):clf = joblib.load(os.path.join(model_dir, "model.joblib"))return clfif __name__ == "__main__":print("Estrazione degli argomenti")parser = argparse.ArgumentParser()# Iperparametri##### VERRANNO INSERITI DINAMICAMENTE #####{}############################# Directory di dati, modello e outputparser.add_argument("--model-dir", type=str, default=os.environ.get("SM_MODEL_DIR"))parser.add_argument("--train", type=str, default=os.environ.get("SM_CHANNEL_TRAIN"))parser.add_argument("--test", type=str, default=os.environ.get("SM_CHANNEL_TEST"))parser.add_argument("--train-file", type=str, default="train.parquet")parser.add_argument("--test-file", type=str, default="test.parquet")parser.add_argument("--features", type=str)parser.add_argument("--target", type=str)args, _ = parser.parse_known_args()# Carica e prepara i datatrain_df = pd.read_parquet(os.path.join(args.train, args.train_file))test_df = pd.read_parquet(os.path.join(args.test, args.test_file))X_train = train_df[args.features.split()]X_test = test_df[args.features.split()]y_train = train_df[args.target]y_test = test_df[args.target]# Modello di addestramento##### VERRANNO INSERITI DINAMICAMENTE #####{}{}############################pipeline = Pipeline([('preprocessor', preprocessor), ('model', model)])pipeline.fit(X_train, y_train)# Valida il modello e stampa le metrichermse = mean_squared_error(y_test, pipeline.predict(X_test), squared=False)print("RMSE: " + str(rmse))# Salva il modellopercorso = os.path.join(args.model_dir, "model.joblib")joblib.dump(pipeline, percorso)"""# scrivere _script in un file solo per averlo a portata di manowith open("script_draft.py", "w") as f:print(_script, file=f)
Crea combinazioni di preprocessing e modelli
Il dizionario preprocessors
contiene una specifica delle tecniche di preprocessing applicate a tutte le caratteristiche di input del modello. Ogni ricetta è definita utilizzando un oggetto Pipeline
o FeatureUnion
di scikit-learn, che concatenano singole trasformazioni dei dati e le combinano insieme. Ad esempio, mean-imp-scale
è una semplice ricetta che garantisce che i valori mancanti vengano imputati utilizzando i valori medi delle rispettive colonne e che tutte le caratteristiche vengano scalate utilizzando il StandardScaler. Al contrario, la ricetta mean-imp-scale-pca
concatena alcune operazioni aggiuntive:
- Assegna i valori mancanti nelle colonne con la loro media.
- Applica la ridimensionamento delle caratteristiche utilizzando la media e la deviazione standard.
- Calcola la PCA in cima ai dati di input a un valore di soglia di varianza specificato e uniscilo insieme alle caratteristiche di input imputate e scalate.
In questo post, tutte le caratteristiche di input sono numeriche. Se hai più tipi di dati nel tuo dataset di input, dovresti specificare una pipeline più complicata in cui vengono applicati rami di preprocessing diversi a diversi set di tipi di caratteristiche.
preprocessors = { "mean-imp-scale": "preprocessor = Pipeline([('imputer', SimpleImputer(strategy='mean')), ('scaler', StandardScaler())])\n", "mean-imp-scale-knn": "preprocessor = FeatureUnion([('base-features', Pipeline([('imputer', SimpleImputer(strategy='mean')), ('scaler', StandardScaler())])), ('knn', Pipeline([('imputer', SimpleImputer(strategy='mean')), ('scaler', StandardScaler()), ('knn', KMeans(n_clusters=10))]))])\n", "mean-imp-scale-pca": "preprocessor = FeatureUnion([('base-features', Pipeline([('imputer', SimpleImputer(strategy='mean')), ('scaler', StandardScaler())])), ('pca', Pipeline([('imputer', SimpleImputer(strategy='mean')), ('scaler', StandardScaler()), ('pca', PCA(n_components=0.9))]))])\n" }
Il dizionario models
contiene le specifiche di diversi algoritmi su cui addestri il dataset. Ogni tipo di modello ha la seguente specifica nel dizionario:
- script_output – Punti alla posizione dello script di addestramento utilizzato dall’estimatore. Questo campo viene compilato dinamicamente quando il dizionario
models
viene combinato con il dizionariopreprocessors
. - insertions – Definisce il codice che verrà inserito nel file
script_draft.py
e successivamente salvato inscript_output
.La chiave“preprocessor”
è intenzionalmente lasciata vuota perché questa posizione viene riempita con uno dei preprocessors al fine di creare più combinazioni modello-preprocessor. - hyperparameters – Un set di iperparametri che vengono ottimizzati dal lavoro HPO.
- include_cls_metadata – Ulteriori dettagli di configurazione richiesti dalla classe
Tuner
di SageMaker.
Un esempio completo del dizionario models
è disponibile nel repository GitHub.
models = { "rf": { "script_output": None, "insertions": { # Arguments "arguments" : "parser.add_argument('--n_estimators', type=int, default=100)\n"+ " parser.add_argument('--max_depth', type=int, default=None)\n"+ " parser.add_argument('--min_samples_leaf', type=int, default=1)\n"+ " parser.add_argument('--min_samples_split', type=int, default=2)\n"+ " parser.add_argument('--max_features', type=str, default='auto')\n", # Model call "preprocessor": None, "model_call" : "model = RandomForestRegressor(n_estimators=args.n_estimators,max_depth=args.max_depth,min_samples_leaf=args.min_samples_leaf,min_samples_split=args.min_samples_split,max_features=args.max_features)\n" }, "hyperparameters": { "n_estimators": IntegerParameter(100, 2000, "Linear"), "max_depth": IntegerParameter(1, 100, "Logarithmic"), "min_samples_leaf": IntegerParameter(1, 6, "Linear"), "min_samples_split": IntegerParameter(2, 20, "Linear"), "max_features": CategoricalParameter(["auto", "sqrt", "log2"]), }, "include_cls_metadata": False, }}
Successivamente, iteriamo attraverso i dizionari preprocessors
e models
e creiamo tutte le possibili combinazioni. Ad esempio, se il dizionario preprocessors
contiene 10 ricette e hai 5 definizioni di modello nel dizionario models
, il dizionario pipelines contiene 50 pipeline di pre-elaboratore-modello che vengono valutate durante l’HPO. Notare che gli script delle pipeline individuali non vengono creati ancora in questo momento. Il blocco di codice successivo (cella 9) del notebook di Jupyter itera su tutti gli oggetti di preelaboratore-modello nella pipeline, inserisce tutti i pezzi di codice pertinenti e salva localmente una versione specifica della pipeline dello script. Questi script sono utilizzati nei passaggi successivi quando si creano stimatori individuali che vengono collegati al lavoro HPO.
“`html
pipelines = {}for model_name, model_spec in models.items(): pipelines[model_name] = {} for preprocessor_name, preprocessor_spec in preprocessors.items(): pipeline_name = f"{model_name}-{preprocessor_name}" pipelines[model_name][pipeline_name] = {} pipelines[model_name][pipeline_name]["insertions"] = {} pipelines[model_name][pipeline_name]["insertions"]["preprocessor"] = preprocessor_spec pipelines[model_name][pipeline_name]["hyperparameters"] = model_spec["hyperparameters"] pipelines[model_name][pipeline_name]["include_cls_metadata"] = model_spec["include_cls_metadata"] pipelines[model_name][pipeline_name]["insertions"]["arguments"] = model_spec["insertions"]["arguments"] pipelines[model_name][pipeline_name]["insertions"]["model_call"] = model_spec["insertions"]["model_call"] pipelines[model_name][pipeline_name]["script_output"] = f"scripts/{model_name}/script-{pipeline_name}.py"
Definisci gli estimatori
Ora puoi lavorare sulla definizione degli estimatori SageMaker che vengono utilizzati dopo che gli script sono pronti per il lavoro HPO. Iniziamo creando una classe wrapper che definisce alcune proprietà comuni per tutti gli estimatori. Eredita dalla classe SKLearn
e specifica il ruolo, il conteggio delle istanze e il tipo, nonché le colonne utilizzate dallo script come feature e target.
class SKLearnBase(SKLearn): def __init__( self, entry_point=".", # intenzionalmente vuoto, verrà sovrascritto nella prossima funzione framework_version="1.2-1", role=sm_role, instance_count=1, instance_type="ml.c5.xlarge", hyperparameters={ "features": "medianIncome housingMedianAge totalRooms totalBedrooms population households latitude longitude", "target": "medianHouseValue", }, **kwargs, ): super(SKLearnBase, self).__init__( entry_point=entry_point, framework_version=framework_version, role=role, instance_count=instance_count, instance_type=instance_type, hyperparameters=hyperparameters, **kwargs )
Costruiamo ora il dizionario estimators
iterando attraverso tutti gli script generati in precedenza e situati nella directory scripts
. Istanziamo un nuovo estimator utilizzando la classe SKLearnBase
, con un nome di estimator unico e uno degli script. Nota che il dizionario estimators
ha due livelli: il livello superiore definisce una pipeline_family
. Questa è una raggruppamento logico basato sul tipo di modelli da valutare ed è uguale alla lunghezza del dizionario models
. Il secondo livello contiene i singoli tipi di preprocessor combinati con la pipeline_family
data. Questo raggruppamento logico è necessario durante la creazione del lavoro HPO.
estimators = {}for pipeline_family in pipelines.keys(): estimators[pipeline_family] = {} scripts = os.listdir(f"scripts/{pipeline_family}") for script in scripts: if script.endswith(".py"): estimator_name = script.split(".")[0].replace("_", "-").replace("script", "estimator") estimators[pipeline_family][estimator_name] = SKLearnBase( entry_point=f"scripts/{pipeline_family}/{script}", base_job_name=estimator_name, )
Definisci gli argomenti HPO tuner
Per ottimizzare il passaggio di argomenti nella classe HPO Tuner
, la classe dati HyperparameterTunerArgs
viene inizializzata con gli argomenti richiesti dalla classe HPO. Viene fornito un insieme di funzioni che garantiscono che gli argomenti HPO siano restituiti in un formato previsto durante la distribuzione di più definizioni di modello contemporaneamente.
@dataclassclass HyperparameterTunerArgs: base_job_names: list[str] estimators: list[object] inputs: dict[str] objective_metric_name: str hyperparameter_ranges: list[dict] metric_definition: dict[str] include_cls_metadata: list[bool] def get_estimator_dict(self) -> dict: return {k:v for (k, v) in zip(self.base_job_names, self.estimators)} def get_inputs_dict(self) -> dict: return {k:v for (k, v) in zip(self.base_job_names, [self.inputs]*len(self.base_job_names))} def get_objective_metric_name_dict(self) -> dict: return {k:v for (k, v) in zip(self.base_job_names, [self.objective_metric_name]*len(self.base_job_names))} def get_hyperparameter_ranges_dict(self) -> dict: return {k:v for (k, v) in zip(self.base_job_names, self.hyperparameter_ranges)} def get_metric_definition_dict(self) -> dict: return {k:[v] for (k, v) in zip(self.base_job_names, [self.metric_definition]*len(self.base_job_names))} def get_include_cls_metadata_dict(self) -> dict: return {k:v for (k, v) in zip(self.base_job_names, self.include_cls_metadata)}
“`
Il blocco di codice successivo utilizza la classe dati HyperparameterTunerArgs
precedentemente introdotta. Si crea un altro dizionario chiamato hp_args
e si genera un insieme di parametri di input specifici per ogni estimator_family
dal dizionario estimators
. Questi argomenti vengono utilizzati nel passaggio successivo durante l’inizializzazione dei lavori HPO per ogni famiglia di modelli.
hp_args = {}for estimator_family, estimators in estimators.items(): hp_args[estimator_family] = HyperparameterTunerArgs( base_job_names=list(estimators.keys()), estimators=list(estimators.values()), inputs={"train": s3_data_train.uri, "test": s3_data_test.uri}, objective_metric_name="RMSE", hyperparameter_ranges=[pipeline.get("hyperparameters") for pipeline in pipelines[estimator_family].values()], metric_definition={"Name": "RMSE", "Regex": "RMSE: ([0-9.]+).*$"}, include_cls_metadata=[pipeline.get("include_cls_metadata") for pipeline in pipelines[estimator_family].values()], )
Creazione di oggetti HPO tuner
In questo passaggio, si creano sintonizzatori individuali per ogni estimator_family
. Perché si creano tre lavori HPO separati anziché lanciarne solo uno su tutti gli estimatori? La classe HyperparameterTuner
è limitata a 10 definizioni di modelli ad essa collegati. Pertanto, ogni HPO è responsabile della ricerca del preelaboratore che produce i migliori risultati per una determinata famiglia di modelli e del tuning degli iperparametri di quella famiglia di modelli.
Ecco alcuni altri punti riguardanti la configurazione:
- La strategia di ottimizzazione è bayesiana, il che significa che l’HPO monitora attivamente le prestazioni di tutte le prove e orienta l’ottimizzazione verso combinazioni di iperparametri più promettenti. L’arresto anticipato dovrebbe essere impostato su Off o Auto quando si lavora con una strategia bayesiana, che gestisce autonomamente questa logica.
- Ogni lavoro HPO viene eseguito per un massimo di 100 lavori e ne vengono eseguiti 10 in parallelo. Se si stanno gestendo set di dati più grandi, potrebbe essere necessario aumentare il numero totale di lavori.
- Inoltre, potrebbe essere opportuno utilizzare impostazioni che controllano la durata di esecuzione di un lavoro e il numero di lavori che il vostro HPO sta avviando. Un modo per farlo è impostare il tempo di esecuzione massimo in secondi (per questo post, lo abbiamo impostato su 1 ora). Un altro modo consiste nell’utilizzare la recentemente pubblicata
TuningJobCompletionCriteriaConfig
. Essa offre un insieme di impostazioni che monitorano il progresso dei vostri lavori e decidono se è probabile che ulteriori lavori migliorino il risultato. In questo post, abbiamo impostato il numero massimo di lavori di addestramento che non migliorano a 20. In questo modo, se il punteggio non sta migliorando (ad esempio, dalla quarantesima prova in poi), non sarà necessario pagare per le prove rimanenti fino a raggiungeremax_jobs
.
STRATEGY = "Bayesian"OBJECTIVE_TYPE = "Minimize"MAX_JOBS = 100MAX_PARALLEL_JOBS = 10MAX_RUNTIME_IN_SECONDS = 3600EARLY_STOPPING_TYPE = "Off"# RANDOM_SEED = 42 # rimuovere il commento se si desidera la riproducibilità tra le esecuzioniTUNING_JOB_COMPLETION_CRITERIA_CONFIG = TuningJobCompletionCriteriaConfig( max_number_of_training_jobs_not_improving=20, )tuners = {}for estimator_family, hp in hp_args.items(): tuners[estimator_family] = HyperparameterTuner.create( estimator_dict=hp.get_estimator_dict(), objective_metric_name_dict=hp.get_objective_metric_name_dict(), hyperparameter_ranges_dict=hp.get_hyperparameter_ranges_dict(), metric_definitions_dict=hp.get_metric_definition_dict(), strategy=STRATEGY, completion_criteria_config=TUNING_JOB_COMPLETION_CRITERIA_CONFIG, objective_type=OBJECTIVE_TYPE, max_jobs=MAX_JOBS, max_parallel_jobs=MAX_PARALLEL_JOBS, max_runtime_in_seconds=MAX_RUNTIME_IN_SECONDS, base_tuning_job_name=f"custom-automl-{estimator_family}", early_stopping_type=EARLY_STOPPING_TYPE, # l'arresto anticipato dei lavori di addestramento non è attualmente supportato quando vengono utilizzate più definizioni di lavoro di addestramento # random_seed=RANDOM_SEED, )
Ora iteriamo attraverso i dizionari tuners
e hp_args
e avviamo tutti i lavori HPO in SageMaker. Notare l’uso dell’argomento di attesa impostato su False
, ciò significa che il kernel non aspetterà finché i risultati non saranno completi e potrete avviare tutti i lavori contemporaneamente.
È probabile che non tutti i lavori di formazione siano completati e alcuni di essi potrebbero essere interrotti dal lavoro HPO. Il motivo è il TuningJobCompletionCriteriaConfig
: l’ottimizzazione termina se viene soddisfatto uno qualsiasi dei criteri specificati. In questo caso, quando i criteri di ottimizzazione non migliorano per 20 lavori consecutivi.
for tuner, hpo in zip(tuners.values(), hp_args.values()): tuner.fit( inputs=hpo.get_inputs_dict(), include_cls_metadata=hpo.get_include_cls_metadata_dict(), wait=False, )
Analizza i risultati
La cella 15 del notebook controlla se tutti i lavori HPO sono completi e combina tutti i risultati in forma di un dataframe pandas per ulteriori analisi. Prima di analizzare i risultati in dettaglio, diamo un’occhiata generale alla console di SageMaker.
In cima alla pagina Lavori di ottimizzazione iperparametrica, puoi vedere i tre lavori HPO lanciati. Tutti hanno terminato in anticipo e non hanno effettuato tutti i 100 lavori di formazione. Nella schermata seguente, puoi vedere che la famiglia di modelli Elastic-Net ha completato il numero più elevato di prove, mentre gli altri non hanno avuto bisogno di così tanti lavori di formazione per trovare il miglior risultato.
Puoi aprire il lavoro HPO per accedere a ulteriori dettagli, come singoli lavori di formazione, configurazione del lavoro e informazioni sul miglior lavoro di formazione e sulle sue prestazioni.
Produciamo una visualizzazione basata sui risultati per ottenere ulteriori informazioni sulle prestazioni del flusso di lavoro di AutoML attraverso tutte le famiglie di modelli.
Dal grafico seguente, puoi concludere che le prestazioni del modello Elastic-Net
oscillavano tra 70.000 e 80.000 RMSE e alla fine si sono fermate, poiché l’algoritmo non è stato in grado di migliorare le sue prestazioni nonostante abbia provato varie tecniche di preelaborazione e valori degli iperparametri. Sembra anche che le prestazioni di RandomForest
siano variate molto a seconda dell’insieme di iperparametri esplorati da HPO, ma nonostante molti tentativi non è stato possibile scendere al di sotto dell’errore RMSE di 50.000. GradientBoosting
ha ottenuto le migliori prestazioni fin dall’inizio scendendo al di sotto di 50.000 RMSE. HPO ha cercato di migliorare ulteriormente quel risultato, ma non è stato in grado di ottenere prestazioni migliori con altre combinazioni di iperparametri. Una conclusione generale per tutti i lavori HPO è che non sono stati necessari molti lavori per trovare l’insieme di iperparametri migliori per ogni algoritmo. Per migliorare ulteriormente il risultato, sarebbe necessario sperimentare la creazione di più funzionalità e ulteriori tecniche di ingegneria delle caratteristiche.
Puoi anche esaminare una vista più dettagliata della combinazione modello-preprocessore per trarre conclusioni sulle combinazioni più promettenti.
Seleziona il miglior modello e deployalo
Il seguente frammento di codice seleziona il miglior modello in base al valore obiettivo più basso raggiunto. Puoi quindi deployare il modello come endpoint di SageMaker.
df_best_job = df_tuner_results.loc[df_tuner_results["FinalObjectiveValue"] == df_tuner_results["FinalObjectiveValue"].min()]df_best_jobBEST_MODEL_FAMILY = df_best_job["TrainingJobFamily"].values[0]tuners.get(BEST_MODEL_FAMILY).best_training_job()tuners.get(BEST_MODEL_FAMILY).best_estimator()predictor = tuners.get(BEST_MODEL_FAMILY).deploy( initial_instance_count=1, instance_type="ml.c4.large", endpoint_name=f"custom-automl-endpoint-{BEST_MODEL_FAMILY}",)
Pulizia
Per evitare addebiti indesiderati sul tuo account AWS, ti consigliamo di eliminare le risorse AWS utilizzate in questo post:
- Nella console Amazon S3, svuota i dati dal bucket S3 in cui erano archiviati i dati di addestramento.
- Nella console SageMaker, interrompi l’istanza del notebook.
- Elimina il punto di fine del modello se lo hai distribuito. I punti finali dovrebbero essere eliminati quando non sono più in uso, poiché vengono addebitati per il tempo di distribuzione.
sm_client.delete_endpoint(EndpointName=predictor.endpoint)
Conclusione
In questo post, abbiamo mostrato come creare un lavoro HPO personalizzato in SageMaker utilizzando una selezione personalizzata di algoritmi e tecniche di preprocessing. In particolare, questo esempio illustra come automatizzare il processo di generazione di molti script di addestramento e come utilizzare strutture di programmazione Python per un efficiente deployment di numerosi lavori di ottimizzazione parallela. Speriamo che questa soluzione costituisca la struttura di qualsiasi lavoro di messa a punto di modelli personalizzati che si voglia effettuare utilizzando SageMaker per ottenere prestazioni migliori e velocizzare i flussi di lavoro di machine learning.
Consulta le risorse seguenti per approfondire ulteriormente la tua conoscenza su come utilizzare SageMaker HPO:
- Best practices per la messa a punto degli iperparametri
- Amazon SageMaker Automatic Model Tuning ora supporta tre nuovi criteri di completamento per l’ottimizzazione degli iperparametri
- Utilizzo di Scikit-learn con il SageMaker Python SDK
- Sviluppo, addestramento, ottimizzazione e deployment di Scikit-Learn Random Forest