Partager via


Tutoriel : créer, évaluer et noter un modèle de détection des défauts de la machine

Ce tutoriel présente un exemple de bout en bout d’un flux de travail science des données Synapse dans Microsoft Fabric. Le scénario utilise l’apprentissage automatique pour une approche plus systématique du diagnostic des pannes, afin d’identifier les problèmes de manière proactive et de prendre des mesures avant une panne réelle de la machine. L’objectif est de prédire si une machine connaîtra une défaillance en fonction de la température du processus, de la vitesse de rotation, etc.

Ce didacticiel couvre ces étapes :

  • Installer des bibliothèques personnalisées
  • Charger et traiter les données
  • Comprendre les données grâce à l’analyse exploratoire des données
  • Utilisez scikit-learn, LightGBM et MLflow pour former des modèles Machine Learning et utilisez la fonction Fabric Autologging pour suivre les expériences
  • Attribuez un score aux modèles formés avec la caractéristique Fabric PREDICT, enregistrez le meilleur modèle et chargez ce modèle pour les prédictions
  • Afficher la performance du modèle chargé avec des visualisations Power BI

Prérequis

Suivez l’évolution dans un notebook

Vous pouvez choisir l’une de ces options pour suivre l’évolution de la situation dans un notebook :

  • Ouvrez et exécutez le notebook intégré dans l’expérience Science des données
  • Chargez votre notebook à partir de GitHub vers l’expérience Science des données

Ouvrir le notebook intégré

L’exemple de notebook sur les Défaillances de la machine accompagne ce tutoriel.

Pour ouvrir l’exemple de notebook intégré au tutoriel dans l’expérience science des données Synapse :

  1. Accédez à la page d’accueil science des données Synapse.

  2. Sélectionnez Utiliser un échantillon.

  3. Sélectionnez l’échantillon correspondant :

    • À partir de l’onglet par défaut Workflows de bout en bout (Python), si l’exemple concerne un tutoriel Python.
    • À partir de l’onglet Workflows de bout en bout (R), si l’exemple concerne un tutoriel R.
    • À partir de l’onglet Tutoriels rapides, si l’exemple concerne un tutoriel rapide.
  4. Attachez un lakehouse au notebook avant de commencer à exécuter le code.

Importer le notebook à partir de GitHub

Le notebook AISample - Maintenance prédictive accompagne ce tutoriel.

Pour ouvrir le notebook d’accompagnement de ce tutoriel, suivez les instructions fournies dans Préparer votre système pour la science des données afin d’importer le notebook dans votre espace de travail.

Si vous préférez copier et coller le code de cette page, vous pouvez créer un nouveau notebook.

Assurez-vous d’attacher un lakehouse au notebook avant de commencer à exécuter du code.

Étape 1 : Installer des bibliothèques personnalisées

Pour le développement de modèle Machine Learning ou l’analyse de données ad hoc, vous pourriez avoir besoin d’installer rapidement une bibliothèque personnalisée pour votre session Apache Spark. Vous avez deux options d’installation des bibliothèques.

  • Utilisez les capacités d’installation en ligne (%pip ou %conda) de votre notebook pour installer une bibliothèque, dans votre notebook actuel uniquement
  • Vous pouvez également créer un environnement Fabric, installer des bibliothèques à partir de sources publiques ou y charger des bibliothèques personnalisées. Ensuite, l’administrateur de votre espace de travail peut attacher l’environnement en tant qu’environnement par défaut pour l’espace de travail. Toutes les bibliothèques de l’environnement seront ensuite disponibles pour être utilisées dans les notebooks et les définitions de travail Spark dans l’espace de travail. Pour plus d’informations sur les environnements, consultez Créer, configurer et utiliser un environnement dans Microsoft Fabric.

Pour ce tutoriel, utilisez %pip install pour installer imblearn la bibliothèque dans votre notebook.

Remarque

Le noyau PySpark redémarre après l’exécution de %pip install. Installez les bibliothèques nécessaires avant d’exécuter d’autres cellules.

