Maîtriser les logs de modèle de ML sous Microsoft Fabric

Microsoft Fabric est la nouvelle plateforme data & IA de Microsoft, permettant de travailler de bout en bout (de la collecte à la visualisation) des données, selon différentes expériences, correspondant à différents personae du monde de la data : Data Engineer, Data Analyst et également Data Scientist.

Les Scientifiques de données ont la possiblité de lancer un environnement de travail basé sur des notebooks, qui s’exécuteront sur un cluster Spark. Les données pourront bien sûr être stockées dans One Lake, le système central de stockage sur lequel s’appuie Fabric.

Les personnes habituées des environnements comme Azure Machine Learning ou Azure Databricks connaissent bien le produit Open-Source MLFlow, outil devenu un standard pour tracer les hyperparamètres d’entrainement ainsi que les métriques d’évaluation et pour stocker tous les artefacts liés à un modèle de Machine Learning : fichier des requirements, binaire du modèle sauvegardé, définition des input et output

Microsoft a donc également intégré MLFlow au sein de la plateforme Fabric. Et pour simplifier son utilisation, il n’est même pas nécessaire d’appeler explicitement la session MLFlow pour déclencher le suivi des logs ! Il s’agit du mécanisme d’autologging documenté ici.

Pour autant, il peut être intéressant de définir explicitement les entrainements et les éléments (paramètres et métriques) que l’on veut voir enregistrés dans MLFlow.

Dans cet article, nous allons détailler ces deux modes de travail avec MLFlow intégré dans Microsoft Fabric.

Création implicite d’une expérience

Pour illustrer les différentes fonctionnalités, nous allons utiliser du code généré par ChatGPT, à l’aide du prompt suivant :

Ecris-moi un code Python qui illustre une classification Sklearn en utilisant un dataset de ce package

Nous pouvons maintenant exécuter le notebook contenant ce code.

La méthode .fit() de la librairie Scikit-learn déclenche l’enregistrement d’un run (exécution) au sein d’une experiment (expérience) dont le nom est, par défaut, celui du notebook (ici “Notebook-1”).

Ces deux éléments sont des liens cliquables qui vont nous permettre de naviguer dans d’autres éléments maintenant stockés dans l’espace de travail utilisé pour ce notebook.

Les différents artefacts sont liés au run et l’on retrouve en particulier les graphiques générés dans le notebook.

Modifions maintenant la valeur d’un hyperparamètre de l’entrainement afin de comparer deux runs :

model = LogisticRegression(max_iter=200, penalty='None')

Une bonne pratique consiste alors à modifier les noms des runs afin de savoir à quoi ceux-ci correspondent.

Une action manuelle sera nécessaire pour enregistrer le modèle, depuis la vue du run.

Save run as an ML model

Au premier enregistrement du modèle, il est nécessaire de lui attribuer un folder (dossier) puis un nom.

La modèle est alors enregistré en version 1.

L’interface permet alors de déclencher un assistant qui génèrera le code nécessaire à l’inférence (i.e. l’utilisation du modèle pour générer des prévisions).

Le code généré est basé sur la librairie synapseml développé par Microsoft.

Nous disposons maintenant de trois éléments dans le workspace :

  • notebook
  • experiment (tous les runs)
  • ML model

Syntaxes explicites MLFlow

Explorons maintenant les différentes syntaxes MLFlow qui nous permettront de :

  • visualiser l’URI du serveur
  • choisir les entrainements à tracer
  • choisir les hyperparamètres et métriques recueillies
  • enregistrer une nouvelle version du modèle

Le code exécuté de manière implicite était le suivant :

import mlflow

mlflow.autolog(
log_input_examples=False,
log_model_signatures=True,
log_models=True,
disable=True,
exclusive=True,
disable_for_unsupported_versions=True,
silent=True
)

Nous commençons par importer la librairie MLFlow, déjà pré-installée sur le cluster Spark.

Le paramètre le plus important est sans doute “disable” qui permet de désactiver les logs automatiques à l’échelle du notebook (nous verrons plus tard comment le faire au niveau du workspace).

Nous pouvons maintenant définir le nom de l’experiment à l’aide de l’instruction set_experiment() et visualiser l’URI de tracking avec la syntaxe get_tracking_uri().

Voici le code de la classification, adapté pour utiliser explicitement les commandes MLFlow. Le prompt suivant a permis de générer ce code :

Ajoute les éléments nécessaires au tracking des hyperparamètres et métriques dans MLFlow

