{count, plural, one {Corso} other {Corsi}}
Anche se la maggior parte delle persone associa Amazon alle consegne Prime e ai contenuti, l’azienda è anche molto apprezzata dagli sviluppatori. In particolare, Amazon Web Services (AWS) offre tecnologie cloud a oltre 1 milione di utenti attivi, tra cui grandi imprese e piccole e medie aziende.
In questo articolo ci concentreremo su AWS SageMaker, una piattaforma dedicata all’esecuzione di workflow di machine learning (ML) end-to-end su larga scala, parte dell’ecosistema AWS. Al termine dell’articolo, avremo distribuito un modello che potremo usare per inviare richieste e generare previsioni per un compito di classificazione.
Che cos’è Amazon SageMaker?
Amazon SageMaker è un servizio completamente gestito che fornisce strumenti e infrastruttura per creare, addestrare e distribuire modelli di machine learning. Semplifica il workflow di ML, consentendo a data scientist e sviluppatori di creare, addestrare e distribuire modelli in modo rapido ed efficiente.
In un tipico progetto di machine learning, attraverserai molte fasi:
- Acquisizione, pulizia ed esplorazione dei dati.
- Feature engineering e selezione delle feature.
- Addestramento del modello e ottimizzazione degli iperparametri.
- Distribuzione e monitoraggio del modello.
Ogni fase richiede un set di strumenti diverso e un team di esperti per orchestrare il tutto senza intoppi. Amazon SageMaker riunisce l’intero processo in un’unica piattaforma. Ecco alcuni dei suoi vantaggi:
- Servizio di machine learning end-to-end: offre una suite completa di strumenti per ogni fase del ciclo di vita del ML, dalla preparazione dei dati alla distribuzione e al monitoraggio del modello.
- Ambiente di sviluppo integrato: SageMaker Studio offre un IDE che semplifica l’intero workflow di ML, consentendo di creare, addestrare e distribuire modelli da un’unica interfaccia.
- Facilità d’uso: funzionalità come SageMaker Autopilot permettono anche a chi non ha esperienza di coding di generare modelli di alta qualità con pochi clic.
- Scalabilità: scala automaticamente l’infrastruttura per l’addestramento e la distribuzione dei modelli, garantendo prestazioni ottimali senza interventi manuali.
- Conveniente: offre opzioni come Spot Training ed endpoint multi-modello per ridurre i costi di training e hosting.
- Supporto per i framework ML più diffusi: consente ai data scientist di usare i framework preferiti, tra cui TensorFlow, PyTorch e XGBoost.
- Ottimizzazione automatica degli iperparametri: trova automaticamente la configurazione di modello con le migliori prestazioni ottimizzando gli iperparametri.
- Distribuzione robusta del modello: semplifica la distribuzione dei modelli come API in tempo reale o servizi di predizione batch, facilitandone l’integrazione nelle applicazioni.
- Monitoraggio completo: SageMaker Model Monitor traccia continuamente le prestazioni del modello, rilevando drift dei dati e anomalie in produzione.
- Model registry: gestisce il ciclo di vita dei modelli ML, inclusi versioning, flussi di approvazione e storico delle distribuzioni.
- Integrazione senza soluzione di continuità: si integra facilmente con altri servizi AWS, come Amazon S3 per l’archiviazione dei dati, AWS Glue per la preparazione dei dati, AWS Lambda per l’elaborazione event-driven e Amazon CloudWatch per monitoraggio e logging.
- Sicurezza e conformità: garantisce protezione dei dati e conformità agli standard di settore grazie a robuste funzionalità di sicurezza, tra cui supporto VPC, crittografia e policy IAM.
Questi vantaggi rendono Amazon SageMaker una piattaforma potente e flessibile per creare, addestrare e distribuire modelli di machine learning su larga scala.
Configurare la console AWS e l’ambiente per SageMaker
Come accennato, SageMaker fa parte dell’ecosistema AWS, che include molte soluzioni di cloud computing che forniscono storage, rete, database, analytics e funzionalità di machine learning. Tutte queste soluzioni lavorano in sinergia con SageMaker per unificare il tuo workflow di ML.
Per questo motivo, SageMaker richiede la creazione di un account AWS, se non ne hai già uno.
1. Creare un account AWS
Per creare il tuo account, vai su https://aws.amazon.com/ e segui la procedura per creare un nuovo account.
La procedura di registrazione include l’inserimento delle informazioni di fatturazione e la verifica del numero di telefono. Non preoccuparti: non ti verrà addebitato nulla finché non inizierai effettivamente a usare alcune funzionalità di SageMaker (che di solito sono convenienti).
Una volta completato, verrai indirizzato alla tua console AWS, che in genere appare come nell’immagine seguente. Nota che alcuni widget della console potrebbero essere diversi nel tuo caso.

