Machine Learning Academy · Lezione

Pipeline di riaddestramento automatico con GitHub Actions

Imparerete a scrivere un workflow GitHub Actions che si attivi secondo una pianificazione dei dati, esegua l’addestramento, valuti il nuovo modello e lo promuova solo quando supera il baseline in produzione.

Lezione 4 di 413 passaggi

Pipeline di riaddestramento automatico con GitHub Actions è una lezione Machine Learning Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Machine Learning Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Machine Learning Academy include 4 lezioni in totale.

Perché automatizzare il retraining dei modelli?

I modelli addestrati su dati storici peggiorano nel tempo, man mano che cambiano i pattern del mondo reale. Il retraining manuale richiede che un data scientist si ricordi di eseguirlo, avvii gli script, valuti i risultati e aggiorni il deployment: un processo soggetto a ritardi ed errori umani. Le pipeline di retraining automatico vengono eseguite secondo una pianificazione o quando arrivano nuovi dati, addestrano automaticamente un nuovo modello, lo valutano rispetto al champion corrente e lo promuovono solo se le prestazioni migliorano, senza alcun intervento manuale.

GitHub Actions: workflow e trigger

GitHub Actions è una piattaforma CI/CD integrata in GitHub. I workflow sono definiti in file YAML nella directory .github/workflows/ ed eseguiti in risposta a trigger: push del codice, pull request, avvii manuali o pianificazioni cron. Ogni workflow è composto da job (gruppi di passaggi) eseguiti su runner gestiti o self-hosted. Per le pipeline ML, il pattern più comune consiste in un trigger cron pianificato su un runner cloud con GPU.

# .github/workflows/retrain.yml (YAML structure shown)
# name: Model Retraining Pipeline
#
# on:
#   schedule:
#     - cron: '0 2 * * 1'  # every Monday at 2 AM UTC
#   workflow_dispatch:       # also allow manual trigger
#
# jobs:
#   retrain:
#     runs-on: ubuntu-latest
#     steps:
#       - uses: actions/checkout@v4
#       - name: Set up Python
#         uses: actions/setup-python@v5
#         with:
#           python-version: '3.11'
print('Workflow YAML structure shown above.')

Sintassi cron per la pianificazione

Le espressioni cron di GitHub Actions seguono il formato cron standard di Unix: minute hour day month weekday. Tra le pianificazioni comuni per il retraining ML ci sono il retraining settimanale, quando sono disponibili nuovi batch di dati settimanali, e il retraining notturno per i domini in rapida evoluzione. Utilizzi workflow_dispatch insieme a cron, così i data scientist possono avviare il retraining anche manualmente quando pubblicano un nuovo script di training o rilevano un drift.

# Common cron schedule examples for ML pipelines
# '0 2 * * 1'      -- Every Monday at 02:00 UTC (weekly)
# '0 3 * * *'      -- Every day at 03:00 UTC (nightly)
# '0 */6 * * *'    -- Every 6 hours
# '0 2 1 * *'      -- First day of every month at 02:00

# All times are UTC in GitHub Actions
# Use https://crontab.guru to verify cron expressions

# Example in YAML:
# on:
#   schedule:
#     - cron: '0 3 * * *'   # nightly at 3 AM UTC
#   workflow_dispatch:

print('Cron schedule examples shown above.')

Checkout, configurazione di Python e installazione delle dipendenze

I primi passaggi di ogni workflow ML eseguono il checkout del codice del repository, configurano la versione di Python richiesta e installano le dipendenze da requirements.txt. Utilizzi la memorizzazione nella cache delle dipendenze con actions/cache per evitare di reinstallare i pacchetti a ogni esecuzione: è possibile ridurre la durata della pipeline da 10 minuti a meno di 2 minuti riutilizzando i pacchetti pip memorizzati nella cache quando requirements.txt non è cambiato.

