File size: 6,002 Bytes
96ef2ff 19abfdf 96ef2ff 19abfdf 96ef2ff 19abfdf 96ef2ff 19abfdf 96ef2ff 19abfdf 96ef2ff 19abfdf 96ef2ff 19abfdf 96ef2ff 19abfdf 96ef2ff 19abfdf 96ef2ff 19abfdf 96ef2ff |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# app.py
import os
import joblib
import gradio as gr
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import shap
from sklearn.pipeline import Pipeline # Keep for type hinting/structure
# =====================================================================================
# PART 1: MODEL LOADING
# This section now directly loads the model file you have uploaded to the repository.
# =====================================================================================
# <<< CHANGE 1: Update the filename to match your uploaded model.
MODEL_FILE = "machine_failure_prediction_model.joblib"
# <<< CHANGE 2: Remove the model creation logic. We will now directly load your file.
# The app assumes this file exists in your Hugging Face repository.
try:
loaded_model = joblib.load(MODEL_FILE)
print(f"Successfully loaded model from {MODEL_FILE}")
except FileNotFoundError:
print(f"Error: Model file not found at {MODEL_FILE}. Make sure the file is uploaded to the repository.")
# You might want to display an error in the Gradio app itself if the model fails to load.
loaded_model = None # Set to None to handle the error case
# =====================================================================================
# PART 2: BACKEND LOGIC (Prediction and SHAP Calculation)
# =====================================================================================
def predict_failure(Type, air_temperature, process_temperature, rotational_speed, torque, tool_wear):
"""Predicts machine failure and calculates SHAP values using the loaded model."""
if loaded_model is None:
return "Error: Model not loaded.", None
input_data = pd.DataFrame({
'Type': [Type], 'Air temperature [K]': [air_temperature],
'Process temperature [K]': [process_temperature], 'Rotational speed [rpm]': [rotational_speed],
'Torque [Nm]': [torque], 'Tool wear [min]': [tool_wear]
})
preprocessor = loaded_model.named_steps['preprocessor']
classifier = loaded_model.named_steps['classifier']
input_processed = preprocessor.transform(input_data)
probability = classifier.predict_proba(input_processed)[:, 1]
explainer = shap.TreeExplainer(classifier)
shap_values = explainer.shap_values(input_processed)
feature_names = preprocessor.get_feature_names_out()
# SHAP values for the "Failure" class (index 1)
shap_val_failure = shap_values[1][0]
base_val_failure = explainer.expected_value[1]
return probability[0], shap_val_failure, feature_names, base_val_failure
# =====================================================================================
# PART 3: FRONTEND LOGIC (Plotting and Gradio Interface)
# =====================================================================================
def generate_shap_plot(shap_values, feature_names, base_value):
"""Generates a SHAP waterfall plot for the Gradio interface."""
plt.close('all')
explanation = shap.Explanation(
values=shap_values, base_values=base_value, feature_names=feature_names
)
fig, _ = plt.subplots()
shap.waterfall_plot(explanation, max_display=10, show=False)
plt.tight_layout()
return fig
def predict_and_generate_plot(Type, air_temperature, process_temperature, rotational_speed, torque, tool_wear):
"""Wrapper function that connects the backend prediction to the frontend plot."""
result = predict_failure(
Type, air_temperature, process_temperature, rotational_speed, torque, tool_wear
)
if isinstance(result, tuple):
probability, shap_values, feature_names, base_value = result
shap_plot = generate_shap_plot(shap_values, feature_names, base_value)
return f"{probability:.2%}", shap_plot
else:
# Handle the case where the model failed to load
error_message = result
empty_plot = plt.figure()
plt.text(0.5, 0.5, 'Error: Model could not be loaded.', horizontalalignment='center', verticalalignment='center')
return error_message, empty_plot
# Define the Gradio interface layout and components
with gr.Blocks(theme=gr.themes.Soft()) as iface_with_shap:
gr.Markdown("# Machine Failure Prediction with Live SHAP Analysis")
gr.Markdown("Adjust the sliders to see the real-time probability of machine failure and how each feature's value contributes to the prediction.")
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("### Input Features")
type_input = gr.Dropdown(label="Type", choices=['L', 'M', 'H'], value='L')
air_temp_input = gr.Slider(minimum=295, maximum=305, value=300, label="Air temperature [K]")
proc_temp_input = gr.Slider(minimum=305, maximum=315, value=310, label="Process temperature [K]")
rpm_input = gr.Slider(minimum=1000, maximum=3000, value=1500, label="Rotational speed [rpm]")
torque_input = gr.Slider(minimum=5, maximum=80, value=40, label="Torque [Nm]")
wear_input = gr.Slider(minimum=0, maximum=250, value=100, label="Tool wear [min]")
inputs = [type_input, air_temp_input, proc_temp_input, rpm_input, torque_input, wear_input]
with gr.Column(scale=2):
gr.Markdown("### Prediction Outputs")
probability_output = gr.Textbox(label="Probability of Machine Failure")
plot_output = gr.Plot(label="Feature Contribution to Failure (SHAP Waterfall Plot)")
# This makes the app load the first prediction on startup
iface_with_shap.load(
fn=predict_and_generate_plot,
inputs=inputs,
outputs=[probability_output, plot_output]
)
# This connects the UI changes to the prediction function
for input_comp in inputs:
input_comp.change(
fn=predict_and_generate_plot,
inputs=inputs,
outputs=[probability_output, plot_output]
)
# Launch the application
if __name__ == "__main__":
iface_with_shap.launch() |