Salvare e caricare una pipeline con joblib
Imparerete a serializzare su disco una Pipeline addestrata con joblib.dump e ricaricarla in una nuova sessione Python per effettuare previsioni senza un nuovo addestramento.
Salvare e caricare una pipeline con joblib è 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é rendere persistente una Pipeline addestrata?
L'addestramento di una pipeline di machine learning può richiedere minuti o ore. Una volta eseguito il fitting, vorrete salvarla su disco per poterla ricaricare in seguito e ottenere predizioni senza ripetere l'addestramento. La persistenza è inoltre essenziale per la distribuzione: addestrate il modello su una macchina di sviluppo e fornite predizioni su un server di produzione. Il file salvato deve includere sia i passaggi di preprocessing sia i pesi del modello.
Due opzioni di serializzazione: pickle e joblib
Il modulo integrato di Python pickle può serializzare qualsiasi oggetto Python, incluse le pipeline di sklearn. joblib è una libreria di terze parti (inclusa in scikit-learn) generalmente preferita per gli oggetti di machine learning perché è più efficiente con i grandi array NumPy: utilizza il memory mapping invece della copia e può comprimere automaticamente il file di output.
import pickle
import joblib
# Both approaches work; joblib is recommended for sklearn objects
print('pickle version:', pickle.HIGHEST_PROTOCOL)
import sklearn
print('sklearn version:', sklearn.__version__)Salvare con joblib.dump
joblib.dump(obj, filename) serializza la pipeline in un file. Facoltativamente potete impostare compress=3 per utilizzare la compressione zlib (livelli da 1 a 9; 3 offre un buon compromesso tra velocità e dimensioni). La funzione restituisce un elenco dei file creati. Per la maggior parte delle pipeline viene creato un unico file .pkl o .joblib.
import joblib
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris
X, y = load_iris(return_X_y=True)
pipe = Pipeline([
('scaler', StandardScaler()),
('clf', LogisticRegression(C=1.0, max_iter=200))
])
pipe.fit(X, y)
# Save
joblib.dump(pipe, '/tmp/iris_pipeline.joblib')
print('Pipeline saved!')Caricare con joblib.load
joblib.load(filename) deserializza la pipeline nuovamente in un oggetto Python. La pipeline caricata è identica all'originale: contiene gli stessi parametri calcolati dello scaler (media e varianza) e gli stessi pesi del modello. Potete chiamare immediatamente predict, predict_proba o score senza ripetere il fitting.
import joblib
from sklearn.datasets import load_iris
import numpy as np
X, y = load_iris(return_X_y=True)
# Load the saved pipeline
loaded_pipe = joblib.load('/tmp/iris_pipeline.joblib')
# Predict and verify
predictions = loaded_pipe.predict(X[:5])
print('Predictions:', predictions)
print('Test accuracy:', loaded_pipe.score(X, y).round(4))Verificare la fedeltà del percorso completo
Dopo il caricamento, verificate che la pipeline caricata produca predizioni identiche a quelle dell'originale. Qualsiasi differenza indica un problema di serializzazione o un'incompatibilità tra versioni. Un controllo semplice consiste nel confrontare le predizioni elemento per elemento utilizzando np.array_equal.
import joblib
import numpy as np
from sklearn.datasets import load_iris
X, _ = load_iris(return_X_y=True)
# Reload and compare
loaded = joblib.load('/tmp/iris_pipeline.joblib')
# Reload the original reference predictions
# (in practice, save original predictions before reload)
original_preds = loaded.predict(X) # use loaded as reference
loaded2 = joblib.load('/tmp/iris_pipeline.joblib')
reloaded_preds = loaded2.predict(X)
print('Predictions match:', np.array_equal(original_preds, reloaded_preds))Opzioni di compressione in joblib
Le pipeline di grandi dimensioni (ad esempio con RandomForest composto da 1000 alberi) possono occupare centinaia di MB. Utilizzate joblib.dump(pipe, path, compress=3) per comprimere i dati durante il salvataggio. In alternativa, specificate esplicitamente il compressore: compress=('zlib', 3) oppure compress=('lz4', 1) per ottenere la massima velocità. LZ4 è il più veloce; zlib produce file più piccoli, ma è più lento.
import joblib
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris
import os
X, y = load_iris(return_X_y=True)
pipe = Pipeline([('sc', StandardScaler()), ('lr', LogisticRegression())]).fit(X, y)
# Uncompressed
joblib.dump(pipe, '/tmp/pipe_raw.joblib')
# Compressed
joblib.dump(pipe, '/tmp/pipe_compressed.joblib', compress=3)
print('Raw size:', os.path.getsize('/tmp/pipe_raw.joblib'), 'bytes')
print('Compressed size:', os.path.getsize('/tmp/pipe_compressed.joblib'), 'bytes')Utilizzare pickle come alternativa
Se joblib non è disponibile, pickle funziona con le pipeline di sklearn. Utilizzate la modalità binaria ('rb'/'wb') quando aprite il file. Per i modelli piccoli o gli strumenti usati una sola volta tramite script, pickle è perfettamente adeguato; per i sistemi di produzione che gestiscono grandi array NumPy, joblib è fortemente consigliato.
import pickle
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris
X, y = load_iris(return_X_y=True)
pipe = Pipeline([('sc', StandardScaler()), ('lr', LogisticRegression())]).fit(X, y)
# Save with pickle
with open('/tmp/model.pkl', 'wb') as f:
pickle.dump(pipe, f)
# Load with pickle
with open('/tmp/model.pkl', 'rb') as f:
loaded = pickle.load(f)
print('Loaded score:', loaded.score(X, y).round(4))Avvertenze sulla compatibilità delle versioni
Un aspetto critico in produzione è il seguente: una pipeline serializzata con scikit-learn 1.2 potrebbe non essere caricata correttamente con scikit-learn 1.5. Registrate sempre in un file di metadati, accanto al modello salvato, le versioni delle librerie utilizzate durante l'addestramento. Utilizzate pip freeze > requirements.txt oppure registrate le versioni programmaticamente e archiviatele accanto al file del modello.
import sklearn
import numpy as np
import json
import os
metadata = {
'sklearn_version': sklearn.__version__,
'numpy_version': np.__version__,
'model_file': 'iris_pipeline.joblib'
}
with open('/tmp/model_metadata.json', 'w') as f:
json.dump(metadata, f, indent=2)
print(json.dumps(metadata, indent=2))Caricare una Pipeline in uno script di produzione
In un servizio di produzione, il flusso di lavoro è il seguente: caricate la pipeline una sola volta all'avvio (non a ogni richiesta), ricevete le feature di input, applicate il preprocessing con le trasformazioni integrate nella pipeline e restituite le predizioni. Poiché la pipeline include tutto il preprocessing, il codice del servizio non deve conoscere i dettagli di scalatura, codifica o PCA: tutto è incapsulato nell'oggetto salvato.
import joblib
import numpy as np
# At startup (once)
model = joblib.load('/tmp/iris_pipeline.joblib')
def predict(sepal_length, sepal_width, petal_length, petal_width):
features = np.array([[sepal_length, sepal_width, petal_length, petal_width]])
label = model.predict(features)[0]
proba = model.predict_proba(features)[0]
return {'label': int(label), 'confidence': round(float(proba.max()), 4)}
result = predict(5.1, 3.5, 1.4, 0.2)
print('Prediction result:', result)Considerazioni sulla sicurezza dei modelli serializzati con pickle
Non caricate mai un file pickle proveniente da una fonte non attendibile. I file pickle possono eseguire codice arbitrario durante il caricamento: si tratta di un limite fondamentale della sicurezza di Python. Per condividere modelli esternamente, prendete in considerazione alternative più sicure e specifiche per il formato: ONNX per la serializzazione tra framework oppure file joblib condivisi esclusivamente all'interno di un'infrastruttura affidabile. Verificate sempre il checksum del file prima di caricarlo.
import hashlib
def file_sha256(path):
h = hashlib.sha256()
with open(path, 'rb') as f:
for chunk in iter(lambda: f.read(65536), b''):
h.update(chunk)
return h.hexdigest()
checksum = file_sha256('/tmp/iris_pipeline.joblib')
print('Model SHA-256:', checksum)
# In production: compare this checksum with the one stored in your model registryTest rapido di integrità caricamento-predizione
Una buona pratica finale consiste nell'includere nel pacchetto del modello un breve script di controllo che carichi la pipeline, esegua una predizione su un input noto e verifichi l'output atteso. Eseguite questo test nella pipeline CI/CD ogni volta che il modello viene promosso in produzione, così da confermare che il file non sia danneggiato e che l'ambiente sia compatibile.
import joblib
import numpy as np
# Sanity test
model = joblib.load('/tmp/iris_pipeline.joblib')
# Known input (setosa): sepal_length=5.1, sepal_width=3.5, petal_length=1.4, petal_width=0.2
X_test = np.array([[5.1, 3.5, 1.4, 0.2]])
pred = model.predict(X_test)[0]
# Iris class 0 = setosa
assert pred == 0, f'Expected setosa (0) but got {pred}'
print('Sanity test PASSED — model predicts setosa correctly.')Controllo rapido
Verificate la vostra comprensione del salvataggio e del caricamento delle pipeline dopo questa lezione.
Riepilogo della lezione
In questa lezione ha imparato che: joblib.dump e joblib.load salvano e ripristinano una pipeline completa già addestrata, inclusi tutti i parametri di preprocessing; è necessario registrare sempre le versioni delle librerie insieme al modello salvato per garantire un caricamento riproducibile; e non bisogna mai caricare file pickle da fonti non attendibili, perché possono eseguire codice arbitrario. Ora affronteremo i dataset sbilanciati: come rilevare lo sbilanciamento tra le classi e capire perché, in questo contesto, l'accuratezza è una metrica fuorviante.
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 «Salvare e caricare una pipeline con joblib» è gratuita?
Sì — il testo completo di «Salvare e caricare una pipeline con joblib» è 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 «Salvare e caricare una pipeline con joblib»?
Imparerete a serializzare su disco una Pipeline addestrata con joblib.dump e ricaricarla in una nuova sessione Python per effettuare previsioni senza un nuovo addestramento. 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 «Salvare e caricare una pipeline con joblib»?
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
- Costruire la prima pipeline: scaler più classificatore
- ColumnTransformer all’interno di una pipeline
- Cross-validation e grid search di una pipeline completa
- Salvare e caricare una pipeline con joblib