# .github/workflows/retrain.yml -- steps section
# steps:
#   - uses: actions/checkout@v4
#
#   - name: Set up Python 3.11
#     uses: actions/setup-python@v5
#     with:
#       python-version: '3.11'
#
#   - name: Cache pip packages
#     uses: actions/cache@v4
#     with:
#       path: ~/.cache/pip
#       key: pip-${{ hashFiles('requirements.txt') }}
#
#   - name: Install dependencies
#     run: pip install -r requirements.txt

print('Workflow steps shown above.')

Gestione dei secret in GitHub Actions

Le chiavi API, le password dei database e le credenziali cloud non devono mai essere inserite direttamente nei file di workflow. Le memorizzi come GitHub Secrets (Settings → Secrets → Actions) e vi faccia riferimento come ${{ secrets.SECRET_NAME }}. Nei log vengono mascherate e non sono disponibili per le pull request provenienti da fork. Per le pipeline ML, memorizzi come secret le credenziali MLflow, le chiavi dello storage cloud e le stringhe di connessione ai database.

# .github/workflows/retrain.yml -- env section with secrets
# jobs:
#   retrain:
#     runs-on: ubuntu-latest
#     env:
#       MLFLOW_TRACKING_URI: ${{ secrets.MLFLOW_TRACKING_URI }}
#       AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
#       AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
#       DATABASE_URL: ${{ secrets.PROD_DATABASE_URL }}
#
# In train.py, read normally:
import os
DB_URL = os.getenv('DATABASE_URL')
MLFLOW_URI = os.getenv('MLFLOW_TRACKING_URI')
print('Config loaded from environment.')

Il passaggio di training

Il passaggio principale esegue lo script Python di training. Lo script dovrebbe accettare la configurazione tramite variabili d'ambiente (impostate nel workflow), registrare tutti i parametri e le metriche in MLflow e scrivere il nuovo modello nel registry come nuova versione nello stage None. Mantenga lo script idempotente: eseguirlo due volte sugli stessi dati dovrebbe produrre ogni volta una nuova versione nel registry senza danneggiare quelle esistenti.

# train.py -- called by GitHub Actions
import os
import mlflow
import mlflow.sklearn
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.metrics import f1_score

mlflow.set_tracking_uri(os.getenv('MLFLOW_TRACKING_URI', 'http://localhost:5000'))
mlflow.set_experiment('automated_retraining')

with mlflow.start_run(run_name='scheduled_retrain'):
    n_est = int(os.getenv('N_ESTIMATORS', '200'))
    lr = float(os.getenv('LEARNING_RATE', '0.05'))
    mlflow.log_param('n_estimators', n_est)
    mlflow.log_param('learning_rate', lr)

    clf = GradientBoostingClassifier(n_estimators=n_est, learning_rate=lr, random_state=42)
    # clf.fit(X_train, y_train)
    # f1 = f1_score(y_test, clf.predict(X_test))
    # mlflow.log_metric('test_f1', f1)
    # mlflow.sklearn.log_model(clf, 'model', registered_model_name='SentimentClassifier')
    print('Training step complete.')

Il passaggio di valutazione: superare il champion

Dopo il training, un passaggio di valutazione confronta il nuovo modello con il champion corrente in Production. Se il nuovo modello vince, procede alla promozione; altrimenti la pipeline contrassegna la nuova versione come rifiutata (applicandole il tag status=rejected) e mantiene il champion in Production. Utilizzi una variabile di output di GitHub Actions per trasferire la decisione di promozione tra i passaggi.

# evaluate.py -- compare new version against production
from mlflow.tracking import MlflowClient
import sys

client = MlflowClient()
MODEL_NAME = 'SentimentClassifier'

def get_f1(run_id):
    return client.get_run(run_id).data.metrics.get('test_f1', 0)

# Get latest registered version (just added by train.py)
new_versions = client.get_latest_versions(MODEL_NAME, stages=['None'])
new_v = sorted(new_versions, key=lambda v: int(v.version))[-1]
new_f1 = get_f1(new_v.run_id)

