engine-pm-app / app.py
vinayakdnrdd's picture
Upload folder using huggingface_hub
4e2c29e verified
import pandas as pd
import streamlit as st
import joblib
from huggingface_hub import hf_hub_download
st.set_page_config(page_title="Engine Predictive Maintenance", layout="centered")
st.title("Engine Predictive Maintenance")
st.write("Enter sensor values to predict whether maintenance is needed.")
MODEL_REPO = "vinayakdnrdd/engine-pm-model"
MODEL_FILE = "engine_pm_model.joblib"
# Load model
model_path = hf_hub_download(repo_id=MODEL_REPO, filename=MODEL_FILE)
model = joblib.load(model_path)
# ---- Helper: get expected input columns from sklearn Pipeline ----
def get_expected_columns(m):
# Best case: pipeline has feature_names_in_
cols = getattr(m, "feature_names_in_", None)
if cols is not None:
return list(cols)
# Typical: pipeline.named_steps["preprocess"] has feature_names_in_
pre = getattr(m, "named_steps", {}).get("preprocess", None)
if pre is not None:
cols = getattr(pre, "feature_names_in_", None)
if cols is not None:
return list(cols)
# Fallback: derive from transformers definition
exp = []
try:
for _, _, c in pre.transformers:
if isinstance(c, list):
exp.extend(c)
except Exception:
pass
# keep unique order
seen = set()
exp2 = []
for c in exp:
if c not in seen:
exp2.append(c); seen.add(c)
if exp2:
return exp2
# Last fallback: assume these common names
return ["Engine rpm", "Lub oil pressure", "Fuel pressure", "Coolant pressure", "Lub oil temp", "Coolant temp"]
expected_cols = get_expected_columns(model)
with st.expander("Debug (Expected input columns from model)"):
st.write(expected_cols)
# ---- UI inputs ----
engine_rpm = st.number_input("Engine RPM", value=1500.0)
lub_oil_pressure = st.number_input("Lub Oil Pressure", value=2.5)
fuel_pressure = st.number_input("Fuel Pressure", value=3.0)
coolant_pressure = st.number_input("Coolant Pressure", value=1.2)
lub_oil_temp = st.number_input("Lub Oil Temperature", value=85.0)
coolant_temp = st.number_input("Coolant Temperature", value=90.0)
# We store inputs with MANY aliases (case-insensitive matching)
inputs = {
"Engine rpm": engine_rpm,
"engine rpm": engine_rpm,
"Engine_RPM": engine_rpm,
"Engine_Rpm": engine_rpm,
"Lub oil pressure": lub_oil_pressure,
"lub oil pressure": lub_oil_pressure,
"Lub_Oil_Pressure": lub_oil_pressure,
"Fuel pressure": fuel_pressure,
"fuel pressure": fuel_pressure,
"Fuel_Pressure": fuel_pressure,
"Coolant pressure": coolant_pressure,
"coolant pressure": coolant_pressure,
"Coolant_Pressure": coolant_pressure,
"Lub oil temp": lub_oil_temp,
"lub oil temp": lub_oil_temp,
"Lub oil temperature": lub_oil_temp,
"lub oil temperature": lub_oil_temp,
"Lub_Oil_Temperature": lub_oil_temp,
"Coolant temp": coolant_temp,
"coolant temp": coolant_temp,
"Coolant temperature": coolant_temp,
"coolant temperature": coolant_temp,
"Coolant_Temperature": coolant_temp,
}
def find_value_for_col(colname: str):
# exact match
if colname in inputs:
return inputs[colname]
# normalized match
key = colname.strip().lower()
for k, v in inputs.items():
if k.strip().lower() == key:
return v
return None
if st.button("Predict"):
row = {}
missing = []
for col in expected_cols:
v = find_value_for_col(col)
if v is None:
missing.append(col)
else:
row[col] = v
if missing:
st.error("Model expects these columns but app couldn't map them:")
st.write(missing)
st.stop()
X = pd.DataFrame([row], columns=expected_cols)
proba = float(model.predict_proba(X)[0, 1])
pred = int(proba >= 0.5)
st.write(f"Probability (Maintenance Needed): **{proba:.2f}**")
if pred == 1:
st.error("⚠️ Prediction: **Maintenance Needed**")
else:
st.success("✅ Prediction: **Normal Operation**")