Prise en main : Créer votre premier modèle Machine Learning sur Databricks

Cet exemple de notebook montre comment entraîner un modèle de classification Machine Learning sur Databricks. Databricks Runtime pour Machine Learning est fourni avec de nombreuses bibliothèques préinstallées, notamment scikit-learn pour l’apprentissage et les algorithmes de prétraitement, MLflow pour suivre le processus de développement de modèle et Optuna pour mettre à l’échelle le réglage des hyperparamètres.

Dans ce notebook, vous créez un modèle de classification pour prédire si un vin est considéré comme « de haute qualité ». Le jeu de données comprend 11 caractéristiques de différents vins (par exemple, la teneur en alcool, l’acide et le sucre résiduel) et un classement de qualité compris entre 1 et 10.

Ce didacticiel contient les sections suivantes :

  • Partie 1 : Entraîner un modèle de classification avec le suivi MLflow
  • Partie 2 : Réglage des hyperparamètres pour améliorer les performances du modèle
  • Partie 3 : Enregistrer les résultats et les modèles dans le catalogue Unity
  • Partie 4 : Déployer le modèle

Pour plus d’informations sur la productionnalisation du Machine Learning sur Databricks, notamment la gestion du cycle de vie des modèles et l’inférence de modèle, consultez l’Exemple ML de bout en bout.

Le jeu de données est disponible à partir du référentiel de UCI Machine Learning et est présenté dans Modeling wine preferences by data mining from physicochemical properties [Cortez et al., 2009].

Exigences

Paramétrage

Dans cette section, procédez comme suit :

  • Configurez le client MLflow pour utiliser le catalogue Unity comme registre de modèles.
  • Définissez le catalogue et le schéma où le modèle sera inscrit.
  • Lisez les données et enregistrez-les dans les tables du catalogue Unity.
  • Prétraitez les données.

Configurer le client MLflow

Par défaut, le client MLflow Python crée des modèles dans le registre de modèles de l’espace de travail Databricks. Pour enregistrer des modèles dans le catalogue Unity, configurez le client MLflow comme indiqué dans la cellule suivante.

import mlflow
mlflow.set_registry_uri("databricks-uc")

La cellule suivante définit le catalogue et le schéma où le modèle sera inscrit. Vous devez disposer de privilèges USE CATALOG sur le catalogue, et des privilèges USE_SCHEMA, CREATE_TABLE et CREATE_MODEL sur le schéma. Modifiez le catalogue et les noms de schéma dans la cellule suivante si nécessaire.

Pour plus d’informations, consultez la documentation du catalogue Unity.

# Specify the catalog and schema to use. You must have USE_CATALOG privilege on the catalog and USE_SCHEMA, CREATE_TABLE, and CREATE_MODEL privileges on the schema.
# Change the catalog and schema here if necessary.
CATALOG_NAME = "main"
SCHEMA_NAME = "default"

Lire les données et les enregistrer dans des tables dans le catalogue Unity

Le jeu de données est disponible dans databricks-datasets. Dans la cellule suivante, vous importez les données des fichiers .csv dans des Spark DataFrames. Vous écrivez ensuite les DataFrames dans des tables du catalogue Unity. Ces deux éléments conservent les données et vous permettent de contrôler comment les partager avec d’autres personnes.

white_wine = spark.read.csv("/databricks-datasets/wine-quality/winequality-white.csv", sep=';', header=True)
red_wine = spark.read.csv("/databricks-datasets/wine-quality/winequality-red.csv", sep=';', header=True)

# Remove the spaces from the column names
for c in white_wine.columns:
    white_wine = white_wine.withColumnRenamed(c, c.replace(" ", "_"))
for c in red_wine.columns:
    red_wine = red_wine.withColumnRenamed(c, c.replace(" ", "_"))

# Define table names
red_wine_table = f"{CATALOG_NAME}.{SCHEMA_NAME}.red_wine"
white_wine_table = f"{CATALOG_NAME}.{SCHEMA_NAME}.white_wine"

# Write to tables in Unity Catalog
spark.sql(f"DROP TABLE IF EXISTS {red_wine_table}")
spark.sql(f"DROP TABLE IF EXISTS {white_wine_table}")
white_wine.write.saveAsTable(f"{CATALOG_NAME}.{SCHEMA_NAME}.white_wine")
red_wine.write.saveAsTable(f"{CATALOG_NAME}.{SCHEMA_NAME}.red_wine")

Prétraitement des données

# Import required libraries
import numpy as np
import pandas as pd
import sklearn.datasets
import sklearn.metrics
import sklearn.model_selection
import sklearn.ensemble

import matplotlib.pyplot as plt

