Partilhar via


Tutorial: criar, avaliar e pontuar um modelo de deteção de falhas de máquina

Este tutorial apresenta um exemplo completo de um fluxo de trabalho Synapse Data Science no Microsoft Fabric. O cenário usa o aprendizado de máquina para uma abordagem mais sistemática ao diagnóstico de falhas, para identificar problemas proativamente e tomar ações antes de uma falha real da máquina. O objetivo é prever se uma máquina sofreria uma falha com base na temperatura do processo, velocidade de rotação, etc.

Este tutorial aborda estas etapas:

  • Instalar bibliotecas personalizadas
  • Carregar e processar os dados
  • Compreender os dados através da análise exploratória de dados
  • Use scikit-learn, LightGBM e MLflow para treinar modelos de aprendizado de máquina e use o recurso Fabric Autologging para rastrear experimentos
  • Marque os modelos treinados com o recurso Malha PREDICT , salve o melhor modelo e carregue esse modelo para previsões
  • Mostrar o desempenho do modelo carregado com visualizações do Power BI

Pré-requisitos

  • Obtenha uma assinatura do Microsoft Fabric. Ou inscreva-se para uma avaliação gratuita do Microsoft Fabric.

  • Entre no Microsoft Fabric.

  • Use o seletor de experiência no lado esquerdo da sua página inicial para alternar para a experiência Synapse Data Science.

    Screenshot of the experience switcher menu, showing where to select Data Science.

Acompanhe num caderno

Você pode escolher uma destas opções para acompanhar em um bloco de anotações:

  • Abra e execute o bloco de anotações integrado na experiência de Ciência de Dados
  • Carregue seu bloco de anotações do GitHub para a experiência de Ciência de Dados

Abra o bloco de notas incorporado

O bloco de anotações de falha de máquina de exemplo acompanha este tutorial.

Para abrir o bloco de anotações de exemplo integrado do tutorial na experiência Synapse Data Science:

  1. Vá para a página inicial do Synapse Data Science.

  2. Selecione Usar uma amostra.

  3. Selecione a amostra correspondente:

    • Na guia padrão End-to-end workflows (Python), se o exemplo for para um tutorial do Python.
    • Na guia Fluxos de trabalho de ponta a ponta (R), se o exemplo for para um tutorial R.
    • Na guia Tutoriais rápidos, se o exemplo for para um tutorial rápido.
  4. Anexe um lakehouse ao bloco de anotações antes de começar a executar o código.

Importar o bloco de anotações do GitHub

O notebook AISample - Manutenção Preditiva acompanha este tutorial.

Para abrir o bloco de anotações que acompanha este tutorial, siga as instruções em Preparar seu sistema para tutoriais de ciência de dados, para importar o bloco de anotações para seu espaço de trabalho.

Se preferir copiar e colar o código desta página, pode criar um novo bloco de notas.

Certifique-se de anexar um lakehouse ao bloco de anotações antes de começar a executar o código.

Etapa 1: Instalar bibliotecas personalizadas

Para desenvolvimento de modelo de aprendizado de máquina ou análise de dados ad-hoc, talvez seja necessário instalar rapidamente uma biblioteca personalizada para sua sessão do Apache Spark. Você tem duas opções para instalar bibliotecas.

  • Utilize as capacidades de instalação em linha (%pip ou %conda) do seu bloco de notas para instalar uma biblioteca, apenas no seu bloco de notas atual.
  • Como alternativa, você pode criar um ambiente de malha, instalar bibliotecas de fontes públicas ou carregar bibliotecas personalizadas para ele e, em seguida, o administrador do espaço de trabalho pode anexar o ambiente como padrão para o espaço de trabalho. Todas as bibliotecas no ambiente ficarão disponíveis para uso em quaisquer blocos de anotações e definições de trabalho do Spark no espaço de trabalho. Para obter mais informações sobre ambientes, consulte criar, configurar e usar um ambiente no Microsoft Fabric.

Para este tutorial, use %pip install para instalar a imblearn biblioteca em seu bloco de anotações.

Nota

O kernel do PySpark é reiniciado após %pip install as execuções. Instale as bibliotecas necessárias antes de executar quaisquer outras células.

# Use pip to install imblearn
%pip install imblearn

Passo 2: Carregue os dados