prod_versions = client.get_latest_versions(MODEL_NAME, stages=['Production'])
if prod_versions:
    prod_f1 = get_f1(prod_versions[0].run_id)
    print(f'Champion F1: {prod_f1:.4f}  Challenger F1: {new_f1:.4f}')
    should_promote = new_f1 > prod_f1
else:
    print('No champion found.')
    should_promote = True

print('should_promote=' + str(should_promote).lower())
sys.exit(0 if should_promote else 1)  # exit code drives next step

Il passaggio di promozione: esecuzione condizionale

Utilizzi le condizioni if: success() e if: failure() di GitHub Actions sui passaggi o sui job per implementare una promozione condizionale. Dopo il passaggio di valutazione, il passaggio di promozione viene eseguito solo se la valutazione ha avuto esito positivo, cioè se ha vinto il challenger. Utilizzi un passaggio di notifica separato che venga sempre eseguito per inviare un avviso Slack o un'email con l'esito della pipeline, indipendentemente dal fatto che la promozione sia avvenuta.

# promote.py -- transition new version to Production
from mlflow.tracking import MlflowClient

client = MlflowClient()
MODEL_NAME = 'SentimentClassifier'

new_versions = client.get_latest_versions(MODEL_NAME, stages=['None'])
new_v = sorted(new_versions, key=lambda v: int(v.version))[-1]

client.transition_model_version_stage(
    name=MODEL_NAME,
    version=new_v.version,
    stage='Production',
    archive_existing_versions=True
)
print(f'Version {new_v.version} promoted to Production.')

# In the workflow YAML:
# - name: Promote model
#   if: success()  # only runs if evaluate.py exits with 0
#   run: python promote.py

Download dei dati nella pipeline

Le pipeline di retraining hanno bisogno di dati aggiornati. Aggiunga prima del training un passaggio di download dei dati che recuperi i dati più recenti da S3, da un database o da un data lake. Utilizzi snapshot dei dati con versione (contrassegnati da una data) anziché recuperare sempre i dati più recenti, per mantenere la riproducibilità: se un modello ha prestazioni scarse, deve poter riprodurre esattamente i dati di training che ha utilizzato. Registri la versione dei dati come parametro MLflow insieme agli iperparametri del modello.

# download_data.py -- fetch latest training data from S3
import boto3
import os
from datetime import date

DATA_DATE = os.getenv('DATA_DATE', str(date.today()))  # e.g., 2024-06-15
BUCKET = os.getenv('S3_BUCKET', 'my-ml-data')
KEY = f'datasets/sentiment/{DATA_DATE}/train.parquet'

s3 = boto3.client('s3')
os.makedirs('/tmp/data', exist_ok=True)
s3.download_file(BUCKET, KEY, '/tmp/data/train.parquet')
print(f'Downloaded data for {DATA_DATE}')

# In train.py, log data_date as a parameter:
# mlflow.log_param('data_date', DATA_DATE)

Notifiche con webhook Slack

Una pipeline automatica senza notifiche è una scatola nera. Aggiunga un passaggio finale di notifica che venga sempre eseguito (utilizzando if: always()) e pubblichi un riepilogo su Slack o invii un'email. Includa l'esito dell'esecuzione (promosso o rifiutato), il numero della nuova versione, i punteggi F1 del champion e del challenger e un link diretto alla run MLflow per un'analisi dettagliata. Le buone notifiche trasformano un'automazione silenziosa in un workflow collaborativo di data science.

import os
import requests
import json

SLACK_WEBHOOK = os.getenv('SLACK_WEBHOOK_URL')
PROMOTED = os.getenv('PROMOTED', 'false') == 'true'
NEW_VERSION = os.getenv('NEW_VERSION', 'N/A')
NEW_F1 = os.getenv('NEW_F1', 'N/A')

status_icon = ':white_check_mark:' if PROMOTED else ':x:'
status_text = 'Promoted to Production' if PROMOTED else 'Champion retained'

