# streamlit_app/app.py import streamlit as st import pandas as pd import joblib from huggingface_hub import hf_hub_download # --- CONFIGURATION DE LA PAGE --- st.set_page_config( page_title="Prédiction Maladie Cardiaque", page_icon=" ", layout="wide" ) # --- CHARGEMENT DU MODÈLE --- # On utilise le cache de Streamlit pour ne télécharger et charger le modèle qu'une seule fois. # @st.cache_resource def load_model(): """ Télécharge et charge le pipeline de modèle depuis le Hub Hugging Face. """ try: # Remplacez par votre REPO_ID sur Hugging Face repo_id = "NchourupouoM/heart-disease-classifier" filename = "./heart_disease_pipeline.joblib" # model_path = hf_hub_download(repo_id=repo_id, filename=filename) pipeline = joblib.load(filename) return pipeline except Exception as e: st.error(f"Erreur lors du chargement du modèle : {e}") return None pipeline = load_model() # --- INTERFACE UTILISATEUR --- st.title("🤖 Prédiction du Risque de Maladie Cardiaque") st.markdown("Cette application utilise un modèle de Machine Learning pour prédire le risque de maladie cardiaque basé sur les données d'un patient. Entrez les informations dans la barre latérale et cliquez sur 'Prédire'.") # Barre latérale pour les entrées utilisateur with st.sidebar: st.header("👤 Données du Patient") # Dictionnaires pour les options catégorielles (plus clair pour l'utilisateur) sex_options = {0: "Femme", 1: "Homme"} cp_options = {0: "Angine typique", 1: "Angine atypique", 2: "Douleur non angineuse", 3: "Asymptomatique"} fbs_options = {0: "Non (> 120 mg/dl)", 1: "Oui (<= 120 mg/dl)"} restecg_options = {0: "Normal", 1: "Anomalie ST-T", 2: "Hypertrophie ventriculaire gauche"} exang_options = {0: "Non", 1: "Oui"} slope_options = {0: "Ascendant", 1: "Plat", 2: "Descendant"} thal_options = {0: "Normal", 1: "Défaut corrigé", 2: "Défaut réversible"} # Création des widgets de saisie age = st.number_input("Âge", min_value=1, max_value=120, value=50) sex = st.selectbox("Sexe", options=list(sex_options.keys()), format_func=lambda x: sex_options[x]) cp = st.selectbox("Type de douleur thoracique (CP)", options=list(cp_options.keys()), format_func=lambda x: cp_options[x]) trestbps = st.number_input("Pression artérielle au repos (trestbps)", min_value=50, max_value=250, value=120) chol = st.number_input("Cholestérol sérique (chol)", min_value=100, max_value=600, value=200) fbs = st.selectbox("Glycémie à jeun > 120 mg/dl (fbs)", options=list(fbs_options.keys()), format_func=lambda x: fbs_options[x]) restecg = st.selectbox("Résultats électrocardiographiques au repos (restecg)", options=list(restecg_options.keys()), format_func=lambda x: restecg_options[x]) thalach = st.number_input("Fréquence cardiaque maximale atteinte (thalach)", min_value=50, max_value=250, value=150) exang = st.selectbox("Angine de poitrine induite par l'exercice (exang)", options=list(exang_options.keys()), format_func=lambda x: exang_options[x]) oldpeak = st.number_input("Dépression ST induite par l'exercice (oldpeak)", min_value=0.0, max_value=10.0, value=1.0, step=0.1) slope = st.selectbox("Pente du segment ST à l'exercice de pointe (slope)", options=list(slope_options.keys()), format_func=lambda x: slope_options[x]) ca = st.number_input("Nombre de vaisseaux principaux colorés par fluoroscopie (ca)", min_value=0, max_value=4, value=0) thal = st.selectbox("Thalassémie (thal)", options=list(thal_options.keys()), format_func=lambda x: thal_options[x]) predict_button = st.button("Lancer la Prédiction", type="primary") # --- PRÉDICTION ET AFFICHAGE --- if pipeline is not None and predict_button: # 1. Créer un DataFrame avec les entrées utilisateur # Les noms de colonnes DOIVENT correspondre à ceux utilisés lors de l'entraînement input_data = { 'age': [age], 'sex': [sex], 'cp': [cp], 'trestbps': [trestbps], 'chol': [chol], 'fbs': [fbs], 'restecg': [restecg], 'thalach': [thalach], 'exang': [exang], 'oldpeak': [oldpeak], 'slope': [slope], 'ca': [ca], 'thal': [thal] } input_df = pd.DataFrame(input_data) st.subheader("📋 Données fournies pour la prédiction :") st.dataframe(input_df) # 2. Faire la prédiction prediction = pipeline.predict(input_df)[0] prediction_proba = pipeline.predict_proba(input_df)[0] # 3. Afficher le résultat st.subheader("🎯 Résultat de la Prédiction") if prediction == 1: st.error("🔴 Risque de maladie cardiaque DÉTECTÉ", icon="🚨") else: st.success("🟢 Faible risque de maladie cardiaque", icon="✅") # Afficher les probabilités col1, col2 = st.columns(2) with col1: st.metric("Probabilité de Faible Risque", f"{prediction_proba[0]*100:.2f}%") with col2: st.metric("Probabilité de Risque Élevé", f"{prediction_proba[1]*100:.2f}%") st.progress(prediction_proba[1]) elif pipeline is None: st.warning("Le modèle n'a pas pu être chargé. Veuillez vérifier la connexion ou la configuration du repository Hugging Face.")