# Use pip to install imblearn
%pip install imblearn

Étape 2 : Chargement des données

Le jeu de données simule la journalisation des paramètres d’une machine de fabrication en fonction du temps, ce qui est courant dans les paramètres industriels. Il se compose de 10 000 points de données stockés sous forme de lignes avec des fonctionnalités sous forme de colonnes. Les fonctionnalités incluent :

  • Un identificateur unique (UID) compris entre 1 et 10 000

  • ID produit, composé d’une lettre L (pour low), M (pour medium), ou H (pour high), pour indiquer la variante de qualité du produit, et d’un numéro de série spécifique à la variante. Les variantes de faible, moyenne et haute qualité constituent respectivement 60 %, 30 % et 10 % de tous les produits

  • Température de l’air, en degrés Kelvin (K)

  • Température du processus, en degrés Kelvin

  • Vitesse de rotation, en révolutions par minute (RPM)

  • Couple, en Newton-Mètres (Nm)

  • Usure de l’outil, en minutes. Les variantes de qualité H, M et L ajoutent respectivement 5, 3 et 2 minutes d’usure à l’outil utilisé dans le processus

  • Étiquette d’échec de l’ordinateur pour indiquer si l’ordinateur a échoué dans le point de données spécifique. Ce point de données spécifique peut avoir l’un des cinq modes d’échec indépendants suivants :

    • Échec d’usure de l’outil (TWF) : l’outil est remplacé ou échoue à un temps d’usure de l’outil sélectionné au hasard entre 200 et 240 minutes
    • Défaillance de la dissipation thermique (HDF) : la dissipation thermique entraîne une défaillance du processus si la différence entre la température de l’air et la température du processus est inférieure à 8,6 K, et si la vitesse de rotation de l’outil est inférieure à 1380 tr/min
    • Panne de courant (PWF) : le produit du couple et de la vitesse de rotation (en rad/s) est égal à la puissance requise pour le processus. Le processus échoue si cette puissance est inférieure à 3 500 W ou supérieure à 9 000 W
    • Défaillance due à la surcharge (OSF) : si le produit de l’usure de l’outil et du couple dépasse 11 000 Nm minimum pour la variante de produit L (12 000 pour M, 13 000 pour H), le processus échoue en raison d’une surcharge
    • Échecs aléatoires (RNF) : chaque processus a un risque d’échec de 0,1 %, quels que soient les paramètres du processus

Remarque

Si au moins l’un des modes d’échec ci-dessus est vrai, le processus échoue et l’étiquette « Échec de l’ordinateur » est définie sur 1. La méthode d’apprentissage automatique ne peut pas déterminer quel mode d’échec a provoqué l’échec du processus.

Télécharger le jeu de données et le charger dans le lakehouse

Connectez-vous au conteneur Azure Open Datasets et chargez le jeu de données de maintenance prédictive. Ce code télécharge une version du jeu de données disponible au public, puis la stocke dans un lakehouse Fabric :

Important

Ajoutez un lakehouse au notebook avant de l’exécuter. Sinon, une erreur s’affiche. Pour plus d’informations sur l’ajout d’un lakehouse, consultez Connecter des lakehouses et des notebooks.

# Download demo data files into the lakehouse if they don't exist
import os, requests
DATA_FOLDER = "Files/predictive_maintenance/"  # Folder that contains the dataset
DATA_FILE = "predictive_maintenance.csv"  # Data file name
remote_url = "https://synapseaisolutionsa.blob.core.windows.net/public/MachineFaultDetection"
file_list = ["predictive_maintenance.csv"]
download_path = f"/lakehouse/default/{DATA_FOLDER}/raw"

if not os.path.exists("/lakehouse/default"):
    raise FileNotFoundError(
        "Default lakehouse not found, please add a lakehouse and restart the session."
    )
os.makedirs(download_path, exist_ok=True)
for fname in file_list:
    if not os.path.exists(f"{download_path}/{fname}"):
        r = requests.get(f"{remote_url}/{fname}", timeout=30)
        with open(f"{download_path}/{fname}", "wb") as f:
            f.write(r.content)