with mlflow.start_run():

    # Hyperparamètres
    max_iter = 200

    # Créer un modèle de régression logistique
    model = LogisticRegression(max_iter=max_iter)
    model.fit(X_train, y_train)

    # Prédire les étiquettes pour l'ensemble de test
    y_pred = model.predict(X_test)

    # Évaluer la performance du modèle
    accuracy = accuracy_score(y_test, y_pred)
    conf_matrix = confusion_matrix(y_test, y_pred)
    class_report = classification_report(y_test, y_pred, output_dict=True)

    # Enregistrer les hyperparamètres et les métriques dans MLFlow
    mlflow.log_param("max_iter", max_iter)
    mlflow.log_metric("accuracy", accuracy)
    for label, metrics in class_report.items():
        if isinstance(metrics, dict):
            for metric_name, metric_value in metrics.items():
                mlflow.log_metric(f"{label}_{metric_name}", metric_value)

    # Enregistrer la matrice de confusion comme une image
    plt.figure(figsize=(8, 6))
    plt.imshow(conf_matrix, interpolation='nearest', cmap=plt.cm.Blues)
    plt.title('Confusion Matrix')
    plt.colorbar()
    tick_marks = np.arange(len(iris.target_names))
    plt.xticks(tick_marks, iris.target_names, rotation=45)
    plt.yticks(tick_marks, iris.target_names)

    fmt = 'd'
    thresh = conf_matrix.max() / 2.
    for i, j in np.ndindex(conf_matrix.shape):
        plt.text(j, i, format(conf_matrix[i, j], fmt),
                 ha="center", va="center",
                 color="white" if conf_matrix[i, j] > thresh else "black")

    plt.ylabel('True label')
    plt.xlabel('Predicted label')
    plt.tight_layout()
    plt.savefig("confusion_matrix.png")
    mlflow.log_artifact("confusion_matrix.png")

    # Enregistrer le modèle entraîné
    mlflow.sklearn.log_model(model, "iris-classifier-model")

    # Affichage des coefficients de la régression logistique
    print("Coefficients de la régression logistique:")
    print(model.coef_)

    # Afficher les coefficients sous forme graphique
    plt.figure(figsize=(10, 5))
    plt.bar(range(len(model.coef_[0])), model.coef_[0])
    plt.xlabel('Features')
    plt.ylabel('Coefficient Value')
    plt.title('Coefficients de la Régression Logistique pour chaque Feature')
    plt.savefig("coefficients.png")
    mlflow.log_artifact("coefficients.png")

print(f"Accuracy: {accuracy:.2f}")
print("Confusion Matrix:")
print(conf_matrix)
print("Classification Report:")
print(classification_report(y_test, y_pred))

Les liens sont toujours disponibles dans les logs de la cellule du notebook.

Le modèle est ainsi déjà enregistré, il n’est plus nécessaire de réaliser l’étape manuelle vue précécemment.

Enfin, il est possible (recommandé) d’améliorer le log du modèle en précisant des exemples d’input et d’output, ce que l’on appelle la signature du modèle.

# Enregistrer le modèle avec sa signature
from mlflow.models.signature import infer_signature

signature = infer_signature(
    X_test, y_pred
)

model_name = "orders-outliers-model"

mlflow.sklearn.log_model(
        model,
        model_name,
        signature=signature,
        registered_model_name=model_name
)

   Pour conserver la cohérence avec l’entrainement du modèle, les couples d’objets X_train, y_train ou X_test, y_pred peuvent être utilisés.

Paramètre du workspace : automatic log

Lorsque votre méthode de travail se sera arrêtée sur l’une ou l’autre des possibilités, vous pourrez jouer avec le paramètre “automatic log”, disponible à la granularité du workspace.

Si vous envisagez de maximiser la portabilité de vos notebooks (les exécuter sur Azure Machine Learning ou bien Azure Databricks par exemple), il sera sans doute plus judicieux de favoriser l’écriture explicite des commandes MLFlow.

La data de bout en bout avec Microsoft Fabric

Lors de la conférence Build 2023, Microsoft a annoncé la sortie d’un nouveau produit dans le monde de la Data & AI. Si l’on excepte le rebranding de SQL Datawarehouse en Synapse Analytics et la sortie plus confidentielle de Data Explorer, il faut sans doute remonter à 2015 et l’arrivée de Power BI pour assister à un tel chamboulement dans l’offre de la firme de Redmond.

