Una guida completa su ZenML per principianti semplificando MLOps

Un'approfondita guida per principianti su ZenML semplificare MLOps

Sei nuovo nel campo della Data Science, del Machine Learning o del MLOps e ti senti sopraffatto dalla scelta degli strumenti? Considera ZenML, uno strumento di orchestrazione per pipeline di produzione ottimizzate. In questo articolo, esploreremo le capacità e le caratteristiche di ZenML per semplificare il tuo percorso nel MLOps.

Obiettivi di apprendimento

    <li Concetti e comandi di ZenML
  • Creazione di pipeline con ZenML
  • Tracciamento metadati, memorizzazione nella cache e versioning
  • Parametri e configurazioni
  • Funzionalità avanzate di ZenML

Questo articolo è stato pubblicato come parte del Data Science Blogathon.

Iniziamo a comprendere cosa è ZenML, perché si distingue dagli altri strumenti e come utilizzarlo.

Cosa è ZenML?

ZenML è un framework open-source MLOps (Machine Learning Operations) per Data Scientists, ML Engineers e MLOps Developers. Favorisce la collaborazione nello sviluppo di pipeline ML pronte per la produzione. ZenML è conosciuto per la sua semplicità, flessibilità e natura indipendente dall’uso dello strumento. Fornisce interfacce e astrazioni appositamente progettate per flussi di lavoro di apprendimento automatico, consentendo agli utenti di integrare facilmente gli strumenti preferiti e personalizzare i flussi di lavoro per soddisfare le loro esigenze uniche.

Perché dovremmo usare ZenML?

ZenML offre vantaggi ai data scientist, agli ML engineer e agli MLOps engineer in diversi modi fondamentali:

  1. Semplificazione nella creazione delle pipeline: Costruisci facilmente pipeline di apprendimento automatico con ZenML utilizzando i decoratori @step e @pipeline.
  2. Tracciamento dei metadati e versioning senza sforzo: ZenML fornisce una dashboard user-friendly per tenere traccia delle pipeline, delle esecuzioni, dei componenti e degli artefatti.
  3. Deployment automatizzato: ZenML semplifica il deployment del modello, eliminando la necessità di immagini docker personalizzate.
  4. Flessibilità cloud: Effettua il deployment del tuo modello su qualsiasi piattaforma basata su cloud in modo semplice utilizzando comandi semplici con ZenML.
  5. Infrastruttura MLOps standardizzata: ZenML consente a tutti i membri del team di eseguire le pipeline configurando ZenML come ambiente di staging e di produzione, garantendo una configurazione MLOps standardizzata.
  6. Integrazioni senza soluzione di continuità: Integra facilmente ZenML con strumenti di tracciamento degli esperimenti come Weights and Biases, MLflow e altri ancora.

Guida all’installazione di ZenML

Per installare ZenML nel terminale, utilizza i seguenti comandi:

Installazione di ZenML:

pip install zenml

Per accedere alla dashboard locale, installa con l’opzione server:

pip install "zenml[server]

Per verificare se ZenML è correttamente installato e controllarne la versione, esegui:

zenml version

Terminologia importante di ZenML

  1. Pipeline: Una serie di passaggi nel flusso di lavoro di machine learning.
  2. Artifacts: Input e output di ogni passaggio nella pipeline.
  3. Artifact Store: Un repository versionato per la memorizzazione degli artefatti, che migliora la velocità di esecuzione della pipeline. ZenML fornisce un repository locale di default, memorizzato sul tuo sistema locale.
  4. Componenti: Configurazioni per le funzioni utilizzate nella pipeline di machine learning.
  5. Stack: Una collezione di componenti e infrastrutture. Lo stack predefinito di ZenML include:
    • Artifact Store
    • Orchestral