message = {
    'text': (f'{status_icon} *ML Retraining Pipeline*\n'
             f'Model: SentimentClassifier v{NEW_VERSION}\n'
             f'Status: {status_text}\n'
             f'New F1: {NEW_F1}')
}
if SLACK_WEBHOOK:
    requests.post(SLACK_WEBHOOK, data=json.dumps(message))
    print('Slack notification sent.')

Panoramica completa del workflow YAML

Un workflow completo di retraining automatico ha cinque job sequenziali: download_data (recupera il dataset più recente), train (esegue lo script di training e registra i dati in MLflow), evaluate (confronta il modello con il champion in produzione), promote (modifica lo stage se vince il challenger) e notify (invia sempre un avviso Slack). Ogni job passa gli output a quello successivo utilizzando gli output dei job di GitHub Actions o file di artefatti condivisi. L'intera pipeline viene eseguita senza supervisione secondo una pianificazione settimanale.

# Full workflow summary (pseudo-YAML)
# name: Weekly Model Retraining
# on:
#   schedule: [{cron: '0 3 * * 1'}]
#   workflow_dispatch: {}
# jobs:
#   download_data:
#     runs-on: ubuntu-latest
#     steps: [checkout, setup-python, install, run download_data.py]
#   train:
#     needs: download_data
#     steps: [checkout, setup-python, install, run train.py]
#   evaluate:
#     needs: train
#     steps: [checkout, setup-python, install, run evaluate.py]
#   promote:
#     needs: evaluate
#     if: success()
#     steps: [checkout, setup-python, install, run promote.py]
#   notify:
#     needs: [evaluate, promote]
#     if: always()
#     steps: [run notify.py]
print('Full workflow YAML structure shown above.')

Verifica rapida

Verifichi la sua comprensione dei concetti di Machine Learning con Python presentati in questa lezione.

Riepilogo della lezione

In questa lezione ha imparato che i trigger cron di GitHub Actions eseguono il retraining secondo una pianificazione senza intervento manuale, che gli script di valutazione implementano il pattern champion/challenger, così vengono promossi solo i modelli migliori e che la gestione dei secret mantiene le credenziali fuori dai file YAML dei workflow utilizzando i GitHub Secrets crittografati. Nel prossimo argomento esploreremo il rilevamento del data drift, cioè l'identificazione dei casi in cui la distribuzione degli input si allontana dalle condizioni di training, la causa più comune del degrado dei modelli in produzione.

Gratis per iniziare

Impara Python con un tutor IA — gratis

Scrivi ed esegui vero codice nel tuo browser, ricevi aiuto istantaneo da un tutor IA disponibile 24/7, e riprendi da dove hai lasciato sul web o nell'app.

Corsi
30
Lezioni
120

Domande Frequenti

La lezione «Pipeline di riaddestramento automatico con GitHub Actions» è gratuita?

Sì — il testo completo di «Pipeline di riaddestramento automatico con GitHub Actions» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Machine Learning Academy, passa a CoddyKit PRO. Il corso Machine Learning Academy include 4 lezioni in totale.

Cosa imparerò in «Pipeline di riaddestramento automatico con GitHub Actions»?

Imparerete a scrivere un workflow GitHub Actions che si attivi secondo una pianificazione dei dati, esegua l’addestramento, valuti il nuovo modello e lo promuova solo quando supera il baseline in pro… Eserciti Machine Learning Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Machine Learning Academy?

Non è richiesta alcuna esperienza precedente. Machine Learning Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.

Quanto tempo richiede la lezione «Pipeline di riaddestramento automatico con GitHub Actions»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Machine Learning Academy?

Sì. Ogni lezione Machine Learning Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Tracciamento degli esperimenti con MLflow: registrare parametri, metriche e artifact
  2. Ambienti riproducibili con Docker per il machine learning
  3. Model Registry: staging, produzione e archiviazione
  4. Pipeline di riaddestramento automatico con GitHub Actions
← Torna a Machine Learning Academy