Upload 8 files
Browse files- ann_model.h5 +3 -0
- ann_model_scaler.pkl +3 -0
- app.py +137 -0
- attaque_cardiaque.csv +0 -0
- attaque_cardiaque_MONTI_VINCENT_LOIC_DEEP.ipynb +0 -0
- meilleur_modele.pkl +3 -0
- random_forest_optimise.pkl +3 -0
- scaler.pkl +3 -0
ann_model.h5
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:37ed7c2d8714a63df63b64030ecf89d924bf5db817611618b68402a2c18f45ac
|
3 |
+
size 67408
|
ann_model_scaler.pkl
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:75d15cc02db058e1b21df7eb6b8dd01cd3fcfc0ddcb6015e1cf94468e1122f1e
|
3 |
+
size 1336
|
app.py
ADDED
@@ -0,0 +1,137 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# app.py : Application Streamlit avec Modèle Classique et ANN
|
2 |
+
|
3 |
+
import streamlit as st
|
4 |
+
import pandas as pd
|
5 |
+
import numpy as np
|
6 |
+
import joblib
|
7 |
+
import matplotlib.pyplot as plt
|
8 |
+
from tensorflow.keras.models import load_model
|
9 |
+
|
10 |
+
st.set_page_config(page_title="App Cardiaque", layout="centered")
|
11 |
+
|
12 |
+
# Chargement des modèles et scalers
|
13 |
+
model = joblib.load("meilleur_modele.pkl")
|
14 |
+
scaler = joblib.load("scaler.pkl")
|
15 |
+
ann_model = load_model("ann_model.h5")
|
16 |
+
ann_scaler = joblib.load("ann_model_scaler.pkl")['scaler']
|
17 |
+
|
18 |
+
def home():
|
19 |
+
st.title("🫀 Application de Prédiction Cardiaque")
|
20 |
+
st.markdown(
|
21 |
+
"""
|
22 |
+
Cette application prédit le **risque de décès** chez les patients atteints d'insuffisance cardiaque
|
23 |
+
à partir de données cliniques.
|
24 |
+
|
25 |
+
**Fonctionnalités :**
|
26 |
+
- Prédiction individuelle (modèle classique)
|
27 |
+
- Prédiction avec modèle ANN (réseau de neurones)
|
28 |
+
- Chargement de fichiers CSV pour des prédictions multiples
|
29 |
+
- Historique de session
|
30 |
+
- Visualisation des probabilités et importance des variables
|
31 |
+
|
32 |
+
"""
|
33 |
+
)
|
34 |
+
|
35 |
+
def collect_input():
|
36 |
+
age = st.slider("Âge", 18, 100, 50)
|
37 |
+
anaemia = st.selectbox("Anémie", [0, 1], format_func=lambda x: "Oui" if x else "Non")
|
38 |
+
creatinine_phosphokinase = st.number_input("Créatinine phosphokinase", 10, 10000, 200)
|
39 |
+
diabetes = st.selectbox("Diabète", [0, 1], format_func=lambda x: "Oui" if x else "Non")
|
40 |
+
ejection_fraction = st.slider("Fraction d'éjection (%)", 10, 80, 35)
|
41 |
+
high_blood_pressure = st.selectbox("Hypertension", [0, 1], format_func=lambda x: "Oui" if x else "Non")
|
42 |
+
platelets = st.number_input("Plaquettes (en µL)", 25000.0, 850000.0, 300000.0)
|
43 |
+
serum_creatinine = st.number_input("Créatinine sérique", 0.1, 10.0, 1.0)
|
44 |
+
serum_sodium = st.slider("Sodium sérique", 110, 150, 135)
|
45 |
+
sex = st.selectbox("Sexe", [0, 1], format_func=lambda x: "Homme" if x else "Femme")
|
46 |
+
smoking = st.selectbox("Fumeur", [0, 1], format_func=lambda x: "Oui" if x else "Non")
|
47 |
+
time = st.slider("Temps depuis admission (jours)", 0, 300, 100)
|
48 |
+
|
49 |
+
return pd.DataFrame([{
|
50 |
+
'age': age, 'anaemia': anaemia, 'creatinine_phosphokinase': creatinine_phosphokinase,
|
51 |
+
'diabetes': diabetes, 'ejection_fraction': ejection_fraction, 'high_blood_pressure': high_blood_pressure,
|
52 |
+
'platelets': platelets, 'serum_creatinine': serum_creatinine, 'serum_sodium': serum_sodium,
|
53 |
+
'sex': sex, 'smoking': smoking, 'time': time
|
54 |
+
}])
|
55 |
+
|
56 |
+
def prediction_page():
|
57 |
+
st.title("🔍 Prédiction Individuelle (Modèle Classique)")
|
58 |
+
input_df = collect_input()
|
59 |
+
st.write("### Données entrées :", input_df)
|
60 |
+
|
61 |
+
if st.button("Prédire avec modèle classique"):
|
62 |
+
X_scaled = scaler.transform(input_df)
|
63 |
+
prediction = model.predict(X_scaled)[0]
|
64 |
+
proba = model.predict_proba(X_scaled)[0]
|
65 |
+
st.markdown(f"**Probabilité de décès :** {proba[1]*100:.2f}%")
|
66 |
+
st.markdown(f"**Probabilité de survie :** {proba[0]*100:.2f}%")
|
67 |
+
|
68 |
+
fig, ax = plt.subplots()
|
69 |
+
ax.bar(["Survie", "Décès"], proba, color=["green", "red"])
|
70 |
+
st.pyplot(fig)
|
71 |
+
|
72 |
+
if prediction == 1:
|
73 |
+
st.error("⚠️ Risque élevé de décès détecté.")
|
74 |
+
else:
|
75 |
+
st.success("✅ Le patient a de bonnes chances de survie.")
|
76 |
+
|
77 |
+
if "history" not in st.session_state:
|
78 |
+
st.session_state["history"] = []
|
79 |
+
st.session_state["history"].append({
|
80 |
+
"Survie (%)": round(proba[0]*100, 2),
|
81 |
+
"Décès (%)": round(proba[1]*100, 2),
|
82 |
+
"Décès prédit": "Oui" if prediction == 1 else "Non"
|
83 |
+
})
|
84 |
+
|
85 |
+
def ann_prediction_page():
|
86 |
+
st.title("🤖 Prédiction avec Réseau de Neurones (ANN)")
|
87 |
+
input_df = collect_input()
|
88 |
+
st.write("### Données entrées :", input_df)
|
89 |
+
|
90 |
+
if st.button("Prédire avec modèle ANN"):
|
91 |
+
X_ann_scaled = ann_scaler.transform(input_df)
|
92 |
+
ann_pred = ann_model.predict(X_ann_scaled)[0][0]
|
93 |
+
st.metric("Probabilité de décès (ANN)", f"{ann_pred*100:.2f}%")
|
94 |
+
|
95 |
+
fig, ax = plt.subplots()
|
96 |
+
ax.bar(["Survie", "Décès"], [1-ann_pred, ann_pred], color=["green", "red"])
|
97 |
+
st.pyplot(fig)
|
98 |
+
|
99 |
+
if ann_pred >= 0.5:
|
100 |
+
st.error("⚠️ Risque élevé détecté (ANN)")
|
101 |
+
else:
|
102 |
+
st.success("✅ Faible risque détecté (ANN)")
|
103 |
+
|
104 |
+
def batch_prediction_page():
|
105 |
+
st.title("📁 Prédiction depuis un Fichier CSV")
|
106 |
+
uploaded_file = st.file_uploader("Charger un fichier CSV", type="csv")
|
107 |
+
if uploaded_file:
|
108 |
+
try:
|
109 |
+
data = pd.read_csv(uploaded_file)
|
110 |
+
X_scaled = scaler.transform(data)
|
111 |
+
preds = model.predict(X_scaled)
|
112 |
+
probas = model.predict_proba(X_scaled)
|
113 |
+
data["Décès prédit"] = preds
|
114 |
+
data["Probabilité de décès"] = np.round(probas[:, 1] * 100, 2)
|
115 |
+
st.dataframe(data)
|
116 |
+
st.download_button("📥 Télécharger résultats", data.to_csv(index=False), "resultats.csv")
|
117 |
+
except Exception as e:
|
118 |
+
st.error(f"Erreur lors du traitement : {e}")
|
119 |
+
|
120 |
+
def history_page():
|
121 |
+
st.title("📚 Historique de Prédictions")
|
122 |
+
if "history" in st.session_state and st.session_state["history"]:
|
123 |
+
hist_df = pd.DataFrame(st.session_state["history"])
|
124 |
+
st.dataframe(hist_df)
|
125 |
+
else:
|
126 |
+
st.info("Aucune prédiction enregistrée dans cette session.")
|
127 |
+
|
128 |
+
pages = {
|
129 |
+
"🏠 Accueil": home,
|
130 |
+
"🔍 Prédiction (Classique)": prediction_page,
|
131 |
+
"🤖 Prédiction Deep Learning": ann_prediction_page,
|
132 |
+
"📁 Prédiction en lot": batch_prediction_page,
|
133 |
+
"📚 Historique": history_page
|
134 |
+
}
|
135 |
+
|
136 |
+
choice = st.sidebar.radio("Navigation", list(pages.keys()))
|
137 |
+
pages[choice]()
|
attaque_cardiaque.csv
ADDED
The diff for this file is too large to render.
See raw diff
|
|
attaque_cardiaque_MONTI_VINCENT_LOIC_DEEP.ipynb
ADDED
The diff for this file is too large to render.
See raw diff
|
|
meilleur_modele.pkl
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:456f291fc453354f9a7bca1c093e905d69a8208e61a8935191ff2d34f200e1d1
|
3 |
+
size 1986425
|
random_forest_optimise.pkl
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:fc3bdf8b6e68d80f6c9e3f175af0b1bd7905fd7c1a7ef141e93a92ccf4d6c1c8
|
3 |
+
size 3917625
|
scaler.pkl
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:5d477972299ba08445507af6e5c5003c909a8bce771b9e481ffc6ffaf9711580
|
3 |
+
size 1319
|