La parte sinistra di questa immagine rappresenta la parte di codifica, mentre quella destra è l’infrastruttura. C’è una chiara separazione tra queste due parti, in modo da poter modificare facilmente l’ambiente in cui viene eseguita la pipeline.

  • Flavors: Soluzioni create mediante l’integrazione di altri strumenti MLOps con ZenML, che estendono la classe di astrazione di base dei componenti.
  • Materializzatori: Definiscono come i dati di input e output vengono passati tra i passaggi tramite l’artifact store. Tutti i materializzatori rientrano nella classe di base Materializer. È anche possibile creare materializzatori personalizzati per integrare strumenti non presenti in ZenML.
  • ZenML Server: Utilizzato per il deployment dei modelli di apprendimento automatico e per effettuare previsioni.

Comandi importanti di ZenML

Comando per inizializzare un nuovo repository:

zenml init

Comando per eseguire il dashboard localmente:

zenml up

Output:

Comando per conoscere lo stato delle nostre Zenml Pipelines:

zenml show

Comando per vedere la configurazione dello stack attivo:

zenml stack describe

CLI:

Comando per vedere l’elenco di tutti gli stack registrati:

zenml stack list

Output:

Dashboard:

Creazione della tua prima Pipeline

Prima di tutto, dobbiamo importare pipeline, step da ZenML per creare la nostra pipeline:

#importiamo i moduli necessari per creare passi e pipeline
from zenml import pipeline, step

#Definiamo il passo e restituiamo una stringa.
@step
def sample_step_1() -> str:
    return "Benvenuto a"

#Prendiamo 2 input e stampiamo l'output.
@step
def sample_step_2(input_1: str, input_2: str) -> None:
    print(input_1 + " " + input_2)

#Definiamo una pipeline.
@pipeline
def my_first_pipeline():
    input_1 = sample_step_1()
    sample_step_2(input_1, "Analytics Vidhya")

#Eseguiamo la pipeline.
my_first_pipeline()

In questa pipeline di esempio, abbiamo costruito due passaggi individuali, che poi abbiamo integrato nell’intera pipeline. Abbiamo ottenuto questo utilizzando i decoratori @step e @pipeline.

Dashboard: Goditi la visualizzazione della tua pipeline

Parametri e Rinominazione di una Pipeline

Puoi migliorare questa pipeline introducendo dei parametri. Ad esempio, ti mostrerò come modificare il nome dell’esecuzione della pipeline in ‘Analytics Vidya run’ utilizzando il metodo with_options(), specificando il parametro run_name.

#Qui stiamo usando il metodo with_options() per modificare il nome dell'esecuzione della pipeline.
my_first_pipeline = my_first_pipeline.with_options(
    run_name="Analytics Vidya run")

Puoi vedere il nuovo nome qui nel dashboard:

Se un passaggio ha più output, è meglio avere annotazioni di tipo tuple. Ad esempio:

#Qui, ci sono 4 output, quindi stiamo usando Tuple. Qui, stiamo utilizzando le Annotazioni per indicare a cosa si riferiscono questi output.
def train_data() -> Tuple[
    Annotated[pd.DataFrame, "X_train"],
    Annotated[pd.DataFrame, "X_test"],
    Annotated[pd.Series, "Y_train"],
    Annotated[pd.Series, "Y_test"],
]:

Possiamo anche aggiungere data e ora ad esso.

#qui stiamo usando data e ora all'interno dei segnaposti, che #verranno automaticamente sostituiti con la data e l'ora correnti. my_first_pipeline = my_first_pipeline.with_options(
    run_name="new_run_name_{{date}}_{{time}}")
my_first_pipeline()

Dashboard:

Caching

La cache accelera il processo di esecuzione del pipeline sfruttando le uscite delle esecuzioni precedenti quando non ci sono modifiche nel codice, risparmiando tempo e risorse. Per abilitare la cache, basta includere un parametro insieme al decoratore @pipeline.

#qui, la cache è abilitata come parametro della funzione.@pipeline(enable_cache=True)def my_first_pipeline():

Ci sono occasioni in cui è necessario regolare dinamicamente il codice o le iniezioni. In tali casi, è possibile disabilitare la cache impostando enable_cache su False.

Nel dashboard, i livelli della gerarchia saranno come segue:

Puoi utilizzare le proprietà del modello per recuperare le informazioni del pipeline. Ad esempio, nell’esempio seguente, accediamo al nome del pipeline usando model.name.

model=my_first_pipeline.modelprint(model.name)