O conjunto de dados simula o registro dos parâmetros de uma máquina de fabricação em função do tempo, o que é comum em ambientes industriais. Ele consiste em 10.000 pontos de dados armazenados como linhas com recursos como colunas. As funcionalidades incluem:

  • Um identificador único (UID) que varia de 1 a 10000

  • ID do produto, que consiste em uma letra L (para baixo), M (para médio) ou H (para alto), para indicar a variante de qualidade do produto, e um número de série específico da variante. Variantes de baixa, média e alta qualidade representam 60%, 30% e 10% de todos os produtos, respectivamente

  • Temperatura do ar, em graus Kelvin (K)

  • Temperatura de processo, em graus Kelvin

  • Velocidade de rotação, em rotações por minuto (RPM)

  • Torque, em Newton-Metros (Nm)

  • Desgaste da ferramenta, em minutos. As variantes de qualidade H, M e L adicionam 5, 3 e 2 minutos de desgaste da ferramenta, respectivamente, à ferramenta usada no processo

  • Um rótulo de falha da máquina, para indicar se a máquina falhou no ponto de dados específico. Este ponto de dados específico pode ter qualquer um dos seguintes cinco modos de falha independentes:

    • Falha de desgaste da ferramenta (TWF): a ferramenta é substituída ou falha em um tempo de desgaste da ferramenta selecionado aleatoriamente, entre 200 e 240 minutos
    • Falha de dissipação de calor (HDF): a dissipação de calor causa uma falha no processo se a diferença entre a temperatura do ar e a temperatura do processo for inferior a 8,6 K e a velocidade de rotação da ferramenta for inferior a 1380 RPM
    • Falha de energia (PWF): o produto do torque e da velocidade de rotação (em rad/s) é igual à potência necessária para o processo. O processo falha se essa potência cair abaixo de 3.500 W ou exceder 9.000 W
    • OverStrain Failure (OSF): se o produto do desgaste e torque da ferramenta exceder 11.000 Nm mínimo para a variante de produto L (12.000 para M, 13.000 para H), o processo falhará devido a sobretensão
    • Falhas Aleatórias (RNF): cada processo tem uma chance de falha de 0,1%, independentemente dos parâmetros do processo

Nota

Se pelo menos um dos modos de falha acima for verdadeiro, o processo falhará e o rótulo "falha da máquina" será definido como 1. O método de aprendizado de máquina não pode determinar qual modo de falha causou a falha do processo.

Faça o download do conjunto de dados e faça o upload para a casa do lago

Conecte-se ao contêiner de Conjuntos de Dados Abertos do Azure e carregue o conjunto de dados de Manutenção Preditiva. Esse código baixa uma versão disponível publicamente do conjunto de dados e, em seguida, armazena-o em um lago de malha:

Importante

Adicione uma casa de lago ao bloco de anotações antes de executá-lo. Caso contrário, você receberá um erro. Para obter informações sobre como adicionar uma casa de lago, consulte Conectar casas de lago e blocos de anotações.

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

Depois de baixar o conjunto de dados na lakehouse, você pode carregá-lo como um Spark DataFrame:

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

Esta tabela mostra uma visualização dos dados:

IUD ID do Produto Type Temperatura do ar [K] Temperatura de processo [K] Velocidade de rotação [rpm] Binário [Nm] Desgaste da ferramenta [min] Destino Tipo de falha
5 M14860 Seg 298.1 308.6 1551 42.8 0 0 Sem falha
2 L47181 L 298.2 308.7 1408 46.3 3 0 Sem falha
3 L47182 L 298.1 308.5 1498 49.4 5 0 Sem falha
4 L47183 L 298.2 308.6 1433 39.5 7 0 Sem falha
5 L47184 L 298.2 308.7 1408 40,0 9 0 Sem falha

Escrever um DataFrame do Spark em uma tabela delta lakehouse

Formate os dados (por exemplo, substitua os espaços por sublinhados) para facilitar as operações do Spark nas etapas subsequentes:

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

Esta tabela mostra uma visualização dos dados com nomes de colunas reformatados:

IUD Product_ID Type Air_temperature_[K] Process_temperature_[K] Rotational_speed_[rpm] Torque_[Nm] Tool_wear_[min] Destino Failure_Type
5 M14860 Seg 298.1 308.6 1551 42.8 0 0 Sem falha
2 L47181 L 298.2 308.7 1408 46.3 3 0 Sem falha
3 L47182 L 298.1 308.5 1498 49.4 5 0 Sem falha
4 L47183 L 298.2 308.6 1433 39.5 7 0 Sem falha
5 L47184 L 298.2 308.7 1408 40,0 9 0 Sem falha
# 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}")

Etapa 3: Pré-processar dados e realizar análise exploratória de dados

Converta o Spark DataFrame em um Pandas DataFrame, para usar bibliotecas de plotagem populares compatíveis com Pandas.

Gorjeta

Para um conjunto de dados grande, talvez seja necessário carregar uma parte desse conjunto de dados.

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

Converta colunas específicas do conjunto de dados em flutuações ou tipos inteiros, conforme necessário, e mapeie cadeias de caracteres (, , ) em valores numéricos ('L'0, 'M'1, 'H'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})

Explore dados através de visualizações

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