2. Creare un’istanza notebook
Ora creeremo una sessione JupyterLab per eseguire codice sulle macchine cloud di Amazon.
Dalla tua console AWS, cerca la dashboard di SageMaker usando la barra di ricerca in alto:

Poi scorri fino a trovare la scheda “Notebooks” e al suo interno l’opzione “Notebooks instances”. Non vedrai alcuna istanza, quindi dobbiamo crearne una:

Per creare un nuovo notebook, clicca su “Create notebook instance” nell’angolo in alto a destra. Poi compila i seguenti campi:
- Dai un nome al notebook. In questo caso, io l’ho chiamato
sagemaker-test. - Il campo “Notebook instance type” specifica il tipo di macchina per il kernel del notebook. Io scelgo ml.t3.large, che ha 8 GB di RAM e 2 core CPU. Al momento della stesura, costa circa $0,12 l’ora (consulta la pagina dei prezzi di SageMaker per informazioni aggiornate).
- Nella sezione “Permissions and encryption”, scegli “Create new user”, che creerà automaticamente un utente IAM con i permessi necessari per eseguire l’istanza del notebook.
Una volta inserite tutte le informazioni richieste, clicca su “Create notebook instance”.
Quando lo stato da “Pending” passa a “inService”, puoi avviare JupyterLab cliccando sul link “Open in JupyterLab” accanto al notebook:

Non appena l’istanza è in servizio, il tempo inizia a scorrere e la fatturazione parte. Se decidi di fare una pausa, non dimenticare di interrompere l’istanza cliccando su “Actions” e poi “Stop” per evitare costi inutili. L’arresto per inattività è di due ore per impostazione predefinita:

Se interrompi un’istanza notebook, potrai riavviarla in seguito. Il tuo ambiente verrà preservato.
Caricare un dataset da usare in AWS SageMaker
In questa sezione vedremo come caricare un file locale sui server di Amazon, un requisito per SageMaker.
1. Scaricare un dataset di esempio
Costruiremo un classificatore multi-classe usando il Dry Bean dataset del repository UCI ML. Contiene 13mila istanze di fagioli e le loro 15 misurazioni numeriche.
Il compito è classificarli in sette tipi di fagioli: Seker, Barbunya, Bombay, Cali, Dermosan, Horoz e Sira.

I sette tipi di fagioli: Seker, Barbunya, Bombay, Cali, Dermosan, Horoz e Sira.
Dopo il download, salva il file Excel contenuto nello ZIP scaricato nella tua cartella dati locale in JupyterLab, quindi aggiungi il seguente codice al tuo notebook:
from pathlib import Path
cwd = Path.cwd()
data_path = cwd / "data" / "Dry_Bean_Dataset.xlsx"
Poi, aggiungendo il codice seguente, possiamo leggere il file Excel con pandas e salvarlo come CSV:
import pandas as pd
beans = pd.read_excel(data_path)
beans.to_csv(cwd / "data" / "dry_bean.csv", index=False)
2. Creare un bucket S3 e caricarvi i dati
Il nostro dataset deve trovarsi in un bucket S3 affinché SageMaker vi possa accedere. AWS S3 è una soluzione di archiviazione cloud che ti consente di conservare oggetti relativi al progetto in bucket ospitati sui server Amazon.
Per creare un bucket, segui questi passaggi:
- Vai alla console S3. Puoi cercare “S3” nella barra di ricerca.
- Clicca su “Create bucket”.
- Dai un nome al bucket.
- Il nome del bucket deve essere univoco a livello globale, quindi non potrai usare
dry-bean-bucketcome ho fatto io. - Lascia la configurazione predefinita negli altri campi.
- Clicca su “Create bucket”.

Una volta creato il bucket, cliccaci sopra per caricare il file CSV che abbiamo salvato prima:
- Nel bucket, clicca su “Upload” e poi su “Add files”.
- Seleziona il file CSV.
- Clicca di nuovo su “Upload”.

