mr-usman commited on
Commit
fd6fbf7
·
verified ·
1 Parent(s): dcff38b

Upload 16 files

Browse files
colelithiasis_dataset.xlsx ADDED
Binary file (16.7 kB). View file
 
encoder.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f931d3e82fc7ab6868eb41036e2c84c14dc0efb7920b70d0a0a547f7e4975155
3
+ size 1604
gda.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1062eb7b2283f57c001ad6546390ac969fec7aa91d55182947db1307887cc256
3
+ size 3224
health_status_classification.ipynb ADDED
@@ -0,0 +1,569 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "id": "7abd29b8",
6
+ "metadata": {},
7
+ "source": [
8
+ "# Health Status Classification\n",
9
+ "\n",
10
+ "This notebook classifies individuals into \"Healthy\" or \"Patient\" categories using SVM and Random Forest classifiers. It includes:\n",
11
+ "- Data preprocessing\n",
12
+ "- Training of classifiers\n",
13
+ "- Comparison of performance metrics\n",
14
+ "- Visualization of results\n"
15
+ ]
16
+ },
17
+ {
18
+ "cell_type": "markdown",
19
+ "id": "299604b4",
20
+ "metadata": {},
21
+ "source": [
22
+ "## Data Preprocessing"
23
+ ]
24
+ },
25
+ {
26
+ "cell_type": "markdown",
27
+ "id": "22ee7ce2",
28
+ "metadata": {},
29
+ "source": [
30
+ "### 1. Import Dependecies"
31
+ ]
32
+ },
33
+ {
34
+ "cell_type": "code",
35
+ "execution_count": 252,
36
+ "id": "76a44a0d",
37
+ "metadata": {},
38
+ "outputs": [],
39
+ "source": [
40
+ "import pandas as pd\n",
41
+ "from sklearn.model_selection import train_test_split\n",
42
+ "from sklearn.preprocessing import StandardScaler, LabelEncoder\n",
43
+ "from sklearn.svm import SVC\n",
44
+ "from sklearn.ensemble import RandomForestClassifier\n",
45
+ "from sklearn.metrics import classification_report, confusion_matrix, accuracy_score\n",
46
+ "import matplotlib.pyplot as plt\n",
47
+ "import seaborn as sns"
48
+ ]
49
+ },
50
+ {
51
+ "cell_type": "markdown",
52
+ "id": "a27c6dc7",
53
+ "metadata": {},
54
+ "source": [
55
+ "### 2. Load Dataset"
56
+ ]
57
+ },
58
+ {
59
+ "cell_type": "code",
60
+ "execution_count": 253,
61
+ "id": "3772870e",
62
+ "metadata": {},
63
+ "outputs": [
64
+ {
65
+ "data": {
66
+ "text/html": [
67
+ "<div>\n",
68
+ "<style scoped>\n",
69
+ " .dataframe tbody tr th:only-of-type {\n",
70
+ " vertical-align: middle;\n",
71
+ " }\n",
72
+ "\n",
73
+ " .dataframe tbody tr th {\n",
74
+ " vertical-align: top;\n",
75
+ " }\n",
76
+ "\n",
77
+ " .dataframe thead th {\n",
78
+ " text-align: right;\n",
79
+ " }\n",
80
+ "</style>\n",
81
+ "<table border=\"1\" class=\"dataframe\">\n",
82
+ " <thead>\n",
83
+ " <tr style=\"text-align: right;\">\n",
84
+ " <th></th>\n",
85
+ " <th>Patient No.</th>\n",
86
+ " <th>Gender</th>\n",
87
+ " <th>Age</th>\n",
88
+ " <th>Family history</th>\n",
89
+ " <th>Height</th>\n",
90
+ " <th>Weight</th>\n",
91
+ " <th>BMI</th>\n",
92
+ " <th>Obese/non obese</th>\n",
93
+ " <th>Cholesterol</th>\n",
94
+ " <th>Triglycerides level</th>\n",
95
+ " <th>HDL level</th>\n",
96
+ " <th>LDL level</th>\n",
97
+ " <th>VLDL level</th>\n",
98
+ " <th>Health_status</th>\n",
99
+ " </tr>\n",
100
+ " </thead>\n",
101
+ " <tbody>\n",
102
+ " <tr>\n",
103
+ " <th>0</th>\n",
104
+ " <td>1</td>\n",
105
+ " <td>Female</td>\n",
106
+ " <td>65</td>\n",
107
+ " <td>No</td>\n",
108
+ " <td>1.64</td>\n",
109
+ " <td>64</td>\n",
110
+ " <td>23.80</td>\n",
111
+ " <td>Non-obese</td>\n",
112
+ " <td>145</td>\n",
113
+ " <td>119</td>\n",
114
+ " <td>60</td>\n",
115
+ " <td>66.0</td>\n",
116
+ " <td>19.0</td>\n",
117
+ " <td>healthy</td>\n",
118
+ " </tr>\n",
119
+ " <tr>\n",
120
+ " <th>1</th>\n",
121
+ " <td>2</td>\n",
122
+ " <td>Female</td>\n",
123
+ " <td>50</td>\n",
124
+ " <td>Yes</td>\n",
125
+ " <td>1.70</td>\n",
126
+ " <td>70</td>\n",
127
+ " <td>24.22</td>\n",
128
+ " <td>Non-obese</td>\n",
129
+ " <td>220</td>\n",
130
+ " <td>107</td>\n",
131
+ " <td>69</td>\n",
132
+ " <td>134.0</td>\n",
133
+ " <td>17.0</td>\n",
134
+ " <td>healthy</td>\n",
135
+ " </tr>\n",
136
+ " <tr>\n",
137
+ " <th>2</th>\n",
138
+ " <td>3</td>\n",
139
+ " <td>Female</td>\n",
140
+ " <td>45</td>\n",
141
+ " <td>No</td>\n",
142
+ " <td>1.67</td>\n",
143
+ " <td>63</td>\n",
144
+ " <td>22.59</td>\n",
145
+ " <td>Non-obese</td>\n",
146
+ " <td>190</td>\n",
147
+ " <td>251</td>\n",
148
+ " <td>42</td>\n",
149
+ " <td>108.0</td>\n",
150
+ " <td>40.0</td>\n",
151
+ " <td>healthy</td>\n",
152
+ " </tr>\n",
153
+ " <tr>\n",
154
+ " <th>3</th>\n",
155
+ " <td>4</td>\n",
156
+ " <td>Female</td>\n",
157
+ " <td>48</td>\n",
158
+ " <td>No</td>\n",
159
+ " <td>1.61</td>\n",
160
+ " <td>79</td>\n",
161
+ " <td>30.48</td>\n",
162
+ " <td>Obese</td>\n",
163
+ " <td>228</td>\n",
164
+ " <td>185</td>\n",
165
+ " <td>65</td>\n",
166
+ " <td>134.0</td>\n",
167
+ " <td>29.0</td>\n",
168
+ " <td>healthy</td>\n",
169
+ " </tr>\n",
170
+ " <tr>\n",
171
+ " <th>4</th>\n",
172
+ " <td>5</td>\n",
173
+ " <td>Male</td>\n",
174
+ " <td>74</td>\n",
175
+ " <td>No</td>\n",
176
+ " <td>1.76</td>\n",
177
+ " <td>83</td>\n",
178
+ " <td>26.79</td>\n",
179
+ " <td>Non-obese</td>\n",
180
+ " <td>157</td>\n",
181
+ " <td>113</td>\n",
182
+ " <td>49</td>\n",
183
+ " <td>90.0</td>\n",
184
+ " <td>18.0</td>\n",
185
+ " <td>healthy</td>\n",
186
+ " </tr>\n",
187
+ " </tbody>\n",
188
+ "</table>\n",
189
+ "</div>"
190
+ ],
191
+ "text/plain": [
192
+ " Patient No. Gender Age Family history Height Weight BMI \\\n",
193
+ "0 1 Female 65 No 1.64 64 23.80 \n",
194
+ "1 2 Female 50 Yes 1.70 70 24.22 \n",
195
+ "2 3 Female 45 No 1.67 63 22.59 \n",
196
+ "3 4 Female 48 No 1.61 79 30.48 \n",
197
+ "4 5 Male 74 No 1.76 83 26.79 \n",
198
+ "\n",
199
+ " Obese/non obese Cholesterol Triglycerides level HDL level LDL level \\\n",
200
+ "0 Non-obese 145 119 60 66.0 \n",
201
+ "1 Non-obese 220 107 69 134.0 \n",
202
+ "2 Non-obese 190 251 42 108.0 \n",
203
+ "3 Obese 228 185 65 134.0 \n",
204
+ "4 Non-obese 157 113 49 90.0 \n",
205
+ "\n",
206
+ " VLDL level Health_status \n",
207
+ "0 19.0 healthy \n",
208
+ "1 17.0 healthy \n",
209
+ "2 40.0 healthy \n",
210
+ "3 29.0 healthy \n",
211
+ "4 18.0 healthy "
212
+ ]
213
+ },
214
+ "execution_count": 253,
215
+ "metadata": {},
216
+ "output_type": "execute_result"
217
+ }
218
+ ],
219
+ "source": [
220
+ "# Load dataset\n",
221
+ "data = pd.read_excel(r'colelithiasis_dataset.xlsx')\n",
222
+ "data.head()"
223
+ ]
224
+ },
225
+ {
226
+ "cell_type": "code",
227
+ "execution_count": 9,
228
+ "id": "7edf91ac",
229
+ "metadata": {},
230
+ "outputs": [
231
+ {
232
+ "name": "stdout",
233
+ "output_type": "stream",
234
+ "text": [
235
+ "<class 'pandas.core.frame.DataFrame'>\n",
236
+ "RangeIndex: 100 entries, 0 to 99\n",
237
+ "Data columns (total 14 columns):\n",
238
+ " # Column Non-Null Count Dtype \n",
239
+ "--- ------ -------------- ----- \n",
240
+ " 0 Patient No. 100 non-null int64 \n",
241
+ " 1 Gender 100 non-null object \n",
242
+ " 2 Age 100 non-null int64 \n",
243
+ " 3 Family history 100 non-null object \n",
244
+ " 4 Height 100 non-null float64\n",
245
+ " 5 Weight 100 non-null int64 \n",
246
+ " 6 BMI 100 non-null float64\n",
247
+ " 7 Obese/non obese 100 non-null object \n",
248
+ " 8 Cholesterol 100 non-null int64 \n",
249
+ " 9 Triglycerides level 100 non-null int64 \n",
250
+ " 10 HDL level 100 non-null int64 \n",
251
+ " 11 LDL level 100 non-null float64\n",
252
+ " 12 VLDL level 100 non-null float64\n",
253
+ " 13 Health_status 100 non-null object \n",
254
+ "dtypes: float64(4), int64(6), object(4)\n",
255
+ "memory usage: 11.1+ KB\n"
256
+ ]
257
+ }
258
+ ],
259
+ "source": [
260
+ "data.info()"
261
+ ]
262
+ },
263
+ {
264
+ "cell_type": "code",
265
+ "execution_count": 10,
266
+ "id": "aae142a0",
267
+ "metadata": {},
268
+ "outputs": [
269
+ {
270
+ "data": {
271
+ "text/plain": [
272
+ "Health_status\n",
273
+ "patient 60\n",
274
+ "healthy 40\n",
275
+ "Name: count, dtype: int64"
276
+ ]
277
+ },
278
+ "execution_count": 10,
279
+ "metadata": {},
280
+ "output_type": "execute_result"
281
+ }
282
+ ],
283
+ "source": [
284
+ "data['Health_status'].value_counts()"
285
+ ]
286
+ },
287
+ {
288
+ "cell_type": "code",
289
+ "execution_count": 11,
290
+ "id": "aafe0526",
291
+ "metadata": {},
292
+ "outputs": [],
293
+ "source": [
294
+ "# Drop unnecessary columns (e.g., Patient No.)\n",
295
+ "data = data.drop(columns=['Patient No.'])"
296
+ ]
297
+ },
298
+ {
299
+ "cell_type": "markdown",
300
+ "id": "c7907326",
301
+ "metadata": {},
302
+ "source": [
303
+ "### 3. Feature Encoding"
304
+ ]
305
+ },
306
+ {
307
+ "cell_type": "code",
308
+ "execution_count": 12,
309
+ "id": "7f22b9a6",
310
+ "metadata": {},
311
+ "outputs": [],
312
+ "source": [
313
+ "# Encode categorical variables\n",
314
+ "le_health_status = LabelEncoder()\n",
315
+ "data['Health_status'] = le_health_status.fit_transform(data['Health_status']) # 0 for healthy, 1 for patient\n",
316
+ "le_gender = LabelEncoder()\n",
317
+ "data['Gender'] = le_gender.fit_transform(data['Gender']) # 0 for Female, 1 for Male\n",
318
+ "le_family_history = LabelEncoder()\n",
319
+ "data['Family history'] = le_family_history.fit_transform(data['Family history']) # 0 for No, 1 for Yes\n",
320
+ "le_obese = LabelEncoder()\n",
321
+ "data['Obese/non obese'] = le_obese.fit_transform(data['Obese/non obese']) # 0 for Non-obese, 1 for Obese"
322
+ ]
323
+ },
324
+ {
325
+ "cell_type": "markdown",
326
+ "id": "bcf93f5f",
327
+ "metadata": {},
328
+ "source": [
329
+ "### 4. Split features and target"
330
+ ]
331
+ },
332
+ {
333
+ "cell_type": "code",
334
+ "execution_count": 13,
335
+ "id": "eab4be22",
336
+ "metadata": {},
337
+ "outputs": [],
338
+ "source": [
339
+ "# Features and target\n",
340
+ "X = data.drop(columns=['Health_status'])\n",
341
+ "y = data['Health_status']\n"
342
+ ]
343
+ },
344
+ {
345
+ "cell_type": "markdown",
346
+ "id": "c5ed059c",
347
+ "metadata": {},
348
+ "source": [
349
+ "### 5. Split data into training and testing sets"
350
+ ]
351
+ },
352
+ {
353
+ "cell_type": "code",
354
+ "execution_count": 244,
355
+ "id": "cdeca4f2",
356
+ "metadata": {},
357
+ "outputs": [],
358
+ "source": [
359
+ "# Split the data\n",
360
+ "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)"
361
+ ]
362
+ },
363
+ {
364
+ "cell_type": "markdown",
365
+ "id": "0558f2c8",
366
+ "metadata": {},
367
+ "source": [
368
+ "### 6. Scalling the features"
369
+ ]
370
+ },
371
+ {
372
+ "cell_type": "code",
373
+ "execution_count": 245,
374
+ "id": "a037923f",
375
+ "metadata": {},
376
+ "outputs": [],
377
+ "source": [
378
+ "# Scale the features using StandardScaler\n",
379
+ "scaler = StandardScaler()\n",
380
+ "X_train = scaler.fit_transform(X_train)\n",
381
+ "X_test = scaler.transform(X_test)"
382
+ ]
383
+ },
384
+ {
385
+ "cell_type": "markdown",
386
+ "id": "d934c22c",
387
+ "metadata": {},
388
+ "source": [
389
+ "## Training of classifiers"
390
+ ]
391
+ },
392
+ {
393
+ "cell_type": "markdown",
394
+ "id": "c7fd1e71",
395
+ "metadata": {},
396
+ "source": [
397
+ "### 1. Support Vector Machine (SVM)"
398
+ ]
399
+ },
400
+ {
401
+ "cell_type": "code",
402
+ "execution_count": 246,
403
+ "id": "aca26b71",
404
+ "metadata": {},
405
+ "outputs": [],
406
+ "source": [
407
+ "# SVM Classifier\n",
408
+ "svm_model = SVC(kernel='linear', C=0.9, random_state=42)\n",
409
+ "svm_model.fit(X_train, y_train)\n",
410
+ "svm_preds = svm_model.predict(X_test)"
411
+ ]
412
+ },
413
+ {
414
+ "cell_type": "markdown",
415
+ "id": "e8bfefa5",
416
+ "metadata": {},
417
+ "source": [
418
+ "### 2. Random Forest Classifier"
419
+ ]
420
+ },
421
+ {
422
+ "cell_type": "code",
423
+ "execution_count": 247,
424
+ "id": "a5ad9d40",
425
+ "metadata": {},
426
+ "outputs": [],
427
+ "source": [
428
+ "# Random Forest Classifier\n",
429
+ "rf_model = RandomForestClassifier(n_estimators=100, class_weight='balanced', random_state=42)\n",
430
+ "rf_model.fit(X_train, y_train)\n",
431
+ "rf_preds = rf_model.predict(X_test)"
432
+ ]
433
+ },
434
+ {
435
+ "cell_type": "markdown",
436
+ "id": "e3fb4a5a",
437
+ "metadata": {},
438
+ "source": [
439
+ "## Comparison of performance metrics"
440
+ ]
441
+ },
442
+ {
443
+ "cell_type": "code",
444
+ "execution_count": 249,
445
+ "id": "2ddc5b12",
446
+ "metadata": {},
447
+ "outputs": [
448
+ {
449
+ "name": "stdout",
450
+ "output_type": "stream",
451
+ "text": [
452
+ "\n",
453
+ "Performance Metrics for SVM\n",
454
+ "Accuracy: 0.65\n",
455
+ "\n",
456
+ "Classification Report:\n",
457
+ " precision recall f1-score support\n",
458
+ "\n",
459
+ " 0 0.55 0.75 0.63 8\n",
460
+ " 1 0.78 0.58 0.67 12\n",
461
+ "\n",
462
+ " accuracy 0.65 20\n",
463
+ " macro avg 0.66 0.67 0.65 20\n",
464
+ "weighted avg 0.68 0.65 0.65 20\n",
465
+ "\n",
466
+ "\n",
467
+ "Performance Metrics for Random Forest\n",
468
+ "Accuracy: 0.7\n",
469
+ "\n",
470
+ "Classification Report:\n",
471
+ " precision recall f1-score support\n",
472
+ "\n",
473
+ " 0 0.60 0.75 0.67 8\n",
474
+ " 1 0.80 0.67 0.73 12\n",
475
+ "\n",
476
+ " accuracy 0.70 20\n",
477
+ " macro avg 0.70 0.71 0.70 20\n",
478
+ "weighted avg 0.72 0.70 0.70 20\n",
479
+ "\n"
480
+ ]
481
+ }
482
+ ],
483
+ "source": [
484
+ "def print_metrics(y_true, y_pred, model_name):\n",
485
+ " print(f\"\\nPerformance Metrics for {model_name}\")\n",
486
+ " print(\"Accuracy:\", accuracy_score(y_true, y_pred))\n",
487
+ " print(\"\\nClassification Report:\")\n",
488
+ " print(classification_report(y_true, y_pred))\n",
489
+ "\n",
490
+ "print_metrics(y_test, svm_preds, \"SVM\")\n",
491
+ "print_metrics(y_test, rf_preds, \"Random Forest\")"
492
+ ]
493
+ },
494
+ {
495
+ "cell_type": "markdown",
496
+ "id": "38eefbb6",
497
+ "metadata": {},
498
+ "source": [
499
+ "## Visualization of results"
500
+ ]
501
+ },
502
+ {
503
+ "cell_type": "code",
504
+ "execution_count": 251,
505
+ "id": "f74a2f74",
506
+ "metadata": {},
507
+ "outputs": [
508
+ {
509
+ "data": {
510
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAABHoAAAHqCAYAAAB7kSmRAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAUB1JREFUeJzt3Qm8VGX9OP5nLiogAm4goKKWK+KKZuaWW2ZGLqVlmrjUNw0XJEzp9zU1FdA2Tc0tUyvX3CuN1ETTIhGXXFJx19TccAEVDe7/9Tnf/wz3Xi9wr3funXvOvN++jjBn5p555sxczmc+z+d5nlJjY2NjAgAAACD3GmrdAAAAAACqQ6IHAAAAoCAkegAAAAAKQqIHAAAAoCAkegAAAAAKQqIHAAAAoCAkegAAAAAKQqIHAAAAoCAkegAAAAAKQqIH6tyPfvSj9IlPfCL16NEjbbjhhlU//v77759WXXXVqh83r6ZMmZJKpVL2JwBUg2tt/Zk1a1b65je/mQYNGpTFFWPGjKn6c8RnKj5b/J/jjz8+O9eQBxI9FNaDDz6YvvKVr6RVVlkl9erVK6244oppxx13TGeccUZ2/7333pv9Y/2///u/CzzGjBkzsseMHTu22T/wDQ0N6fnnn//I499+++3Uu3fv7DGHHnpom9o5d+7cdOGFF6bPfvazadlll009e/bMLqwHHHBAuueee1Jn+vOf/5y+973vpS222CJrw4QJE1JRPPPMM9n7ENtJJ53U6mP22Wef7P6lllrqYz3HpZdemk477bQOthSAvLjooosq15bYFltssSy+iC/D//73v2vdvG57nppuxxxzTOqOIga67rrr2vUzEfedcMIJaYMNNshiiYgBhw8fno4++uj04osvps5ub5znQw45JP3mN79J3/jGN1IRPz933nnnR+5vbGxMK6+8cnb/F7/4xS57vyFPFqt1A6Az/O1vf0vbbrttGjp0aPrWt76V9XZEYmbq1Knp9NNPT4cddljaeOON09prr50uu+yyBSYC4ot82HfffZvtj2RM/FwkSZq65ppr2tXO9957L+2xxx7pT3/6U9p6663T97///SzZE0mKK6+8Ml188cXpueeeSyuttFLqDH/5y1+ypNUFF1yQllhiiU55jvPPPz/Nmzcv1Uok+eK9apnQmz17drr++uuz+z+u+Hw89NBD7epFi/c53vfOOt8AdL4f/vCHabXVVkvvv/9+FlvEF9P4QhrXhI5cV4p6npqKREh3FF/8o4Nwt912a9Pjn3rqqbTDDjtkcdqee+6Z/ud//ie7tv/zn//M4qprr702Pf74453W3ojhPv3pT6fjjjuu057jsccey+LEWonfpYi1ttxyy2b7b7/99vTCCy9k8XhXvd8hYsnumqiEliR6KKSTTz459e/fP02bNi0tvfTSze575ZVXmlV0HHvssVmQFhfLliJBEMmgSAo19YUvfKHVRE9cjHbZZZd09dVXt6mdRx11VJbk+dnPfvaRZEFcuGN/Z4pzEb1PnZl0WHzxxVMtxXsVCbgHHngg63EriyTPBx98kD7/+c9nwVJniy8DcZ4jYPIlACDfdt5557TJJptkf4/hM8svv3w65ZRT0g033JD22muvWjevW56naorOmj59+qRa+e9//5t11P3nP//JhmK3TEREHBqfh86O4YYNG9apz9GRREq1Yrjf/e536ec//3lWPdc03h4xYkR67bXXuqQd5c9btKFpO6A7M3SLQnryySfTuuuu+5EkTxg4cGCzRE/Typ2mpk+fnvVklB/T1Ne//vV0//33p0cffbSy7+WXX84SBnFfW0RPxLnnnpsNJ2utIiTmzBk3blyzap777rsvC5r69euXlQhvv/32WZKqtXLXu+66KxtyNmDAgOzitPvuu6dXX3218rh4TAzXiotXuTw2frY85Cn+3lLsj+FrZe+8807W9hhqFsFAnNt4PTEsbmHzBsRzfve7383KbuPn1lprrfTjH/84K8Vt+XwxBC5Ka6MHMB4b72skx9pq8803z3oTW77Hl1xySZbkiQqqliIJFAm7IUOGZM/5yU9+Mp144onZMLuyGGr3xz/+MT377LOV81d+neV5eC6//PKs9yfK+pdccsmsxLvlHD3/+te/smTbfvvt16wN0TMcn4Eo/wage9tqq60q8UdZdCb84Ac/yL6QRudTXIvjcbfddluzny1fd+M6eN5552XXnLj2bLrpplmHVUvla2J0GsSfUTnSmvZea+MLdSQO4poU184YAh8iVll99dWz54trX7S3WiJuinMS5yZitl133TW7LjZVHjb/yCOPZDHWMsss0yyx8tvf/jY7x9HuuKZ/7Wtf+8jw+hiK/+Uvfzmr8I7XEbFVPO6tt96qnIM4X1FJXb6mL2xumujQiw6k//f//t9Hkjwh4rRI9jQV57fczkgMRrV4y+F+8ZwR38X+qDSJv0ccF/FgOQYpxxFPP/10FoeU2xvvSzkGbPketTY/4KLOyYLm6IlKpqhginMdsU10lEY7Wnu+qE6P8xDHjueIuPWJJ55IbbX33nun119/Pd18883Nfq+uuuqqBcbb8Rn/zGc+k5ZbbrnsXMc5j8c3tbD3e2Gft5Zz9EQcHbd/9atffaRaKPbfeOONbX6tUG1SkhRSzMvz97//PSuhXliJcCQA4mIQF6Konokv1mXlxEBrF5IYfhMXrXhMlCWHK664IrsgR4KgLW666aasR6itY6offvjhLBiK4CEqiaJSJoKvCLqihHWzzTZr9vgYnhYXp6gMigt+zCUTgVy0M8R47ggo77777vTLX/4y2xfnoj0OPvjg7OIZx43gMC7GkaCIIK1lFVRZBJhf+tKXskD3oIMOyiaAnjx5clbdFIFNyyqmOF5U5HznO99Jffv2zXp1IjCJUum4iLc1UIhAcNKkSdmFN3qAYn6iOAetJY0iUIr3MhJl8WcEohGsR6ImJq8OEdxFMBQJu3KbW871E8mhqOKJAG3OnDmtVk6ts8462ePi9UcJcZybCD4i4IhqsvLnC4Duq/zFOq67ZXHNiOtrXINiGHl0jsSQnp122im79rZcACFiinjMt7/97exadeqpp2ZVI/HFulwdG9euuAbGNXfixInZdTfm9Gs5xLu919q//vWvWTXS6NGjs9tx7Jj7JOKNX/ziF9k1eObMmVmbDjzwwDZXwsZ1smXVRSQ5wi233JJ1XsWCEPEFOoY1xzyKMW9gdBi17CSK5MIaa6yRfYkuJ6siiRCV2VFFFZVV0aEVx4g4LTrHInkUiYE453EdjtgoEhtxDv7whz+kN998M0vCRTwQP/+pT30qG4IVIuG2IHGuQltjuIgr4n2K5F2c26gEiqkEolOu3M6ySOhEeyOui6RFnKef/OQnWXtiPp6IG6K9Rx55ZPa+RzIvREKordpyTloT7Y5Y8d13302HH354FodFsiQ+axEPRqdiUxF3RSVzxEHxWYjPT3Sg/uMf/2hTO+MzEEnHqKKPz0o5fo5jRVIqYsKW4rxGe+J54nVGp1t8duK1lWP0trzfrX3eWor3NGLUiBejozOSqpEgjXmb4vcuKpKgZhqhgP785z839ujRI9s233zzxu9973uNkydPbvzggw8+8tizzjor/vXO7i+bO3du44orrpj9bFPHHXdc9thXX321cdy4cY2rr7565b5NN9208YADDsj+Ho8ZPXr0Qtt45JFHZo+777772vSadtttt8Ylllii8cknn6zse/HFFxv79u3buPXWW1f2XXjhhdlxd9hhh8Z58+Y1e744H2+++WZl36hRoxr79OnT7Hmefvrp7OfjOC3F/jgHZf3791/k64znWGWVVSq3r7vuuuw4J510UrPHfeUrX2kslUqNTzzxRLPni9fcdN8DDzyQ7T/jjDMW+rzl1/GjH/2o8aGHHsr+/te//rXyni+11FKNs2fPbvUcvPvuux853re//e3GJZdcsvH999+v7Ntll12avbay2267LXu+T3ziEx85Vvm++LPp523LLbdsXGGFFRpfe+217JwutthijdOmTVvoawSga5WvsbfccksWCzz//PONV111VeOAAQMae/bsmd0u++9//9s4Z86cZj8/c+bM7N/6Aw888CPXq+WWW67xjTfeqOy//vrrs/2///3vK/s23HDDxsGDBze7lkfME4/ryLU22h7tKDv33HOz/YMGDWp8++23K/vHjx+f7W/62IWdp9a2pq9l4MCBja+//nqza3xDQ0Pjfvvt95HYa++99272HM8880wW15x88snN9j/44IPZNbS8P+Ks+Pnf/e53C21zxAIRE7TFRhttlMVAbRGxZ7zO4cOHN7733nuV/X/4wx+ydv3gBz+o7Ivnj30//OEPP/J8I0aMaLYv3u+IQ1o77y3fn5axR1vPSTxH03MyZsyYZvFUeOeddxpXW221xlVXXTWLZ5o+3zrrrNPsd+D000/P9sd7tDDl1xFx0JlnnpnFuuV4as8992zcdtttF3gOWsZdcf7j3G+33XZter8X9Hlrel9TL730UuOyyy7buOOOO2avNd6roUOHNr711lsLfY3Q2QzdopAiqx4VPZHRj9La6EGInosYQlPuhSn76le/mvWUNR3aExUy0bPR2rCtsqj0ifLTKKsu/9nWYVvlnr4QVSqLEr070YsXZbzR81U2ePDg7Dmj6qV8vLLooWhaXhrVQHGcGGpULdEDFb0y7VlZIspYo3IqeoKaih6piDejp6apmOiwaS/L+uuvn1U1RQ9nW8Vwr/i56BEK8V5HeXiUHLcmSn3Lonc1eiPj/EUPVtPheosyatSo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N3XFFVdkn4F436IN++yzT+MLL7zQ7DEListaW9a7taXFw5NPPtm4ww47ZM+zwgorNH7/+99vvPnmm5vFHm09J63FW3H8r3zlK1nsEz/7qU99Kvtct+VzUv5cxeejGp+f1s7BBRdckH3W4/XHZyGO1dr5W9D7vbDPW8vj7LHHHlkM/MwzzzR73PXXX5897pRTTllo+6EzleJ/C08FAQAAAJAHaskAAAAACkKiBwAAAKAgJHoAAAAACkKiBwDoFmIFmljpruU2evToWjcNAKBLzJ07Nx177LHZanCxMm+sMnjiiSe2ugrwglheHQDoFqZNm5YFN2UPPfRQ2nHHHbMlgAEA6sEpp5ySzj777HTxxRenddddN91zzz3pgAMOSP3790+HH354m45h1S0AoFsaM2ZM+sMf/pBmzJiRVfYAABTdF7/4xbTCCiukCy64oLLvy1/+clbd89vf/rZNxzB0CwDoNHPmzElvv/12sy32LcoHH3yQBTMHHnigJA8AUDfx0Gc+85l06623pscffzy7/cADD6Q777wz7bzzzvU9dGvQt66qdROgLjxz9ldq3QSoC7268Grde6NDq3q8o3ddPp1wwgnN9h133HHp+OOPX+jPXXfddenNN99M+++/f1XbU08+ffFetW4C1IUp+15U6yZAXejVY8kue67SjitV9XjHbfHNNsdDxxxzTJYIWnvttVOPHj2yYe0nn3xy2meffeo70QMAdA/jx49PY8eObbavZ8+ei/y5KFeOnqshQ4Z0YusAALpXPHTllVemSy65JF166aXZHD33339/Npw9YqJRo0a16fkkegCA+UrVHdUdQUxbEjtNPfvss+mWW25J11xzTVXbAgDQJlUeNt6eeOioo47Kqnq+9rWvZbfXW2+9LDaaOHGiRA8A8DF0g/lwLrzwwjRw4MC0yy671LopAEA9aqjdU7/77rupoaF5A2II17x589p8DIkeAKDbiCAmEj3RY7XYYsIUAKC+jBw5MpuTZ+jQodnQrfvuuy/99Kc/zRaoaCsRFADQaUO32iuGbD333HPtCmYAAIpS4XzGGWekY489Nn3nO99Jr7zySjY3z7e//e30gx/8oM3HkOgBALqNz33uc6mxsbHWzQAAqIm+ffum0047Lds+LokeAKBbzdEDAFBTpZRrEj0AQLcZugUAUHOlfGd6RHMAAAAABaGiBwAo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1glp5vtvp5X7DU7vfDC71k2DQrnnnnvTV/f+alp3+Lpp7tz/pjNOOzMd/M1D0jW/vyYtuWTvWjcPqkqih5o59PNrpX/PfC+r4Cl77rV3a9omKKKzz7ug2e0fnjwpbbvV5ulfjzycRmyyac3aRfekoge61jeG75r+M/v1dNJdZ1f2vTTr1Zq2CYro7PPOanb7hxNOSNtuuX361yOPpBGbjKhZu+ieSjmPhyR6qJmdNhiSbnv4P+n8b386bb7m8umlN99LF015Kl3y16dr3TQotFnvvJP92a9//1o3hW4o74EN5M1WK2+Spr74QDp5myPTRisMS6+++0a65rE/p+tn3FrrpkGhzXpnVvaneIgixkM1TfS89tpr6Ve/+lX6+9//nl5++eVs36BBg9JnPvOZtP/++6cBAwbUsnl0sqED+qRRn/1EOvfmGen0Gx9NG666TDrpaxumD/87L13592dr3TwopHnz5qVTT5mQNtxo47TGGmvWujmAeKjuDek7MO2x1o7psof/mC5+8Nq0znKfTEd+6oD04bz/phufvL3WzYPixkOTfpw23HjDtMYaq9e6OVCcRM+0adPSTjvtlM0PscMOO6Q11/y/Lxz/+c9/0s9//vM0adKkNHny5LTJJpss9Dhz5szJtqYa536YSj0W79T203ENpVJ64JmZaeK1D2W3H3r+zbT2iv3Sftt8QqIHOsmEk05IT86YkS76zaW1bgrdVb47sHKnM+OheR/OTQ2L9+jU9tNxDakh/ev1J9M5912W3X78jWfSJ5cZmnZfc0eJHugkE06cmJ6c8US66LcX1ropdFOlnMdDNUv0HHbYYWnPPfdM55xzzkfKohobG9PBBx+cPSZ6txZm4sSJ6YQTTmi2r89Ge6alRuzVKe2mel556730+EtvN9s346V30i4br1SzNkGRTTjph+mO26ekX13827TCoEG1bg7dVN5LlfOmM+OhFXcdllbafd1OaTfV89p7M9Mzb77QbN8zb72QPrvKZjVrExTZhJMmpTtu/2v61a8vSCsMWqHWzaGbKuU8Hmqo1RM/8MAD6cgjj2z1BMa+uO/+++9f5HHGjx+f3nrrrWZbnw1376RWU013P/F6+uSgvs32fWKFvumF103IDNUUXxYjyfOXW29O5//q4rTSSivXuklAF8RDQ764die1mmr65yuPpaH9hzTbt3K/Iell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lnMPXn755bV7cgCA/5/JmAGAwsh7YAMAkOeh7NWQ96FnAAAAAPz/VPQAABU578ACAEj1XuGsogcAAACgIFT0AACFGZMOANBReY+GJHoAgAp5HgCg3jXkPCAydAsAAACgIFT0AACF6cECAKj3eEiiBwCoyHdYAwDQcXmfs9DQLQAAAICCUNEDABSmBwsAoKMM3QIACqMh33ENAECH5T0cMnQLAAAAoCBU9AAAFYZuAQD1riHn8VCbEj033HBDmw/4pS99qSPtAQDolsRDAEBhEj277bZbm3sB586d29E2AQA1kvMOrE4lHgKA+tCQ84CoTYmeefPmdX5LAICaM3RrwcRDAFAfSjmPh0zGDAAAAFDPkzHPnj073X777em5555LH3zwQbP7Dj/88Gq1DQDoYpZXbzvxEAAUU0POK3ranei577770he+8IX07rvvZgHOsssum1577bW05JJLpoEDBwpsACDH8l6q3FXEQwBQXKWU6mvo1pFHHplGjhyZZs6cmXr37p2mTp2ann322TRixIj04x//uHNaCQDQjYiHAIDCJHruv//+9N3vfjc1NDSkHj16pDlz5qSVV145nXrqqen73/9+57QSAOiyHqxqbkUlHgKAYg/daqji1uXtb+8PLL744llQE6I0Ocalh/79+6fnn3+++i0EALpM3gObriIeAoDiash5PNTuOXo22mijNG3atLTGGmukbbbZJv3gBz/IxqT/5je/ScOHD++cVgIAdCPiIQCgu2p3Rc+ECRPS4MGDs7+ffPLJaZlllkmHHHJIevXVV9N5553XGW0EALpIdDpVcysq8RAAFHtxilIVt25f0bPJJptU/h6lyn/605+q3SYAgG5NPAQAdFftTvQAAMVleXUAoN41pDpL9Ky22moLDQKfeuqpjrYJAKgReZ62EQ8BQHGVch4QtTvRM2bMmGa3P/zww3TfffdlJctHHXVUNdsGANAtiYcAgMIkeo444ohW95911lnpnnvuqUabAIAaKfKS6NUkHgKA4mqoYTx0/PHHpxNOOKHZvrXWWis9+uijXT/0bOedd05XX311tQ4HANSAVbc6RjwEAMVI9DRUcWuvddddN7300kuV7c4776zNZMxXXXVVWnbZZat1OACA3BEPAQAdtdhii6VBgwZ9/J9v7w9stNFGzSYmamxsTC+//HJ69dVX0y9+8YuP3RAAoPbyPvlgVxEPAUBxlWocD82YMSMNGTIk9erVK22++eZp4sSJaejQoZ2X6Nl1112bveiGhoY0YMCA9NnPfjatvfba7T0cAEDuiIcAgLaaM2dOtjXVs2fPbGtps802SxdddFE2L08M24r5erbaaqv00EMPpb59+7bp+UqN0QVVMLuce3etmwB14S/n/LrWTYC68N59Z3bZcx127b+qerwzdl+nqsej7a59+vJaNwHqwh7/M67WTYC60HjzC132XN+765iqHm/Jm3t9ZILl4447Lpt4eVHefPPNtMoqq6Sf/vSn6aCDDuqcip4ePXpkWaWBAwc22//6669n++bOndveQwIA3UStS5XzQjwEAMVVqnI8NH78+DR27Nhm+1qr5mnN0ksvndZcc830xBNPdN6qWwsqAIoypCWWWKK9hwMAyB3xEADQVpHU6devX7OtrYmeWbNmpSeffDINHjy4zc/X5oqen//855XM1i9/+cu01FJLVe6LXqs77rjDmHQAyLkGBT0LJR4CgOJrqGGF87hx49LIkSOz4VovvvhiNsQrKon33nvv6id6fvazn1V6sM4555zsicqi52rVVVfN9gMA+SXRs3DiIQAovlKqXUD0wgsvZEmdGA4eCz1sueWWaerUqdnfq57oefrpp7M/t91223TNNdekZZZZ5uO1GgAgp8RDAEBnuvzyji+m0O7JmG+77bYOPykA0D2ZjLltxEMAUFylnMdD7Z6M+ctf/nI65ZRTPrL/1FNPTXvuuWe12gUA1GjoVjW3ohIPAUBxxRw91dy6vP3t/YGYZPALX/jCR/bvvPPO2X0AAEUnHgIAuqt2D92Kpb1aWzZ08cUXT2+//Xa12gUA1EDOK5W7jHgIAIqr1P6amG6l3a1fb7310hVXXNHqhEHDhg2rVrsAALot8RAAUJiKnmOPPTbtscce6cknn0zbbbddtu/WW29Nl156abrqqqs6o40AQBepxTjyPBIPAUBxNeQ8Hmp3omfkyJHpuuuuSxMmTMgCmd69e6cNNtgg/eUvf0nLLrts57QSAOgS+S5U7jriIQAorlK9JXrCLrvskm0hxqFfdtllady4cWn69Olp7ty51W4jAEC3Ix4CAArVcRcrSowaNSoNGTIk/eQnP8nKlqdOnVrd1gEAXSo6sKq5FZ14CACKp1Tl/7p1Rc/LL7+cLrroonTBBRdkPVd77bVXmjNnTla6bOJBAMi/vI9J7wriIQAotoacx0MN7RmLvtZaa6V//vOf6bTTTksvvvhiOuOMMzq3dQAA3Yh4CADo7tpc0XPTTTelww8/PB1yyCFpjTXW6NxWAQA1kfMOrE4nHgKA4ivVS0XPnXfemd555500YsSItNlmm6Uzzzwzvfbaa53bOgCgSzWUqrsVjXgIAIqvocr/dX372+jTn/50Ov/889NLL72Uvv3tb6fLL788m3hw3rx56eabb86CHgCAIhMPAQDdXbtTS3369EkHHnhg1qP14IMPpu9+97tp0qRJaeDAgelLX/pS57QSAOiyyQeruRWVeAgAij10q1TFrat1qIYoJiM89dRT0wsvvJAuu+yy6rUKACAnxEMAQHfSruXVF6RHjx5pt912yzYAIL8KXITT6cRDAFAMpZwHRFVJ9AAAxVDECZQBANqjIeU7IOr66Z8BAAAA6BQqegCAilLOe7AAADrK0C0AoDAM3QIA6l1DzhM9hm4BAAAAFISKHgCgQkUPAFDvSjkfyq6iBwAAAKAgVPQAAIWZfBAAoKMaSvmuiZHoAQAqDN0CAOpdKecdX/lOUwEAAABQoaIHAKjIeQcWAECq98mYJXoAgIoGmR4AoM415DweMnQLAOiWJk2alI2RHzNmTK2bAgCQGyp6AIBuNxnztGnT0rnnnpvWX3/9WjcFAKgzpZwP3VLRAwBURKVyNbePY9asWWmfffZJ559/flpmmWWq/RIBABY5dKuaW1eT6AEAupXRo0enXXbZJe2www61bgoAQO4YugUAVDRUuVR5zpw52dZUz549s601l19+ebr33nuzoVsAALVQKuW7JibfrQcAurWJEyem/v37N9tiX2uef/75dMQRR6RLLrkk9erVq8vbCgBQBCp6AICKag8jHz9+fBo7dmyzfQuq5pk+fXp65ZVX0sYbb1zZN3fu3HTHHXekM888M6sM6tGjR3UbCABQsMmYJXoAgE5bdWthw7Ra2n777dODDz7YbN8BBxyQ1l577XT00UdL8gAAXaKhBhMoV5NEDwDQLfTt2zcNHz682b4+ffqk5ZZb7iP7AQBonUQPAFCYHiwAgI4q5TwekugBACq6W1wzZcqUWjcBAKgzDTmfo8eqWwAAAAAFoaIHAKgwdAsAqHelnMdDEj0AQEXO4xoAgA4rlfI9+CnfrQcAAACgQkUPAFChBwgAqHcNJmMGAAAAoDtQ0QMAFGbyQQCAeo+HJHoAgIp8hzUAAB1XynlEZOgWAAAAQEGo6AEAKhpyXqoMANBRhm4BAIWR77AGAKDjrLoFAAAAQLegogcAqMh5pTIAQIeVSvmuicl36wEAAACoUNEDABRm8kEAgHpfXl2iBwCoUOoLANS7Us47vsRzAAAAAN3QpEmTssTTmDFj2vwzKnoAgML0YAEAFGXo1rRp09K5556b1l9//Xb9nIoeAKCiVOUNACCPHV+lKm4fx6xZs9I+++yTzj///LTMMsu062clegAAAAC6kdGjR6dddtkl7bDDDu3+WUO3AIAKQ7cAgHrXUOW65Dlz5mRbUz179sy21lx++eXp3nvvzYZufRwqegCAZoFBNTcAgHofujVx4sTUv3//Zlvsa83zzz+fjjjiiHTJJZekXr16faz2q+gBAAAA6CTjx49PY8eObbZvQdU806dPT6+88kraeOONK/vmzp2b7rjjjnTmmWdmlUE9evRY6PNJ9AAAFYZuAQD1rlTluuSFDdNqafvtt08PPvhgs30HHHBAWnvttdPRRx+9yCRPkOgBAAAA6Ab69u2bhg8f3mxfnz590nLLLfeR/Qsi0QMAVKjnAQDqXSnnFc4SPQBARc7jGgCADit1s66vKVOmtOvxFsQAAAAAKAgVPQBARUM368ECAOhqDTkvcZboAQAqch7XAAAUbuhWexm6BQAAAFAQKnoAgML0YAEA1PuqWyp6AAAAAApCRQ8AUJHzDiwAgA4r5bwmRqIHAKiw6hYAUO9KOe/5yneaCgAAAIAKFT0AQEXOO7AAAFK9VzhL9AAAFRI9AEC9K+U8IDJ0CwAAAKAgVPQAABWlnJcqAwDUezwk0QMAVDTkO64BAOgwQ7cAAAAA6BZU9AAAhSlVBgDoqFLOa2Ly3XoAAAAAKlT0AAAVOR+SDgDQYQ05D4gkegCACkO3AIB6V8p5PGToFgAAAEBBqOgBACosrw4A1LuSoVsAQFHkvVQZAKDe4yGJHmrm6yNWTPtssmKzfc/PfC8dfOWDNWsTFNGjfzwhrTJkuY/sP+eKO9KRk66sSZsAaN2UK/6a/nThLWmL3T6dRh68c62bA4XR0NCQjv/G2LTv9nukQcsOTC++/nK66M+/SyddcnqtmwZVJ9FDTT3zxrvpf//wWOX23MbGmrYHimjLfX+UejQZjzNs9SHpxnMOS9fcfF9N20X3lPNKZci15x/7d/rHjfekQautUOumQOEc/dXvpENG7pdGnTomPfzs42mTNTdIF477SXpr9jvpjOt+Vevm0c2Uch4QSfRQU/PmNaaZ731Y62ZAob02c1az2+MOGJ6efO7V9NfpM2rWJrqvfIc1kF9z3puTrjj16rTHEV9Kf7nsjlo3BwrnM8M2Sdf/7c/pxrv/kt1+9j8vpL233TV9aq0Na900uqGGnK9ble/Wk3tD+vdKv953w3TB3uuncdt9Ig1YaolaNwkKbfHFeqSvfWHTdPH1f691UwBo4vqz/pjW+tQaaY2NP1nrpkAh/e2Re9L2G22R1lhxtez2+p9YJ205fNN007Tbat00qK9Ez/PPP58OPPDAWjeDTvLYK7PSz6Y8lX5w42PprL8+mwb17ZlO/dI6qffi3fpjCbn2pW3XT0v37Z1++/t/1LopdFMNpVJVNzpOPFR8D0x5MP37iZfS5w/YodZNgcKadPlZ6fIpN6RHf3V7+uCmp9N9Z09Op13zy3TpX66tddPopkO3SlXculq3/kb9xhtvpIsvvnihj5kzZ056++23m21zP/ygy9rIxzf9+bfSnU/NTM+88V6694W30nE3PZ76LNEjbfWJZWvdNCisUbt9Jk2+65H00qtv1bopQCfHQx/OMTQ6D9589a30+3NuSl/73pfT4kssXuvmQGHttc3ItM92u6evTzw0bXzIzmnUj45M4/Y8OO2341dq3TQo1hw9N9xww0Lvf+qppxZ5jIkTJ6YTTjih2b7Vd/lmWnPktzrcPrrW7A/mpn+/9X4a3L9XrZsChTR08DJpu83WSl8bd36tm0I3pganOPHQXod/OX1tjC8w3d2/Z7yYZr05O51x6LmVffPmzUvPPPRs+vsNd6eTfn9saujRrftmIRd+9K3/TZOuOCtdMeX//s196JlH0yoDV0zjv3Zo+vXNV9W6eXQzpZxHRDVN9Oy2225ZGVPjQlZaWlSZ0/jx49PYsWOb7dvr1/+sWhvpOr0Wa0iD+/VKf5nxeq2bAoX0jS9tnl554510018frnVT6M7yHdfkUmfFQ3968fqqtZHOs/qGn0hjzvlOs31X/eS6NGDl5dM2e20pyQNVsmSv3lkStam58+Zmy65D0VbdqumnevDgwemaa67JfuFa2+69995FHqNnz56pX79+zbYei5vQNw8O+vTKafjgvmngUkukdVZYKv3vTmukeY2N6fYnJHqgMy5W++366XTJH/6R5s5tHuQAtdVZ8dDiPQ0DyoOeS/ZMg1Zdodm2eK8l0pL9lsz+DlTH76fenP7f1w9PX/jUdmmVFVZKu23x+TT2y/+Trr3rT7VuGhSromfEiBFp+vTpadddd231/kX1bpFvy/VZIn1v+0+mfr0WS2+999/08MvvpLHXPZLefv+/tW4aFE4M2Ro6eNl08XVTa90Uurm8lyrnkXgIoPMdduax6cT9j0q/OHxCGrj08unF119O5/7xt+mHvz2t1k2jGyrlPB6qaaLnqKOOSrNnz17g/auvvnq67TbL3RXVqbc+WesmQN24deqjqfdGh9a6GeRAziuVc0k8REvf/tEBtW4CFM6s92anI88+PttgUSR6OmCrrbZa6P19+vRJ22yzTZe1BwCgq4mHAIDCJHoAgO4l3/1XAABVkPMSZ1OMAwAAABSEih4AYL58d2ABAHSYOXoAgMLIe2ADANBRseJlnhm6BQAAAFAQKnoAgIqcd2ABAKR6r3CW6AEAKvId1gAAdFzeEz2GbgEAAAAUhIoeAGC+fHdgAQB0mMmYAYBClSpX87/2OPvss9P666+f+vXrl22bb755uummmzrttQIAdLd4qBokegCAbmGllVZKkyZNStOnT0/33HNP2m677dKuu+6aHn744Vo3DQAgNwzdAgAqalmpPHLkyGa3Tz755KzKZ+rUqWndddetWbsAgPpSyvlYdokeAKDbmTt3bvrd736XZs+enQ3hAgCgbSR6AICKavdfzZkzJ9ua6tmzZ7a15sEHH8wSO++//35aaqml0rXXXpuGDRtW5VYBACyYyZgBgOIoVXebOHFi6t+/f7Mt9i3IWmutle6///70j3/8Ix1yyCFp1KhR6ZFHHunSUwAA1LdSzidjVtEDAHSa8ePHp7Fjxzbbt6BqnrDEEkuk1VdfPfv7iBEj0rRp09Lpp5+ezj333E5vKwBAEUj0AAAV1e51WtgwrbaYN2/eR4Z+AQB0plLOh25J9AAAFbWMa6L6Z+edd05Dhw5N77zzTrr00kvTlClT0uTJk2vXKACg7pSsugUA0HGvvPJK2m+//dJLL72UzeWz/vrrZ0meHXfcsdZNAwDIDYkeAKCilv1XF1xwQQ2fHQDg/6joAQCKI99xDQBAqvc5eiyvDgAAAFAQKnoAgMKUKgMA1Hs8pKIHAAAAoBs4++yzswUp+vXrl22bb755uummm9p1DBU9AEBFzoekAwDkuqJnpZVWSpMmTUprrLFGamxsTBdffHHadddd03333ZfWXXfdNh1DogcAqJDnAQDqXamGPV8jR45sdvvkk0/OqnymTp0q0QMAAABQa3PmzMm2pnr27JltCzN37tz0u9/9Ls2ePTsbwtVW5ugBAOYrVXkDAKjzgGjixImpf//+zbbYtyAPPvhgWmqppbJE0MEHH5yuvfbaNGzYsDa3XkUPAFCYVSYAALrb0K3x48ensWPHNtu3sGqetdZaK91///3prbfeSldddVUaNWpUuv3229uc7JHoAQAAAOgkbRmm1dQSSyyRVl999ezvI0aMSNOmTUunn356Ovfcc9v08xI9AECFVbcAgHpX6mYVzvPmzfvIHD8LI9EDAAAA0A3EMK+dd945DR06NL3zzjvp0ksvTVOmTEmTJ09u8zEkegCAiu7VfwUAUF8VPa+88krab7/90ksvvZRN2rz++utnSZ4dd9yxzceQ6AEA5pPpAQDqXKmGY9kvuOCCDh/D8uoAAAAABaGiBwDotpMPAgB0tVLO4yGJHgCgwqpbAEC9K+U80WPoFgAAAEBBqOgBACry3X8FAJDvyZirQaIHAJgv33ENAECHGboFAAAAQLegogcAKEwPFgBAvQ/dUtEDAAAAUBAqegCAipx3YAEApHqvcJboAQAq8h3WAABUQ74jIkO3AAAAAApCRQ8AUJQOLACAVO/hkEQPAFCYMekAAB1l1S0AAAAAugUVPQBARc47sAAAqiDfAZFEDwBQkLAGAKDj8h4PGboFAAAAUBAqegCACkO3AABKKc9U9AAAAAAUhIoeAKAwPVgAAPW+vLpEDwBQkfO4BgCg7hm6BQAAAFAQKnoAgAoFPQBAvSvlPCKS6AEAKgzdAgDqXSnniR5DtwAAAAAKQkUPAFCYHiwAgHqnogcAAACgIFT0AADzKegBAOpcKeeTFkr0AAAV+Q5rAAAwdAsAAACgIFT0AAAVOa9UBgBI9b44hUQPAFCYwAYAoOPyHQ8ZugUAAABQECp6AICidGABAKR6D4ckegCAwgQ2AAD1vry6oVsAAAAABaGiBwCoyHkHFgBAFeQ7IFLRAwAAAFAQKnoAgArLqwMA9a6U8k2iBwCoMHQLAKCU8szQLQAAAICCUNEDAAAAUJDl1SV6AICKnMc1AAB1z9AtAAAAgIJQ0QMAVFh1CwCod6Wcx0MqegAAAAAKQkUPAFBhjh4AgFLKM4keAKAgYQ0AQMflPR4ydAsAAACgIFT0AADF6cICAOigUs7Hskv0AACFWWUCAKDj8h0PGboFAAAAUBAqegCAipxXKgMAdFjewyGJHgCgMIENAEC9R0SGbgEAAAAUhEQPANC8A6uaWztMnDgxbbrppqlv375p4MCBabfddkuPPfZYZ71SAIAFrrpVza2r4yGJHgCgW7j99tvT6NGj09SpU9PNN9+cPvzww/S5z30uzZ49u9ZNAwDITTxkjh4AoFssr/6nP/2p2e2LLroo68maPn162nrrrWvWLgCAPMVDEj0AQLdcdeutt97K/lx22WVr3RQAoI6UutFkzB8nHpLoAQA6zZw5c7KtqZ49e2bbwsybNy+NGTMmbbHFFmn48OGd3EoAgOLEQ6XGxsbGj91aqJL40MekU+PHj1/khx34ePyeUQvHH398OuGEE5rtO+6447L9C3PIIYekm266Kd15551ppZVW6uRWQu35Nxq6ht816iEekuihW3j77bdT//79s7K0fv361bo5UEh+z8hLD9ahhx6arr/++nTHHXek1VZbrQtaCbXn32joGn7XqId4yNAtAKDTtKUsuSz6ng477LB07bXXpilTpkjyAACF0LOL4yGJHgCgW4ilRC+99NKs96pv377p5ZdfzvZHz2vv3r1r3TwAgFzEQ4Zu0S0ooYTO5/eM7q60gCW/LrzwwrT//vt3eXugK/k3GrqG3zXqIR5S0UO3EGVsMRmVCdGg8/g9o7vT90Q98280dA2/a9RDPKSiBwAAAKAgGmrdAAAAAACqQ6IHAAAAoCAkegAAAAAKQqKHmjvrrLPSqquumnr16pU222yzdPfdd9e6SVA4d9xxRxo5cmQaMmRINpP/ddddV+smAdCEeAg6l1iIeiLRQ01dccUVaezYsdnM9/fee2/aYIMN0k477ZReeeWVWjcNCmX27NnZ71d8kQCgexEPQecTC1FPrLpFTUWP1aabbprOPPPM7Pa8efPSyiuvnA477LB0zDHH1Lp5UEjRi3Xttdem3XbbrdZNAUA8BF1OLETRqeihZj744IM0ffr0tMMOO1T2NTQ0ZLf//ve/17RtAABdQTwEQLVJ9FAzr732Wpo7d25aYYUVmu2P2y+//HLN2gUA0FXEQwBUm0QPAAAAQEFI9FAzyy+/fOrRo0f6z3/+02x/3B40aFDN2gUA0FXEQwBUm0QPNbPEEkukESNGpFtvvbWyLyYfjNubb755TdsGANAVxEMAVNtiVT8itEMsJTpq1Ki0ySabpE996lPptNNOy5Y+POCAA2rdNCiUWbNmpSeeeKJy++mnn073339/WnbZZdPQoUNr2jaAeicegs4nFqKeWF6dmoulRH/0ox9lEw5uuOGG6ec//3m2zChQPVOmTEnbbrvtR/bHF4uLLrqoJm0CYD7xEHQusRD1RKIHAAAAoCDM0QMAAABQEBI9AAAAAAUh0QMAAABQEBI9AAAAAAUh0QMAAABQEBI9AAAAAAUh0QMAAABQEBI9AAAAAAUh0QO0yf7775922223yu3PfvazacyYMV3ejilTpqRSqZTefPPNLn9uAKB+iYWAvJDogQIEHXGxj22JJZZIq6++evrhD3+Y/vvf/3bq815zzTXpxBNPbNNjBSQAQGcRCwE0t1iL20AOff7zn08XXnhhmjNnTrrxxhvT6NGj0+KLL57Gjx/f7HEffPBBFgBVw7LLLluV4wAAdJRYCGA+FT1QAD179kyDBg1Kq6yySjrkkEPSDjvskG644YZKifHJJ5+chgwZktZaa63s8c8//3zaa6+90tJLL50FKbvuumt65plnKsebO3duGjt2bHb/csstl773ve+lxsbGZs/Zslw5Aqujjz46rbzyyll7ojftggsuyI677bbbZo9ZZpllst6saFeYN29emjhxYlpttdVS79690wYbbJCuuuqqZs8Twdqaa66Z3R/HadpOAIAgFgKYT6IHCigCgeixCrfeemt67LHH0s0335z+8Ic/pA8//DDttNNOqW/fvumvf/1ruuuuu9JSSy2V9YSVf+YnP/lJuuiii9KvfvWrdOedd6Y33ngjXXvttQt9zv322y9ddtll6ec//3n617/+lc4999zsuBHsXH311dljoh0vvfRSOv3007PbEdj8+te/Tuecc056+OGH05FHHpn23XffdPvtt1eCsD322CONHDky3X///emb3/xmOuaYYzr57AEAeScWAupaI5Bro0aNatx1112zv8+bN6/x5ptvbuzZs2fjuHHjsvtWWGGFxjlz5lQe/5vf/KZxrbXWyh5bFvf37t27cfLkydntwYMHN5566qmV+z/88MPGlVZaqfI8YZtttmk84ogjsr8/9thj0cWVPXdrbrvttuz+mTNnVva9//77jUsuuWTj3/72t2aPPeiggxr33nvv7O/jx49vHDZsWLP7jz766I8cCwCoX2IhgObM0QMFEL1T0WMUPVRRAvz1r389HX/88dn49PXWW6/ZWPQHHnggPfHEE1kvVlPvv/9+evLJJ9Nbb72V9TRtttlmlfsWW2yxtMkmm3ykZLkseph69OiRttlmmza3Odrw7rvvph133LHZ/uhJ22ijjbK/R29Y03aEzTffvM3PAQDUB7EQwHwSPVAAMV777LPPzoKYGH8ewUhZnz59mj121qxZacSIEemSSy75yHEGDBjwscuj2yvaEf74xz+mFVdcsdl9Ma4dAKCtxEIA80n0QAFEABMT/rXFxhtvnK644oo0cODA1K9fv1YfM3jw4PSPf/wjbb311tntWJ50+vTp2c+2JnrKovcsxpPH5IctlXvRYmLDsmHDhmVBzHPPPbfA3q911lknm0ixqalTp7bpdQIA9UMsBDCfyZihzuyzzz5p+eWXz1aXiAkIn3766TRlypR0+OGHpxdeeCF7zBFHHJEmTZqUrrvuuvToo4+m73znO+nNN99c4DFXXXXVNGrUqHTggQdmP1M+5pVXXpndHytgxAoTUVb96quvZj1YUS49bty4bNLBiy++OCuVvvfee9MZZ5yR3Q4HH3xwmjFjRjrqqKOyyQsvvfTSbGJEAICPSywEFJ1ED9SZJZdcMt1xxx1p6NCh2SoO0VN00EEHZePSy71a3/3ud9M3vvGNLGCJceARiOy+++4LPW6US3/lK1/JAqG11147fetb30qzZ8/O7oty5BNOOCFbJWKFFVZIhx56aLb/xBNPTMcee2y24kS0I1a7iPLlWGI0RBtjlYoImGK50ViRYsKECZ1+jgCA4hILAUVXihmZa90IAAAAADpORQ8AAABAQUj0AAAAABSERA8AAABAQUj0AAAAABSERA8AAABAQUj0AAAAABSERA8AAABAQUj0AAAAABSERA8AAABAQUj0AAAAABSERA8AAABAQUj0AAAAAKRi+P8AEr+nGwxk/aQAAAAASUVORK5CYII=",
511
+ "text/plain": [
512
+ "<Figure size 1200x500 with 4 Axes>"
513
+ ]
514
+ },
515
+ "metadata": {},
516
+ "output_type": "display_data"
517
+ }
518
+ ],
519
+ "source": [
520
+ "# Confusion Matrices\n",
521
+ "svm_cm = confusion_matrix(y_test, svm_preds)\n",
522
+ "rf_cm = confusion_matrix(y_test, rf_preds)\n",
523
+ "\n",
524
+ "fig, axes = plt.subplots(1, 2, figsize=(12, 5))\n",
525
+ "sns.heatmap(svm_cm, annot=True, fmt='d', cmap='Blues', ax=axes[0])\n",
526
+ "axes[0].set_title('SVM Confusion Matrix')\n",
527
+ "axes[0].set_xlabel('Predicted')\n",
528
+ "axes[0].set_ylabel('Actual')\n",
529
+ "\n",
530
+ "sns.heatmap(rf_cm, annot=True, fmt='d', cmap='Greens', ax=axes[1])\n",
531
+ "axes[1].set_title('Random Forest Confusion Matrix')\n",
532
+ "axes[1].set_xlabel('Predicted')\n",
533
+ "axes[1].set_ylabel('Actual')\n",
534
+ "\n",
535
+ "plt.tight_layout()\n",
536
+ "plt.show()\n"
537
+ ]
538
+ },
539
+ {
540
+ "cell_type": "code",
541
+ "execution_count": null,
542
+ "id": "3a2c284f",
543
+ "metadata": {},
544
+ "outputs": [],
545
+ "source": []
546
+ }
547
+ ],
548
+ "metadata": {
549
+ "kernelspec": {
550
+ "display_name": "ml_env",
551
+ "language": "python",
552
+ "name": "python3"
553
+ },
554
+ "language_info": {
555
+ "codemirror_mode": {
556
+ "name": "ipython",
557
+ "version": 3
558
+ },
559
+ "file_extension": ".py",
560
+ "mimetype": "text/x-python",
561
+ "name": "python",
562
+ "nbconvert_exporter": "python",
563
+ "pygments_lexer": "ipython3",
564
+ "version": "3.13.1"
565
+ }
566
+ },
567
+ "nbformat": 4,
568
+ "nbformat_minor": 5
569
+ }
installation.ipynb ADDED
File without changes
lr_model.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3afb60ab51259121d4188b2e23fa705e3f6c100a4965e4769e0812d36677d3b6
3
+ size 1391
main.py ADDED
@@ -0,0 +1,314 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import numpy as np
4
+ import matplotlib.pyplot as plt
5
+ import seaborn as sns
6
+ import joblib
7
+ from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
8
+ from plotly import graph_objects as go
9
+
10
+ st.set_page_config(layout="wide")
11
+
12
+ # Load Dataset
13
+ def load_data():
14
+ data = pd.read_excel(r'Model Training/colelithiasis_dataset.xlsx') # Update with your dataset file path
15
+ data.drop('Patient No.', axis=1, inplace=True)
16
+ return data
17
+
18
+ # Initialize Session State
19
+ if "data" not in st.session_state:
20
+ st.session_state.data = load_data()
21
+
22
+ def introduction_page():
23
+ st.title("Introduction")
24
+ st.markdown("""
25
+ ## Project Overview
26
+ This project analyzes the Colelithiasis dataset to perform exploratory data analysis (EDA) and prediction using pre-trained machine learning models. The goal is to provide insights into the data and make predictions efficiently.
27
+
28
+ ## Objectives
29
+ - Perform EDA to uncover patterns and insights.
30
+ - Use pre-trained machine learning models for predictions.
31
+ - Create an interactive Streamlit application.
32
+ """)
33
+
34
+ def stats_page():
35
+ st.title("Exploratory Data Analysis")
36
+
37
+ # Dataset Overview
38
+ st.subheader("Dataset Overview")
39
+ st.dataframe(st.session_state.data.head())
40
+
41
+ # Summary Statistics
42
+ st.subheader("Summary Statistics")
43
+ st.write(st.session_state.data.describe())
44
+
45
+ # Correlation Matrix
46
+ st.subheader("Correlation Analysis")
47
+
48
+ # encode the target variable
49
+ data = st.session_state.data.copy()
50
+ data['Health_status'].replace({'healthy': 0, 'patient': 1}, inplace=True)
51
+
52
+ # apply ordinal encoding to the categorical columns
53
+ categorical_columns = ['Gender','Family history','Obese/non obese']
54
+ encoder = joblib.load('Model Training\encoder.pkl')
55
+ data[categorical_columns] = encoder.transform(data[categorical_columns])
56
+
57
+ correlation = data.corr()
58
+ plt.figure(figsize=(5, 3))
59
+ # reduce the font size of the heatmap
60
+ sns.set(font_scale=0.5)
61
+ sns.heatmap(correlation, annot=True, cmap="coolwarm", fmt=".2f")
62
+ st.pyplot(plt, use_container_width=False)
63
+
64
+ def eda_page():
65
+ st.title("Exploratory Data Analysis")
66
+
67
+ # Interactive Visualizations
68
+ st.subheader("Visualizations")
69
+ chart_type = st.selectbox("Choose Chart Type", ["Histogram", "Scatter Plot", "Box Plot"])
70
+
71
+ if chart_type == "Histogram":
72
+ column = st.selectbox("Choose Column for Visualization", st.session_state.data.columns)
73
+ fig = go.Figure()
74
+ fig.add_trace(go.Histogram(x=st.session_state.data[column], name=column, marker_color="indigo"))
75
+ fig.update_layout(
76
+ title=dict(text="Histogram Analysis", x=0.5, font=dict(size=22)),
77
+ xaxis_title=column,
78
+ yaxis_title="Count",
79
+ legend=dict(title="Legend", orientation="h", x=0.5, xanchor="center"),
80
+ bargap=0.2,
81
+ hovermode="x unified",
82
+ template="plotly_dark"
83
+ )
84
+ st.plotly_chart(fig)
85
+
86
+ elif chart_type == "Scatter Plot":
87
+ x_col = st.selectbox("Choose X-axis Column", st.session_state.data.columns)
88
+ y_col = st.selectbox("Choose Y-axis Column", st.session_state.data.columns)
89
+ fig = go.Figure()
90
+ fig.add_trace(go.Scatter(
91
+ x=st.session_state.data[x_col],
92
+ y=st.session_state.data[y_col],
93
+ mode="markers",
94
+ marker=dict(size=10, color="purple", line=dict(width=1, color="white")),
95
+ name=f"{y_col} vs {x_col}"
96
+ ))
97
+ fig.update_layout(
98
+ title=dict(text="Scatter Plot Analysis", x=0.5, font=dict(size=22)),
99
+ xaxis_title=x_col,
100
+ yaxis_title=y_col,
101
+ legend=dict(title="Legend", orientation="h", x=0.5, xanchor="center"),
102
+ hovermode="closest",
103
+ template="plotly_dark"
104
+ )
105
+ st.plotly_chart(fig)
106
+
107
+ elif chart_type == "Box Plot":
108
+ column = st.selectbox("Choose Column for Visualization", st.session_state.data.columns)
109
+ fig = go.Figure()
110
+ fig.add_trace(go.Box(
111
+ y=st.session_state.data[column],
112
+ name=column,
113
+ boxmean="sd",
114
+ marker_color="teal"
115
+ ))
116
+ fig.update_layout(
117
+ title=dict(text="Boxplot Analysis", x=0.5, font=dict(size=22)),
118
+ yaxis_title=column,
119
+ legend=dict(title="Legend", orientation="h", x=0.5, xanchor="center"),
120
+ hovermode="y",
121
+ template="plotly_dark"
122
+ )
123
+ st.plotly_chart(fig)
124
+
125
+
126
+ def model_page():
127
+ st.title("Model Evaluation")
128
+ test_data = pd.read_excel(r'Model Training\test_data.xlsx')
129
+
130
+
131
+ # encode the target variable
132
+ test_data['Health_status'].replace({'healthy': 0, 'patient': 1}, inplace=True)
133
+
134
+ # apply ordinal encoding to the categorical columns
135
+ categorical_columns = ['Gender','Family history','Obese/non obese']
136
+ encoder = joblib.load('Model Training\encoder.pkl')
137
+
138
+ X = test_data.drop( columns=['Health_status'])
139
+ X[categorical_columns] = encoder.transform(X[categorical_columns])
140
+ y = test_data['Health_status']
141
+
142
+ # apply standard scalling to numberical features in X
143
+ numerical_columns = [col_name for col_name in X.columns if col_name not in categorical_columns]
144
+ scaler = joblib.load('Model Training\scaler.pkl')
145
+ X[numerical_columns] = scaler.transform(X[numerical_columns])
146
+
147
+ # Model Selection
148
+ st.text("Model Selection")
149
+ model_choice = st.selectbox("Choose a Pre-trained Model", ["SVM - Linear", "SVM - Polynomial", "SVM - RBF",
150
+ "Random Forest","Random Forest Boosted", "Logistic Regression", "GDA"])
151
+
152
+ # Load pre-trained model
153
+ model = None
154
+ if model_choice == "SVM - Linear":
155
+ model = joblib.load('Model Training\svm_model_linear.pkl')
156
+ elif model_choice == "SVM - Polynomial":
157
+ model = joblib.load('Model Training\svm_model_poly.pkl')
158
+ elif model_choice == "SVM - RBF":
159
+ model = joblib.load('Model Training\svm_model_rbf.pkl')
160
+ elif model_choice == "Random Forest":
161
+ model = joblib.load('Model Training\rf_model.pkl')
162
+ elif model_choice == "Random Forest Boosted":
163
+ model = joblib.load('Model Training\rf_boosted.pkl')
164
+ elif model_choice == "Logistic Regression":
165
+ model = joblib.load('Model Training\lr_model.pkl')
166
+ elif model_choice == "GDA":
167
+ model = joblib.load('Model Training\gda.pkl')
168
+
169
+
170
+ if model:
171
+ # Make Predictions
172
+ y_pred = model.predict(X)
173
+ col1, col2 = st.columns(2)
174
+ with col1:
175
+ st.subheader("### Predictions on the Test Data:")
176
+ st.dataframe(pd.DataFrame({"Actual": y, "Predicted": y_pred}))
177
+
178
+ with col2:
179
+ st.subheader("Classification Report")
180
+ report = classification_report(y, y_pred, output_dict=True)
181
+ report_df = pd.DataFrame(report).transpose().reset_index()
182
+ report_df.drop('support', axis=1, inplace=True)
183
+ report_df.set_index(['index'], inplace=True)
184
+ report_df.rename(index={'0.0': 'Negative', '1.0': 'Positive'}, inplace=True)
185
+ report_df.iloc[report_df.index.get_loc('accuracy'), 0:2] = ''
186
+ st.table(report_df)
187
+
188
+ st.subheader("Confusion Matrix")
189
+ conf_matrix = confusion_matrix(y, y_pred)
190
+ # Generate text annotations for the confusion matrix
191
+ text_annotations = np.array([[str(value) for value in row] for row in conf_matrix])
192
+
193
+ col1, col2 = st.columns(2)
194
+ with col1:
195
+ # Create the heatmap using seaborn
196
+ plt.figure(figsize=(3 , 3))
197
+ sns.heatmap(conf_matrix, annot=text_annotations, fmt="", cmap="Blues", cbar=False, square=True)
198
+ plt.xlabel("Predicted")
199
+ plt.ylabel("Actual")
200
+ plt.title("Confusion Matrix")
201
+ st.pyplot(plt)
202
+
203
+
204
+ def prediction_page():
205
+ st.title("Get Your Diagnosis")
206
+ st.subheader("Symptoms Entry Form")
207
+ # Model Selection
208
+ model_choice = st.selectbox("Choose a Pre-trained Model", ["SVM - Linear", "SVM - Polynomial", "SVM - RBF",
209
+ "Random Forest","Random Forest Boosted", "Logistic Regression", "GDA"])
210
+
211
+ # Load pre-trained model
212
+ model = None
213
+ if model_choice == "SVM - Linear":
214
+ model = joblib.load('Model Training\svm_model_linear.pkl')
215
+ elif model_choice == "SVM - Polynomial":
216
+ model = joblib.load('Model Training\svm_model_poly.pkl')
217
+ elif model_choice == "SVM - RBF":
218
+ model = joblib.load('Model Training\svm_model_rbf.pkl')
219
+ elif model_choice == "Random Forest":
220
+ model = joblib.load('Model Training\rf_model.pkl')
221
+ elif model_choice == "Random Forest Boosted":
222
+ model = joblib.load('Model Training\rf_boosted.pkl')
223
+ elif model_choice == "Logistic Regression":
224
+ model = joblib.load('Model Training\lr_model.pkl')
225
+ elif model_choice == "GDA":
226
+ model = joblib.load('Model Training\gda.pkl')
227
+
228
+ with st.form(key="health_data_form"):
229
+ col1, col2, col3, col4 = st.columns(4)
230
+
231
+ with col1:
232
+ # Categorical features with dropdown selection
233
+ gender = st.selectbox("Gender", ["Male", "Female"], key="gender")
234
+ weight = st.number_input("Weight (kg)", min_value=0, step=1, key="weight")
235
+ cholesterol = st.number_input("Cholesterol (mg/dL)", min_value=0, step=1, key="cholesterol")
236
+ with col2:
237
+ family_history = st.selectbox("Family History of Illness", ["Yes", "No"], key="family_history")
238
+ bmi = st.number_input("BMI", min_value=0.0, step=0.1, key="bmi")
239
+ triglycerides = st.number_input("Triglycerides Level (mg/dL)", min_value=0, step=1, key="triglycerides")
240
+
241
+ with col3:
242
+ height = st.number_input("Height (cm)", min_value=0.0, step=0.1, key="height")
243
+ obese_status = st.selectbox("Obese/Non Obese", ["Obese", "Non-Obese"], key="obese_status")
244
+ ldl = st.number_input("LDL Level (mg/dL)", min_value=0.0, step=0.1, key="ldl")
245
+
246
+ with col4:
247
+ vldl = st.number_input("VLDL Level (mg/dL)", min_value=0.0, step=0.1, key="vldl")
248
+
249
+
250
+
251
+ # Submit button
252
+ submit_button = st.form_submit_button(label="Submit" )
253
+
254
+ if submit_button:
255
+ # Create a DataFrame directly with the user input data
256
+ data = pd.DataFrame({
257
+ "Gender": [gender],
258
+ "Family history": [family_history],
259
+ "Height": [height],
260
+ "Weight": [weight],
261
+ "BMI": [bmi],
262
+ "Obese/non obese": [obese_status],
263
+ "Cholesterol": [cholesterol],
264
+ "Triglycerides": [triglycerides],
265
+ "LDL level": [ldl],
266
+ "VLDL level": [vldl]
267
+ })
268
+
269
+
270
+ columns = ['Gender', 'Family history', 'Height', 'Weight', 'BMI', 'Obese/non obese', 'Cholesterol', 'Triglycerides level', 'LDL level', 'VLDL level']
271
+ data = data.reindex(columns=columns, fill_value=0)
272
+
273
+ categorical_columns = ['Gender','Family history','Obese/non obese']
274
+ numerical_columns = [col_name for col_name in data.columns if col_name not in categorical_columns]
275
+ # Encoding categorical data
276
+ encoder = joblib.load('Model Training\encoder.pkl')
277
+ data[categorical_columns] = encoder.transform(data[categorical_columns])
278
+
279
+ # Scaling the numeric features
280
+ scaler = joblib.load('Model Training\scaler.pkl')
281
+ data[numerical_columns] = scaler.transform(data[numerical_columns])
282
+
283
+
284
+
285
+ prediction = int(model.predict(data)[0])
286
+ st.write(f"### Predicted Diagnosis: {'Positive' if prediction == 1 else 'Negative'}")
287
+
288
+
289
+ def conclusion_page():
290
+ st.title("Conclusion")
291
+ st.markdown("""
292
+ ## Key Takeaways
293
+ - Comprehensive EDA provides actionable insights into the data.
294
+ - Pre-trained machine learning models allow efficient predictions.
295
+ - The interactive app makes the analysis accessible and engaging.
296
+
297
+ Thank you for exploring this project!
298
+ """)
299
+
300
+ # Sidebar Navigation Menu with radio buttons for page selection
301
+ page = st.sidebar.radio("Navigation Menu", ["Introduction","Descriptive Statistics", "Data Analytics", "Model Evaluation", "Get Your Diagnosis", "Conclusion"])
302
+
303
+ if page == "Introduction":
304
+ introduction_page()
305
+ elif page == "Descriptive Statistics":
306
+ stats_page()
307
+ elif page == "Data Analytics":
308
+ eda_page()
309
+ elif page == "Model Evaluation":
310
+ model_page()
311
+ elif page == "Get Your Diagnosis":
312
+ prediction_page()
313
+ elif page == "Conclusion":
314
+ conclusion_page()
requirements.txt ADDED
Binary file (2.01 kB). View file
 
rf_boosted.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5bcff453f23629ac8c235105320385407489a939858ec303db312ebb934f704e
3
+ size 179112
rf_model.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:994d9d2dbee5adf22ee6434a0a778a0dae2f37c4883e414948a9b3fed3f53482
3
+ size 562377
scaler.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:125d5da89197d1212608fa958179f4601f9e98f7efe03640a72cbbd33ecc84e1
3
+ size 1183
svm_model_linear.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7636d9a64fcdc959b7d3d614e7d2567c4da70539e6147558dbedf8159b0ef637
3
+ size 9611
svm_model_poly.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1dcb91962b964f4d63a0acefbe2842d3d72af04c54e2c8a9341bea9688b9e027
3
+ size 8203
svm_model_rbf.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ddd0af20c80ecad7f8770169f9c8ba98aecf7271b20eddd5ca5d838a04edfecc
3
+ size 9019
test_data.xlsx ADDED
Binary file (6.5 kB). View file
 
training.ipynb ADDED
The diff for this file is too large to render. See raw diff