import optuna
from mlflow.optuna.storage import MlflowStorage
from mlflow.pyspark.optuna.study import MlflowSparkStudy
# Load data from Unity Catalog as Pandas dataframes
white_wine = spark.read.table(f"{CATALOG_NAME}.{SCHEMA_NAME}.white_wine").toPandas()
red_wine = spark.read.table(f"{CATALOG_NAME}.{SCHEMA_NAME}.red_wine").toPandas()

# Add Boolean fields for red and white wine
white_wine['is_red'] = 0.0
red_wine['is_red'] = 1.0
data_df = pd.concat([white_wine, red_wine], axis=0)

# Define classification labels based on the wine quality
data_labels = data_df['quality'].astype('int') >= 7
data_df = data_df.drop(['quality'], axis=1)

# Split 80/20 train-test
X_train, X_test, y_train, y_test = sklearn.model_selection.train_test_split(
  data_df,
  data_labels,
  test_size=0.2,
  random_state=1
)

Partie 1. Entraîner un modèle de classification

# Enable MLflow autologging for this notebook
mlflow.autolog()

Ensuite, entraînez un classifieur dans le contexte d’une exécution MLflow, qui journalise automatiquement le modèle entraîné et de nombreux paramètres et métriques associés.

Vous pouvez compléter la journalisation avec des métriques supplémentaires telles que le score AUC du modèle sur le jeu de données de test.

with mlflow.start_run(run_name='gradient_boost') as run:
    model = sklearn.ensemble.GradientBoostingClassifier(random_state=0)

    # Models, parameters, and training metrics are tracked automatically
    model.fit(X_train, y_train)

    predicted_probs = model.predict_proba(X_test)
    roc_auc = sklearn.metrics.roc_auc_score(y_test, predicted_probs[:,1])
    roc_curve = sklearn.metrics.RocCurveDisplay.from_estimator(model, X_test, y_test)

    # Save the ROC curve plot to a file
    roc_curve.figure_.savefig("roc_curve.png")

    # The AUC score on test data is not automatically logged, so log it manually
    mlflow.log_metric("test_auc", roc_auc)

    # Log the ROC curve image file as an artifact
    mlflow.log_artifact("roc_curve.png")

    print("Test AUC of: {}".format(roc_auc))

Afficher les exécutions MLflow

Pour afficher l'exécution de l'entraînement enregistrée, cliquez sur l'icône en haut à droite du bloc-notes pour faire apparaître la barre latérale de l'expérimentation. Experiment icon Si nécessaire, cliquez sur l’icône d’actualisation pour extraire et surveiller les dernières exécutions.

Expériences répertoriées dans la barre latérale droite

Pour afficher la page d’expérience MLflow plus détaillée, cliquez sur l’icône de page d’expérience. Cette page vous permet de comparer les exécutions et d’afficher les détails des exécutions spécifiques. Voir Suivre le développement de modèles à l’aide de MLflow.

Charger des modèles

Vous pouvez également accéder aux résultats d’une exécution spécifique à l’aide de l’API MLflow. Le code de la cellule suivante montre comment charger le modèle entraîné dans une exécution MLflow donnée et l’utiliser pour effectuer des prédictions. Vous pouvez également trouver des extraits de code pour charger des modèles spécifiques sur la page d’exécution MLflow.

# After a model has been logged, you can load it in different notebooks or jobs
# mlflow.pyfunc.load_model makes model prediction available under a common API
model_loaded = mlflow.pyfunc.load_model(
  'runs:/{run_id}/model'.format(
    run_id=run.info.run_id
  )
)

predictions_loaded = model_loaded.predict(X_test)
predictions_original = model.predict(X_test)

# The loaded model should match the original
assert(np.array_equal(predictions_loaded, predictions_original))

Partie 2. Optimisation des hyperparamètres

À ce stade, vous avez formé un modèle simple et utilisé le service de suivi MLflow pour organiser votre travail. Ensuite, vous pouvez effectuer un réglage plus sophistiqué à l’aide d’Optuna.

Formation parallèle à l’aide d’Optuna

Optuna est une bibliothèque Python open source pour le réglage des hyperparamètres qui offre une scalabilité horizontale sur plusieurs capacités de calcul. Pour plus d’informations sur l’utilisation d’Optuna dans Databricks, consultez Optimisation des hyperparamètres avec Optuna.

