Delen via


Zelfstudie: een machinefoutdetectiemodel maken, evalueren en beoordelen

In deze handleiding vindt u een end-to-end voorbeeld van een Synapse Data Science-werkstroom in Microsoft Fabric. In het scenario wordt machine learning gebruikt voor een systematischere benadering van foutdiagnose, om proactief problemen te identificeren en acties uit te voeren voordat een machinefout daadwerkelijk mislukt. Het doel is om te voorspellen of een machine een storing ondervindt op basis van procestemperatuur, rotatiesnelheid, enzovoort.

In deze zelfstudie worden de volgende stappen behandeld:

  • Aangepaste bibliotheken installeren
  • De gegevens laden en verwerken
  • Inzicht in de gegevens via experimentele gegevensanalyse
  • Gebruik scikit-learn, LightGBM en MLflow om machine learning-modellen te trainen en gebruik de functie Autologging van infrastructuur om experimenten bij te houden
  • Score de getrainde modellen met de functie Fabric PREDICT, sla het beste model op en laad dat model voor voorspellingen
  • De prestaties van het geladen model weergeven met Power BI-visualisaties

Voorwaarden

Volg mee in een notitieboekje

U kunt een van deze opties kiezen om te volgen in een notitieblok.

  • Open het ingebouwde notebook en voer het uit.
  • Upload uw notebook vanuit GitHub.

Het ingebouwde notebook openen

Het notitieboek met voorbeeldexemplaar machinefout hoort bij deze zelfstudie.

  1. Als u het voorbeeldnotitieblok voor deze zelfstudie wilt openen, volgt u de instructies in Uw systeem voorbereiden op zelfstudies voor gegevenswetenschap.

  2. Zorg ervoor dat u een lakehouse koppelt aan het notebook voordat u begint code uit te voeren.

Het notebook importeren vanuit GitHub

De AISample - Predictive Maintenance notebook begeleidt deze zelfstudie.

Stap 1: Aangepaste bibliotheken installeren

Voor het ontwikkelen van machine learning-modellen of ad-hocgegevensanalyse moet u mogelijk snel een aangepaste bibliotheek voor uw Apache Spark-sessie installeren. U hebt twee opties om bibliotheken te installeren.

  • Gebruik de inline-installatiemogelijkheden (%pip of %conda) van uw notitieblok om alleen een bibliotheek in uw huidige notitieblok te installeren.
  • U kunt ook een Fabric-omgeving maken, bibliotheken installeren uit openbare bronnen of aangepaste bibliotheken ernaar uploaden. Vervolgens kan uw werkruimtebeheerder de omgeving als standaard voor de werkruimte koppelen. Alle bibliotheken in de omgeving zijn vervolgens beschikbaar voor gebruik in notebooks en Spark-taakdefinities in de werkruimte. Zie een omgeving maken, configureren en gebruiken in Microsoft Fabricvoor meer informatie over omgevingen.

Voor deze zelfstudie gebruikt u %pip install om de imblearn-bibliotheek in uw notebook te installeren.

Notitie

De PySpark-kernel wordt opnieuw opgestart nadat %pip install wordt uitgevoerd. Installeer de benodigde bibliotheken voordat u andere cellen uitvoert.

# Use pip to install imblearn
%pip install imblearn

Stap 2: de gegevens laden

De gegevensset simuleert logboekregistratie van parameters van een productiemachine als een functie van tijd, wat gebruikelijk is in industriële instellingen. Het bestaat uit 10.000 gegevenspunten die zijn opgeslagen als rijen met functies als kolommen. De functies zijn onder andere:

  • Een unieke id (UID) die varieert van 1 tot 10000

  • Product-id, bestaande uit een letter L (voor laag), M (gemiddeld) of H (voor hoog), om de variant van de productkwaliteit en een specifiek serienummer aan te geven. Lage, gemiddelde en hoogwaardige varianten vormen respectievelijk 60%, 30%en 10% van alle producten

  • Luchttemperatuur, in graden Kelvin (K)

  • Procestemperatuur, in graden Kelvin

  • Rotatiesnelheid, in revoluties per minuut (RPM)

  • Koppel, in Newton-Meters (Nm)

  • Gereedschap slijtage, in minuten. De kwaliteitsvarianten H, M en L voegen respectievelijk 5, 3 en 2 minuten aan slijtage toe aan het gereedschap dat in het proces wordt gebruikt

  • Een machinefoutlabel om aan te geven of de machine is mislukt in het specifieke gegevenspunt. Dit specifieke gegevenspunt kan een van de volgende vijf onafhankelijke foutmodi hebben:

    • Tool Wear Failure (TWF): het gereedschap wordt vervangen of mislukt in een willekeurig geselecteerde slijtagetijd van het gereedschap, tussen 200 en 240 minuten
    • Heat Dissipation Failure (HDF): warmtedissipatie veroorzaakt een procesfout als het verschil tussen de luchttemperatuur en de procestemperatuur kleiner is dan 8,6 K en de draaisnelheid van het gereedschap kleiner is dan 1380 RPM
    • Stroomstoring (PWF): het product van koppel- en rotatiesnelheid (in rad/s) is gelijk aan het vermogen dat nodig is voor het proces. Het proces mislukt als deze macht lager is dan 3500 W of groter is dan 9.000 W
    • OverStrain Failure (OSF): als het product van slijtage en koppel van gereedschap hoger is dan 11.000 Minimum Nm voor de L-productvariant (12.000 voor M, 13.000 voor H), mislukt het proces vanwege overstrain
    • Willekeurige fouten (RNF): elk proces heeft een foutkans van 0,1%, ongeacht de procesparameters