Puoi vedere l’ultima esecuzione della pipeline tramite:

model = my_first_pipeline.modelprint(model.name)# Ora possiamo accedere all'ultima esecuzione della pipelinerun = model.last_runprint("ultima esecuzione:", run)

Output:

Accedere alla pipeline tramite CLI

È possibile recuperare la pipeline senza fare affidamento sulle definizioni della pipeline utilizzando il metodo Client().get_pipeline().

Comando:

from zenml.client import Clientpipeline_model = Client().get_pipeline("my_first_pipeline")

Output:

Anche se è possibile visualizzare comodamente tutte le pipeline e le esecuzioni nel dashboard di ZenML, è importante notare che è anche possibile accedere a queste informazioni tramite il Cliente e la CLI di ZenML.

Utilizzando il Cliente:

#qui abbiamo creato un'istanza del Cliente ZenML() per utilizzare il metodo list_pipelines()pipelines=Client().list_pipelines()

Output:

Utilizzando la CLI:

zenml pipeline list

Output:

Dashboard:

Componenti dello stack ZenML CLI

Per visualizzare tutti gli artefatti esistenti, è sufficiente eseguire il seguente comando:

zenml artifact-store list

Output:

Dashboard:

Per vedere l’elenco degli orchestratori,

zenml orchestrator list

Output:

Dashboard:

Per registrare un nuovo artifact store, seguire il comando:

zenml artifact-store register my_artifact_store --flavor=local

Puoi anche apportare modifiche o cancellazioni all’artifact store corrente sostituendo la parola chiave “register” con “update” o “delete”. Per accedere a ulteriori dettagli sullo stack registrato, puoi eseguire il comando:

zenml artifact-store describe my_artifact_store

Output:

Dashboard:

Come abbiamo dimostrato in precedenza per l’artifact store, puoi anche passare a uno stack attivo diverso.

zenml stack register my_stack -o default -a my_artifact_store

Come abbiamo dimostrato in precedenza per l’artifact store, puoi anche passare a uno stack attivo diverso.

zenml stack set my_stack

Ora puoi notare che lo stack attivo è stato correttamente passato da “default” a “my_stack”.

Dashboard: Puoi vedere il nuovo Stack qui nella dashboard.

Suggerimenti e buone pratiche

1. Incorpora robuste pratiche di logging nel tuo progetto:

#importa i moduli necessaridall'importazione di zenml import pipeline, stepimporta client da zenml.clientimporta get_logger da zenml.loggerget_loggerlogger=get_logger(__name__)#Qui stiamo creando un pipeline con 2 passi. In stepdef def, forniamo una descrizione all'input e output del passo. Il passo di anteprima semplice restituisce semplicemente una stringa con un messaggio di benvenuto.def @stepdef sample_step_1()->str:    return "Benvenuto a"def @stepdef sample_step_2(input_1:str,input_2:str)->None:    print(input_1+" "+input_2)@pipelinedef my_first_pipeline():    input_1=sample_step_1()    sample_step_2(input_1,"Analytics Vidya")#Qui si crea un'istanza del client e si registra la pipeline al client (consultare la registrazione API per altri parametri).client = Client()client.create_pipeline(my_first_pipeline)

Output:

2. Assicurati che il tuo progetto abbia un template ben strutturato. Un template pulito migliora la leggibilità del codice e facilita la comprensione da parte di chi lo esamina.

My_Project/                             # Progetto repo├── data/                               # Cartella del set di dati├── notebook/ .ipynb                    # File del notebook Jupyter├── pipelines/                          # Cartella delle pipeline ZenML│   ├── deployment_pipeline.py          # Pipeline di distribuzione│   ├── training_pipeline.py            # Pipeline di addestramento│   └── *altri file├── assets├── src/                                # Cartella del codice sorgente├── steps/                              # Cartella dei passi ZenML├── app.py                              # Applicazione web├── Dockerfile(* Opzionale)├── requirements.txt                    # Elenco dei pacchetti necessari per il progetto├── README.md                           # Documentazione del progetto└── .zen/