def objective(trial):
  # Enable autologging on each worker
  mlflow.autolog()
  with mlflow.start_run(nested=True):
    params = {
      'n_estimators': trial.suggest_int('n_estimators', 20, 1000),
      'learning_rate': trial.suggest_float('learning_rate', 0.05, 1.0, log=True),
      'max_depth': trial.suggest_int('max_depth', 2, 5),
    }
    model_hp = sklearn.ensemble.GradientBoostingClassifier(
      random_state=0,
      **params
    )
    model_hp.fit(X_train, y_train)
    predicted_probs = model_hp.predict_proba(X_test)
    # Tune based on the test AUC
    # In production, you could use a separate validation set instead
    roc_auc = sklearn.metrics.roc_auc_score(y_test, predicted_probs[:,1])
    mlflow.log_metric('test_auc', roc_auc)

    # Negate the AUC because Optuna minimizes the objective by default
    return -roc_auc


with mlflow.start_run(run_name='gb_optuna') as run:
  # Use the MLflow Tracking Server as the Optuna storage backend
  experiment_id = mlflow.active_run().info.experiment_id
  mlflow_storage = MlflowStorage(experiment_id=experiment_id)

  # MlflowSparkStudy distributes the tuning using Spark workers
  mlflow_study = MlflowSparkStudy(
    study_name="gb-optuna-tuning",
    storage=mlflow_storage,
  )

  mlflow_study.optimize(objective, n_trials=32, n_jobs=4)

Exécutions de recherche pour récupérer le meilleur modèle

Étant donné que toutes les exécutions sont suivies par MLflow, vous pouvez récupérer les métriques et les paramètres de la meilleure exécution à l’aide de l’API de recherche d'exécutions de MLflow pour trouver l’exécution de réglage avec le taux d'AUC de test le plus élevé.

Ce modèle paramétré doit fonctionner mieux que les modèles plus simples entraînés dans la partie 1.

# Sort runs by their test auc. In case of ties, use the most recent run.
best_run = mlflow.search_runs(
  order_by=['metrics.test_auc DESC', 'start_time DESC'],
  max_results=10,
).iloc[0]
print('Best Run')
print('AUC: {}'.format(best_run["metrics.test_auc"]))
print('Num Estimators: {}'.format(best_run["params.n_estimators"]))
print('Max Depth: {}'.format(best_run["params.max_depth"]))
print('Learning Rate: {}'.format(best_run["params.learning_rate"]))

best_model_pyfunc = mlflow.pyfunc.load_model(
  'runs:/{run_id}/model'.format(
    run_id=best_run.run_id
  )
)

# Make a dataset with all predictions
best_model_predictions = X_test
best_model_predictions["prediction"] = best_model_pyfunc.predict(X_test)

Partie 3. Enregistrer les résultats et les modèles dans le catalogue Unity

predictions_table = f"{CATALOG_NAME}.{SCHEMA_NAME}.predictions"
spark.sql(f"DROP TABLE IF EXISTS {predictions_table}")

results = spark.createDataFrame(best_model_predictions)

# Write results back to Unity Catalog from Python
results.write.saveAsTable(f"{CATALOG_NAME}.{SCHEMA_NAME}.predictions")
model_uri = 'runs:/{run_id}/model'.format(
    run_id=best_run.run_id
  )

mlflow.register_model(model_uri, f"{CATALOG_NAME}.{SCHEMA_NAME}.wine_quality_model")

Partie 4. Déployer un modèle

Après avoir enregistré votre modèle dans le catalogue Unity, vous pouvez le déployer à l’aide de l’interface utilisateur de service. Les instructions suivantes fournissent une brève description. Pour plus d'informations, consultez Créer des points d'accès de modèles personnalisés.

  1. Cliquez sur Mise en service dans la barre latérale pour afficher l’interface utilisateur de mise en service.

Interface utilisateur pour le déploiement de modèles

  1. Cliquez sur Créer un point de service.

  2. Dans le champ Nom , indiquez un nom pour votre point de terminaison.

  3. Dans la section Entités servies

    1. Cliquez sur le champ Entités pour ouvrir le formulaire Sélectionner une entité servie.
    2. Sélectionnez Mes modèles - Catalogue Unity. Le formulaire est mis à jour dynamiquement en fonction de votre sélection.
    3. Sélectionnez la version wine_quality_model du modèle que vous souhaitez déployer.
    4. Sélectionnez 100 comme pourcentage de trafic que vous souhaitez acheminer vers votre modèle servi.
    5. Sélectionnez l’UC comme type de calcul pour cet exemple.
    6. Sous Scale-out de calcul, sélectionnez Small comme taille de scale-out de calcul.
  4. Cliquez sur Créer. La page Points de terminaison de service s’affiche avec l’état de point de terminaison De service affiché comme Non prêt.

  5. Lorsque votre point de terminaison est prêt, sélectionnez Utiliser pour envoyer une demande d’inférence au point de terminaison.

Exemple de bloc-notes

Prise en main : Créer votre premier modèle Machine Learning sur Databricks

Obtenir le notebook