print("Downloaded demo data files into lakehouse.")

Après avoir téléchargé le jeu de données dans la lakehouse, vous pouvez le charger en tant que DataFrame Spark :

df = (
    spark.read.option("header", True)
    .option("inferSchema", True)
    .csv(f"{DATA_FOLDER}raw/{DATA_FILE}")
    .cache()
)
df.show(5)

Ce tableau présente un aperçu des données :

UDI Product ID Type Air temperature [K] Process temperature [K] Rotational speed [rpm] Torque [Nm] Tool wear [min] Cible Type d’échec
1 M14860 M 298.1 308.6 1551 42.8 0 0 Aucun échec
2 L47181 L 298,2 308.7 1408 46.3 3 0 Aucun échec
3 L47182 L 298.1 308.5 1498 49.4 5 0 Aucun échec
4 L47183 L 298,2 308.6 1433 39,5 7 0 Aucun échec
5 L47184 L 298,2 308.7 1408 40,0 9 0 Aucun échec

Écrire un DataFrame Spark dans une table delta lakehouse

Formatez les données (par exemple, remplacez les espaces par des traits de soulignement) pour faciliter les opérations Spark dans les étapes suivantes :

# Replace the space in the column name with an underscore to avoid an invalid character while saving 
df = df.toDF(*(c.replace(' ', '_') for c in df.columns))
table_name = "predictive_maintenance_data"
df.show(5)

Ce tableau présente un aperçu des données avec des noms de colonnes reformatés :

UDI Product_ID Type Air_temperature_[K] Process_temperature_[K] Rotational_speed_[rpm] Torque_[Nm] Tool_wear_[min] Cible Failure_Type
1 M14860 M 298.1 308.6 1551 42.8 0 0 Aucun échec
2 L47181 L 298,2 308.7 1408 46.3 3 0 Aucun échec
3 L47182 L 298.1 308.5 1498 49.4 5 0 Aucun échec
4 L47183 L 298,2 308.6 1433 39,5 7 0 Aucun échec
5 L47184 L 298,2 308.7 1408 40,0 9 0 Aucun échec
# Save data with processed columns to the lakehouse 
df.write.mode("overwrite").format("delta").save(f"Tables/{table_name}")
print(f"Spark DataFrame saved to delta table: {table_name}")

Étape 3 : Prétraiter les données et effectuer une analyse exploratoire des données

Convertissez le DataFrame Spark en DataFrame pandas, afin d’utiliser les bibliothèques de traçage populaires compatibles avec Pandas.

Conseil

Pour un grand jeu de données, il se peut que vous deviez charger une partie de ce jeu de données.

data = spark.read.format("delta").load("Tables/predictive_maintenance_data")
SEED = 1234
df = data.toPandas()
df.drop(['UDI', 'Product_ID'],axis=1,inplace=True)
# Rename the Target column to IsFail
df = df.rename(columns = {'Target': "IsFail"})
df.info()

Convertissez des colonnes spécifiques du jeu de données en nombres flottants ou entiers, selon les besoins, et mappez des chaînes ('L', 'M', 'H') en valeurs numériques (0, 1, 2) :

# Convert temperature, rotational speed, torque, and tool wear columns to float
df['Air_temperature_[K]'] = df['Air_temperature_[K]'].astype(float)
df['Process_temperature_[K]'] = df['Process_temperature_[K]'].astype(float)
df['Rotational_speed_[rpm]'] = df['Rotational_speed_[rpm]'].astype(float)
df['Torque_[Nm]'] = df['Torque_[Nm]'].astype(float)
df['Tool_wear_[min]'] = df['Tool_wear_[min]'].astype(float)

# Convert the 'Target' column to an integer 
df['IsFail'] = df['IsFail'].astype(int)
# Map 'L', 'M', 'H' to numerical values 
df['Type'] = df['Type'].map({'L': 0, 'M': 1, 'H': 2})

Explorer les données via des visualisations

