Musabbirkm commited on
Commit
82acae5
·
verified ·
1 Parent(s): 498876b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +327 -328
app.py CHANGED
@@ -1,328 +1,327 @@
1
- import streamlit as st
2
- import joblib
3
- import pandas as pd
4
-
5
-
6
- # Page config must be first command
7
- st.set_page_config(
8
- page_title="❤️ Heart Disease Prediction System",
9
- page_icon="❤️",
10
- layout="wide",
11
- initial_sidebar_state="expanded"
12
- )
13
-
14
-
15
- # Load the pre-trained model
16
- @st.cache_resource
17
- def load_model():
18
- try:
19
- production_model = joblib.load('models/uci_heart_disease_model.pkl')
20
- return production_model['model'], production_model['metadata']['threshold']
21
- except Exception as e:
22
- st.error(f"Error loading model: {e}")
23
- st.stop()
24
-
25
-
26
- model, optimal_threshold = load_model()
27
-
28
-
29
- # Function to process input and make predictions
30
- def predict_heart_disease(user_input):
31
- try:
32
- # Feature engineering
33
- user_input['hr_age_ratio'] = user_input['thalach'] / (user_input['age'] + 1e-5)
34
- user_input['bp_oldpeak'] = user_input['trestbps'] * (user_input['oldpeak'] + 1)
35
- user_input['risk_score'] = (user_input['age'] / 50 + user_input['chol'] / 200 + user_input['trestbps'] / 140)
36
-
37
- # Make prediction
38
- probabilities = model.predict_proba(user_input)[:, 1]
39
- predictions = (probabilities >= optimal_threshold).astype(int)
40
-
41
- # Create results DataFrame
42
- results = pd.DataFrame({
43
- 'Prediction': predictions,
44
- 'Diagnosis': ['Heart Disease' if p == 1 else 'Healthy' for p in predictions],
45
- 'Probability': probabilities,
46
- })
47
-
48
- # Combine with input features for display
49
- display_data = pd.concat([user_input[['age', 'sex', 'cp', 'trestbps', 'chol']], results], axis=1)
50
-
51
- return results, display_data
52
-
53
- except Exception as e:
54
- st.error(f"Prediction error: {e}")
55
- return None, None
56
-
57
-
58
- # Main app interface
59
- st.title("❤️ Heart Disease Prediction")
60
-
61
- # Create tabs
62
- tab1, tab2 ,tab3= st.tabs(["Single Prediction", "Batch Prediction","Data & Model Info"])
63
-
64
- with tab1:
65
- st.header("Single Patient Prediction")
66
-
67
- # Input form
68
- with st.form("prediction_form"):
69
- col1, col2 = st.columns(2)
70
-
71
- with col1:
72
- st.subheader("Patient Information")
73
- age = st.slider("Age", 18, 100, 50)
74
- sex = st.radio("Sex", ["Male (1)", "Female (0)"], index=0)
75
- cp = st.selectbox("Chest Pain Type",
76
- ["Typical angina (1)", "Atypical angina (2)",
77
- "Non-anginal pain (3)", "Asymptomatic (4)"])
78
- trestbps = st.slider("Resting Blood Pressure (mmHg)", 90, 200, 120)
79
- chol = st.slider("Serum Cholesterol (mg/dl)", 150, 350, 200)
80
-
81
- with col2:
82
- st.subheader("Clinical Measurements")
83
- fbs = st.radio("Fasting Blood Sugar > 120 mg/dl", ["Yes (1)", "No (0)"], index=1)
84
- restecg = st.selectbox("Resting ECG Results",
85
- ["Normal (0)", "ST-T wave abnormality (1)",
86
- "Left ventricular hypertrophy (2)"])
87
- thalach = st.slider("Maximum Heart Rate Achieved (bpm)", 60, 200, 150)
88
- exang = st.radio("Exercise Induced Angina", ["Yes (1)", "No (0)"], index=1)
89
- oldpeak = st.slider("ST Depression Induced by Exercise", 0.0, 6.0, 1.0, step=0.1)
90
- slope = st.selectbox("Slope of Peak Exercise ST Segment",
91
- ["Upsloping (1)", "Flat (2)", "Downsloping (3)"])
92
- ca = st.slider("Number of Major Vessels", 0, 4, 0)
93
- thal = st.selectbox("Thalassemia",
94
- ["Normal (3)", "Fixed defect (6)", "Reversible defect (7)"])
95
-
96
- submitted = st.form_submit_button("Predict Heart Disease Risk")
97
-
98
- if submitted:
99
- # Preprocess inputs
100
- user_input = pd.DataFrame({
101
- 'age': [age],
102
- 'sex': [1 if sex.startswith("Male") else 0],
103
- 'cp': [int(cp.split("(")[1].strip(")"))],
104
- 'trestbps': [trestbps],
105
- 'chol': [chol],
106
- 'fbs': [1 if fbs.startswith("Yes") else 0],
107
- 'restecg': [int(restecg.split("(")[1].strip(")"))],
108
- 'thalach': [thalach],
109
- 'exang': [1 if exang.startswith("Yes") else 0],
110
- 'oldpeak': [oldpeak],
111
- 'slope': [int(slope.split("(")[1].strip(")"))],
112
- 'ca': [ca],
113
- 'thal': [int(thal.split("(")[1].strip(")"))],
114
- })
115
-
116
- # Get predictions
117
- results, display_data = predict_heart_disease(user_input)
118
-
119
- if results is not None:
120
- st.subheader("Prediction Results")
121
-
122
- # Display the formatted results
123
- st.markdown(f"""
124
- ### Heart Disease Prediction Results
125
- **Using threshold:** {optimal_threshold:.3f}
126
- """)
127
-
128
- # Show detailed results in expandable section
129
- with st.expander("View Detailed Results"):
130
- st.dataframe(display_data)
131
-
132
- # Show risk assessment
133
- probability = results['Probability'].iloc[0]
134
- prediction = results['Diagnosis'].iloc[0]
135
-
136
- if probability > 0.7:
137
- risk_level = "High"
138
- recommendation = "Immediate consultation with cardiologist recommended"
139
- color = "red"
140
- elif probability > 0.4:
141
- risk_level = "Medium"
142
- recommendation = "Further tests recommended"
143
- color = "orange"
144
- else:
145
- risk_level = "Low"
146
- recommendation = "No immediate concerns, maintain regular checkups"
147
- color = "green"
148
-
149
- # Display metrics in columns
150
- col1, col2, col3 = st.columns(3)
151
- with col1:
152
- st.metric("Prediction", prediction)
153
- with col2:
154
- st.metric("Probability", f"{probability * 100:.2f}%")
155
- with col3:
156
- st.metric("Risk Level", risk_level)
157
-
158
- # Show recommendation
159
- st.markdown(f"""
160
- <div style='background-color:#f0f2f6; padding:10px; border-radius:5px;'>
161
- <h4 style='color:{color};'>Recommendation: {recommendation}</h4>
162
- </div>
163
- """, unsafe_allow_html=True)
164
-
165
- with tab2:
166
- st.header("Batch Prediction")
167
-
168
- uploaded_file = st.file_uploader("Upload CSV file with patient data", type=["csv"])
169
-
170
- if uploaded_file is not None:
171
- try:
172
- test_data = pd.read_csv(uploaded_file)
173
- st.success("File uploaded successfully!")
174
-
175
- # Check for required columns
176
- required_cols = ['age', 'sex', 'cp', 'trestbps', 'chol', 'fbs', 'restecg',
177
- 'thalach', 'exang', 'oldpeak', 'slope', 'ca', 'thal']
178
-
179
- missing_cols = [col for col in required_cols if col not in test_data.columns]
180
- if missing_cols:
181
- st.error(f"Missing required columns: {', '.join(missing_cols)}")
182
- else:
183
- # Get predictions
184
- results, display_data = predict_heart_disease(test_data)
185
-
186
- if results is not None:
187
- st.subheader("Prediction Results")
188
-
189
- # Show summary statistics
190
- st.markdown(f"""
191
- ### Batch Prediction Results
192
- **Using threshold:** {optimal_threshold:.3f}
193
- """)
194
-
195
- # Combine results with original data
196
- full_results = test_data.copy()
197
- full_results['Probability'] = results['Probability']
198
- full_results['Prediction'] = results['Prediction']
199
- full_results['Diagnosis'] = results['Diagnosis']
200
-
201
- # Show results in expandable section
202
- with st.expander("View All Predictions"):
203
- st.dataframe(full_results)
204
-
205
- # Show statistics
206
- st.subheader("Statistics")
207
- col1, col2, col3 = st.columns(3)
208
- with col1:
209
- st.metric("Total Patients", len(full_results))
210
- with col2:
211
- st.metric("Heart Disease Cases", full_results['Prediction'].sum())
212
- with col3:
213
- st.metric("Healthy Cases", len(full_results) - full_results['Prediction'].sum())
214
-
215
- # Add download button
216
- csv = full_results.to_csv(index=False)
217
- st.download_button(
218
- "Download Results",
219
- csv,
220
- "heart_disease_predictions.csv",
221
- "text/csv"
222
- )
223
-
224
- except Exception as e:
225
- st.error(f"Error processing file: {e}")
226
-
227
- sample_data = pd.DataFrame({
228
- 'age': [52, 63, 45, 67, 58],
229
- 'sex': [1, 1, 0, 0, 1],
230
- 'cp': [3, 4, 2, 3, 4],
231
- 'trestbps': [125, 145, 130, 120, 136],
232
- 'chol': [212, 233, 204, 228, 319],
233
- 'fbs': [0, 1, 0, 0, 0],
234
- 'restecg': [0, 1, 0, 1, 0],
235
- 'thalach': [168, 150, 172, 129, 152],
236
- 'exang': [0, 0, 0, 1, 0],
237
- 'oldpeak': [1.0, 2.3, 1.4, 2.6, 0.0],
238
- 'slope': [2, 3, 1, 2, 1],
239
- 'ca': [2, 0, 0, 1, 0],
240
- 'thal': [3, 3, 3, 7, 3]
241
- })
242
-
243
- with tab3:
244
- st.header("Data & Model Information")
245
-
246
- st.subheader("Dataset Information")
247
- st.markdown("""
248
- The model was trained on the UCI Heart Disease Dataset containing the following features:
249
- - **Demographic**: Age, Sex
250
- - **Clinical**: Blood Pressure, Cholesterol, etc.
251
- - **Electrocardiographic**: Resting ECG, Exercise ST segment, etc.
252
- """)
253
-
254
- st.subheader("Sample Data")
255
- st.dataframe(sample_data)
256
-
257
- st.subheader("Model Performance")
258
- st.markdown("""
259
- - **Accuracy**: 85.2% (on test set)
260
- - **Precision**: 83.1%
261
- - **Recall**: 87.5%
262
- - **F1-score**: 85.2%
263
-
264
- **📈 Additional Metrics:**
265
- - **ROC AUC:** `0.909`
266
- - **Sensitivity (Recall):** `0.95` _(for Heart Disease)_
267
- - **Specificity:** `0.76` _(for Healthy)_
268
- - **Balanced Accuracy:** `0.855`
269
- - **False Positive Rate (FPR):** `0.24`
270
- - **False Negative Rate (FNR):** `0.05`
271
- - **Precision (Heart Disease):** `0.80`
272
- - **Precision (Healthy):** `0.95`
273
- - **F1 Score (Overall):** `0.85`
274
- - **Support Size:** `46` patients
275
- """)
276
-
277
- st.subheader("Risk Interpretation Guide")
278
- st.markdown("""
279
- - **High Risk (>70%)**: Strong recommendation for cardiologist consultation
280
- - **Medium Risk (40-70%)**: Suggest additional tests
281
- - **Low Risk (<40%)**: Likely healthy, maintain regular checkups
282
- """)
283
-
284
- st.subheader("Terms of Use")
285
- st.markdown("""
286
- This tool is for informational purposes only and should not replace
287
- professional medical advice. Always consult a healthcare provider
288
- for medical diagnosis and treatment.
289
- """)
290
-
291
- # Sidebar with info
292
- with st.sidebar:
293
- st.title("❤️ Heart Disease Prediction")
294
- st.markdown("""
295
- ## About This App
296
- This application predicts the likelihood of heart disease based on clinical features using a machine learning model.
297
-
298
- ### Model Information
299
- - **Algorithm**: Random Forest Classifier
300
- - **Dataset**: UCI Heart Disease Dataset
301
- - **Optimal Threshold**: {:.3f}
302
- - **Version**: 1.1
303
-
304
- ### How It Works
305
- 1. Enter patient details
306
- 2. Click 'Predict' button
307
- 3. View prediction results
308
- """.format(optimal_threshold))
309
-
310
- st.markdown("---")
311
- st.markdown("""
312
- ### Feature Descriptions
313
- - **Age**: Patient's age in years
314
- - **Sex**: Gender (1 = Male, 0 = Female)
315
- - **CP**: Chest pain type (1-4)
316
- - **Trestbps**: Resting blood pressure (mmHg)
317
- - **Chol**: Serum cholesterol (mg/dl)
318
- - **FBS**: Fasting blood sugar > 120 mg/dl
319
- - **Restecg**: Resting ECG results
320
- - **Thalach**: Maximum heart rate achieved
321
- - **Exang**: Exercise induced angina
322
- - **Oldpeak**: ST depression induced by exercise
323
- - **Slope**: Slope of peak exercise ST segment
324
- - **CA**: Number of major vessels colored by fluoroscopy
325
- - **Thal**: Thalassemia (3,6,7)
326
- """)
327
- if __name__ == "__main__":
328
- st.run()
 
