Architettura basata su Container Docker
Il modello di distribuzione di SageMaker prevede l'incapsulamento dei modelli ML/DL in immagini Docker. Semplificando, da un'immagine, è dinamicamente generato un container che è eseguito automaticamente su un'istanza EC2 Amazon Elastic Computer Cloud dedicata e ottimizzata per l'impiego ML Amazon SageMaker ML Instance Types. Il modello è pacchettizzato in modo da essere accessibile attraverso una RESTful API che è automaticamente collegata ad un endpoint HTTPS in grado di offrire un punto di contatto robusto e scalabile verso il modo esterno. Questo tipo di approccio ben si coniuga con uno stile architetturale a microservizi.
Lo stile architetturale a microservizi è un approccio allo sviluppo di una singola applicazione come insieme di piccoli servizi, ciascuno dei quali viene eseguito da un proprio processo e comunica con un meccanismo snello, spesso una HTTP API. Martin Fowler
SageMaker offre anche un insieme di immagini Docker preconfigurate in cui sono incapsulati framework ML/DL e implementazioni di algoritmi base. Utilizzando queste immagini è possibile costruire rapidamente semplici modelli facilmente distribuibili.
Setup Iniziale su SageMaker
Il primo passo consiste nell'accedere alla console di SageMaker e da questa attivare (o creare) una notebook instance. A seguire, facendo click su Open, accediamo all'istanza Jupyter. Dalla finestra di Jupyter, facciamo click su New e apriamo una finestra Terminal nel browser, ossia una shell sulla nostra istanza EC2. Siamo loggati come utenti ec2-user
.
Dalla linea di comando digitiamo:
cd SageMaker
Quindi cloniamo (git clone) il package git CNTK_KERAS_SAGEMAKER
che ho appositamente predisposto per agevolare le prossime operazioni.
cd CNTK_KERAS_SAGEMAKER/container
Per semplicità, chiamiamo questo punto di accesso cartella base.
Struttura del Progetto
La cartella base è così organizzata:
build_and_push_to_ecr.sh
: lo script file per la generazione dell'immagine e il pushing sul registro Docker ECR Amazon Elastic Container RegistryDockerfile
: il file di testo contenente le istruzioni necessarie per creare una nuova immagine basata su Microsoft CNTK (versione 2.3 con supporto per Py27 e CPU). Il file può essere facilmente modificato per selezionare una versione più recente di CNTK sia con supporto GPU sia Py2 o Py3. Per ulteriori informazioni consultare la pagina CNTK Docker Containerskeras.json
: il file di testo contente le impostazioni per il framework Keras (versione 2.0.6 o superiore) incluso nell'immagine. Queste impostazioni consentono l'integrazione di Keras con la libreria CNTK. Il file è automaticamente caricato all'interno dell'immagine durante la fase di buildingcontext
: la cartella che contiene i file dati e di configurazione per la creazione del modellosetup
: la cartella che contiene i file script che permettono a SageMaker di istanziare un container e attivare un modello richiamando le funzioni di addestramento e predizioneevaluation
: la cartella con file dati esemplificativi e i notebook jupyter che illustrano come utilizzare il modello basato su CNTK da un notebook in SageMaker
Cartella Context
La cartella context
è utilizzata esclusivamente per finalità di test in locale (ossia prima di operare su ECR e con SageMaker) e replica al suo interno una gerarchia che riflette esattamente il funzionamento a regime di SageMaker.
Input files:
hyperparameters.json
: contiene i parametri di configurazione del nostro modellotrainset.csv
etestset.csv
: contenenti rispettivamente training e testing set
Output folders:
model
: per il salvataggio del modello addestrato (pesi e architettura)output
: per logging
Il popolamento delle cartelle model
e output
è automatico, a valle della fase di addestramento del modello.
Test in Locale
Per testare in modalità locale il funzionamento del container e del modello in esso incapsulato, è necessario spostarsi nella cartella base e creare un'immagine Docker locale usando il comando:
docker build -t cntkdemo .
Dopo la creazione dell'immagine cntkdemo
è possibile spostarsi nella cartella evaluation
e digitare uno dei seguenti comandi:
# Per istanziare il modello ed eseguire il training
./run_local.sh train
# Per attivare il modello in modalità serving (in attesa di richieste)
./run_local.sh serve
# Per richiedere una predizione usando un file di dati di validazione
./predict.py eval_data.csv
Lo script predict.py
richiede che un'istanza del modello sia funzionante in modalità serving in una finestra Terminal dedicata. Nella cartella evaluation
sono anche memorizzati i file eval_data.csv
ed eval_pred.csv
contenenti dati di validazione del modello.
Programmazione del Modello
La programmazione del modello è confinata entro specifici file memorizzati all'interno della cartella setup
. In particolare, gli unici due punti dove inseriamo i nostri sviluppi custom sono:
File train
All'interno della funzione train()
è confinato il codice per:
- La lettura dei file di training e testing
- La lettura dei parametri di configurazione
- La costruzione del modello
- L'addestramento e la serializzazione delle impostazioni (pesi e architettura)
Nell'esempio fornito, si utilizza Keras per interfacciarsi a CNTK e creare una semplice rete neurale. È possibile utilizzare qualsiasi libreria Python, istanziare più algoritmi ML/DL per la creazione di modelli di qualsiasi complessità.
File predictor.py
All'interno della funzione get_model()
è confinato il codice per:
- L'istanziazione del modello (a partire dai file dei pesi e dell'architettura creati con l'esecuzione di
train
) - L'implementazione della funzione di predizione
Deployment su ECR
Dopo aver verificato, in locale, il corretto funzionamento del container e del modello in esso incapsulato, possiamo generare (build) una nuova immagine e spedirla (push) al registro Docker ECR. Per questa operazione dobbiamo spostarci nella cartella base ed eseguire l'istruzione:
./build_and_push_to_ecr.sh cntkdemo-ecr-4
dove cntkdemo-ecr-4
è un nome che ho arbitrariamente assegnato all'immagine.
Possiamo visualizzare l'elenco delle immagini (sia in locale sia su ECR) digitando l'istruzione:
docker images
Utilizzo con SageMaker
Abbandondiamo la finestra del Terminal e accediamo al Jupyter su SageMaker. Quindi, spostiamoci nella cartella CNTK_KERAS_SAGEMAKER/container/evaluation
. In questa cartella sono precaricati tre notebook.
Notebook HowToPrepareModel
Il notebook contiene le istruzioni per:
Il caricamento dei dataset di training e testing dalla cartella locale
context
ad una cartella remota sullo storage S3 Amazon Simple Storage associato all'utenzaLa predisposizione del container, attraverso l'impiego dell'interfaccia
sage.estimator.Estimator
(consultare Amazon SageMaker Python SDK per ulteriori dettagli sull'SDK Python per SageMaker) specificando:- Il riferimento all'immagine precedentemente caricata su ECR
- Il tipo di istanza EC2 da attivare
- Il puntamento alla cartella su S3 creata e popolata al passo precedente
La configurazione dei parametri del modello attraverso il metodo
set_hyperparameters
dell'Estimator (i parametri sono esattamente gli stessi che in locale abbiamo specificato all'interno del filehyperparameters.json
)L'addestramento del modello attraverso l'invocazione del metodo
fit
dell'Estimator
Al termine dell'addestramento, i file dei pesi e dell'architettura saranno automaticamente compressi nell'archivio model.tar.gz
che è salvato su S3. L'insieme dei file contenenti pesi e architettura è chiamato model artifact.
Possiamo ottenere l'indirizzo esteso del model artifact memorizzato su S3 eseguendo l'istruzione:
estimator.model_data
### Notebook HowToDeployModel
Il notebook contiene le istruzioni per:
- Istanziare il modello partendo dal model artifact generato nella sezione precedente
- Assegnare il container ad un endpoint HTTPS
- Attivare l'endpoint (l'attivazione può richiedere qualche minuto)
### Notebook HowToInvokeModel
Il notebook contiene le istruzioni per:
- Caricare i dati di validazione dal file locale
eval_data.csv
- Accedere all'endpoint HTTPS per invocare la funzione di predizione. L'accesso all'endpoint avviene attraverso il metodo invoke_endpoint
comodamente richiamabile attraverso il modulo boto3
(boto3 è l'SDK Python per l'accesso ai servizi AWS)
Il payload dell'invocazione è composto dai dati di validazione che abbiamo opportunamente letto e pre-trattato per l'invio.
Il notebook include istruzioni esemplificative per l'estrazione dei risultati dalla response e la valutazione dell'accuratezza usando i dati ground truth memorizzati in eval_pred.csv
, ma questi sono passaggi semplici.