Ajeeb57's picture
Update app.py
73f4f3c verified
Raw
History Blame Contribute Delete
10.8 kB
# ============================================
# HEART ATTACK PREDICTION APP
# Random Forest & XGBoost
# ============================================
import streamlit as st
import pandas as pd
import numpy as np
import joblib
import os
# Konfigurasi halaman
st.set_page_config(
page_title="Prediksi Serangan Jantung",
page_icon="❤️",
layout="wide"
)
# ============================================
# LOAD MODEL (dengan cache)
# ============================================
@st.cache_resource
def load_models():
rf_model = joblib.load('random_forest_model.pkl')
xgb_model = joblib.load('xgboost_model.pkl')
label_encoders = joblib.load('label_encoders.pkl')
return rf_model, xgb_model, label_encoders
@st.cache_data
def load_feature_names():
# Sesuaikan dengan dataset kamu
features = [
'age', 'gender', 'region', 'income_level', 'hypertension',
'diabetes', 'cholesterol_level', 'obesity', 'waist_circumference',
'family_history', 'smoking_status', 'alcohol_consumption',
'physical_activity', 'dietary_habits', 'air_pollution_exposure',
'stress_level', 'sleep_hours', 'blood_pressure_systolic',
'blood_pressure_diastolic', 'fasting_blood_sugar',
'cholesterol_hdl', 'cholesterol_ldl', 'triglycerides',
'EKG_results', 'previous_heart_disease', 'medication_usage',
'participated_in_free_screening'
]
return features
# ============================================
# FUNGSI PREPROCESSING INPUT
# ============================================
def preprocess_input(data, label_encoders):
"""Convert input form menjadi dataframe yang siap prediksi"""
df = pd.DataFrame([data])
# Kolom kategorikal yang perlu di-encode
categorical_cols = ['gender', 'region', 'income_level', 'smoking_status',
'alcohol_consumption', 'physical_activity',
'dietary_habits', 'air_pollution_exposure',
'stress_level', 'EKG_results']
for col in categorical_cols:
if col in df.columns and col in label_encoders:
try:
df[col] = label_encoders[col].transform(df[col].astype(str))
except:
df[col] = 0
# Pastikan tipe data numerik
for col in df.columns:
df[col] = pd.to_numeric(df[col], errors='coerce').fillna(0)
return df
# ============================================
# MAIN APP
# ============================================
def main():
st.title("🫀 Prediksi Risiko Serangan Jantung")
st.markdown("""
### Aplikasi Prediksi Menggunakan:
- **Random Forest Classifier**
- **XGBoost Classifier**
Masukkan data pasien di bawah ini untuk mengetahui risiko serangan jantung.
""")
# Load model
try:
rf_model, xgb_model, label_encoders = load_models()
except Exception as e:
st.error(f"❌ Gagal load model: {e}")
st.info("Pastikan file model (random_forest_model.pkl, xgboost_model.pkl, label_encoders.pkl) ada di folder yang sama.")
return
# ============================================
# FORM INPUT
# ============================================
with st.form("prediction_form"):
st.subheader("📋 Data Pasien")
col1, col2, col3 = st.columns(3)
with col1:
age = st.number_input("Usia (tahun)", min_value=20, max_value=100, value=55)
gender = st.selectbox("Jenis Kelamin", ["Male", "Female"])
region = st.selectbox("Wilayah", ["Urban", "Rural"])
income_level = st.selectbox("Tingkat Pendapatan", ["Low", "Middle", "High"])
hypertension = st.selectbox("Hipertensi", [0, 1], format_func=lambda x: "Ya" if x == 1 else "Tidak")
diabetes = st.selectbox("Diabetes", [0, 1], format_func=lambda x: "Ya" if x == 1 else "Tidak")
cholesterol_level = st.number_input("Kolesterol Total (mg/dL)", min_value=100, max_value=350, value=200)
obesity = st.selectbox("Obesitas", [0, 1], format_func=lambda x: "Ya" if x == 1 else "Tidak")
waist_circumference = st.number_input("Lingkar Pinggang (cm)", min_value=20, max_value=180, value=90)
with col2:
family_history = st.selectbox("Riwayat Keluarga", [0, 1], format_func=lambda x: "Ya" if x == 1 else "Tidak")
smoking_status = st.selectbox("Status Merokok", ["Never", "Past", "Current"])
alcohol_consumption = st.selectbox("Konsumsi Alkohol", ["None", "Moderate", "Heavy"])
physical_activity = st.selectbox("Aktivitas Fisik", ["Low", "Moderate", "High"])
dietary_habits = st.selectbox("Kebiasaan Makan", ["Unhealthy", "Healthy"])
air_pollution_exposure = st.selectbox("Paparan Polusi Udara", ["Low", "Moderate", "High"])
stress_level = st.selectbox("Tingkat Stres", ["Low", "Moderate", "High"])
sleep_hours = st.number_input("Jam Tidur (jam)", min_value=3.0, max_value=9.0, value=7.0, step=0.1)
with col3:
blood_pressure_systolic = st.number_input("Tekanan Darah Sistolik", min_value=90, max_value=200, value=120)
blood_pressure_diastolic = st.number_input("Tekanan Darah Diastolik", min_value=60, max_value=130, value=80)
fasting_blood_sugar = st.number_input("Gula Darah Puasa (mg/dL)", min_value=70, max_value=250, value=100)
cholesterol_hdl = st.number_input("Kolesterol HDL (mg/dL)", min_value=10, max_value=100, value=50)
cholesterol_ldl = st.number_input("Kolesterol LDL (mg/dL)", min_value=10, max_value=300, value=130)
triglycerides = st.number_input("Trigliserida (mg/dL)", min_value=50, max_value=400, value=150)
EKG_results = st.selectbox("Hasil EKG", ["Normal", "Abnormal"])
previous_heart_disease = st.selectbox("Riwayat Serangan Jantung", [0, 1], format_func=lambda x: "Ya" if x == 1 else "Tidak")
medication_usage = st.selectbox("Penggunaan Obat", [0, 1], format_func=lambda x: "Ya" if x == 1 else "Tidak")
participated_in_free_screening = st.selectbox("Ikut Skrining Gratis", [0, 1], format_func=lambda x: "Ya" if x == 1 else "Tidak")
submitted = st.form_submit_button("🔮 Prediksi", type="primary")
# ============================================
# PROSES PREDIKSI
# ============================================
if submitted:
with st.spinner("🔮 Memproses prediksi..."):
# Kumpulkan data
input_data = {
'age': age,
'gender': gender,
'region': region,
'income_level': income_level,
'hypertension': hypertension,
'diabetes': diabetes,
'cholesterol_level': cholesterol_level,
'obesity': obesity,
'waist_circumference': waist_circumference,
'family_history': family_history,
'smoking_status': smoking_status,
'alcohol_consumption': alcohol_consumption,
'physical_activity': physical_activity,
'dietary_habits': dietary_habits,
'air_pollution_exposure': air_pollution_exposure,
'stress_level': stress_level,
'sleep_hours': sleep_hours,
'blood_pressure_systolic': blood_pressure_systolic,
'blood_pressure_diastolic': blood_pressure_diastolic,
'fasting_blood_sugar': fasting_blood_sugar,
'cholesterol_hdl': cholesterol_hdl,
'cholesterol_ldl': cholesterol_ldl,
'triglycerides': triglycerides,
'EKG_results': EKG_results,
'previous_heart_disease': previous_heart_disease,
'medication_usage': medication_usage,
'participated_in_free_screening': participated_in_free_screening
}
# Preprocess
df_input = preprocess_input(input_data, label_encoders)
# Prediksi (konversi ke float)
rf_pred = rf_model.predict(df_input)[0]
rf_proba = float(rf_model.predict_proba(df_input)[0][1]) # <- tambahkan float()
xgb_pred = xgb_model.predict(df_input)[0]
xgb_proba = float(xgb_model.predict_proba(df_input)[0][1]) # <- tambahkan float()
# ============================================
# TAMPILKAN HASIL
# ============================================
st.subheader("📊 Hasil Prediksi")
col1, col2 = st.columns(2)
with col1:
st.markdown("### 🌲 Random Forest")
if rf_pred == 1:
st.error(f"⚠️ **BERISIKO** (Probabilitas: {rf_proba:.2%})")
else:
st.success(f"✅ **TIDAK BERISIKO** (Probabilitas: {rf_proba:.2%})")
# Sekarang aman karena sudah float
st.progress(rf_proba)
st.caption(f"Probabilitas risiko: {rf_proba:.2%}")
with col2:
st.markdown("### ⚡ XGBoost")
if xgb_pred == 1:
st.error(f"⚠️ **BERISIKO** (Probabilitas: {xgb_proba:.2%})")
else:
st.success(f"✅ **TIDAK BERISIKO** (Probabilitas: {xgb_proba:.2%})")
st.progress(xgb_proba) # Sekarang aman
st.caption(f"Probabilitas risiko: {xgb_proba:.2%}")
with col2:
st.markdown("### ⚡ XGBoost")
if xgb_pred == 1:
st.error(f"⚠️ **BERISIKO** (Probabilitas: {xgb_proba:.2%})")
else:
st.success(f"✅ **TIDAK BERISIKO** (Probabilitas: {xgb_proba:.2%})")
st.progress(xgb_proba)
st.caption(f"Probabilitas risiko: {xgb_proba:.2%}")
# Interpretasi
st.markdown("---")
st.subheader("📝 Interpretasi")
avg_proba = (rf_proba + xgb_proba) / 2
if avg_proba >= 0.7:
st.error("🚨 **RISIKO TINGGI!** Segera konsultasikan ke dokter.")
elif avg_proba >= 0.4:
st.warning("⚠️ **RISIKO SEDANG.** Perhatikan gaya hidup dan rutin cek kesehatan.")
else:
st.success("✅ **RISIKO RENDAH.** Tetap jaga pola makan dan olahraga teratur.")
if __name__ == "__main__":
main()