1
+ import streamlit as st
2
+ import joblib
3
+ import pandas as pd
4
+
5
+
6
+ # Page config
7
+ st.set_page_config(
8
+ page_title="❤️ Heart Disease Prediction System",
9
+ page_icon="❤️",
10
+ layout="wide",
11
+ initial_sidebar_state="expanded"
12
+ )
13
+
14
+
15
+ # trained model
16
+ @st.cache_resource
17
+ def load_model():
18
+ try:
19
+ production_model = joblib.load('models/uci_heart_disease_model.pkl')
20
+ return production_model['model'], production_model['metadata']['threshold']
21
+ except Exception as e:
22
+ st.error(f"Error loading model: {e}")
23
+ st.stop()
24
+
25
+
26
+ model, optimal_threshold = load_model()
27
+
28
+
29
+
30
+ def predict_heart_disease(user_input):
31
+ try:
32
+ # Feature engineering
33
+ user_input['hr_age_ratio'] = user_input['thalach'] / (user_input['age'] + 1e-5)
34
+ user_input['bp_oldpeak'] = user_input['trestbps'] * (user_input['oldpeak'] + 1)
35
+ user_input['risk_score'] = (user_input['age'] / 50 + user_input['chol'] / 200 + user_input['trestbps'] / 140)
36
+
37
+ #prediction
38
+ probabilities = model.predict_proba(user_input)[:, 1]
39
+ predictions = (probabilities >= optimal_threshold).astype(int)
40
+
41
+ # results DataFrame
42
+ results = pd.DataFrame({
43
+ 'Prediction': predictions,
44
+ 'Diagnosis': ['Heart Disease' if p == 1 else 'Healthy' for p in predictions],
45
+ 'Probability': probabilities,
46
+ })
47
+
48
+ # input features for display
49
+ display_data = pd.concat([user_input[['age', 'sex', 'cp', 'trestbps', 'chol']], results], axis=1)
50
+
51
+ return results, display_data
52
+
53
+ except Exception as e:
54
+ st.error(f"Prediction error: {e}")
55
+ return None, None
56
+
57
+
58
+ # Main app interface
59
+ st.title("❤️ Heart Disease Prediction")
60
+
61
+ # tabs
62
+ tab1, tab2 ,tab3= st.tabs(["Single Prediction", "Batch Prediction","Data & Model Info"])
63
+
64
+ with tab1:
65
+ st.header("Single Patient Prediction")
66
+
67
+ # Input form
68
+ with st.form("prediction_form"):
69
+ col1, col2 = st.columns(2)
70
+
71
+ with col1:
72
+ st.subheader("Patient Information")
73
+ age = st.slider("Age", 18, 100, 50)
74
+ sex = st.radio("Sex", ["Male (1)", "Female (0)"], index=0)
75
+ cp = st.selectbox("Chest Pain Type",
76
+ ["Typical angina (1)", "Atypical angina (2)",
77
+ "Non-anginal pain (3)", "Asymptomatic (4)"])
78
+ trestbps = st.slider("Resting Blood Pressure (mmHg)", 90, 200, 120)
79
+ chol = st.slider("Serum Cholesterol (mg/dl)", 150, 350, 200)
80
+
81
+ with col2:
82
+ st.subheader("Clinical Measurements")
83
+ fbs = st.radio("Fasting Blood Sugar > 120 mg/dl", ["Yes (1)", "No (0)"], index=1)
84
+ restecg = st.selectbox("Resting ECG Results",
85
+ ["Normal (0)", "ST-T wave abnormality (1)",
86
+ "Left ventricular hypertrophy (2)"])
87
+ thalach = st.slider("Maximum Heart Rate Achieved (bpm)", 60, 200, 150)
88
+ exang = st.radio("Exercise Induced Angina", ["Yes (1)", "No (0)"], index=1)
89
+ oldpeak = st.slider("ST Depression Induced by Exercise", 0.0, 6.0, 1.0, step=0.1)
90
+ slope = st.selectbox("Slope of Peak Exercise ST Segment",
91
+ ["Upsloping (1)", "Flat (2)", "Downsloping (3)"])
92
+ ca = st.slider("Number of Major Vessels", 0, 4, 0)
93
+ thal = st.selectbox("Thalassemia",
94
+ ["Normal (3)", "Fixed defect (6)", "Reversible defect (7)"])
95
+
96
+ submitted = st.form_submit_button("Predict Heart Disease Risk")
97
+
98
+ if submitted:
99
+ # Preprocess inputs
100
+ user_input = pd.DataFrame({
101
+ 'age': [age],
102
+ 'sex': [1 if sex.startswith("Male") else 0],
103
+ 'cp': [int(cp.split("(")[1].strip(")"))],
104
+ 'trestbps': [trestbps],
105
+ 'chol': [chol],
106
+ 'fbs': [1 if fbs.startswith("Yes") else 0],
107
+ 'restecg': [int(restecg.split("(")[1].strip(")"))],
108
+ 'thalach': [thalach],
109
+ 'exang': [1 if exang.startswith("Yes") else 0],
110
+ 'oldpeak': [oldpeak],
111
+ 'slope': [int(slope.split("(")[1].strip(")"))],
112
+ 'ca': [ca],
113
+ 'thal': [int(thal.split("(")[1].strip(")"))],
114
+ })
115
+
116
+ # predictions
117
+ results, display_data = predict_heart_disease(user_input)
118
+
119
+ if results is not None:
120
+ st.subheader("Prediction Results")
121
+
122
+ # formatted results
123
+ st.markdown(f"""
124
+ ### Heart Disease Prediction Results
125
+ **Using threshold:** {optimal_threshold:.3f}
126
+ """)
127
+
128
+ # results section
129
+ with st.expander("View Detailed Results"):
130
+ st.dataframe(display_data)
131
+
132
+ # risk assessment
133
+ probability = results['Probability'].iloc[0]
134
+ prediction = results['Diagnosis'].iloc[0]
135
+
136
+ if probability > 0.7:
137
+ risk_level = "High"
138
+ recommendation = "Immediate consultation with cardiologist recommended"
139
+ color = "red"
140
+ elif probability > 0.4:
141
+ risk_level = "Medium"
142
+ recommendation = "Further tests recommended"
143
+ color = "orange"
144
+ else:
145
+ risk_level = "Low"
146
+ recommendation = "No immediate concerns, maintain regular checkups"
147
+ color = "green"
148
+
149
+
150
+ col1, col2, col3 = st.columns(3)
151
+ with col1:
152
+ st.metric("Prediction", prediction)
153
+ with col2:
154
+ st.metric("Probability", f"{probability * 100:.2f}%")
155
+ with col3:
156
+ st.metric("Risk Level", risk_level)
157
+
158
+ # recommendation
159
+ st.markdown(f"""
160
+ <div style='background-color:#f0f2f6; padding:10px; border-radius:5px;'>
161
+ <h4 style='color:{color};'>Recommendation: {recommendation}</h4>
162
+ </div>
163
+ """, unsafe_allow_html=True)
164
+
165
+ with tab2:
166
+ st.header("Batch Prediction")
167
+
168
+ uploaded_file = st.file_uploader("Upload CSV file with patient data", type=["csv"])
169
+
170
+ if uploaded_file is not None:
171
+ try:
172
+ test_data = pd.read_csv(uploaded_file)
173
+ st.success("File uploaded successfully!")
174
+
175
+ # required columns
176
+ required_cols = ['age', 'sex', 'cp', 'trestbps', 'chol', 'fbs', 'restecg',
177
+ 'thalach', 'exang', 'oldpeak', 'slope', 'ca', 'thal']
178
+
179
+ missing_cols = [col for col in required_cols if col not in test_data.columns]
180
+ if missing_cols:
181
+ st.error(f"Missing required columns: {', '.join(missing_cols)}")
182
+ else:
183
+ # predictions
184
+ results, display_data = predict_heart_disease(test_data)
185
+
186
+ if results is not None:
187
+ st.subheader("Prediction Results")
188
+
189
+ # summary statistics
190
+ st.markdown(f"""
191
+ ### Batch Prediction Results
192
+ **Using threshold:** {optimal_threshold:.3f}
193
+ """)
194
+
195
+ # results with original data
196
+ full_results = test_data.copy()
197
+ full_results['Probability'] = results['Probability']
198
+ full_results['Prediction'] = results['Prediction']
199
+ full_results['Diagnosis'] = results['Diagnosis']
200
+
201
+ # results section
202
+ with st.expander("View All Predictions"):
203
+ st.dataframe(full_results)
204
+
205
+ # statistics
206
+ st.subheader("Statistics")
207
+ col1, col2, col3 = st.columns(3)
208
+ with col1:
209
+ st.metric("Total Patients", len(full_results))
210
+ with col2:
211
+ st.metric("Heart Disease Cases", full_results['Prediction'].sum())
212
+ with col3:
213
+ st.metric("Healthy Cases", len(full_results) - full_results['Prediction'].sum())
214
+
215
+ #download button
216
+ csv = full_results.to_csv(index=False)
217
+ st.download_button(
218
+ "Download Results",
219
+ csv,
220
+ "heart_disease_predictions.csv",
221
+ "text/csv"
222
+ )
223
+
224
+ except Exception as e:
225
+ st.error(f"Error processing file: {e}")
226
+
227
+ sample_data = pd.DataFrame({
228
+ 'age': [52, 63, 45, 67, 58],
229
+ 'sex': [1, 1, 0, 0, 1],
230
+ 'cp': [3, 4, 2, 3, 4],
231
+ 'trestbps': [125, 145, 130, 120, 136],
232
+ 'chol': [212, 233, 204, 228, 319],
233
+ 'fbs': [0, 1, 0, 0, 0],
234
+ 'restecg': [0, 1, 0, 1, 0],
235
+ 'thalach': [168, 150, 172, 129, 152],
236
+ 'exang': [0, 0, 0, 1, 0],
237
+ 'oldpeak': [1.0, 2.3, 1.4, 2.6, 0.0],
238
+ 'slope': [2, 3, 1, 2, 1],
239
+ 'ca': [2, 0, 0, 1, 0],
240
+ 'thal': [3, 3, 3, 7, 3]
241
+ })
242
+
243
+ with tab3:
244
+ st.header("Data & Model Information")
245
+
246
+ st.subheader("Dataset Information")
247
+ st.markdown("""
248
+ The model was trained on the UCI Heart Disease Dataset containing the following features:
249
+ - **Demographic**: Age, Sex
250
+ - **Clinical**: Blood Pressure, Cholesterol, etc.
251
+ - **Electrocardiographic**: Resting ECG, Exercise ST segment, etc.
252
+ """)
253
+
254
+ st.subheader("Sample Data")
255
+ st.dataframe(sample_data)
256
+
257
+ st.subheader("Model Performance")
258
+ st.markdown("""
259
+ - **Accuracy**: 85.2% (on test set)
260
+ - **Precision**: 83.1%
261
+ - **Recall**: 87.5%
262
+ - **F1-score**: 85.2%
263
+
264
+ **📈 Additional Metrics:**
265
+ - **ROC AUC:** `0.909`
266
+ - **Sensitivity (Recall):** `0.95` _(for Heart Disease)_
267
+ - **Specificity:** `0.76` _(for Healthy)_
268
+ - **Balanced Accuracy:** `0.855`
269
+ - **False Positive Rate (FPR):** `0.24`
270
+ - **False Negative Rate (FNR):** `0.05`
271
+ - **Precision (Heart Disease):** `0.80`
272
+ - **Precision (Healthy):** `0.95`
273
+ - **F1 Score (Overall):** `0.85`
274
+ - **Support Size:** `46` patients
275
+ """)
276
+
277
+ st.subheader("Risk Interpretation Guide")
278
+ st.markdown("""
279
+ - **High Risk (>70%)**: Strong recommendation for cardiologist consultation
280
+ - **Medium Risk (40-70%)**: Suggest additional tests
281
+ - **Low Risk (<40%)**: Likely healthy, maintain regular checkups
282
+ """)
283
+
284
+ st.subheader("Terms of Use")
285
+ st.markdown("""
286
+ This tool is for informational purposes only and should not replace
287
+ professional medical advice. Always consult a healthcare provider
288
+ for medical diagnosis and treatment.
289
+ """)
290
+
291
+ # Sidebar with info
292
+ with st.sidebar:
293
+ st.title("❤️ Heart Disease Prediction")
294
+ st.markdown("""
295
+ ## About This App
296
+ This application predicts the likelihood of heart disease based on clinical features using a machine learning model.
297
+
298
+ ### Model Information
299
+ - **Algorithm**: Random Forest Classifier
300
+ - **Dataset**: UCI Heart Disease Dataset
301
+ - **Optimal Threshold**: {:.3f}
302
+ - **Version**: 1.1
303
+
304
+ ### How It Works
305
+ 1. Enter patient details
306
+ 2. Click 'Predict' button
307
+ 3. View prediction results
308
+ """.format(optimal_threshold))
309
+
310
+ st.markdown("---")
311
+ st.markdown("""
312
+ ### Feature Descriptions
313
+ - **Age**: Patient's age in years
314
+ - **Sex**: Gender (1 = Male, 0 = Female)
315
+ - **CP**: Chest pain type (1-4)
316
+ - **Trestbps**: Resting blood pressure (mmHg)
317
+ - **Chol**: Serum cholesterol (mg/dl)
318
+ - **FBS**: Fasting blood sugar > 120 mg/dl
319
+ - **Restecg**: Resting ECG results
320
+ - **Thalach**: Maximum heart rate achieved
321
+ - **Exang**: Exercise induced angina
322
+ - **Oldpeak**: ST depression induced by exercise
323
+ - **Slope**: Slope of peak exercise ST segment
324
+ - **CA**: Number of major vessels colored by fluoroscopy
325
+ - **Thal**: Thalassemia (3,6,7)
326
+ """)
327
+