# Import packages and set plotting style
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
sns.set_style('darkgrid')

# Create the correlation matrix
corr_matrix = df.corr(numeric_only=True)

# Plot a heatmap
plt.figure(figsize=(10, 8))
sns.heatmap(corr_matrix, annot=True)
plt.show()

Screenshot showing a plot of the correlation matrix of features.

Comme prévu, l’échec (IsFail) a une corrélation avec les fonctionnalités sélectionnées (colonnes). La matrice de corrélation montre que Air_temperature, Process_temperature, Rotational_speedTorque, et Tool_wear ont la corrélation la plus élevée avec la IsFail variable.

# Plot histograms of select features
fig, axes = plt.subplots(2, 3, figsize=(18,10))
columns = ['Air_temperature_[K]', 'Process_temperature_[K]', 'Rotational_speed_[rpm]', 'Torque_[Nm]', 'Tool_wear_[min]']
data=df.copy()
for ind, item in enumerate (columns):
    column = columns[ind]
    df_column = data[column]
    df_column.hist(ax = axes[ind%2][ind//2], bins=32).set_title(item)
fig.supylabel('count')
fig.subplots_adjust(hspace=0.2)
fig.delaxes(axes[1,2])

Screenshot showing a graph plot of the features.

Comme le montrent les graphiques tracés, les variables Air_temperature, Process_temperature, Rotational_speed, Torque, et Tool_wear ne sont pas éparses. Ils semblent avoir une bonne continuité dans l’espace de fonctionnalité. Ces graphiques confirment que l’entraînement d’un modèle Machine Learning sur cet ensemble de données produit probablement des résultats fiables qui peuvent se généraliser à un nouveau jeu de données.

Inspecter la variable cible pour rechercher un déséquilibre de classe

Comptez le nombre d’échantillons pour les machines qui ont échoué et celles qui n’ont pas échoué, et inspectez le bilan des données pour chaque classe (IsFail=0, IsFail=1) :

# Plot the counts for no failure and each failure type
plt.figure(figsize=(12, 2))
ax = sns.countplot(x='Failure_Type', data=df)
for p in ax.patches:
    ax.annotate(f'{p.get_height()}', (p.get_x()+0.4, p.get_height()+50))

plt.show()

# Plot the counts for no failure versus the sum of all failure types
plt.figure(figsize=(4, 2))
ax = sns.countplot(x='IsFail', data=df)
for p in ax.patches:
    ax.annotate(f'{p.get_height()}', (p.get_x()+0.4, p.get_height()+50))

plt.show()

Screenshot of a plot showing that samples are imbalanced.

Les graphiques indiquent que la classe sans échec (représentée par IsFail=0 dans le deuxième graphique) constitue la plupart des échantillons. Utilisez une technique de suréchantillonnage pour créer un jeu de données d’entraînement plus équilibré :

# Separate features and target
features = df[['Type', 'Air_temperature_[K]', 'Process_temperature_[K]', 'Rotational_speed_[rpm]', 'Torque_[Nm]', 'Tool_wear_[min]']]
labels = df['IsFail']

# Split the dataset into the training and testing sets
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(features, labels, test_size=0.2, random_state=42)

# Ignore warnings
import warnings
warnings.filterwarnings('ignore')
# Save test data to the lakehouse for use in future sections
table_name = "predictive_maintenance_test_data"
df_test_X = spark.createDataFrame(X_test)
df_test_X.write.mode("overwrite").format("delta").save(f"Tables/{table_name}")
print(f"Spark DataFrame saved to delta table: {table_name}")

Suréchantillonner pour équilibrer les classes dans le jeu de données d’entraînement

L’analyse précédente a montré que le jeu de données est fortement déséquilibré. Ce déséquilibre devient un problème, car la classe minoritaire a trop peu d’exemples pour que le modèle puisse apprendre efficacement la délimitation de décision.

SMOTE peut résoudre le problème. SMOTE est une technique de suréchantillonnage largement utilisée qui génère des exemples synthétiques. Il génère des exemples pour la classe minoritaire sur la base des distances euclidiennes entre les points de données. Cette méthode diffère du suréchantillonnage aléatoire, car elle crée de nouveaux exemples qui ne dupliquent pas simplement la classe minoritaire. La méthode devient une technique plus efficace pour gérer les jeux de données déséquilibrés.

# Disable MLflow autologging because you don't want to track SMOTE fitting
import mlflow

mlflow.autolog(disable=True)

from imblearn.combine import SMOTETomek
smt = SMOTETomek(random_state=SEED)
X_train_res, y_train_res = smt.fit_resample(X_train, y_train)

# Plot the counts for both classes
plt.figure(figsize=(4, 2))
ax = sns.countplot(x='IsFail', data=pd.DataFrame({'IsFail': y_train_res.values}))
for p in ax.patches:
    ax.annotate(f'{p.get_height()}', (p.get_x()+0.4, p.get_height()+50))

plt.show()

Screenshot of a plot showing that samples are balanced.

Vous avez correctement équilibré le jeu de données. Vous pouvez maintenant passer à la formation du modèle.

Étape 4 : former et évaluer les modèles

MLflow enregistre des modèles, les entraîne et les compare, puis choisit le meilleur modèle à des fins de prédiction. Vous pouvez utiliser les trois modèles suivants pour la formation au modèle :

  • Classification par forêts aléatoires
  • Classifieur de régression logistique
  • Classifieur XGBoost

Entraîner un classifieur de forêt aléatoire

import numpy as np 
from sklearn.ensemble import RandomForestClassifier
from mlflow.models.signature import infer_signature
from sklearn.metrics import f1_score, accuracy_score, recall_score

mlflow.set_experiment("Machine_Failure_Classification")
mlflow.autolog(exclusive=False) # This is needed to override the preconfigured autologging behavior

with mlflow.start_run() as run:
    rfc_id = run.info.run_id
    print(f"run_id {rfc_id}, status: {run.info.status}")
    rfc = RandomForestClassifier(max_depth=5, n_estimators=50)
    rfc.fit(X_train_res, y_train_res) 
    signature = infer_signature(X_train_res, y_train_res)

    mlflow.sklearn.log_model(
        rfc,
        "machine_failure_model_rf",
        signature=signature,
        registered_model_name="machine_failure_model_rf"
    ) 

    y_pred_train = rfc.predict(X_train)
    # Calculate the classification metrics for test data
    f1_train = f1_score(y_train, y_pred_train, average='weighted')
    accuracy_train = accuracy_score(y_train, y_pred_train)
    recall_train = recall_score(y_train, y_pred_train, average='weighted')

    # Log the classification metrics to MLflow
    mlflow.log_metric("f1_score_train", f1_train)
    mlflow.log_metric("accuracy_train", accuracy_train)
    mlflow.log_metric("recall_train", recall_train)

    # Print the run ID and the classification metrics
    print("F1 score_train:", f1_train)
    print("Accuracy_train:", accuracy_train)
    print("Recall_train:", recall_train)    

    y_pred_test = rfc.predict(X_test)
    # Calculate the classification metrics for test data
    f1_test = f1_score(y_test, y_pred_test, average='weighted')
    accuracy_test = accuracy_score(y_test, y_pred_test)
    recall_test = recall_score(y_test, y_pred_test, average='weighted')

    # Log the classification metrics to MLflow
    mlflow.log_metric("f1_score_test", f1_test)
    mlflow.log_metric("accuracy_test", accuracy_test)
    mlflow.log_metric("recall_test", recall_test)

    # Print the classification metrics
    print("F1 score_test:", f1_test)
    print("Accuracy_test:", accuracy_test)
    print("Recall_test:", recall_test)

D’après la sortie, les jeux de données d’entraînement et de test donnent un score F1, une précision et un rappel d’environ 0,9 lors de l’utilisation du classifieur de forêt aléatoire.

Entraîner un classifieur de régression logistique

from sklearn.linear_model import LogisticRegression

with mlflow.start_run() as run:
    lr_id = run.info.run_id
    print(f"run_id {lr_id}, status: {run.info.status}")
    lr = LogisticRegression(random_state=42)
    lr.fit(X_train_res, y_train_res)
    signature = infer_signature(X_train_res, y_train_res)
  
    mlflow.sklearn.log_model(
        lr,
        "machine_failure_model_lr",
        signature=signature,
        registered_model_name="machine_failure_model_lr"
    ) 

    y_pred_train = lr.predict(X_train)
    # Calculate the classification metrics for training data
    f1_train = f1_score(y_train, y_pred_train, average='weighted')
    accuracy_train = accuracy_score(y_train, y_pred_train)
    recall_train = recall_score(y_train, y_pred_train, average='weighted')

    # Log the classification metrics to MLflow
    mlflow.log_metric("f1_score_train", f1_train)
    mlflow.log_metric("accuracy_train", accuracy_train)
    mlflow.log_metric("recall_train", recall_train)

    # Print the run ID and the classification metrics
    print("F1 score_train:", f1_train)
    print("Accuracy_train:", accuracy_train)
    print("Recall_train:", recall_train)    

    y_pred_test = lr.predict(X_test)
    # Calculate the classification metrics for test data
    f1_test = f1_score(y_test, y_pred_test, average='weighted')
    accuracy_test = accuracy_score(y_test, y_pred_test)
    recall_test = recall_score(y_test, y_pred_test, average='weighted')

    # Log the classification metrics to MLflow
    mlflow.log_metric("f1_score_test", f1_test)
    mlflow.log_metric("accuracy_test", accuracy_test)
    mlflow.log_metric("recall_test", recall_test)

Entraîner un classifieur XGBoost

from xgboost import XGBClassifier

with mlflow.start_run() as run:
    xgb = XGBClassifier()
    xgb_id = run.info.run_id 
    print(f"run_id {xgb_id}, status: {run.info.status}")
    xgb.fit(X_train_res.to_numpy(), y_train_res.to_numpy()) 
    signature = infer_signature(X_train_res, y_train_res)
  
    mlflow.xgboost.log_model(
        xgb,
        "machine_failure_model_xgb",
        signature=signature,
        registered_model_name="machine_failure_model_xgb"
    ) 

    y_pred_train = xgb.predict(X_train)
    # Calculate the classification metrics for training data
    f1_train = f1_score(y_train, y_pred_train, average='weighted')
    accuracy_train = accuracy_score(y_train, y_pred_train)
    recall_train = recall_score(y_train, y_pred_train, average='weighted')

    # Log the classification metrics to MLflow
    mlflow.log_metric("f1_score_train", f1_train)
    mlflow.log_metric("accuracy_train", accuracy_train)
    mlflow.log_metric("recall_train", recall_train)

    # Print the run ID and the classification metrics
    print("F1 score_train:", f1_train)
    print("Accuracy_train:", accuracy_train)
    print("Recall_train:", recall_train)    

    y_pred_test = xgb.predict(X_test)
    # Calculate the classification metrics for test data
    f1_test = f1_score(y_test, y_pred_test, average='weighted')
    accuracy_test = accuracy_score(y_test, y_pred_test)
    recall_test = recall_score(y_test, y_pred_test, average='weighted')

    # Log the classification metrics to MLflow
    mlflow.log_metric("f1_score_test", f1_test)
    mlflow.log_metric("accuracy_test", accuracy_test)
    mlflow.log_metric("recall_test", recall_test)

Étape 5 : sélectionner le meilleur modèle et prévoir les sorties

Dans la section précédente, vous avez formé trois classifieurs différents : la forêt aléatoire, la régression logistique et XGBoost. Vous avez maintenant le choix entre un accès programmatique aux résultats ou l’utilisation de l’interface utilisateur (IU).

Pour l’option chemin d’accès à l’UI, naviguez dans votre espace de travail et filtrez les modèles.

Screenshot of the filter, with models selected.

Sélectionnez des modèles individuels pour plus d’informations sur les performances du modèle.

Screenshot of performance details for models.

Cet exemple montre comment accéder de manière programmatique aux modèles via MLflow :

runs = {'random forest classifier':   rfc_id,
        'logistic regression classifier': lr_id,
        'xgboost classifier': xgb_id}

# Create an empty DataFrame to hold the metrics
df_metrics = pd.DataFrame()

# Loop through the run IDs and retrieve the metrics for each run
for run_name, run_id in runs.items():
    metrics = mlflow.get_run(run_id).data.metrics
    metrics["run_name"] = run_name
    df_metrics = df_metrics.append(metrics, ignore_index=True)

# Print the DataFrame
print(df_metrics)

Bien que XGBoost produise les meilleurs résultats sur le jeu d’apprentissage, ses performances sont médiocres sur le jeu de données de test. Cette mauvaise performance indique un surajustement. Le classifieur de régression logistique donne de mauvais résultats sur les jeux de données d’entraînement et de test. Dans l’ensemble, la forêt aléatoire offre un bon équilibre entre les performances de formation et la prévention du surajustement.

Dans la section suivante, choisissez le modèle de forêt aléatoire enregistré et effectuez une prédiction à l’aide de la fonctionnalité PREDICT :

from synapse.ml.predict import MLFlowTransformer

model = MLFlowTransformer(
    inputCols=list(X_test.columns),
    outputCol='predictions',
    modelName='machine_failure_model_rf',
    modelVersion=1
)

Avec l’objet MLFlowTransformer que vous avez créé pour charger le modèle à des fins d’inférence, utilisez l’API Transformer pour noter le modèle sur le jeu de données de test :

predictions = model.transform(spark.createDataFrame(X_test))
predictions.show()

Ce tableau présente la sortie :

Type Air_temperature_[K] Process_temperature_[K] Rotational_speed_[rpm] Torque_[Nm] Tool_wear_[min] les prédictions
0 300.6 309.7 1639,0 30,4 121.0 0
0 303.9 313.0 1551.0 36.8 140.0 0
1 299.1 308.6 1491.0 38.5 166 0
0 300.9 312.1 1359.0 51.7 146.0 1
0 303.7 312.6 1621.0 38,8 182.0 0
0 299.0 310.3 1868.0 24.0 221.0 1
2 297.8 307.5 1631,0 31.3 124.0 0
0 297.5 308.2 1327.0 56,5 189.0 1
0 301.3 310.3 1460.0 41,5 197.0 0
2 297.6 309.0 1413.0 40.2 51,0 0
1 300.9 309.4 1724.0 25,6 119.0 0
0 303.3 311.3 1389.0 53.9 39.0 0
0 298.4 307.9 1981.0 23,2 16,0 0
0 299,3 308.8 1636.0 29,9 201.0 0
1 298.1 309.2 1460.0 45,8 80,0 0
0 300.0 309.5 1728.0 26,0 37,0 0
2 299.0 308.7 1940.0 19.9 98.0 0
0 302.2 310.8 1383.0 46.9 45.0 0
0 300.2 309.2 1431,0 51.3 57,0 0
0 299.6 310.2 1468,0 48,0 9.0 0

Sauvegardez les données dans le lakehouse. Les données sont ensuite disponibles pour les utilisations ultérieures, par exemple un tableau de bord Power BI.

# Save test data to the lakehouse for use in the next section. 
table_name = "predictive_maintenance_test_with_predictions"
predictions.write.mode("overwrite").format("delta").save(f"Tables/{table_name}")
print(f"Spark DataFrame saved to delta table: {table_name}")

Étape 6 : visualiser les informations commerciales via des visualisations dans Power BI

Affichez les résultats dans un format hors connexion, avec un tableau de bord Power BI.

Screenshot of the data displayed as a Power BI dashboard.

Le tableau de bord montre que Tool_wear et Torque créent une frontière visible entre les cas d’échec et de non échec, comme prévu par l’analyse de corrélation de l’étape 2.