Per creare un progetto MLOps completo end-to-end, è consigliabile aderire a questo template di progetto. Assicurati sempre che i file dei passi e delle pipeline siano organizzati in una cartella separata. Includi una documentazione dettagliata per migliorare la comprensione del codice. La cartella .zen viene generata automaticamente quando si inizia ZenML utilizzando il comando “zenml init”. È anche possibile utilizzare i notebook per archiviare i file del notebook Colab o Jupyter.

3. Quando si gestiscono più output in un passo, è consigliabile utilizzare le annotazioni Tuple.

4. Ricorda di impostare enable_cache su False, soprattutto quando si pianificano le esecuzioni delle pipeline per aggiornamenti regolari, come l’importazione dinamica di nuovi dati (approfondiremo la pianificazione temporale più avanti in questo blog).

ZenML Server e la sua distribuzione

ZenML Server funge da hub centralizzato per archiviare, gestire ed eseguire pipeline. È possibile ottenere una visione completa delle sue funzionalità attraverso l’immagine qui sotto:

In questa configurazione, il database SQLite archivia tutti gli stack, i componenti e le pipeline. “Deployment” si riferisce alla generazione di previsioni da parte del modello addestrato su dati in tempo reale in un ambiente di produzione. ZenML offre due opzioni di deployment: ZenML Cloud e deployment su server autonomo.

Ordine di esecuzione dei passaggi

Per impostazione predefinita, ZenML esegue i passaggi nell’ordine in cui sono definiti. Tuttavia, è possibile modificare questo ordine. Vediamo come:

from zenml import pipelinedef my_first_pipeline():#qui, indichiamo che il passaggio 1 viene eseguito solo dopo il passaggio 2.    sample_step_1 = step_1(after="step_2")    sample_step_2 = step_2()#Quindi, eseguiremo il passaggio 3 solo dopo che sia il passaggio 1 che il passaggio 2 sono stati eseguiti.        step_3(sample_step_1, sample_step_2)

In questo scenario, abbiamo modificato l’ordine predefinito di esecuzione dei passaggi. In particolare, abbiamo programmato l’esecuzione del passaggio 1 solo dopo l’esecuzione del passaggio 2, e l’esecuzione del passaggio 3 dopo che sia il passaggio 1 che il passaggio 2 sono stati eseguiti.

Abilita/Disabilita i log

È possibile abilitare o disabilitare il salvataggio dei log nel repository degli artefatti regolando il parametro “enable_step_logs”. Vediamo come fare:

#Qui, stiamo disabilitando i log nel passaggio, come parametro.@step(enable_step_logs=False)def sample_step_2(input_1: str, input_2: str) -> None:    print(input_1 + " " + input_2)

Output:

Prima del logging:

Dopo il logging:

Tipi di impostazioni

Ci sono due tipi di impostazioni in ZenML:

  1. Impostazioni generali: Queste impostazioni possono essere utilizzate in tutte le pipeline (ad esempio, le impostazioni Docker).
  2. Impostazioni specifiche dei componenti dello stack: Queste sono impostazioni di configurazione specifiche del runtime e differiscono dalle impostazioni di registrazione dei componenti dello stack che sono statiche per natura, mentre queste sono dinamiche. Ad esempio, MLFlowTrackingURL è un’impostazione di registrazione, mentre il nome dell’esperimento e le relative configurazioni specifiche del runtime sono impostazioni specifiche del componente dello stack. È possibile sovrascrivere le impostazioni specifiche del componente dello stack durante il runtime, ma non le impostazioni di registrazione.

Pianificazione temporale dei modelli

Possiamo automatizzare il deployment del modello di machine learning pianificandolo per l’esecuzione in determinati orari utilizzando i cron job. Questo non solo risparmia tempo, ma garantisce anche che il processo venga eseguito negli orari designati senza ritardi. Vediamo come configurare tutto ciò:

