zeynepbkn01's picture
Update app.py
68429bd verified
Raw
History Blame Contribute Delete
14.3 kB
#This code for Hugging Face Gradio App
import gradio as gr
import pandas as pd
import numpy as np
import joblib
import matplotlib.pyplot as plt
import os
import sys
from lime import lime_tabular
# Error handling information
print("Python version:", sys.version)
print("Current working directory:", os.getcwd())
print("Files in current directory:", os.listdir())
# Global LIME explainer değişkeni
lime_explainer = None
# Model and preprocessor loading in a try-except block
try:
print("Model loading attempt...")
model = joblib.load('optimized_random_forest_model.pkl')
print("Model loaded successfully!")
print("Preprocessor loading attempt...")
preprocessor = joblib.load('preprocessor.pkl')
print("Preprocessor loaded successfully!")
# Define numeric and categorical features
categorical_features = ['gender', 'oral', 'tartar']
numerical_features = ['age', 'height(cm)', 'weight(kg)', 'waist(cm)', 'eyesight(left)',
'eyesight(right)', 'hearing(left)', 'hearing(right)', 'systolic',
'relaxation', 'fasting blood sugar', 'Cholesterol', 'triglyceride',
'HDL', 'LDL', 'hemoglobin', 'Urine protein', 'serum creatinine',
'AST', 'ALT', 'Gtp', 'dental caries']
# Preparing feature names
try:
print("Preparing feature names...")
numeric_feature_names = numerical_features.copy()
categorical_encoder = preprocessor.named_transformers_['cat']
onehot_encoder = categorical_encoder.named_steps['onehot']
encoded_feature_names = onehot_encoder.get_feature_names_out(categorical_features)
all_feature_names = np.concatenate([numeric_feature_names, encoded_feature_names])
print("Feature names prepared successfully!")
# Check the values that categorical variables can take
print("Checking categorical variable categories...")
categories = onehot_encoder.categories_
for i, cat in enumerate(categorical_features):
print(f"{cat} categories: {categories[i]}")
# LIME explainer will be initialized during first prediction
print("LIME explainer will be initialized during first prediction")
except Exception as e:
print(f"Error preparing feature names: {e}")
all_feature_names = numerical_features + [f"{cat}_{val}" for cat in categorical_features for val in ['M', 'F', 'Y', 'N']]
print("Using default feature names:", all_feature_names[:5], "...")
except Exception as e:
print(f"Critical error loading model or preprocessor: {e}")
print("Model files may be missing or corrupted.")
error_message = f"Error loading model: {str(e)}"
def get_instance_feature_importance_lime(processed_data, input_data):
"""
LIME is used to calculate the feature importance values for a prediction
"""
global lime_explainer
try:
# Initialize the LIME explainer (first use)
if lime_explainer is None:
print("Initializing LIME explainer for the first time...")
# Determine feature_names and class_names for LIME
lime_explainer = lime_tabular.LimeTabularExplainer(
training_data=processed_data, # Use the first example as training data
feature_names=all_feature_names,
class_names=["Non-Smoker", "Smoker"],
mode="classification",
discretize_continuous=True
)
print("LIME explainer initialized")
# Generate LIME explanation
print("Generating LIME explanation...")
explanation = lime_explainer.explain_instance(
data_row=processed_data[0],
predict_fn=model.predict_proba,
num_features=5, # Show the top 5 features
top_labels=1 # Only the most likely class
)
# Get the explanation for the most likely class
most_likely_class_idx = explanation.top_labels[0]
# Get the top 5 features
feature_importance = explanation.as_list(label=most_likely_class_idx)
top_features = [feature_name for feature_name, importance in feature_importance]
print(f"LIME explanation generated: {top_features}")
return top_features
except Exception as e:
print(f"Error calculating LIME feature importance: {e}")
import traceback
traceback.print_exc()
# If LIME fails, use the default global feature importance
print("Falling back to global feature importances...")
try:
feature_importances = model.feature_importances_
feature_importance_df = pd.DataFrame({
'Feature': all_feature_names,
'Importance': feature_importances
}).sort_values('Importance', ascending=False)
return feature_importance_df.head(5)['Feature'].tolist()
except:
return ["Feature importance calculation failed"]
def make_prediction(age, gender, height, weight, waist, eyesight_left, eyesight_right,
hearing_left, hearing_right, systolic, relaxation, fasting_blood_sugar,
cholesterol, triglyceride, hdl, ldl, hemoglobin, urine_protein,
serum_creatinine, ast, alt, gtp, tartar, dental_caries):
try:
print("Prediction function called")
# In the original dataset, the oral value is fixed as 'Y', so we prepare the categorical converter accordingly
oral = 'Y' # Oral always has the value 'Y'
# Check the values of categorical variables
try:
categorical_encoder = preprocessor.named_transformers_['cat']
onehot_encoder = categorical_encoder.named_steps['onehot']
categories = onehot_encoder.categories_
# Check the values used by the model
gender_values = categories[0] # gender categories
tartar_values = categories[2] # tartar categories
print(f"Valid gender values for the model: {gender_values}")
print(f"Valid tartar values for the model: {tartar_values}")
# Check valid values
if gender not in gender_values:
print(f"WARNING: '{gender}' is not a valid 'gender' value. Using '{gender_values[0]}'.")
gender = gender_values[0]
if tartar not in tartar_values:
print(f"WARNING: '{tartar}' is not a valid 'tartar' value. Using '{tartar_values[0]}'.")
tartar = tartar_values[0]
except Exception as e:
print(f"Error during categorical variable validation: {e}")
# Create a DataFrame with the input values
input_data = pd.DataFrame({
'age': [age],
'gender': [gender],
'height(cm)': [height],
'weight(kg)': [weight],
'waist(cm)': [waist],
'eyesight(left)': [eyesight_left],
'eyesight(right)': [eyesight_right],
'hearing(left)': [hearing_left],
'hearing(right)': [hearing_right],
'systolic': [systolic],
'relaxation': [relaxation],
'fasting blood sugar': [fasting_blood_sugar],
'Cholesterol': [cholesterol],
'triglyceride': [triglyceride],
'HDL': [hdl],
'LDL': [ldl],
'hemoglobin': [hemoglobin],
'Urine protein': [urine_protein],
'serum creatinine': [serum_creatinine],
'AST': [ast],
'ALT': [alt],
'Gtp': [gtp],
'oral': [oral], # Fixed 'Y' value used
'tartar': [tartar],
'dental caries': [dental_caries]
})
print("Preprocessing data...")
# Apply preprocessing
processed_data = preprocessor.transform(input_data)
print("Preprocessing completed!")
print("Making prediction...")
# Make prediction
prediction_proba = model.predict_proba(processed_data)[0]
prediction = model.predict(processed_data)[0]
print(f"Prediction result: {prediction}, Probability: {prediction_proba}")
# Prepare result message
if prediction == 1:
result = "Smoker"
probability = prediction_proba[1] * 100
else:
result = "Non-Smoker"
probability = prediction_proba[0] * 100
# Calculate the instance-specific feature importance with LIME
print("Calculating instance-specific feature importance with LIME...")
top_features = get_instance_feature_importance_lime(processed_data, input_data)
top_features_str = ", ".join(top_features)
print(f"Top features for this instance: {top_features_str}")
print("Prediction completed, results returned")
return result, f"{probability:.2f}%", top_features_str
except Exception as e:
print(f"Unexpected error during prediction: {e}")
return f"Error: {str(e)}", "Error occurred", "Prediction failed"
# Create Gradio interface
print("Creating Gradio interface...")
with gr.Blocks(title="Smoking Status Prediction") as app:
gr.Markdown("# Smoking Status Prediction Model")
gr.Markdown("""This application predicts whether a person is a smoker based on health and demographic data.
The model uses Random Forest classifier trained on a dataset of health indicators.""")
with gr.Tab("Make Prediction"):
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("### Demographics")
age = gr.Slider(18, 90, step=1, label="Age", value=40)
gender = gr.Dropdown(["M", "F"], label="Gender", value="M")
height = gr.Slider(140, 200, step=1, label="Height (cm)", value=170)
weight = gr.Slider(40, 150, step=1, label="Weight (kg)", value=70)
waist = gr.Slider(50, 150, step=1, label="Waist Circumference (cm)", value=85)
gr.Markdown("### Vision and Hearing")
eyesight_left = gr.Slider(0.1, 2.0, step=0.1, label="Eyesight (Left)", value=1.0)
eyesight_right = gr.Slider(0.1, 2.0, step=0.1, label="Eyesight (Right)", value=1.0)
hearing_left = gr.Slider(0.0, 1.0, step=0.1, label="Hearing (Left)", value=1.0)
hearing_right = gr.Slider(0.0, 1.0, step=0.1, label="Hearing (Right)", value=1.0)
with gr.Column(scale=1):
gr.Markdown("### Blood Pressure and Sugar")
systolic = gr.Slider(90, 200, step=1, label="Systolic Blood Pressure", value=120)
relaxation = gr.Slider(50, 150, step=1, label="Diastolic Blood Pressure", value=80)
fasting_blood_sugar = gr.Slider(50, 300, step=1, label="Fasting Blood Sugar", value=95)
gr.Markdown("### Cholesterol Profile")
cholesterol = gr.Slider(100, 350, step=1, label="Total Cholesterol", value=190)
triglyceride = gr.Slider(30, 600, step=1, label="Triglyceride", value=120)
hdl = gr.Slider(20, 100, step=1, label="HDL Cholesterol", value=55)
ldl = gr.Slider(30, 250, step=1, label="LDL Cholesterol", value=110)
with gr.Column(scale=1):
gr.Markdown("### Blood and Urine Tests")
hemoglobin = gr.Slider(8, 20, step=0.1, label="Hemoglobin", value=14.0)
urine_protein = gr.Slider(1, 6, step=1, label="Urine Protein", value=1)
serum_creatinine = gr.Slider(0.2, 2.0, step=0.1, label="Serum Creatinine", value=0.9)
gr.Markdown("### Liver Function")
ast = gr.Slider(10, 200, step=1, label="AST", value=25)
alt = gr.Slider(10, 200, step=1, label="ALT", value=25)
gtp = gr.Slider(10, 300, step=1, label="GTP", value=30)
gr.Markdown("### Dental Health")
# We don't use input for the 'oral' variable because it's always 'Y' in the original dataset
tartar = gr.Dropdown(["Y", "N"], label="Tartar", value="Y")
dental_caries = gr.Slider(0, 3, step=1, label="Dental Caries", value=0)
predict_btn = gr.Button("Predict Smoking Status")
with gr.Row():
with gr.Column():
prediction_result = gr.Textbox(label="Prediction Result")
probability_result = gr.Textbox(label="Confidence")
top_features = gr.Textbox(label="Top Features for This Prediction")
with gr.Tab("Model Information"):
gr.Markdown("## Model Information")
gr.Markdown("""
### Random Forest Classifier
This model uses a Random Forest Classifier to predict smoking status based on health indicators.
The model was trained on a dataset containing demographic, biometric, and health-related features.
### Top Features Used by the Model
The most important features for prediction include:
- Hemoglobin
- HDL Cholesterol (higher in non-smokers)
- Age
- Gender
- Height
- Weight
### Model Performance
On the test dataset, the model achieved:
- Accuracy: ~80%
- Precision: ~78%
- Recall: ~79%
""")
# Connect the prediction function
predict_btn.click(
fn=make_prediction,
inputs=[age, gender, height, weight, waist, eyesight_left, eyesight_right,
hearing_left, hearing_right, systolic, relaxation, fasting_blood_sugar,
cholesterol, triglyceride, hdl, ldl, hemoglobin, urine_protein,
serum_creatinine, ast, alt, gtp, tartar, dental_caries],
outputs=[prediction_result, probability_result, top_features]
)
print("Gradio interface created, launching application...")
# Launch the app
if __name__ == "__main__":
app.launch()