Como esperado, a falha () se correlaciona com os recursos selecionados (IsFailcolunas). A matriz de correlação mostra que Air_temperature, , , Process_temperature, Rotational_speedTorquee Tool_wear têm a maior correlação com a IsFail variável.

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

Como mostram os gráficos plotados, as Air_temperaturevariáveis , , , Torque, Process_temperatureRotational_speede Tool_wear não são esparsas. Eles parecem ter uma boa continuidade no espaço de recursos. Esses gráficos confirmam que o treinamento de um modelo de aprendizado de máquina nesse conjunto de dados provavelmente produz resultados confiáveis que podem ser generalizados para um novo conjunto de dados.

Inspecionar a variável de destino em busca de desequilíbrio de classe

Conte o número de amostras para máquinas com e sem falha e inspecione o balanço de dados para cada 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.

Os gráficos indicam que a classe sem falha (mostrada como IsFail=0 no segundo gráfico) constitui a maioria das amostras. Use uma técnica de sobreamostragem para criar um conjunto de dados de treinamento mais equilibrado:

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

Amostra excessiva para equilibrar classes no conjunto de dados de treinamento

A análise anterior mostrou que o conjunto de dados é altamente desequilibrado. Esse desequilíbrio torna-se um problema, porque a classe minoritária tem poucos exemplos para que o modelo aprenda efetivamente o limite da decisão.

SMOTE pode resolver o problema. SMOTE é uma técnica de sobreamostragem amplamente utilizada que gera exemplos sintéticos. Gera exemplos para a classe minoritária com base nas distâncias euclidianas entre pontos de dados. Este método difere da sobreamostragem aleatória, porque cria novos exemplos que não apenas duplicam a classe minoritária. O método torna-se uma técnica mais eficaz para lidar com conjuntos de dados desequilibrados.

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

Você equilibrou com êxito o conjunto de dados. Agora você pode passar para o treinamento modelo.

Passo 4: Treinar e avaliar os modelos

O MLflow regista modelos, treina e compara vários modelos e escolhe o melhor modelo para efeitos de previsão. Você pode usar os três modelos a seguir para treinamento de modelo:

  • Classificador de floresta aleatório
  • Classificador de regressão logística
  • Classificador XGBoost

Treinar um classificador de floresta aleatório

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)

A partir da saída, os conjuntos de dados de treinamento e teste produzem uma pontuação F1, precisão e recordação de cerca de 0,9 ao usar o classificador de floresta aleatório.

Treinar um classificador de regressão logística

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)

Treinar um classificador 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)

Passo 5: Selecione o melhor modelo e preveja as saídas

Na seção anterior, você treinou três classificadores diferentes: floresta aleatória, regressão logística e XGBoost. Agora você tem a opção de acessar programaticamente os resultados ou usar a interface do usuário (UI).

Para a opção de caminho da interface do usuário, navegue até o espaço de trabalho e filtre os modelos.

Screenshot of the filter, with models selected.

Selecione modelos individuais para obter detalhes sobre o desempenho do modelo.

Screenshot of performance details for models.

Este exemplo mostra como acessar programaticamente os modelos por meio do 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)

Embora o XGBoost produza os melhores resultados no conjunto de treinamento, ele tem um desempenho ruim no conjunto de dados de teste. Esse fraco desempenho indica sobreajuste. O classificador de regressão logística tem um desempenho fraco em conjuntos de dados de treinamento e teste. No geral, a floresta aleatória atinge um bom equilíbrio entre o desempenho do treinamento e evitar o overfitting.

Na próxima seção, escolha o modelo de floresta aleatória registrada e execute uma previsão com o recurso PREDICT :

from synapse.ml.predict import MLFlowTransformer

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

Com o objeto criado para carregar o modelo para inferência, use a API do Transformer para pontuar o MLFlowTransformer modelo no conjunto de dados de teste:

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

Esta tabela mostra a saída:

Type Air_temperature_[K] Process_temperature_[K] Rotational_speed_[rpm] Torque_[Nm] Tool_wear_[min] previsões
0 300.6 309.7 1639,0 30,4 121.0 0
0 303.9 313.0 1551.0 36,8 140.0 0
5 299.1 308.6 1491.0 38.5 166.0 0
0 300.9 312.1 1359.0 51.7 146.0 5
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 5
0 301.3 310.3 1460.0 41.5 197.0 0
2 297.6 309.0 1413.0 40.2 51,0 0
5 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
5 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

Salve os dados na casa do lago. Em seguida, os dados ficam disponíveis para usos posteriores - por exemplo, um painel do 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}")

Etapa 6: Exibir business intelligence por meio de visualizações no Power BI

Mostrar os resultados em um formato offline, com um painel do Power BI.

Screenshot of the data displayed as a Power BI dashboard.

O painel mostra isso Tool_wear e cria um limite percetível entre casos com e Torque sem falha, conforme esperado da análise de correlação anterior na etapa 2.