File size: 4,816 Bytes
f17b126
2d28a61
f17b126
f718541
 
f17b126
 
f718541
ffbd98b
2d28a61
 
f718541
f17b126
f718541
 
 
 
 
f17b126
2d28a61
 
 
f718541
2d28a61
 
f718541
2d28a61
 
 
 
 
ffbd98b
2d28a61
 
 
ffbd98b
2d28a61
 
 
 
ffbd98b
2d28a61
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ffbd98b
 
2d28a61
 
 
ffbd98b
2d28a61
 
 
 
ffbd98b
2d28a61
 
 
 
 
 
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
133
134
135
136
137
138
139
140
141

import streamlit as st
import joblib
import pandas as pd
import numpy as np
from huggingface_hub import hf_hub_download

# --- Hugging Face Model Repository Details ---
REPO_ID_MODEL = "RajendrakumarPachaiappan/engine-predictive-model"
# Assuming the best model found in the notebook was Random Forest based on your script
MODEL_FILENAME = "final_random_forest_model.joblib" 
SCALER_FILENAME = "standard_scaler.joblib"

# The six feature columns for input
FEATURE_COLS = [
    'Engine_RPM', 'Lub_Oil_Pressure', 'Fuel_Pressure',
    'Coolant_Pressure', 'Lub_Oil_Temperature', 'Coolant_Temperature'
]

# --- Caching Function to Load Model and Scaler ---
@st.cache_resource
def load_artifacts():
    """
    Downloads and loads the model and scaler from the Hugging Face Hub.
    The @st.cache_resource decorator ensures this function only runs once.
    """
    try:
        with st.spinner("Downloading and loading model artifacts..."):
            # Download and load the model
            model_path = hf_hub_download(repo_id=REPO_ID_MODEL, filename=MODEL_FILENAME, repo_type="model")
            model = joblib.load(model_path)

            # Download and load the scaler
            scaler_path = hf_hub_download(repo_id=REPO_ID_MODEL, filename=SCALER_FILENAME, repo_type="model")
            scaler = joblib.load(scaler_path)

        return model, scaler
    except Exception as e:
        st.error(f"CRITICAL ERROR: Failed to load model or scaler. Check repository ID and filenames. Error: {e}")
        return None, None

# Load the model and scaler
model, scaler = load_artifacts()

# --- Streamlit UI Setup ---
st.set_page_config(
    page_title="Engine Predictive Maintenance",
    layout="centered",
    initial_sidebar_state="expanded"
)

st.title("🚗 Engine Predictive Maintenance Model")
st.markdown(
    "Use the sliders below to input the current engine sensor readings and predict "
    "if the engine is running **NORMAL (0)** or requires **IMMEDIATE MAINTENANCE (1)**. "
    "This model uses a pre-trained Random Forest classifier."
)
st.markdown(
    "**Note:** The slider ranges are based on the minimum and maximum values observed in the training dataset (19,535 records)."
)

if model is None or scaler is None:
    st.stop() # Stop the app if artifacts failed to load

# --- Input Components ---
st.header("Sensor Readings")


# Define ranges based on the provided dataset statistics
# Format: (min_value, max_value, mean_value/default) - all values are floats.
ranges = {
    'Engine_RPM': (61.0, 2239.0, 791.0), 
    'Lub_Oil_Pressure': (0.0, 7.3, 3.3),
    'Fuel_Pressure': (0.0, 21.1, 6.7),
    'Coolant_Pressure': (0.0, 7.5, 2.3),
    'Lub_Oil_Temperature': (71.3, 89.6, 77.6),
    'Coolant_Temperature': (61.7, 195.5, 78.4),
}

input_values = {}
# Use Streamlit columns for a cleaner, side-by-side layout
col1, col2 = st.columns(2)
columns = [col1, col2]

for i, col_name in enumerate(FEATURE_COLS):
    # Determine which column to place the widget in
    current_col = columns[i % 2] 

    min_val, max_val, default_val = ranges[col_name]
    
    # Clean up names for display in the UI and set units
    label = col_name.replace('_', ' ')
    unit = ""
    if "RPM" in col_name:
        unit = " (rev/min)"
    elif "Pressure" in col_name:
        unit = " (bar/kPa)"
    elif "Temperature" in col_name:
        unit = " (°C)"


    with current_col:
        input_values[col_name] = st.slider(
            label=f"{label}{unit}",
            min_value=min_val,
            max_value=max_val,
            value=default_val,
            step=0.1,
            help=f"Current reading for {label}. Full data range: [{min_val}, {max_val}]"
        )

# --- Prediction Logic ---
if st.button("Predict Engine Condition", type="primary"):
    # 1. Prepare data for the model
    # Convert input_values dictionary to a DataFrame row
    input_df = pd.DataFrame([input_values], columns=FEATURE_COLS)

    # 2. Scale the input data using the pre-trained StandardScaler
    # The scaler must be fitted on the same data distribution as the model
    input_scaled = scaler.transform(input_df)

    # 3. Make prediction
    # The output is a numpy array, we take the first element (the prediction)
    prediction = model.predict(input_scaled)[0]
    
    # 4. Display results
    st.subheader("Prediction Result")
    
    if prediction == 1:
        st.error(
            "🔴 FAULTY (1): Immediate Maintenance Required! "
            "High probability of engine failure detected. Check for high RPM, low pressures, or extreme temperatures."
        )
    else:
        st.success(
            "🟢 NORMAL (0): Operating within expected parameters. "
            "Engine health is currently good."
        )
        
    st.caption(f"Raw Model Prediction (0=Normal, 1=Faulty): {prediction}")