Dopodiché, puoi tornare all’interfaccia JupyterLab perché finalmente eseguiremo un po’ di codice!
Workflow end-to-end di addestramento e distribuzione del modello in AWS SageMaker
In questa sezione percorreremo un workflow end-to-end che ci porterà da un dataset CSV a un modello distribuito su un endpoint. Ma prima di addentrarci nei dettagli tecnici, prendiamoci un momento per capire a grandi linee cosa faremo.
Panoramica ad alto livello dei workflow ML in SageMaker
Fare machine learning in SageMaker è leggermente diverso dal farlo in locale. Abbiamo già coperto i primi passi:
- Creare un account AWS.
- Creare un’istanza notebook.
- Creare un bucket S3 per il progetto.
Come i notebook locali, le istanze notebook di SageMaker servono per analisi esplorativa: pulizia, esplorazione, ingestione dei dati e sperimentazioni di base.
Quando arrivi alla fase di addestramento del modello, SageMaker si aspetta che tu segua le sue regole. In particolare, per distribuire i tuoi modelli personalizzati come endpoint, SageMaker richiede uno script di training che faccia quanto segue:
- Carichi i dati dalla loro origine.
- Addestri un singolo modello.
- Salvi il modello e i relativi artifact.
- Riporti le metriche.
Lo script deve anche accettare dinamicamente qualsiasi variabile come argomento da riga di comando. Quindi, tutto ciò che vuoi poter modificare in futuro nello script deve essere impostato come argomento da CLI (iperparametri del modello, percorsi dei file, ecc.).
Una volta pronto questo script, viene passato a speciali estimator forniti da SageMaker. Sono compagni dei principali librerie ML come scikit-learn, XGBoost, TensorFlow, PyTorch, ecc. Usando questi estimator, SageMaker costruisce container Docker attorno al tuo script, distribuendolo come endpoint per servirlo in scala.
Tutti i punti precedenti inizieranno ad avere senso man mano che li attraverseremo passo dopo passo.
1. Configurare l’istanza notebook per SageMaker
Iniziamo importando le librerie necessarie all’interno del notebook sagemaker-test che hai creato prima:
import boto3
import numpy as np
import pandas as pd
import sagemaker
from sagemaker import get_execution_role
from sklearn.model_selection import train_test_split
Ecco cosa fanno alcuni di questi import:
sagemakerè l’SDK Python ufficiale che addestra e distribuisce modelli di machine learning su Amazon SageMaker. Con l’SDK puoi addestrare e distribuire modelli usando i framework di deep learning più diffusi, algoritmi forniti da Amazon o i tuoi algoritmi integrati in immagini Docker compatibili con SageMaker.boto3è un altro SDK Python ufficiale, ma funge da ponte tra il tuo codice e tutti i servizi AWS, non solo SageMaker. Puoi saperne di più su boto3 in questo corso.
Dopo gli import, creiamo alcune risorse che useremo lungo il tutorial:
sm_boto3 = boto3.client("sagemaker")
sess = sagemaker.Session()
- Nel codice sopra, creiamo prima un oggetto client SageMaker usando
boto3. - Poi creiamo una sessione SageMaker.
Entrambi questi oggetti ci permettono di interagire con la piattaforma SageMaker in modi diversi.
Ora definiamo alcune variabili globali di cui abbiamo bisogno:
region = sess.boto_session.region_name
BUCKET_URI = "s3://dry-bean-bucket"
BUCKET_NAME = "dry-bean-bucket"
DATASET_PATH = f"{BUCKET_URI}/dry_bean.csv"
TARGET_NAME = "Class"
Queste variabili sono autoesplicative e le useremo in tutto il tutorial.
2. Caricare i dati da un bucket S3 in SageMaker
Nella maggior parte dei tuoi progetti dati, il dataset di training sarà archiviato in una soluzione di storage cloud come BigQuery, GCS o un bucket AWS S3. Noi l’abbiamo salvato nell’ultimo, quindi carichiamolo usando pandas. Per farlo, aggiungi al notebook il codice seguente ed eseguilo:
dry_bean = pd.read_csv(DATASET_PATH)
dry_bean.head()

