Update app.py
Browse files
app.py
CHANGED
|
@@ -5,10 +5,12 @@ os.environ["TF_ENABLE_ONEDNN_OPTS"] = "0"
|
|
| 5 |
import numpy as np
|
| 6 |
import gradio as gr
|
| 7 |
import joblib
|
| 8 |
-
import spaces
|
| 9 |
from tensorflow.keras.models import load_model
|
| 10 |
|
| 11 |
-
#
|
|
|
|
|
|
|
| 12 |
knn_model = joblib.load("knn_model.pkl")
|
| 13 |
svm_model = joblib.load("rbf_svm_model.pkl")
|
| 14 |
ann_model = load_model("ann_model.keras")
|
|
@@ -16,7 +18,9 @@ ann_model = load_model("ann_model.keras")
|
|
| 16 |
scaler_rfe = joblib.load("scaler_rfe.pkl")
|
| 17 |
selected_features = joblib.load("selected_features.pkl")
|
| 18 |
|
| 19 |
-
#
|
|
|
|
|
|
|
| 20 |
gender_map = {"Female": 0, "Male": 1}
|
| 21 |
binary_map = {"No": 0, "Yes": 1}
|
| 22 |
ordinal_map = {"Low": 0, "Medium": 1, "High": 2}
|
|
@@ -32,31 +36,50 @@ def encode_input_value(feature, value):
|
|
| 32 |
if feature == 'alcohol': return alcohol_map[value]
|
| 33 |
return float(value)
|
| 34 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
@spaces.GPU
|
| 36 |
-
def
|
| 37 |
-
|
| 38 |
-
X_input = np.array([encoded_inputs], dtype=float)
|
| 39 |
-
X_scaled = scaler_rfe.transform(X_input)
|
| 40 |
-
|
| 41 |
-
if model_choice == "KNN":
|
| 42 |
-
y_pred = knn_model.predict(X_scaled)[0]
|
| 43 |
-
y_prob = knn_model.predict_proba(X_scaled)[0][1]
|
| 44 |
-
elif model_choice == "SVM":
|
| 45 |
-
y_pred = svm_model.predict(X_scaled)[0]
|
| 46 |
-
if hasattr(svm_model, "predict_proba"):
|
| 47 |
-
y_prob = svm_model.predict_proba(X_scaled)[0][1]
|
| 48 |
-
else:
|
| 49 |
-
score = svm_model.decision_function(X_scaled)[0]
|
| 50 |
-
y_prob = 1 / (1 + np.exp(-score))
|
| 51 |
-
else:
|
| 52 |
-
y_prob = float(ann_model.predict(X_scaled, verbose=0)[0][0])
|
| 53 |
-
y_pred = int(y_prob >= 0.5)
|
| 54 |
-
|
| 55 |
-
status = "Yes" if int(y_pred) == 1 else "No"
|
| 56 |
-
probability_text = f"{y_prob:.4f} ({y_prob * 100:.2f}%)"
|
| 57 |
-
|
| 58 |
-
return status, probability_text, model_choice
|
| 59 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 60 |
feature_labels = {
|
| 61 |
'age': 'Age', 'gender': 'Gender', 'blood_pressure': 'Blood Pressure',
|
| 62 |
'cholesterol': 'Cholesterol Level', 'exercise': 'Exercise Habits',
|
|
|
|
| 5 |
import numpy as np
|
| 6 |
import gradio as gr
|
| 7 |
import joblib
|
| 8 |
+
import spaces # Still needed for the dummy function
|
| 9 |
from tensorflow.keras.models import load_model
|
| 10 |
|
| 11 |
+
# ============================================================
|
| 12 |
+
# LOAD MODELS & SCALERS
|
| 13 |
+
# ============================================================
|
| 14 |
knn_model = joblib.load("knn_model.pkl")
|
| 15 |
svm_model = joblib.load("rbf_svm_model.pkl")
|
| 16 |
ann_model = load_model("ann_model.keras")
|
|
|
|
| 18 |
scaler_rfe = joblib.load("scaler_rfe.pkl")
|
| 19 |
selected_features = joblib.load("selected_features.pkl")
|
| 20 |
|
| 21 |
+
# ============================================================
|
| 22 |
+
# ENCODING MAPS
|
| 23 |
+
# ============================================================
|
| 24 |
gender_map = {"Female": 0, "Male": 1}
|
| 25 |
binary_map = {"No": 0, "Yes": 1}
|
| 26 |
ordinal_map = {"Low": 0, "Medium": 1, "High": 2}
|
|
|
|
| 36 |
if feature == 'alcohol': return alcohol_map[value]
|
| 37 |
return float(value)
|
| 38 |
|
| 39 |
+
# ============================================================
|
| 40 |
+
# ZERO-GPU WORKAROUND
|
| 41 |
+
# ============================================================
|
| 42 |
+
# This satisfies Hugging Face's ZeroGPU requirement without
|
| 43 |
+
# crashing your actual Scikit-Learn/TensorFlow models.
|
| 44 |
@spaces.GPU
|
| 45 |
+
def dummy_startup():
|
| 46 |
+
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
|
| 48 |
+
# ============================================================
|
| 49 |
+
# PREDICTION FUNCTION (NO GPU DECORATOR)
|
| 50 |
+
# ============================================================
|
| 51 |
+
def predict_heart_disease(model_choice, *feature_values):
|
| 52 |
+
try:
|
| 53 |
+
encoded_inputs = [encode_input_value(f, v) for f, v in zip(selected_features, feature_values)]
|
| 54 |
+
X_input = np.array([encoded_inputs], dtype=float)
|
| 55 |
+
X_scaled = scaler_rfe.transform(X_input)
|
| 56 |
+
|
| 57 |
+
if model_choice == "KNN":
|
| 58 |
+
y_pred = knn_model.predict(X_scaled)[0]
|
| 59 |
+
y_prob = knn_model.predict_proba(X_scaled)[0][1]
|
| 60 |
+
elif model_choice == "SVM":
|
| 61 |
+
y_pred = svm_model.predict(X_scaled)[0]
|
| 62 |
+
if hasattr(svm_model, "predict_proba"):
|
| 63 |
+
y_prob = svm_model.predict_proba(X_scaled)[0][1]
|
| 64 |
+
else:
|
| 65 |
+
score = svm_model.decision_function(X_scaled)[0]
|
| 66 |
+
y_prob = 1 / (1 + np.exp(-score))
|
| 67 |
+
else: # ANN
|
| 68 |
+
y_prob = float(ann_model.predict(X_scaled, verbose=0)[0][0])
|
| 69 |
+
y_pred = int(y_prob >= 0.5)
|
| 70 |
+
|
| 71 |
+
status = "Yes" if int(y_pred) == 1 else "No"
|
| 72 |
+
probability_text = f"{y_prob:.4f} ({y_prob * 100:.2f}%)"
|
| 73 |
+
|
| 74 |
+
return status, probability_text, model_choice
|
| 75 |
+
|
| 76 |
+
except Exception as e:
|
| 77 |
+
# If an error happens, this will print it directly to the Gradio UI
|
| 78 |
+
return f"Error: {str(e)}", "Error", model_choice
|
| 79 |
+
|
| 80 |
+
# ============================================================
|
| 81 |
+
# UI DEFINITION
|
| 82 |
+
# ============================================================
|
| 83 |
feature_labels = {
|
| 84 |
'age': 'Age', 'gender': 'Gender', 'blood_pressure': 'Blood Pressure',
|
| 85 |
'cholesterol': 'Cholesterol Level', 'exercise': 'Exercise Habits',
|