Notitie

Als ten minste één van de bovenstaande foutmodi waar is, mislukt het proces en wordt het label 'machinefout' ingesteld op 1. De machine learning-methode kan niet bepalen welke foutmodus de procesfout heeft veroorzaakt.

De gegevensset downloaden en uploaden naar het lakehouse

Maak verbinding met de Azure Open Datasets-container en laad de gegevensset Predictief onderhoud. Met deze code wordt een openbaar beschikbare versie van de gegevensset gedownload en vervolgens opgeslagen in een Fabric Lakehouse:

Belangrijk

Voeg een lakehouse aan het notebook toe voordat je het uitvoert. Anders krijgt u een foutmelding. Zie Connect lakehouses en notebooksvoor meer informatie over het toevoegen van een lakehouse.

# 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.")

Nadat u de gegevensset in lakehouse hebt gedownload, kunt u deze laden als een Spark DataFrame:

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

In deze tabel ziet u een voorbeeld van de gegevens:

UDI product-ID Type Luchttemperatuur [K] Procestemperatuur [K] Draaisnelheid [rpm] Koppel [Nm] Slijtage van gereedschap [min] Doel Fouttype
1 M14860 M 298.1 308.6 1551 42.8 0 0 Geen fout
2 L47181 L 298.2 308.7 1408 46.3 3 0 Geen fout
3 L47182 L 298.1 308.5 1498 49.4 5 0 Geen fout
4 L47183 L 298.2 308.6 1433 39.5 7 0 Geen fout
5 L47184 L 298.2 308.7 1408 40.0 9 0 Geen fout

Een Spark DataFrame schrijven naar een Lakehouse Delta-tabel

Maak de gegevens op (vervang bijvoorbeeld de spaties door onderstrepingstekens) om Spark-bewerkingen in de volgende stappen te vergemakkelijken:

# 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)

In deze tabel ziet u een voorbeeld van de gegevens met opnieuw opgemaakte kolomnamen:

UDI Product_ID Type Luchttemperatuur_[K] Proces_temperatuur_[K] Rotatiesnelheid_[rpm] Torque_[Nm] Gereedschapslijtage_[min] Doel Faalt_type
1 M14860 M 298.1 308.6 1551 42.8 0 0 Geen fout
2 L47181 L 298.2 308.7 1408 46.3 3 0 Geen fout
3 L47182 L 298.1 308,5 1498 49.4 5 0 Geen fout
4 L47183 L 298,2 308,6 1433 39.5 7 0 Geen fout
5 L47184 L 298.2 308.7 1408 40.0 9 0 Geen fout
# 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}")

Stap 3: Gegevens vooraf verwerken en verkennende gegevensanalyse uitvoeren

Converteer het Spark DataFrame naar een Pandas DataFrame om populaire plottingbibliotheken te gebruiken die compatibel zijn met Pandas.

Fooi

Voor een grote gegevensset moet u mogelijk een deel van die gegevensset laden.

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()

Converteer specifieke kolommen van de gegevensset naar floats of gehele getallen naar behoefte en wijs tekenreeksen ('L', 'M', 'H') toe aan numerieke waarden (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})

Gegevens verkennen via visualisaties

# 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()

Schermopname van een plot van de correlatiematrix met functies.

Zoals verwacht, correleert fout (IsFail) met de geselecteerde functies (kolommen). De correlatiematrix laat zien dat Air_temperature, Process_temperature, Rotational_speed, Torqueen Tool_wear de hoogste correlatie hebben met de IsFail variabele.

# 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])

Schermopname van een grafiekdiagram van de functies.

Zoals de weergegeven grafieken tonen, zijn de variabelen Air_temperature, Process_temperature, Rotational_speed, Torqueen Tool_wear niet schaars. Ze lijken goede continuïteit te hebben in de functieruimte. Deze plots bevestigen dat het trainen van een machine learning-model op deze gegevensset waarschijnlijk betrouwbare resultaten produceert die kunnen generaliseren naar een nieuwe gegevensset.