Un vantaggio di lavorare in un notebook SageMaker è che possiamo leggere i file da S3 direttamente con pandas. Tutti gli ambienti SageMaker sono configurati con le tue credenziali per consentire a pandas di scaricare il CSV dal bucket. Il codice non avrebbe funzionato se lo avessi eseguito in locale.
3. Eseguire EDA in SageMaker
Dedicare del tempo all’EDA (Exploratory Data Analysis) deve far parte di ogni tuo progetto e questo non fa eccezione. Tuttavia, qui non faremo un’analisi approfondita perché ci allontanerebbe dal tema principale dell’articolo.
Ci accontenteremo di stampare qualche statistica riassuntiva e alcuni grafici:
dry_bean.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 13611 entries, 0 to 13610
Data columns (total 17 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Area 13611 non-null int64
1 Perimeter 13611 non-null float64
2 MajorAxisLength 13611 non-null float64
3 MinorAxisLength 13611 non-null float64
4 AspectRation 13611 non-null float64
5 Eccentricity 13611 non-null float64
6 ConvexArea 13611 non-null int64
7 EquivDiameter 13611 non-null float64
8 Extent 13611 non-null float64
9 Solidity 13611 non-null float64
10 roundness 13611 non-null float64
11 Compactness 13611 non-null float64
12 ShapeFactor1 13611 non-null float64
13 ShapeFactor2 13611 non-null float64
14 ShapeFactor3 13611 non-null float64
15 ShapeFactor4 13611 non-null float64
16 Class 13611 non-null object
dtypes: float64(14), int64(2), object(1)
memory usage: 1.8+ MB
Le informazioni sopra indicano che ci sono 16 feature numeriche e un singolo target chiamato Class. Il dataset è piccolo, con solo 13mila istanze, quindi non avremo bisogno di macchine potenti né di spendere molto per addestrare un modello.
Ora creiamo un pair plot di alcune feature importanti usando seaborn:
import seaborn as sns
sns.pairplot(
dry_bean,
vars=["Area", "MajorAxisLength", "MinorAxisLength", "Eccentricity", "roundness"],
hue="Class",
);

I grafici mostrano che i fagioli sono chiaramente distinti in base alle loro misurazioni fisiche. I fagioli verdi (Bombay) sono particolarmente ben definiti.
Possiamo anche tracciare una matrice di correlazione per vedere la relazione tra le feature:
import matplotlib.pyplot as plt
correlation = dry_bean.corr(numeric_only=True)
# Crea una heatmap quadrata centrata su 0
sns.heatmap(correlation, center=0, square=True, cmap="coolwarm", vmin=-1, vmax=1)
plt.show()

Il grafico mostra molte feature perfettamente correlate (positive e negative), il che ha senso dato che tutte le feature sono legate a misurazioni fisiche.
A questo punto, lascio a te il proseguimento dell’esplorazione.
4. Preparare i dati per l’addestramento del modello in SageMaker
Dopo l’esplorazione, devi affrontare eventuali problemi qualitativi o logici nel dataset e creare nuove feature se necessario prima dell’addestramento.
Il dataset Dry Bean è piuttosto pulito, quindi il nostro lavoro è semplice. Dobbiamo solo codificare il target perché contiene testo. Useremo scikit-learn per farlo:
from sklearn.preprocessing import LabelEncoder
# Per il preprocessing
df = dry_bean.copy(deep=True)
# Codifica del target
le = LabelEncoder()
df[TARGET_NAME] = le.fit_transform(df[TARGET_NAME])
Una volta completato il preprocessing, dobbiamo dividere il dataset:
from sklearn.model_selection import train_test_split
# Suddividi i dati in due insiemi
train, test = train_test_split(df, random_state=1, test_size=0.2)
Volendo, puoi suddividere ulteriormente i dati in un terzo set di validazione, ma per ora terremo le cose semplici.
Ora salviamo i dataset come CSV:
train.to_csv("dry-bean-train.csv")
test.to_csv("dry-bean-test.csv")
E carichiamoli nel nostro bucket S3:
# Invia i dati su S3. SageMaker preleverà i dati di training da S3
trainpath = sess.upload_data(
path="dry-bean-train.csv",
bucket=BUCKET_NAME,
key_prefix="sagemaker/sklearncontainer",
)
testpath = sess.upload_data(
path="dry-bean-test.csv",
bucket=BUCKET_NAME,
key_prefix="sagemaker/sklearncontainer",
)
La funzione .upload_data() dell’oggetto sessione restituisce il percorso completo al file caricato, che viene memorizzato rispettivamente nelle variabili trainpath e testpath. Useremo questi percorsi più avanti.
5. Scrivere uno script di training per SageMaker
In una nuova cella del notebook, incolla il seguente codice:
%%writefile script.py
import argparse
import os
import joblib
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import balanced_accuracy_score
if __name__ == "__main__":
print("extracting arguments")
parser = argparse.ArgumentParser()
# Hyperparameters sent by the client are passed as command-line arguments to the script.
parser.add_argument("--n-estimators", type=int, default=10)
parser.add_argument("--min-samples-leaf", type=int, default=3)
# Data, model, and output directories
parser.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="dry-bean-train.csv")
parser.add_argument("--test-file", type=str, default="dry-bean-test.csv")
args, _ = parser.parse_known_args()
print("reading data")
train_df = pd.read_csv(os.path.join(args.train, args.train_file))
test_df = pd.read_csv(os.path.join(args.test, args.test_file))
print("building training and testing datasets")
X_train = train_df.drop("Class", axis=1)
X_test = test_df.drop("Class", axis=1)
y_train = train_df[["Class"]]
y_test = test_df[["Class"]]
# Train model
print("training model")
model = RandomForestClassifier(
n_estimators=args.n_estimators,
min_samples_leaf=args.min_samples_leaf,
n_jobs=-1,
)
model.fit(X_train, y_train)
# Print abs error
print("validating model")
bal_acc_train = balanced_accuracy_score(y_train, model.predict(X_train))
bal_acc_test = balanced_accuracy_score(y_test, model.predict(X_test))
print(f"Train balanced accuracy: {bal_acc_train:.3f}")
print(f"Test balanced accuracy: {bal_acc_test:.3f}")
# Persist model
path = os.path.join(args.model_dir, "model.joblib")
joblib.dump(model, path)
print("model persisted at " + path)
Il magic command %%writefile script.py nello script sopra converte il contenuto della cella in uno script Python invece di eseguirlo.
Ora esaminiamo passo passo cosa succede nello script:
import argparse
import os
import joblib
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import balanced_accuracy_score
Per prima cosa importiamo alcune librerie necessarie.
if __name__ == "__main__":
print("extracting arguments")
parser = argparse.ArgumentParser()
# Hyperparameters sent by the client are passed as command-line arguments to the script.
parser.add_argument("--n-estimators", type=int, default=10)
parser.add_argument("--min-samples-leaf", type=int, default=3)
# Data, model, and output directories
parser.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="dry-bean-train.csv")
parser.add_argument("--test-file", type=str, default="dry-bean-test.csv")
args, _ = parser.parse_known_args()
Poi creiamo un oggetto parser per leggere gli argomenti da riga di comando. Come detto, qualsiasi valore che potresti voler aggiornare in futuro deve essere passato come argomento CLI. Questa sezione definisce tali argomenti:
- Due iperparametri per l’oggetto Random Forest Classifier.
- Cinque percorsi di input e output, inclusi artifact del modello e file dei dataset.
Se fai attenzione ai valori predefiniti delle directory model-dir, train e test, vedrai alcune variabili d’ambiente. Queste provengono dalla documentazione dell’SDK SageMaker, che fornisce anche istruzioni per scrivere tali script.
print("reading data")
train_df = pd.read_csv(os.path.join(args.train, args.train_file))
test_df = pd.read_csv(os.path.join(args.test, args.test_file))
print("building training and testing datasets")
X_train = train_df.drop("Class", axis=1)
X_test = test_df.drop("Class", axis=1)
y_train = train_df[["Class"]]
y_test = test_df[["Class"]]
Una volta definiti i valori dinamici, leggiamo e costruiamo i dataset di training e test. Come vedi, invece di passare un percorso hard-coded, stiamo usando i valori args.argument.
# Train model
print("training model")
model = RandomForestClassifier(
n_estimators=args.n_estimators,
min_samples_leaf=args.min_samples_leaf,
n_jobs=-1,
)
model.fit(X_train, y_train)
# Print abs error
print("validating model")
bal_acc_train = balanced_accuracy_score(y_train, model.predict(X_train))
bal_acc_test = balanced_accuracy_score(y_test, model.predict(X_test))
print(f"Train balanced accuracy: {bal_acc_train:.3f}")
print(f"Test balanced accuracy: {bal_acc_test:.3f}")
Addestriamo il modello e lo valutiamo sia sul dataset di training sia su quello di test, quindi stampiamo le prestazioni.
# Persist model
path = os.path.join(args.model_dir, "model.joblib")
joblib.dump(model, path)
print("model persisted at " + path)
Infine salviamo il modello nella directory del modello usando joblib.
Quando esegui questa cella nel tuo notebook, apparirà il file script.py nel tuo ambiente JupyterLab. Puoi verificare che funzioni correttamente eseguendolo così:
! python script.py --n-estimators 100 \
--min-samples-leaf 2 \
--model-dir ./ \
--train ./ \
--test ./ \
extracting arguments
reading data
building training and testing datasets
validating model
Train balanced accuracy: 1.000
Test balanced accuracy: 0.998
model persisted at ./modejoblib
Ottimo, abbiamo ottenuto un balanced accuracy del 99%—difficile fare di meglio! Questo significa che possiamo finalmente avviare un job di training.
6. Creare un job di training personalizzato in SageMaker
Ora passeremo lo script a un oggetto estimator di SageMaker. Nel contesto di AWS, un job di training è un processo in cui un modello viene addestrato usando un algoritmo specificato, un dataset e risorse di calcolo fornite da AWS SageMaker. A differenza dell’addestramento su una macchina locale o un notebook, questo job viene eseguito nel cloud su infrastruttura scalabile, consentendo maggiore potenza computazionale, elaborazione più rapida e la capacità di gestire dataset più grandi.
Aggiungi il seguente codice in una nuova cella del tuo notebook:
# Usiamo l'Estimator dello SDK Python di SageMaker
from sagemaker.sklearn.estimator import SKLearn
FRAMEWORK_VERSION = "0.23-1"
sklearn_estimator = SKLearn(
entry_point="script.py",
role=get_execution_role(),
instance_count=1,
instance_type="ml.c5.xlarge",
framework_version=FRAMEWORK_VERSION,
base_job_name="rf-scikit",
hyperparameters={
"n-estimators": 100,
"min-samples-leaf": 3,
},
)
Nel codice sopra, la classe SKLearn gestisce gli script di scikit-learn. Ha alcuni parametri essenziali che meritano spiegazione:
entry_point: il percorso allo script.role: l’utente che ha accesso a SageMaker.instance_count: quante macchine avviare.instance_type: il tipo di macchina.
Per gli iperparametri, passa solo quelli definiti nello script di training. Altrimenti si verificherà un errore.
Ora possiamo adattare questo estimator ai nostri dati:
# Avvia il job di training, chiamata sincrona
sklearn_estimator.fit({"train": trainpath, "test": testpath}, wait=True)
Se ricordi dalle sezioni precedenti di questo tutorial, trainpath e testpath sono percorsi di bucket S3 che puntano ai nostri file CSV.
Una volta eseguita la cella, l’addestramento parte:
INFO:sagemaker:Creating training-job with name: rf-scikit-2024-06-04-10-36-31-142
2024-06-04 10:36:31 Starting - Starting the training job...
2024-06-04 10:36:46 Starting - Preparing the instances for training...
2024-06-04 10:37:13 Downloading - Downloading input data...
2024-06-04 10:37:53 Training - Training image download completed. Training in progress...
SageMaker scarica l’immagine Docker necessaria per eseguire codice scikit-learn ed esegue il tuo script. Al termine, otterrai il seguente messaggio:
2024-06-04 10:38:17 Uploading - Uploading generated training model
2024-06-04 10:38:17 Completed - Training job completed
Training seconds: 65
Billable seconds: 65
Se vai nella sezione “SageMaker” > “Traning” > “Training Jobs” della tua dashboard SageMaker, vedrai anche il job di training elencato lì.
7. Usare le Spot Instances durante il training per ridurre i costi
Dato che il nostro dataset è piccolo, ce la siamo cavata usando una macchina economica e di bassa configurazione per l’addestramento: ml.c5.xlarge. Tuttavia, nei tuoi progetti potresti dover gestire dataset con milioni di record o enormi raccolte di immagini. In quei casi, dovrai scegliere macchine con potenza significativamente maggiore e GPU.
Usare queste macchine on demand può essere molto costoso. Per ridurre i costi, Amazon offre le Spot Training instances. Con queste istanze, puoi scegliere risorse di calcolo potenti a un prezzo ridotto con una sola condizione: l’addestramento non partirà immediatamente. Invece, SageMaker aspetta che la domanda sia bassa e che la macchina richiesta sia disponibile.
Per abilitare lo Spot Training, devi aggiungere solo un paio di righe all’ultimo blocco di codice:
spot_sklearn_estimator = SKLearn(
entry_point="script.py",
role=get_execution_role(),
instance_count=1,
instance_type="ml.c5.xlarge",
framework_version=FRAMEWORK_VERSION,
base_job_name="rf-scikit",
hyperparameters={
"n-estimators": 100,
"min-samples-leaf": 3,
},
use_spot_instances=True,
max_wait=7200,
max_run=3600,
)
Impostando use_spot_instances su True, fai usare a spot_sklearn_estimator lo spot training. Puoi anche impostare il tempo massimo di attesa affinché una spot instance sia disponibile e il tempo massimo di esecuzione dell’addestramento.
L’addestramento parte effettivamente quando richiami .fit():
# Avvia il job di training, chiamata sincrona
spot_sklearn_estimator.fit({"train": trainpath, "test": testpath}, wait=True)
8. Ottimizzazione degli iperparametri con SageMaker
Usando lo stesso script di training, possiamo ottenere un modello con iperparametri ottimizzati con un workflow simile.
Per prima cosa importiamo la classe IntegerParameter da sagemaker.tuner:
from sagemaker.tuner import IntegerParameter
La classe IntegerParameter permette a SageMaker di definire intervalli di esplorazione per parametri che accettano valori interi. Il modulo tuner contiene classi per altri tipi di parametri:
CategoricalParameter: definisce iperparametri che assumono un insieme discreto di valori categorici.ContinuousParameter: definisce intervalli di esplorazione per iperparametri che accettano valori continui.
Ma in questo tutorial resteremo su IntegerParameter perché stiamo ottimizzando solo due parametri della Random Forest:
# Usiamo l'Hyperparameter Tuner
from sagemaker.tuner import IntegerParameter
# Definisci i limiti di esplorazione
hyperparameter_ranges = {
"n-estimators": IntegerParameter(20, 100),
"min-samples-leaf": IntegerParameter(2, 6),
}
Poi creiamo un oggetto tuner:
# Crea l'Optimizer
Optimizer = sagemaker.tuner.HyperparameterTuner(
estimator=sklearn_estimator,
hyperparameter_ranges=hyperparameter_ranges,
base_tuning_job_name="RF-tuner",
objective_type="Maximize",
objective_metric_name="balanced-accuracy",
metric_definitions=[
{"Name": "balanced-accuracy", "Regex": "Test balanced accuracy: ([0-9.]+).*$"}
], # Estrai la metrica dai log con una regexp
max_jobs=10,
max_parallel_jobs=2,
)
I parametri essenziali dell’Optimizer sono:
estimator: l’oggetto estimator, compatibile con il tuo script di training.hyperparameter_ranges: l’intervallo dei parametri definito con le classi del modulo tuner.objective_type: se massimizzare o minimizzare la metrica. La balanced accuracy va massimizzata.metric_definitions: il nome delle metriche da ottimizzare e come ricavarle dai log di training.
Il parametro metric_definitions è un po’ insidioso perché offre molta flessibilità su come definire le metriche.
Nello script di training, riportiamo la balanced accuracy con il seguente messaggio di log:
print(f"Train balanced accuracy: {bal_acc_train:.3f}")
print(f"Test balanced accuracy: {bal_acc_test:.3f}")
Quello che metric_definitions ci chiede è di catturare quel messaggio usando espressioni regolari. Quindi abbiamo il seguente dizionario, che assegna un nome personalizzato alla metrica catturata che inizia con “Test balanced accuracy”.
{
"Name": "balanced-accuracy",
"Regex": "Test balanced accuracy: ([0-9.]+).*$",
}
Il resto del codice ti sarà familiare:
Optimizer.fit({"train": trainpath, "test": testpath})
INFO:sagemaker:Creating hyperparameter tuning job with name: RF-tuner-240604-1049
Una volta che l’optimizer termina l’ottimizzazione, puoi visualizzare i risultati in un DataFrame:
# Ottieni i risultati del tuner in un df
results = Optimizer.analytics().dataframe()
while results.empty:
time.sleep(1)
results = Optimizer.analytics().dataframe()
results.head()