Dans ce premier article dédié à Microsoft Fabric, nous allons revenir sur les architectures cloud dites Modern Data Platform et Lakehouse pour bien comprendre le positionnement du produit. Ensuite, nous verrons en quoi ce nouveau service se différencie de l’existant, que ce soit Azure Synapse Analytics ou Power BI, et à qui il s’adresse.

Voici d’ores et déjà le nouveau logo avec lequel nous allons nous familiariser.

Modern Data Platform

L’architecture Modern Data Platform enchaine quatre étapes fondamentales : ingestion > stockage > calcul > exposition auxquelles peut s’ajouter une étape d’enrichissement grâce à l’intelligence artificielle (services cognitifs, machine learning).

https://learn.microsoft.com/en-us/azure/architecture/example-scenario/dataplate2e/data-platform-end-to-end?tabs=portal

Cette architecture, bien que très complète et performante dans le cloud, par son découpage des tâches, montre une certaine complexité, non pas dans l’utilisation des différents services mais bien dans la communication entre ces services (les fameuses flèches entre les logos !). Une première réponse a été apportée avec le produit Azure Synapse Analytics qui regroupe :

  • l’ingestion de données au travers d’un module similaire à Azure Data Factory
  • le calcul avec les moteurs SQL (dedicated ou serverless) et Spark
  • la gestion des données de streaming avec Data Explorer

Ce ne sont pas des formats propriétaires

Et vous, êtes-vous plutôt tables ou plutôt fichiers ? Il n’est plus nécessaire de choisir depuis l’essor des formats de fichiers orientés colonnes comme Apache Parquet ou Delta (ce dernier étant très fortement soutenu par la société Databricks). Plutôt que de dupliquer le contenu des fichiers dans des tables (avec tous les problèmes que cela implique : gestion des mises à jour, espace de stockage, ressources de calcul différentes…), il est beaucoup plus judicieux de travailler avec la logique d’une metastore qui contiendra uniquement les métadonnées nécessaires et autorisera l’accès aux données en langage SQL.

Microsoft Fabric est donc logiquement bâti autour de l’approche dite lakehouse et c’est même le nom du composant de stockage que l’on pourra déployer dans les espaces de travail (workspaces).

Ce n’est pas (que) Synapse Analytics

Avec Microsoft Fabric, le niveau d’intégration de ces différentes briques est maintenant complet, puisque le produit gère simultanément :

  • le stockage sous le nom de “OneLake” (il faut voir ici une similitude, au moins dans le nom, avec OneDrive)
  • l’ingestion avec toujours Data Factory (ses nombreux connecteurs, ses pipelines visuels)
  • le calcul, toujours avec Spark ou SQL, mais cette fois sans distinction dedicated ou serverless
  • la data science s’appuyant sur Azure Machine Learning
  • le stockage et calcul des données de streaming avec Synapse Data Explorer
  • l’exposition avec le service Power BI
  • l’ordonnancement avec un nouveau composant à venir, nommé Data Activator, que l’on peut rapprocher par exemple du rôle d’un service comme Azure Logic Apps

Un nouveau service Power BI ?

Microsoft Fabric est un produit de type Software as a Service (SaaS). Il n’y a donc pas de client à installer localement, tout se fait au travers d’un navigateur web. Si vous connaissez bien Power BI, vous savez qu’historiquement, deux actions ont longtemps été absentes de l’édition des rapports dans le navigateur : la modélisation et les calculs DAX. Ces opérations sont désormais réalisables dans l’interface en ligne.

Les utilisateurs de Power BI ont également dû longtemps choisir entre rapidité d’affichage (mode import) et donnée fraîche (mode Direct Query). Le mode hybride avec par exemple, la gestion de tables d’agrégats a pu permettre de trouver un compromis mais il fallait un niveau d’expertise assez avancée pour se lancer dans une telle approche. Aujourd’hui, Microsoft Fabric propose le concept de Direct Lake, qui, comme son nom l’indique, propose de travailler sur un mode “Direct Query” sur les sources disponibles dans OneLake.

Malgré l’existence des pipelines de déploiement (licence Premium exigée), l’approche DevOps dans Power BI a toujours été très laborieuse. Nous disposerons, avec Microsoft Fabric, d’un source versioning dans les repositories Azure DevOps (autres gestionnaires à venir sans doute prochainement). Reste à voir en pratique comment se mettra en place le travail collaboratif.

Autre nouveauté sur le plan de la gouvernance et de l’organisation des différents projets : la notion de domain. Les traditionnels groupes de travail (workspaces) peuvent maintenant être assignés à des domaines (sous-entendus fonctionnels), facilitant ainsi la structuration des éléments au sein du tenant.