from zenml.config.schedule import Schedulefrom zenml import step,pipeline#Definiamo il passaggio e restituiamo una stringa.@stepdef sample_step_1()->str:    return "Benvenuto a"#Prendi 2 input e stampa l'output@stepdef sample_step_2(input_1:str,input_2:str)->None:    print(input_1+" "+input_2)    @pipelinedef my_first_pipeline():  logger.info("È un progetto dimostrativo")  input_1=sample_step_1()  sample_step_2(input_1,"Analytics Vidya")#Qui utilizziamo il cron job per pianificare le nostre pipeline.schedule = Schedule(cron_expression="0 7 * * 1")my_first_pipeline = my_first_pipeline.with_options(schedule=schedule)my_first_pipeline()

In questo contesto, l’espressione del cron job segue il formato (minuto, ora, giorno del mese, mese, giorno della settimana). Qui ho pianificato la pipeline per essere eseguita ogni lunedì alle 7 del mattino.

In alternativa, possiamo anche utilizzare intervalli di tempo:

from zenml.config.schedule import Schedulefrom zenml import pipeline@pipelinedef my_first_pipeline():  input_1 = sample_step_1()  sample_step_2(input_1, "Analytics Vidya")#qui, stiamo utilizzando datetime.now () per indicare il nostro tempo attuale e#il parametro interval_second viene utilizzato per indicare gli intervalli di tempo regolari in cui deve essere eseguito.schedule = Schedule(start_time=datetime.now(), interval_second=3000)my_first_pipeline = my_first_pipeline.with_options(schedule=schedule)my_first_pipeline()

Ho scritto del codice per avviare la nostra pipeline, a partire dal momento presente e ripetersi ogni intervallo di 5 minuti.

Contesto Step

Il contesto step viene utilizzato per accedere alle informazioni relative allo step attualmente in esecuzione, come il suo nome, il nome dell’esecuzione e il nome della pipeline. Queste informazioni possono essere preziose per scopi di logging e debugging.

#importare moduli necessarifrom zenml import pipeline, stepfrom zenml.client import Clientfrom zenml.logger import get_loggerfrom zenml.config.schedule import Schedulefrom zenml import get_step_context#Ottenere un logger per il modulo correntelogger = get_logger(__name__)@stepdef sample_step_1() -> str:# accedi al contesto dello step all'interno della funzione step   step_context = get_step_context()      pipeline_name = step_context.pipeline.name    run_name = step_context.pipeline_run.name    step_name = step_context.step_run.name    logger.info("Nome della pipeline: %s", pipeline_name)    logger.info("Nome dell'esecuzione: %s", run_name)    logger.info("Nome dello step: %s", step_name)    logger.info("È un progetto dimostrativo")    return "Benvenuto"@step()def sample_step_2(input_1: str, input_2: str) -> None: # accedere al contesto dello step in questa seconda funzione step       step_context = get_step_context()      pipeline_name = step_context.pipeline.name    run_name = step_context.pipeline_run.name    step_name = step_context.step_run.name    logger.info("Nome della pipeline: %s", pipeline_name)    logger.info("Nome dell'esecuzione: %s", run_name)    logger.info("Nome dello step: %s", step_name)    print(input_1 + " " + input_2)@pipelinedef my_first_pipeline():    input_1 = sample_step_1()    sample_step_2(input_1, "Analytics Vidya")my_first_pipeline()

Output:

Conclusion

In questa guida completa, abbiamo coperto tutto ciò che c’è da sapere su ZenML, dall’installazione alle funzionalità avanzate come la personalizzazione dell’ordine di esecuzione, la creazione di programmi di lavoro e l’utilizzo dei contesti degli step. Speriamo che questi concetti legati a ZenML ti permettano di creare pipeline di machine learning in modo più efficiente, rendendo il tuo percorso MLOps più semplice e agevole.

Punti Chiave

  1. ZenML semplifica la creazione di pipeline di machine learning tramite l’uso di decoratori come @step e @pipeline, rendendolo accessibile anche ai principianti.
  2. La dashboard di ZenML offre un monitoraggio senza sforzo di pipeline, componenti dello stack, artefatti ed esecuzioni, semplificando la gestione del progetto.
  3. ZenML si integra perfettamente con altre tool MLOps come Weights & Biases e MLflow, arricchendo il tuo toolkit.
  4. I contesti degli step forniscono informazioni preziose sullo step corrente, facilitando il logging e il debugging.

Domande Frequenti