Poi puoi recuperare il miglior estimator:
best_estimator = Optimizer.best_estimator()
9. Distribuire modelli su endpoint in SageMaker
Una volta deciso quale modello usare per i tuoi esperimenti, puoi caricarlo su SageMaker con tutti i suoi artifact. Questo compito può essere svolto usando boto3:
artifact_path = sm_boto3.describe_training_job(
TrainingJobName=best_estimator.latest_training_job.name
)["ModelArtifacts"]["S3ModelArtifacts"]
print("Model artifact persisted at " + artifact)
Model artifact persisted at s3://sagemaker-us-east-1-496320894061/RF-tuner-240604-1049-009-38d75f35/output/model.tar.gz
La funzione describe_training_job() prende un oggetto estimator e lo invia a una posizione S3 predefinita fornita da SageMaker. Qui sopra puoi vedere che la funzione ha convertito il modello in un tarball prima del caricamento.
I modelli caricati saranno visibili nella sezione “Inference” > “Models” della tua dashboard SageMaker:

Se clicchi su uno di essi, vedrai un pulsante “Create endpoint” in alto a destra:

Puoi distribuire il modello usando quel pulsante, oppure farlo via codice tornando all’istanza notebook e usando il metodo .deploy():
from sagemaker.sklearn.model import SKLearnModel
model = SKLearnModel(
model_data=artifact_path,
role=get_execution_role(),
entry_point="script.py",
framework_version=FRAMEWORK_VERSION,
)
Questa volta usiamo la classe SKLearnModel, che serve per modelli già addestrati. Richiede la posizione S3 in cui sono memorizzati gli artifact e lo script usato per addestrarlo. Una volta fornita questa informazione, puoi eseguire il codice per distribuirlo:
predictor = model.deploy(instance_type="ml.c5.large", initial_instance_count=1)
INFO:sagemaker:Creating model with name: sagemaker-scikit-learn-2024-06-04-11-03-54-465
INFO:sagemaker:Creating endpoint-config with name sagemaker-scikit-learn-2024-06-04-11-03-54-960
INFO:sagemaker:Creating endpoint with name sagemaker-scikit-learn-2024-06-04-11-03-54-960
Successivamente, dovresti vedere l’endpoint elencato nella sezione “Inference” > “Endpoints” della tua dashboard SageMaker:

Per usarlo per la previsione, puoi usare il metodo .predict() dell’oggetto endpoint dal tuo notebook:
preds = predictor.predict(test.sample(4).drop("Class", axis=1))
preds
array([3, 0, 1, 2])
Complimenti, hai appena distribuito il tuo primo modello con SageMaker!
Una volta finito di usarlo, non dimenticare di eliminare l’endpoint, perché genera continuamente nuovi costi:
sm_boto3.delete_endpoint(EndpointName=predictor.endpoint)
Ricorda, ogni istanza notebook che crei in SageMaker include una scheda separata con notebook di esempio che mostrano le diverse funzionalità di SageMaker:

Dai anche un’occhiata alla documentazione ufficiale dello SDK Python di SageMaker.
Conclusione
Oggi abbiamo imparato a usare una delle piattaforme di machine learning enterprise più popolari: AWS SageMaker. Abbiamo visto tutto, dalla creazione di un account AWS alla distribuzione di modelli ML come endpoint usando SageMaker.
Come per ogni piattaforma, abbiamo appena scalfito la superficie. Puoi fare molto di più se la combini con altre tecnologie AWS nei tuoi progetti. Ecco alcune risorse correlate da esplorare:
Sono un creator di contenuti sulla data science con oltre 2 anni di esperienza e uno dei più seguiti su Medium. Mi piace scrivere articoli dettagliati su AI e ML con un pizzico di sarcasmo, perché bisogna pur fare qualcosa per renderli un po’ meno noiosi. Ho pubblicato oltre 130 articoli e un corso su DataCamp, con un altro in arrivo. I miei contenuti sono stati visti da oltre 5 milioni di persone, 20.000 delle quali sono diventate follower sia su Medium che su LinkedIn.


