Spaces:
Sleeping
Sleeping
Upload 16 files
Browse files- colelithiasis_dataset.xlsx +0 -0
- encoder.pkl +3 -0
- gda.pkl +3 -0
- health_status_classification.ipynb +569 -0
- installation.ipynb +0 -0
- lr_model.pkl +3 -0
- main.py +314 -0
- requirements.txt +0 -0
- rf_boosted.pkl +3 -0
- rf_model.pkl +3 -0
- scaler.pkl +3 -0
- svm_model_linear.pkl +3 -0
- svm_model_poly.pkl +3 -0
- svm_model_rbf.pkl +3 -0
- test_data.xlsx +0 -0
- training.ipynb +0 -0
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
|
|