De doelvariabele controleren op onevenwichtigheden in klassen

Tel het aantal steekproeven voor mislukte en niet-gefaileerde machines en inspecteer de gegevensbalans voor elke klasse (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()

Schermopname van een plot die laat zien dat steekproeven ongelijk verdeeld zijn.

De plots geven aan dat de klasse no-failure (weergegeven als IsFail=0 in de tweede plot) de meeste steekproeven vormt. Gebruik een oversampling-techniek om een meer evenwichtige trainingsgegevensset te maken:

# 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}")

Oversample om klassen in de trainingsdataset in balans te brengen

Uit de vorige analyse bleek dat de gegevensset zeer onevenwichtig is. Deze onevenwichtigheid wordt een probleem, omdat de minderheidsklasse te weinig voorbeelden heeft voor het model om effectief de beslissingsgrens te leren.

SMOTE- kan het probleem oplossen. SMOTE is een veelgebruikte oversampling techniek die synthetische voorbeelden genereert. Er worden voorbeelden gegenereerd voor de minderheidsklasse op basis van de Euclidische afstanden tussen gegevenspunten. Deze methode verschilt van willekeurige oversampling, omdat er nieuwe voorbeelden worden gemaakt die niet alleen de minderheidsklasse dupliceren. De methode wordt een effectievere techniek voor het afhandelen van onevenwichtige gegevenssets.

# 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()

Schermopname van een plot waarin wordt aangegeven dat de steekproeven evenwichtig zijn.

U hebt de gegevensset succesvol gebalanceerd. U kunt nu overstappen op modeltraining.

Stap 4: De modellen trainen en evalueren

MLflow- registreert modellen, traint en vergelijkt verschillende modellen en kiest het beste model voor voorspellingsdoeleinden. U kunt de volgende drie modellen gebruiken voor modeltraining:

  • Willekeurige forestclassificatie
  • Logistieke regressieclassificatie
  • XGBoost-classificeerder

Een willekeurige forestclassificatie trainen

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)

Uit de uitvoer leveren zowel de trainings- als de testgegevenssets een F1-score, nauwkeurigheid en herinnering op van ongeveer 0,9 bij het gebruik van de random forest-classificator.

Een logistieke regressieclassificatie trainen

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)

Een XGBoost-classificatie trainen

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)

Stap 5: Het beste model selecteren en uitvoer voorspellen

In de vorige sectie hebt u drie verschillende classificaties getraind: willekeurige forests, logistieke regressie en XGBoost. U hebt nu de keuze om programmatisch toegang te krijgen tot de resultaten of om de gebruikersinterface (UI) te gebruiken.

Voor de optie het UI-pad navigeert u naar uw werkruimte en filtert u de modellen.

Schermopname van het filter, met modellen geselecteerd.

Selecteer afzonderlijke modellen voor meer informatie over de modelprestaties.

Schermopname van prestatiedetails voor modellen.

In dit voorbeeld ziet u hoe u programmatisch toegang kunt krijgen tot de modellen 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)

Hoewel XGBoost de beste resultaten oplevert voor de trainingsset, presteert het slecht op de testgegevensset. Die slechte prestaties duiden op overfitting. De logistieke regressieclassificatie presteert slecht op zowel trainings- als testgegevenssets. Over het algemeen zorgt een random forest voor een goede balans tussen prestaties tijdens training en het voorkomen van overfitting.

Kies in de volgende sectie het geregistreerde willekeurige forestmodel en voer een voorspelling uit met de functie PREDICT:

from synapse.ml.predict import MLFlowTransformer

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

Met het MLFlowTransformer-object dat u hebt gemaakt om het model te laden voor deductie, gebruikt u de Transformer-API om het model te scoren op de testgegevensset:

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

In deze tabel ziet u de uitvoer:

Soort Luchttemperatuur_[K] Proces_temperatuur_[K] Rotatiesnelheid_[rpm] Torque_[Nm] Gereedschapsslijtage_[min] Voorspellingen
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
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

Sla de gegevens op in het lakehouse. De gegevens zijn vervolgens beschikbaar voor later gebruik, bijvoorbeeld een Power BI-dashboard.

# 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}")

Stap 6: Business Intelligence weergeven via visualisaties in Power BI

De resultaten weergeven in een offline-indeling, met een Power BI-dashboard.

Schermopname van de gegevens die worden weergegeven als een Power BI-dashboard.

Het dashboard laat zien dat Tool_wear en Torque een merkbare grens creëren tussen mislukte en niet-uitgevoerde gevallen, zoals verwacht uit de eerdere correlatieanalyse in stap 2.