Qui sont les personae ?

C’est bien toute la famille de la data qui va se réunir au sein de Microsoft Fabric !

Les data engineers vont trouver leur marque dans les menus issus de Synapse Analytics : ingestion de données, pipelines de transformation voire jobs Spark pour les plus codeurs.

Les data scientists manipuleront les environnements, les expériences et les modèles tout comme dans Azure Machine Learning.

Les data analysts connaissent déjà bien l’interface du service Power BI et n’auront plus à basculer du client desktop à l’interface web.

Enfin, les différents modules no code conviendront parfaitement aux “data citizen, qui pourront travailler sur l’ensemble de la chaîne sans avoir à coder.

Dans quelles langues parlons-nous ?

On peut parfois redouter le passage à un nouveau produit car celui-ci implique un temps d’apprentissage en particulier quand il est nécessaire d’appréhender de nouveaux langages. Avec Microsoft Fabric, nous sommes en terrain connu. Voyons cela en détail.

Data engineering (chargement des données)

Il existe quatre modes de chargement de la donnée au sein d’un lakehouse :

  • les dataflow (de génération 2) : no code ou langage M
  • les data pipelines (Data Factory) : no code voire low code si l’on considère les quelques formules qui peuvent être utilisées
  • les notebooks s’exécutant dans un environnement Apache Spark, avec les langages Scala, Python (API pyspark) ou Spark SQL
  • les shortcuts (no code) qui permettent de pointer vers une source déjà présente au sein de OneLake ou bien vers une source externe comme ADLS gen2 ou Amazon S3
Data Warehouse

Ici, et comme depuis un demi-siècle, le langage SQL est roi ! Nous sommes bien évidemment dans la version T-SQL de Microsoft, enrichi par quelques fonctions propres à Synapse Analytics.

Data Science

Nous sommes en terrain connu (et conquis !) pour les scientifiques de données : Scala, Python & R. Pour ces deux derniers, il sera nécessaire d’utiliser les API pyspark et SparkR pour profiter pleinement de la puissance du moteur de calcul distribué.

Streaming

L’intégration du produit Azure Data Explorer s’accompagne bien sûr du langage KustoQL (KQL) pour le chargement et l’interrogation des données.

Modélisation décisionnelles et mesures

Depuis l’arrivée des modèles tabulaires concurrençant les modèles multi-dimensionnels, le langage DAX s’est imposé pour manipuler la couche sémantique de la Business Intelligence. Ici, rien ne change.

OpenAI en copilote ?

Le partenariat entre la société OpenAI et Microsoft s’est renforcé en novembre 2022 et le succès planétaire de ChatGPT a montré tout le potentiels de l’IA générative pour les outils bureautiques (Microsoft Copilot à venir prochainement), comme dans le monde du développement (GitHub Copilot). Microsoft Fabric s’appuie également sur les fundation models tels que GPT ou Codex.

Vous connaissiez la création de visuel en langage naturel depuis plusieurs années dans Power BI ? Voici maintenant la création de rapport ! Le copilot demande une description en quelques mots des attentes en termes de reporting ou d’analyse et la page de rapport se génèrera automatiquement. Tout simplement magique ! Finalement, les spécifications ne sont-elles pas l’étape la plus importante d’un projet de tableau de bord ?

Vous pouvez retrouver plus de détails sur le blog officiel de Power BI.

En attendant la mise en pratique

En conclusion, et avant de passer véritablement aux tests de cette nouvelle plateforme, nous pouvons saluer l’effort de vision de bout en bout de la part de Microsoft, qui vise à fédérer pour les acteurs de la data dans l’entreprise autour d’une même source et d’une gouvernance unifiée.

N’oublions pas non plus le service Azure Databricks qui reste sans doute la plateforme d’entreprise pour les projets Big Data sur Azure, et qui dispose également d’une vision unifiée des usages de la donnée.

De nombreux éléments demandent maintenant à être vérifier dans la pratique :

  • le coût exact du produit à l’usage
  • la capacité à monter à l’échelle avec la volumétrie ou la vélocité requise
  • la collaboration entre les profils data (engineer, analytist, scientist…)
  • la simplicité de gouvernance (data discovery, data catalog, lineage…)
  • la possibilité de travailler dans des environnements multi-tenants
  • … (liste non exhaustive)

Mais que les utilisateurs se rassurent d’ores et déjà : il sera toujours possible d’obtenir les données dans Excel 🙂 !