Tutorial: Creación, evaluación y puntuación de un modelo de detección de errores de máquina
En este tutorial se presenta un ejemplo completo de un flujo de trabajo de ciencia de datos de Synapse en Microsoft Fabric. El escenario usa el aprendizaje automático para un enfoque más sistemático para el diagnóstico de errores, para identificar de forma proactiva los problemas y realizar acciones antes de un error de máquina real. El objetivo es predecir si una máquina experimentaría un error en función de la temperatura del proceso, la velocidad de rotación, etc.
En este tutorial se describen estos pasos:
- Instalación de bibliotecas personalizadas
- Carga y procesamiento de los datos
- Entender los datos a través del análisis exploratorio de datos
- Use scikit-learn, LightGBM y MLflow para entrenar modelos de aprendizaje automático y use la característica De registro automático de Fabric para realizar un seguimiento de los experimentos.
- Puntuar los modelos entrenados utilizando la característica Fabric
PREDICT
, guardar el mejor modelo y cargarlo para realizar predicciones. - Mostrar el rendimiento del modelo cargado con visualizaciones de Power BI
Prerrequisitos
Obtenga una suscripción a Microsoft Fabric. También puede registrarse para obtener una evaluación gratuita de Microsoft Fabric.
Inicie sesión en Microsoft Fabric.
Use el conmutador de experiencia en la parte inferior izquierda de la página principal para cambiar a Fabric.
- Si es necesario, cree un almacén de lago de datos de Microsoft Fabric como se describe en Creación de un almacén de lago de datos en Microsoft Fabric.
Sigue el progreso en un cuaderno
Puede elegir una de estas opciones para seguir en un cuaderno:
- Abra y ejecute el cuaderno integrado.
- Cargue el cuaderno desde GitHub.
Abra el cuaderno integrado.
Errores de máquina es el cuaderno de muestra que acompaña a este tutorial.
Para abrir el cuaderno de ejemplo de este tutorial, siga las instrucciones de Preparar el sistema para tutoriales de ciencia de datos.
Asegúrese de adjuntar un almacén de lago de datos al cuaderno antes de empezar a ejecutar el código.
Importación del cuaderno desde GitHub
El cuaderno AISample - Predictive Maintenance acompaña a este tutorial.
Para abrir el cuaderno complementario de este tutorial, siga las instrucciones de Preparación del sistema para los tutoriales de ciencia de datos a fin de importar el cuaderno a su área de trabajo.
Si prefiere copiar y pegar el código de esta página, puede crear un cuaderno nuevo.
Asegúrese de adjuntar una instancia de lakehouse al cuaderno antes de empezar a ejecutar código.
Paso 1: Instalación de bibliotecas personalizadas
Para el desarrollo de modelos de Machine Learning o el análisis de datos ad hoc, es posible que tenga que instalar rápidamente una biblioteca personalizada para la sesión de Apache Spark. Tiene dos opciones para instalar bibliotecas.
- Use las funcionalidades de instalación en línea (
%pip
o%conda
) del cuaderno para instalar una biblioteca, solo en el cuaderno actual. - Como alternativa, puede crear un entorno de Fabric, instalar bibliotecas desde orígenes públicos o cargar bibliotecas personalizadas en él y, a continuación, el administrador del área de trabajo puede asociar el entorno como valor predeterminado para el área de trabajo. Todas las bibliotecas del entorno estarán disponibles para su uso en los cuadernos y las definiciones de tareas de Spark en el área de trabajo. Para obtener más información sobre los entornos, consulte crear, configurar y usar un entorno en Microsoft Fabric.
Para este tutorial, use %pip install
para instalar la biblioteca imblearn
en su notebook.
Nota
El kernel de PySpark se reinicia después de que se ejecute %pip install
. Instale las bibliotecas necesarias antes de ejecutar cualquier otra celda.
# Use pip to install imblearn
%pip install imblearn
Paso 2: Cargar los datos
El conjunto de datos simula el registro de los parámetros de una máquina de fabricación como función del tiempo, que es común en la configuración industrial. Consta de 10 000 puntos de datos almacenados como filas con características como columnas. Las características incluyen:
Identificador único (UID) que va de 1 a 10000
Id. de producto, que consta de una letra L (para bajo), M (para medio) o H (para alto), para indicar la variante de calidad del producto y un número de serie específico de variante. Variantes de baja, media y alta calidad constituyen 60%, 30%y 10% de todos los productos, respectivamente
Temperatura del aire, en grados Kelvin (K)
Temperatura del proceso, en grados Kelvin
Velocidad rotacional, en revoluciónes por minuto (RPM)
Torque, en Newton-Meters (Nm)
Desgaste de herramientas, en minutos. Las variantes de calidad H, M y L agregan 5, 3 y 2 minutos de desgaste de herramienta respectivamente a la herramienta utilizada en el proceso
Etiqueta de error de la máquina, para indicar si la máquina produjo un error en el punto de datos específico. Este punto de datos específico puede tener cualquiera de los cinco modos de error independientes siguientes:
- Error de desgaste de herramientas (TWF): la herramienta se reemplaza o produce un error en un tiempo de desgaste de herramienta seleccionado aleatoriamente, entre 200 y 240 minutos
- Error de disipación de calor (HDF): la disipación de calor provoca un error en el proceso si la diferencia entre la temperatura del aire y la temperatura del proceso es inferior a 8,6 K y la velocidad rotacional de la herramienta es inferior a 1380 RPM.
- Error de alimentación (PWF): el producto de la velocidad de par y rotación (en rad/s) es igual a la potencia necesaria para el proceso. El proceso produce un error si esta potencia cae por debajo de 3500 W o supera los 9 000 W.
- Error de sobreentrenamiento (OSF): si el producto de desgaste y par de herramientas supera los 11.000 nm mínimos para la variante del producto L (12.000 para M, 13.000 para H), el proceso falla debido a un exceso de entrenamiento
- Errores aleatorios (RNF): cada proceso tiene una probabilidad de error de 0,1%, independientemente de los parámetros del proceso.
Nota
Si al menos uno de los modos de error anteriores es true, se produce un error en el proceso y la etiqueta "error de la máquina" se establece en 1. El método de aprendizaje automático no puede determinar qué modo de error provocó el error del proceso.
Descarga el conjunto de datos y súbelo al almacén de datos en el lago
Conéctese al contenedor de Azure Open Datasets y cargue el conjunto de datos de mantenimiento predictivo. Este código descarga una versión disponible públicamente del conjunto de datos y, a continuación, la almacena en fabric lakehouse:
Importante
Agregue un almacén de lago de datos al cuaderno antes de ejecutarlo. De lo contrario, se producirá un error. Para obtener información sobre cómo agregar un almacén de lago consulte Conexión de almacenes de lago y cuadernos.
# 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.")
Después de descargar el conjunto de datos en lakehouse, puede cargarlo como dataframe de Spark:
df = (
spark.read.option("header", True)
.option("inferSchema", True)
.csv(f"{DATA_FOLDER}raw/{DATA_FILE}")
.cache()
)
df.show(5)
En esta tabla se muestra una vista previa de los datos:
UDI | Id. de producto | Tipo | Temperatura del aire [K] | Temperatura del proceso [K] | Velocidad rotacional [rpm] | Torque [Nm] | Desgaste de herramientas [min] | Destino | Tipo de error |
---|---|---|---|---|---|---|---|---|---|
1 | M14860 | M | 298.1 | 308,6 | 1551 | 42.8 | 0 | 0 | Sin fallo |
2 | L47181 | L | 298,2 | 308,7 | 1408 | 46.3 | 3 | 0 | Sin fallo |
3 | L47182 | L | 298.1 | 308,5 | 1498 | 49.4 | 5 | 0 | Sin fallos |
4 | L47183 | L | 298,2 | 308,6 | 1433 | 39.5 | 7 | 0 | Sin fallo |
5 | L47184 | L | 298,2 | 308,7 | 1408 | 40.0 | 9 | 0 | Sin fallo |
Escritura de un dataframe de Spark en una tabla delta de almacén de lago
Dé formato a los datos (por ejemplo, reemplace los espacios por caracteres de subrayado) para facilitar las operaciones de Spark en pasos posteriores:
# 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)
En esta tabla se muestra una vista previa de los datos con nombres de columna reformateados.
UDI | ID del Producto | Tipo | Temperatura_del_aire_[K] | Temperatura_de_proceso_[K] | Velocidad_de_rotación_[rpm] | Torque_[Nm] | Tool_wear_[min] | Objetivo | Tipo_de_Fallo |
---|---|---|---|---|---|---|---|---|---|
1 | M14860 | M | 298.1 | 308,6 | 1551 | 42.8 | 0 | 0 | Sin fallos |
2 | L47181 | L | 298,2 | 308,7 | 1408 | 46.3 | 3 | 0 | Sin fallo |
3 | L47182 | L | 298.1 | 308,5 | 1498 | 49.4 | 5 | 0 | Sin fallo |
4 | L47183 | L | 298,2 | 308,6 | 1433 | 39.5 | 7 | 0 | Sin fallos |
5 | L47184 | L | 298,2 | 308,7 | 1408 | 40.0 | 9 | 0 | Sin fallo |
# 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}")
Paso 3: Preprocesar datos y realizar análisis exploratorios de datos
Convierta el DataFrame de Spark en un dataFrame de Pandas para usar bibliotecas de trazado populares compatibles con Pandas.
Sugerencia
Para un conjunto de datos grande, es posible que tenga que cargar una parte de ese conjunto de datos.
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()
Convierta columnas específicas del conjunto de datos en tipos flotantes o enteros según sea necesario y asigne cadenas ('L'
, 'M'
, 'H'
) a valores numéricos (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})
Exploración de datos a través de visualizaciones
# 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()
Como se esperaba, el error (IsFail
) se correlaciona con las características seleccionadas (columnas). La matriz de correlación muestra que Air_temperature
, Process_temperature
, Rotational_speed
, Torque
y Tool_wear
tienen la correlación más alta con la variable IsFail
.
# 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])
Como se muestran los gráficos trazados, las variables Air_temperature
, Process_temperature
, Rotational_speed
, Torque
y Tool_wear
no están dispersas. Parecen tener una buena continuidad en el espacio de características. Estos trazados confirman que el entrenamiento de un modelo de aprendizaje automático en este conjunto de datos probablemente genere resultados confiables que pueden generalizarse en un nuevo conjunto de datos.
Inspecciona la variable objetivo para identificar el desequilibrio de clases
Cuente el número de ejemplares de máquinas fallidas y sin fallos, e inspeccione el equilibrio de datos de cada clase (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()
Los trazados indican que la clase sin error (que se muestra como IsFail=0
en el segundo trazado) constituye la mayoría de las muestras. Use una técnica de sobremuestreo para crear un conjunto de datos de entrenamiento más 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}")
Sobremuestreo para equilibrar las clases del conjunto de datos de entrenamiento
El análisis anterior mostró que el conjunto de datos está muy desequilibrado. Ese desequilibrio se convierte en un problema, ya que la clase minoría tiene demasiados ejemplos para que el modelo aprenda eficazmente el límite de decisión.
SMOTE puede resolver el problema. SMOTE es una técnica de sobremuestreo ampliamente utilizada que genera ejemplos sintéticos. Genera ejemplos para la clase minoría en función de las distancias euclidianas entre los puntos de datos. Este método difiere del muestreo aleatorio, ya que crea nuevos ejemplos que no solo duplican la clase minoría. El método se convierte en una técnica más eficaz para controlar conjuntos de datos 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()
Equilibraste exitosamente el conjunto de datos. Ahora puede pasar al entrenamiento del modelo.
Paso 4: Entrenamiento y evaluación de los modelos
MLflow registra modelos, entrena y compara varios modelos y elige el mejor modelo para fines de predicción. Puede usar los tres modelos siguientes para el entrenamiento del modelo:
- Clasificador de bosque aleatorio
- Clasificador de regresión logística
- Clasificador XGBoost
Entrenamiento de un clasificador de bosque aleatorio
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)
Al utilizar el clasificador de bosque aleatorio, los conjuntos de datos de entrenamiento y prueba producen una puntuación F1, exactitud y sensibilidad de aproximadamente 0,9.
Entrenamiento de un clasificador de regresión 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)
Entrenamiento de un clasificador 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)
Paso 5: Seleccionar el mejor modelo y predecir salidas
En la sección anterior, entrenó tres clasificadores diferentes: bosque aleatorio, regresión logística y XGBoost. Ahora tiene la opción de acceder mediante programación a los resultados o usar la interfaz de usuario (UI).
Para la opción ruta de acceso de la interfaz de usuario, vaya al área de trabajo y filtre los modelos.
Seleccione modelos individuales para obtener más información sobre el rendimiento del modelo.
En este ejemplo se muestra cómo acceder mediante programación a los modelos a través de 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)
Aunque XGBoost produce los mejores resultados en el conjunto de entrenamiento, funciona mal en el conjunto de datos de prueba. Ese rendimiento deficiente indica un sobreajuste. El clasificador de regresión logística funciona mal en conjuntos de datos de entrenamiento y prueba. En general, los bosques aleatorios logran un buen equilibrio entre el rendimiento del entrenamiento y evitar el sobreajuste.
En la sección siguiente, elija el modelo de bosque aleatorio registrado y realice una predicción con la característica de PREDICT:
from synapse.ml.predict import MLFlowTransformer
model = MLFlowTransformer(
inputCols=list(X_test.columns),
outputCol='predictions',
modelName='machine_failure_model_rf',
modelVersion=1
)
Con el objeto MLFlowTransformer
que creó para cargar el modelo y realizar inferencias, utilice la API de Transformer para puntuar el modelo en el conjunto de datos de prueba.
predictions = model.transform(spark.createDataFrame(X_test))
predictions.show()
En esta tabla se muestra la salida:
Tipo | Temperatura_del_aire_[K] | Temperatura_del_proceso_[K] | Velocidad_de_rotación_[rpm] | Torque_[Nm] | Tool_wear_[min] | Predicciones |
---|---|---|---|---|---|---|
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 |
Guarde los datos en el almacén de lago de datos. A continuación, los datos estarán disponibles para usos posteriores; por ejemplo, un panel de 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}")
Paso 6: Visualización de la inteligencia empresarial a través de visualizaciones en Power BI
Mostrar los resultados en un formato sin conexión, con un panel de Power BI.
En el panel se muestra que Tool_wear
y Torque
crean un límite notable entre los casos fallidos y no fallidos, como se esperaba del análisis de correlación realizado anteriormente en el paso 2.