Souriktanag commited on
Commit
6ff7ddd
·
verified ·
1 Parent(s): ac922f8

Upload 4 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ Image/360_F_1375669005_ebg3mldxps5ZYrQFlY6EX3eCINwVDeoF.jpg filter=lfs diff=lfs merge=lfs -text
37
+ Image/stress-main.png filter=lfs diff=lfs merge=lfs -text
Final_stress_detection.ipynb ADDED
@@ -0,0 +1,909 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {
6
+ "id": "hykGuW-gdEZM"
7
+ },
8
+ "source": [
9
+ "### 1. Import Libraries\n",
10
+ "\n",
11
+ "We start by importing the required Python libraries for data processing, modeling, visualization, and creating a user interface.\n",
12
+ "\n",
13
+ "- `pandas`, `numpy`: For data handling and numerical operations.\n",
14
+ "- `sklearn`: For machine learning modeling and evaluation.\n",
15
+ "- `matplotlib`, `seaborn`: For plotting.\n",
16
+ "- `joblib`: For saving and loading the trained model and scaler.\n",
17
+ "- `gradio`: To build an interactive web interface for predictions.\n"
18
+ ]
19
+ },
20
+ {
21
+ "cell_type": "code",
22
+ "execution_count": 3,
23
+ "metadata": {
24
+ "id": "c3o9yJlOyqZq"
25
+ },
26
+ "outputs": [
27
+ {
28
+ "name": "stderr",
29
+ "output_type": "stream",
30
+ "text": [
31
+ "c:\\Users\\sourikta.nag\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\tqdm\\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
32
+ " from .autonotebook import tqdm as notebook_tqdm\n"
33
+ ]
34
+ }
35
+ ],
36
+ "source": [
37
+ "import pandas as pd\n",
38
+ "import numpy as np\n",
39
+ "from sklearn.svm import OneClassSVM\n",
40
+ "from sklearn.preprocessing import StandardScaler\n",
41
+ "from sklearn.metrics import confusion_matrix, classification_report\n",
42
+ "import seaborn as sns\n",
43
+ "import matplotlib.pyplot as plt\n",
44
+ "import joblib\n",
45
+ "import gradio as gr"
46
+ ]
47
+ },
48
+ {
49
+ "cell_type": "markdown",
50
+ "metadata": {
51
+ "id": "SkxcqtAibqBS"
52
+ },
53
+ "source": [
54
+ "### 2. Load Dataset\n",
55
+ "\n",
56
+ "We load the simulated stress data from a CSV file into a pandas DataFrame.\n"
57
+ ]
58
+ },
59
+ {
60
+ "cell_type": "code",
61
+ "execution_count": 5,
62
+ "metadata": {
63
+ "id": "XuxMzEo2y_Rq"
64
+ },
65
+ "outputs": [],
66
+ "source": [
67
+ "df = pd.read_csv('simulated_stress_data.csv')"
68
+ ]
69
+ },
70
+ {
71
+ "cell_type": "markdown",
72
+ "metadata": {
73
+ "id": "iDNDdAVudNOk"
74
+ },
75
+ "source": [
76
+ "### 3. Feature Selection and Standardization\n",
77
+ "\n",
78
+ "We select the important physiological features: \n",
79
+ "- Heart Rate (`HR`) \n",
80
+ "- Heart Rate Variability (`HRV`) \n",
81
+ "- Electrodermal Activity (`EDA`)\n",
82
+ "\n",
83
+ "These features are standardized using `StandardScaler` to ensure they are on the same scale. This improves the performance of distance-based models like One-Class SVM.\n"
84
+ ]
85
+ },
86
+ {
87
+ "cell_type": "code",
88
+ "execution_count": 6,
89
+ "metadata": {
90
+ "id": "IccdG-6kzB1h"
91
+ },
92
+ "outputs": [],
93
+ "source": [
94
+ "features = ['HR', 'HRV', 'EDA']\n",
95
+ "X = df[features]\n",
96
+ "scaler = StandardScaler()\n",
97
+ "X_scaled = scaler.fit_transform(X)"
98
+ ]
99
+ },
100
+ {
101
+ "cell_type": "markdown",
102
+ "metadata": {
103
+ "id": "gERCwbz3dXPs"
104
+ },
105
+ "source": [
106
+ "### 4. Train the One-Class SVM\n",
107
+ "\n",
108
+ "One-Class SVM is trained only on \"normal\" (non-stress) data (`label == 0`) to learn the typical behavior. \n",
109
+ "It will later classify any data point that deviates significantly as an anomaly (stress).\n",
110
+ "\n",
111
+ "- `kernel='rbf'`: Allows for non-linear separation.\n",
112
+ "- `nu=0.05`: Indicates the expected proportion of outliers.\n"
113
+ ]
114
+ },
115
+ {
116
+ "cell_type": "code",
117
+ "execution_count": 7,
118
+ "metadata": {
119
+ "colab": {
120
+ "base_uri": "https://localhost:8080/",
121
+ "height": 80
122
+ },
123
+ "id": "kP_vOKCKzEv5",
124
+ "outputId": "37070512-d25e-4287-ac89-f3d2b798a2bd"
125
+ },
126
+ "outputs": [
127
+ {
128
+ "data": {
129
+ "text/html": [
130
+ "<style>#sk-container-id-1 {\n",
131
+ " /* Definition of color scheme common for light and dark mode */\n",
132
+ " --sklearn-color-text: #000;\n",
133
+ " --sklearn-color-text-muted: #666;\n",
134
+ " --sklearn-color-line: gray;\n",
135
+ " /* Definition of color scheme for unfitted estimators */\n",
136
+ " --sklearn-color-unfitted-level-0: #fff5e6;\n",
137
+ " --sklearn-color-unfitted-level-1: #f6e4d2;\n",
138
+ " --sklearn-color-unfitted-level-2: #ffe0b3;\n",
139
+ " --sklearn-color-unfitted-level-3: chocolate;\n",
140
+ " /* Definition of color scheme for fitted estimators */\n",
141
+ " --sklearn-color-fitted-level-0: #f0f8ff;\n",
142
+ " --sklearn-color-fitted-level-1: #d4ebff;\n",
143
+ " --sklearn-color-fitted-level-2: #b3dbfd;\n",
144
+ " --sklearn-color-fitted-level-3: cornflowerblue;\n",
145
+ "\n",
146
+ " /* Specific color for light theme */\n",
147
+ " --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
148
+ " --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, white)));\n",
149
+ " --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
150
+ " --sklearn-color-icon: #696969;\n",
151
+ "\n",
152
+ " @media (prefers-color-scheme: dark) {\n",
153
+ " /* Redefinition of color scheme for dark theme */\n",
154
+ " --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
155
+ " --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, #111)));\n",
156
+ " --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
157
+ " --sklearn-color-icon: #878787;\n",
158
+ " }\n",
159
+ "}\n",
160
+ "\n",
161
+ "#sk-container-id-1 {\n",
162
+ " color: var(--sklearn-color-text);\n",
163
+ "}\n",
164
+ "\n",
165
+ "#sk-container-id-1 pre {\n",
166
+ " padding: 0;\n",
167
+ "}\n",
168
+ "\n",
169
+ "#sk-container-id-1 input.sk-hidden--visually {\n",
170
+ " border: 0;\n",
171
+ " clip: rect(1px 1px 1px 1px);\n",
172
+ " clip: rect(1px, 1px, 1px, 1px);\n",
173
+ " height: 1px;\n",
174
+ " margin: -1px;\n",
175
+ " overflow: hidden;\n",
176
+ " padding: 0;\n",
177
+ " position: absolute;\n",
178
+ " width: 1px;\n",
179
+ "}\n",
180
+ "\n",
181
+ "#sk-container-id-1 div.sk-dashed-wrapped {\n",
182
+ " border: 1px dashed var(--sklearn-color-line);\n",
183
+ " margin: 0 0.4em 0.5em 0.4em;\n",
184
+ " box-sizing: border-box;\n",
185
+ " padding-bottom: 0.4em;\n",
186
+ " background-color: var(--sklearn-color-background);\n",
187
+ "}\n",
188
+ "\n",
189
+ "#sk-container-id-1 div.sk-container {\n",
190
+ " /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n",
191
+ " but bootstrap.min.css set `[hidden] { display: none !important; }`\n",
192
+ " so we also need the `!important` here to be able to override the\n",
193
+ " default hidden behavior on the sphinx rendered scikit-learn.org.\n",
194
+ " See: https://github.com/scikit-learn/scikit-learn/issues/21755 */\n",
195
+ " display: inline-block !important;\n",
196
+ " position: relative;\n",
197
+ "}\n",
198
+ "\n",
199
+ "#sk-container-id-1 div.sk-text-repr-fallback {\n",
200
+ " display: none;\n",
201
+ "}\n",
202
+ "\n",
203
+ "div.sk-parallel-item,\n",
204
+ "div.sk-serial,\n",
205
+ "div.sk-item {\n",
206
+ " /* draw centered vertical line to link estimators */\n",
207
+ " background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));\n",
208
+ " background-size: 2px 100%;\n",
209
+ " background-repeat: no-repeat;\n",
210
+ " background-position: center center;\n",
211
+ "}\n",
212
+ "\n",
213
+ "/* Parallel-specific style estimator block */\n",
214
+ "\n",
215
+ "#sk-container-id-1 div.sk-parallel-item::after {\n",
216
+ " content: \"\";\n",
217
+ " width: 100%;\n",
218
+ " border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n",
219
+ " flex-grow: 1;\n",
220
+ "}\n",
221
+ "\n",
222
+ "#sk-container-id-1 div.sk-parallel {\n",
223
+ " display: flex;\n",
224
+ " align-items: stretch;\n",
225
+ " justify-content: center;\n",
226
+ " background-color: var(--sklearn-color-background);\n",
227
+ " position: relative;\n",
228
+ "}\n",
229
+ "\n",
230
+ "#sk-container-id-1 div.sk-parallel-item {\n",
231
+ " display: flex;\n",
232
+ " flex-direction: column;\n",
233
+ "}\n",
234
+ "\n",
235
+ "#sk-container-id-1 div.sk-parallel-item:first-child::after {\n",
236
+ " align-self: flex-end;\n",
237
+ " width: 50%;\n",
238
+ "}\n",
239
+ "\n",
240
+ "#sk-container-id-1 div.sk-parallel-item:last-child::after {\n",
241
+ " align-self: flex-start;\n",
242
+ " width: 50%;\n",
243
+ "}\n",
244
+ "\n",
245
+ "#sk-container-id-1 div.sk-parallel-item:only-child::after {\n",
246
+ " width: 0;\n",
247
+ "}\n",
248
+ "\n",
249
+ "/* Serial-specific style estimator block */\n",
250
+ "\n",
251
+ "#sk-container-id-1 div.sk-serial {\n",
252
+ " display: flex;\n",
253
+ " flex-direction: column;\n",
254
+ " align-items: center;\n",
255
+ " background-color: var(--sklearn-color-background);\n",
256
+ " padding-right: 1em;\n",
257
+ " padding-left: 1em;\n",
258
+ "}\n",
259
+ "\n",
260
+ "\n",
261
+ "/* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is\n",
262
+ "clickable and can be expanded/collapsed.\n",
263
+ "- Pipeline and ColumnTransformer use this feature and define the default style\n",
264
+ "- Estimators will overwrite some part of the style using the `sk-estimator` class\n",
265
+ "*/\n",
266
+ "\n",
267
+ "/* Pipeline and ColumnTransformer style (default) */\n",
268
+ "\n",
269
+ "#sk-container-id-1 div.sk-toggleable {\n",
270
+ " /* Default theme specific background. It is overwritten whether we have a\n",
271
+ " specific estimator or a Pipeline/ColumnTransformer */\n",
272
+ " background-color: var(--sklearn-color-background);\n",
273
+ "}\n",
274
+ "\n",
275
+ "/* Toggleable label */\n",
276
+ "#sk-container-id-1 label.sk-toggleable__label {\n",
277
+ " cursor: pointer;\n",
278
+ " display: flex;\n",
279
+ " width: 100%;\n",
280
+ " margin-bottom: 0;\n",
281
+ " padding: 0.5em;\n",
282
+ " box-sizing: border-box;\n",
283
+ " text-align: center;\n",
284
+ " align-items: start;\n",
285
+ " justify-content: space-between;\n",
286
+ " gap: 0.5em;\n",
287
+ "}\n",
288
+ "\n",
289
+ "#sk-container-id-1 label.sk-toggleable__label .caption {\n",
290
+ " font-size: 0.6rem;\n",
291
+ " font-weight: lighter;\n",
292
+ " color: var(--sklearn-color-text-muted);\n",
293
+ "}\n",
294
+ "\n",
295
+ "#sk-container-id-1 label.sk-toggleable__label-arrow:before {\n",
296
+ " /* Arrow on the left of the label */\n",
297
+ " content: \"▸\";\n",
298
+ " float: left;\n",
299
+ " margin-right: 0.25em;\n",
300
+ " color: var(--sklearn-color-icon);\n",
301
+ "}\n",
302
+ "\n",
303
+ "#sk-container-id-1 label.sk-toggleable__label-arrow:hover:before {\n",
304
+ " color: var(--sklearn-color-text);\n",
305
+ "}\n",
306
+ "\n",
307
+ "/* Toggleable content - dropdown */\n",
308
+ "\n",
309
+ "#sk-container-id-1 div.sk-toggleable__content {\n",
310
+ " max-height: 0;\n",
311
+ " max-width: 0;\n",
312
+ " overflow: hidden;\n",
313
+ " text-align: left;\n",
314
+ " /* unfitted */\n",
315
+ " background-color: var(--sklearn-color-unfitted-level-0);\n",
316
+ "}\n",
317
+ "\n",
318
+ "#sk-container-id-1 div.sk-toggleable__content.fitted {\n",
319
+ " /* fitted */\n",
320
+ " background-color: var(--sklearn-color-fitted-level-0);\n",
321
+ "}\n",
322
+ "\n",
323
+ "#sk-container-id-1 div.sk-toggleable__content pre {\n",
324
+ " margin: 0.2em;\n",
325
+ " border-radius: 0.25em;\n",
326
+ " color: var(--sklearn-color-text);\n",
327
+ " /* unfitted */\n",
328
+ " background-color: var(--sklearn-color-unfitted-level-0);\n",
329
+ "}\n",
330
+ "\n",
331
+ "#sk-container-id-1 div.sk-toggleable__content.fitted pre {\n",
332
+ " /* unfitted */\n",
333
+ " background-color: var(--sklearn-color-fitted-level-0);\n",
334
+ "}\n",
335
+ "\n",
336
+ "#sk-container-id-1 input.sk-toggleable__control:checked~div.sk-toggleable__content {\n",
337
+ " /* Expand drop-down */\n",
338
+ " max-height: 200px;\n",
339
+ " max-width: 100%;\n",
340
+ " overflow: auto;\n",
341
+ "}\n",
342
+ "\n",
343
+ "#sk-container-id-1 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n",
344
+ " content: \"▾\";\n",
345
+ "}\n",
346
+ "\n",
347
+ "/* Pipeline/ColumnTransformer-specific style */\n",
348
+ "\n",
349
+ "#sk-container-id-1 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
350
+ " color: var(--sklearn-color-text);\n",
351
+ " background-color: var(--sklearn-color-unfitted-level-2);\n",
352
+ "}\n",
353
+ "\n",
354
+ "#sk-container-id-1 div.sk-label.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
355
+ " background-color: var(--sklearn-color-fitted-level-2);\n",
356
+ "}\n",
357
+ "\n",
358
+ "/* Estimator-specific style */\n",
359
+ "\n",
360
+ "/* Colorize estimator box */\n",
361
+ "#sk-container-id-1 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
362
+ " /* unfitted */\n",
363
+ " background-color: var(--sklearn-color-unfitted-level-2);\n",
364
+ "}\n",
365
+ "\n",
366
+ "#sk-container-id-1 div.sk-estimator.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
367
+ " /* fitted */\n",
368
+ " background-color: var(--sklearn-color-fitted-level-2);\n",
369
+ "}\n",
370
+ "\n",
371
+ "#sk-container-id-1 div.sk-label label.sk-toggleable__label,\n",
372
+ "#sk-container-id-1 div.sk-label label {\n",
373
+ " /* The background is the default theme color */\n",
374
+ " color: var(--sklearn-color-text-on-default-background);\n",
375
+ "}\n",
376
+ "\n",
377
+ "/* On hover, darken the color of the background */\n",
378
+ "#sk-container-id-1 div.sk-label:hover label.sk-toggleable__label {\n",
379
+ " color: var(--sklearn-color-text);\n",
380
+ " background-color: var(--sklearn-color-unfitted-level-2);\n",
381
+ "}\n",
382
+ "\n",
383
+ "/* Label box, darken color on hover, fitted */\n",
384
+ "#sk-container-id-1 div.sk-label.fitted:hover label.sk-toggleable__label.fitted {\n",
385
+ " color: var(--sklearn-color-text);\n",
386
+ " background-color: var(--sklearn-color-fitted-level-2);\n",
387
+ "}\n",
388
+ "\n",
389
+ "/* Estimator label */\n",
390
+ "\n",
391
+ "#sk-container-id-1 div.sk-label label {\n",
392
+ " font-family: monospace;\n",
393
+ " font-weight: bold;\n",
394
+ " display: inline-block;\n",
395
+ " line-height: 1.2em;\n",
396
+ "}\n",
397
+ "\n",
398
+ "#sk-container-id-1 div.sk-label-container {\n",
399
+ " text-align: center;\n",
400
+ "}\n",
401
+ "\n",
402
+ "/* Estimator-specific */\n",
403
+ "#sk-container-id-1 div.sk-estimator {\n",
404
+ " font-family: monospace;\n",
405
+ " border: 1px dotted var(--sklearn-color-border-box);\n",
406
+ " border-radius: 0.25em;\n",
407
+ " box-sizing: border-box;\n",
408
+ " margin-bottom: 0.5em;\n",
409
+ " /* unfitted */\n",
410
+ " background-color: var(--sklearn-color-unfitted-level-0);\n",
411
+ "}\n",
412
+ "\n",
413
+ "#sk-container-id-1 div.sk-estimator.fitted {\n",
414
+ " /* fitted */\n",
415
+ " background-color: var(--sklearn-color-fitted-level-0);\n",
416
+ "}\n",
417
+ "\n",
418
+ "/* on hover */\n",
419
+ "#sk-container-id-1 div.sk-estimator:hover {\n",
420
+ " /* unfitted */\n",
421
+ " background-color: var(--sklearn-color-unfitted-level-2);\n",
422
+ "}\n",
423
+ "\n",
424
+ "#sk-container-id-1 div.sk-estimator.fitted:hover {\n",
425
+ " /* fitted */\n",
426
+ " background-color: var(--sklearn-color-fitted-level-2);\n",
427
+ "}\n",
428
+ "\n",
429
+ "/* Specification for estimator info (e.g. \"i\" and \"?\") */\n",
430
+ "\n",
431
+ "/* Common style for \"i\" and \"?\" */\n",
432
+ "\n",
433
+ ".sk-estimator-doc-link,\n",
434
+ "a:link.sk-estimator-doc-link,\n",
435
+ "a:visited.sk-estimator-doc-link {\n",
436
+ " float: right;\n",
437
+ " font-size: smaller;\n",
438
+ " line-height: 1em;\n",
439
+ " font-family: monospace;\n",
440
+ " background-color: var(--sklearn-color-background);\n",
441
+ " border-radius: 1em;\n",
442
+ " height: 1em;\n",
443
+ " width: 1em;\n",
444
+ " text-decoration: none !important;\n",
445
+ " margin-left: 0.5em;\n",
446
+ " text-align: center;\n",
447
+ " /* unfitted */\n",
448
+ " border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
449
+ " color: var(--sklearn-color-unfitted-level-1);\n",
450
+ "}\n",
451
+ "\n",
452
+ ".sk-estimator-doc-link.fitted,\n",
453
+ "a:link.sk-estimator-doc-link.fitted,\n",
454
+ "a:visited.sk-estimator-doc-link.fitted {\n",
455
+ " /* fitted */\n",
456
+ " border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
457
+ " color: var(--sklearn-color-fitted-level-1);\n",
458
+ "}\n",
459
+ "\n",
460
+ "/* On hover */\n",
461
+ "div.sk-estimator:hover .sk-estimator-doc-link:hover,\n",
462
+ ".sk-estimator-doc-link:hover,\n",
463
+ "div.sk-label-container:hover .sk-estimator-doc-link:hover,\n",
464
+ ".sk-estimator-doc-link:hover {\n",
465
+ " /* unfitted */\n",
466
+ " background-color: var(--sklearn-color-unfitted-level-3);\n",
467
+ " color: var(--sklearn-color-background);\n",
468
+ " text-decoration: none;\n",
469
+ "}\n",
470
+ "\n",
471
+ "div.sk-estimator.fitted:hover .sk-estimator-doc-link.fitted:hover,\n",
472
+ ".sk-estimator-doc-link.fitted:hover,\n",
473
+ "div.sk-label-container:hover .sk-estimator-doc-link.fitted:hover,\n",
474
+ ".sk-estimator-doc-link.fitted:hover {\n",
475
+ " /* fitted */\n",
476
+ " background-color: var(--sklearn-color-fitted-level-3);\n",
477
+ " color: var(--sklearn-color-background);\n",
478
+ " text-decoration: none;\n",
479
+ "}\n",
480
+ "\n",
481
+ "/* Span, style for the box shown on hovering the info icon */\n",
482
+ ".sk-estimator-doc-link span {\n",
483
+ " display: none;\n",
484
+ " z-index: 9999;\n",
485
+ " position: relative;\n",
486
+ " font-weight: normal;\n",
487
+ " right: .2ex;\n",
488
+ " padding: .5ex;\n",
489
+ " margin: .5ex;\n",
490
+ " width: min-content;\n",
491
+ " min-width: 20ex;\n",
492
+ " max-width: 50ex;\n",
493
+ " color: var(--sklearn-color-text);\n",
494
+ " box-shadow: 2pt 2pt 4pt #999;\n",
495
+ " /* unfitted */\n",
496
+ " background: var(--sklearn-color-unfitted-level-0);\n",
497
+ " border: .5pt solid var(--sklearn-color-unfitted-level-3);\n",
498
+ "}\n",
499
+ "\n",
500
+ ".sk-estimator-doc-link.fitted span {\n",
501
+ " /* fitted */\n",
502
+ " background: var(--sklearn-color-fitted-level-0);\n",
503
+ " border: var(--sklearn-color-fitted-level-3);\n",
504
+ "}\n",
505
+ "\n",
506
+ ".sk-estimator-doc-link:hover span {\n",
507
+ " display: block;\n",
508
+ "}\n",
509
+ "\n",
510
+ "/* \"?\"-specific style due to the `<a>` HTML tag */\n",
511
+ "\n",
512
+ "#sk-container-id-1 a.estimator_doc_link {\n",
513
+ " float: right;\n",
514
+ " font-size: 1rem;\n",
515
+ " line-height: 1em;\n",
516
+ " font-family: monospace;\n",
517
+ " background-color: var(--sklearn-color-background);\n",
518
+ " border-radius: 1rem;\n",
519
+ " height: 1rem;\n",
520
+ " width: 1rem;\n",
521
+ " text-decoration: none;\n",
522
+ " /* unfitted */\n",
523
+ " color: var(--sklearn-color-unfitted-level-1);\n",
524
+ " border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
525
+ "}\n",
526
+ "\n",
527
+ "#sk-container-id-1 a.estimator_doc_link.fitted {\n",
528
+ " /* fitted */\n",
529
+ " border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
530
+ " color: var(--sklearn-color-fitted-level-1);\n",
531
+ "}\n",
532
+ "\n",
533
+ "/* On hover */\n",
534
+ "#sk-container-id-1 a.estimator_doc_link:hover {\n",
535
+ " /* unfitted */\n",
536
+ " background-color: var(--sklearn-color-unfitted-level-3);\n",
537
+ " color: var(--sklearn-color-background);\n",
538
+ " text-decoration: none;\n",
539
+ "}\n",
540
+ "\n",
541
+ "#sk-container-id-1 a.estimator_doc_link.fitted:hover {\n",
542
+ " /* fitted */\n",
543
+ " background-color: var(--sklearn-color-fitted-level-3);\n",
544
+ "}\n",
545
+ "</style><div id=\"sk-container-id-1\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>OneClassSVM(gamma=&#x27;auto&#x27;, nu=0.05)</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-1\" type=\"checkbox\" checked><label for=\"sk-estimator-id-1\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow\"><div><div>OneClassSVM</div></div><div><a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.6/modules/generated/sklearn.svm.OneClassSVM.html\">?<span>Documentation for OneClassSVM</span></a><span class=\"sk-estimator-doc-link fitted\">i<span>Fitted</span></span></div></label><div class=\"sk-toggleable__content fitted\"><pre>OneClassSVM(gamma=&#x27;auto&#x27;, nu=0.05)</pre></div> </div></div></div></div>"
546
+ ],
547
+ "text/plain": [
548
+ "OneClassSVM(gamma='auto', nu=0.05)"
549
+ ]
550
+ },
551
+ "execution_count": 7,
552
+ "metadata": {},
553
+ "output_type": "execute_result"
554
+ }
555
+ ],
556
+ "source": [
557
+ "X_train = X_scaled[df['label'] == 0]\n",
558
+ "svm = OneClassSVM(kernel='rbf', gamma='auto', nu=0.05) # nu is similar to contamination (regularization parameter)\n",
559
+ "svm.fit(X_train)"
560
+ ]
561
+ },
562
+ {
563
+ "cell_type": "markdown",
564
+ "metadata": {
565
+ "id": "-hk_VnreeH4O"
566
+ },
567
+ "source": [
568
+ "### 5. Make Predictions and Add Column\n",
569
+ "\n",
570
+ "We use the trained SVM to predict the entire dataset and convert predictions to:\n",
571
+ "- `1` = Stress (anomaly)\n",
572
+ "- `0` = No Stress (normal)\n",
573
+ "\n",
574
+ "These are saved as a new column in the DataFrame.\n"
575
+ ]
576
+ },
577
+ {
578
+ "cell_type": "code",
579
+ "execution_count": 8,
580
+ "metadata": {
581
+ "id": "YdjO3Tz7zIDq"
582
+ },
583
+ "outputs": [],
584
+ "source": [
585
+ "pred = svm.predict(X_scaled)"
586
+ ]
587
+ },
588
+ {
589
+ "cell_type": "code",
590
+ "execution_count": 9,
591
+ "metadata": {
592
+ "id": "CNqr0aPszYbx"
593
+ },
594
+ "outputs": [],
595
+ "source": [
596
+ "df['svm_anomaly'] = np.where(pred == -1, 1, 0)"
597
+ ]
598
+ },
599
+ {
600
+ "cell_type": "markdown",
601
+ "metadata": {
602
+ "id": "PchatUMqfH_f"
603
+ },
604
+ "source": [
605
+ "### 6. Evaluate the Model\n",
606
+ "\n",
607
+ "We compare the predicted labels (`svm_anomaly`) against the true labels (`label`) using:\n",
608
+ "- Confusion Matrix\n",
609
+ "- Classification Report (Precision, Recall, F1-score)\n"
610
+ ]
611
+ },
612
+ {
613
+ "cell_type": "code",
614
+ "execution_count": 10,
615
+ "metadata": {
616
+ "id": "tnkKPa6oza_R"
617
+ },
618
+ "outputs": [],
619
+ "source": [
620
+ "y_true = df['label']\n",
621
+ "y_pred = df['svm_anomaly']"
622
+ ]
623
+ },
624
+ {
625
+ "cell_type": "code",
626
+ "execution_count": 11,
627
+ "metadata": {
628
+ "colab": {
629
+ "base_uri": "https://localhost:8080/"
630
+ },
631
+ "id": "MMm8CfDDzeDK",
632
+ "outputId": "b2507be4-9e68-41be-ca5b-7e3d4c414646"
633
+ },
634
+ "outputs": [
635
+ {
636
+ "name": "stdout",
637
+ "output_type": "stream",
638
+ "text": [
639
+ "\n",
640
+ "Confusion Matrix:\n",
641
+ " [[4537 240]\n",
642
+ " [ 0 1943]]\n",
643
+ "\n",
644
+ "Classification Report:\n",
645
+ " precision recall f1-score support\n",
646
+ "\n",
647
+ " 0 1.00 0.95 0.97 4777\n",
648
+ " 1 0.89 1.00 0.94 1943\n",
649
+ "\n",
650
+ " accuracy 0.96 6720\n",
651
+ " macro avg 0.95 0.97 0.96 6720\n",
652
+ "weighted avg 0.97 0.96 0.96 6720\n",
653
+ "\n"
654
+ ]
655
+ }
656
+ ],
657
+ "source": [
658
+ "cm = confusion_matrix(y_true, y_pred)\n",
659
+ "print(\"\\nConfusion Matrix:\\n\", cm)\n",
660
+ "print(\"\\nClassification Report:\\n\", classification_report(y_true, y_pred))"
661
+ ]
662
+ },
663
+ {
664
+ "cell_type": "markdown",
665
+ "metadata": {
666
+ "id": "uQEOr85mcbZz"
667
+ },
668
+ "source": [
669
+ "### 7. Plot the Confusion Matrix\n",
670
+ "\n",
671
+ "We use Seaborn to plot a heatmap of the confusion matrix for better visualization.\n"
672
+ ]
673
+ },
674
+ {
675
+ "cell_type": "code",
676
+ "execution_count": 12,
677
+ "metadata": {
678
+ "colab": {
679
+ "base_uri": "https://localhost:8080/",
680
+ "height": 507
681
+ },
682
+ "id": "0duQF6pQzd8p",
683
+ "outputId": "202b31b9-bbdf-403d-de7f-8e088bc8f2a1"
684
+ },
685
+ "outputs": [
686
+ {
687
+ "data": {
688
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkAAAAHqCAYAAADs9fEjAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvc2/+5QAAAAlwSFlzAAAPYQAAD2EBqD+naQAAVvZJREFUeJzt3Qm8TPX/+PH3tV3Xvi9lj+xLqCx9LVlbZE0iZAshWaOyJqQFIcqeKEshhIQs2YlkKxGVfd/383+8P/3P/Gbu4p6ruebeM6/n4zHcOXPmzGfOnOV93p/lhFiWZQkAAEAQSRDoAgAAANxvBEAAACDoEAABAICgQwAEAACCDgEQAAAIOgRAAAAg6BAAAQCAoEMABAAAgg4BEAAACDoEQLHk999/l+rVq0vq1KklJCRE5s2b59fl//nnn2a5U6ZM8ety47NKlSqZB/4b1iOCFdt+cHF1APTHH39I27ZtJU+ePJI0aVJJlSqVlC9fXkaOHClXr16N1c9u3ry57Ny5U959912ZNm2alC5dWtzi5ZdfNsGXrs/I1qMGf/q6Pj744IMYL//IkSPSv39/2b59u8QnN2/elI8//lgeffRRSZkypaRIkcL8rdP0tUA7fvy4dO/eXQoUKCDJkiWT5MmTS6lSpWTQoEFy7tw5ies06G/RooU89NBDZn/OkiWLVKhQQfr162deP3HihCRKlEheeumlKJdx8eJFCQsLk3r16pnnegFhb6tr166NML/eKSh79uzm9WeffTbaMt65c0c+//xzefzxxyVdunRmO3j44YelWbNmsmHDBs98u3fvNtu4fqf45Mcff/SsL32EhoZK5syZTdAwePBgOXny5D0v+37t9/F13cP/EolLLVq0SJ5//nmzg+rBp0iRInLjxg1zkOvRo4fs2rVLPvvss1j5bA0K1q9fL2+99ZZ07NgxVj4jZ86c5nMSJ04sgaAnmitXrsiCBQukYcOGPq9Nnz7dnKCuXbt2zwfCAQMGSK5cuaREiRKO3/f9999LoFy+fFmeeeYZWbVqlTlRapCYIEECWbJkiXTu3Fm++eYbs01q0BEImzdvlqefflouXbpkAgQNfNSWLVtk6NChsnr16oCuv+js37/fBJMavLRs2dJsG0ePHpVt27bJe++9Z7aXTJkySbVq1WT+/Plm29QgLzz9HXS7DB8k6fY6Y8YMeeKJJ3ym6+/5999/m+OIE6+99pqMGTNGateuLU2aNDH7yb59+2Tx4sXmQqxMmTKek7CWWQMH/S7xjX5P/T1u375tgp5169aZQPSjjz6SWbNmyZNPPnnf9vuYutu6j8v7AGKB5UIHDhywUqRIYRUoUMA6cuRIhNd///13a8SIEbH2+YcOHdIbzFrvv/++5UbNmze3kidPblWvXt2qU6dOhNfz5ctn1a9f/57XwebNm817J0+e7Gj+y5cvW4H2yiuvmDKPGjUqwmujR482r7Vr1y4gZTt79qz14IMPWpkzZ7b27NkT4fVjx45Z77zzjud5xYoVzSMuefXVV61EiRJZf/75Z4TXjh8/7vl72rRpZl1/+eWXkS5Ht9nUqVNb165dM891G9P569WrZ2XIkMG6efOmz/xt2rSxSpUqZeXMmdN65pln7lpGXY8hISHmPeHduXPHp5yzZ882n7ty5cpov7u+98qVK1ZcoOXVcmv5w9u+fbuVKVMmK02aNJEed/2939+rmKx7uJsrAyA90egG/tNPPzmaXw96AwcOtPLkyWMlSZLEHOx69+7tOUja7IPgmjVrrEcffdQKDQ21cufObU2dOtUzT79+/cxnez/0fXbgYP/tzX6Pt++//94qX768OVhrsPHwww+bMtkOHjwY6cFi+fLl1hNPPGElS5bMvPe5556zdu/eHennaSCoZdL5UqVKZb388suOggk7AJoyZYpZB3qCtW3atMks++uvv44QAJ0+fdrq1q2bVaRIEfP+lClTWjVr1jQHzvAH2PAP+3vqiblw4cLWli1brP/9739WWFiY1blz50hP3M2aNTPlC//99SSoB+l//vnH8oe//vrLSpgwofXkk09GOU/lypXNCVznten36tChgzV37lzznXTbK1SokLV48eII7//777+tFi1amBOMPd/EiRMdlW/o0KHms6ZPn+5o/vDr8fr161afPn2skiVLmu1Ety3dxlasWBHhvRp46Hx6AaK/r/7W3hcbN27csPr372/lzZvX/Dbp0qUz27lu73dTo0YNK1euXNGW/dKlS2bbqlWrVoTXNADR36lVq1aeaXYApCdFDV6+++47n++dNm1a68MPP3QUAK1fv94sS/eLu7E/M/zDPiHbn7VkyRITfOl6Gj58uHlN9zXd3rNly2a2g4ceesj8vrdv374vv8PdAiA1Y8YM8/qbb74Zo+03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z56N0XK0jb4GU4kSsanCPerXr29GzZ06darkyZNHjh8/bgaLO336tONl6Pt14DkA90h7gSE4NW/e3Hr22WetAgUKWD169PBMnzt3rvYM9Jl3zpw5VqFChawkSZJYOXPmtD744IO7Lrt48eJW//797/rZ+hnej4MHD1orV640f3/33XdWyZIlrcSJE5tpt2/ftgYPHmzlypXLSpo0qVWsWDFr9uzZnuWdOXPGaty4sZUhQwbzet68ea1JkyaZ165fv2516NDBypIlixUaGmrlyJHDLAsIhLNnz5pt/Mcff4z0dd2/vPcLfa769etn9qvx48eb/SAkJMSzvFatWpltP2XKlFblypWt7du3e5anf1eqVMlKkSKFeV33q82bN5vX/vzzT3MMSJMmjZUsWTKzjy9atOi+rAcg0LisDnIJEyaUwYMHS+PGjeW1116TbNmyRZhn69at0rBhQ3PzOx3kat26dfLqq69K+vTpTTVaZDSlv2LFCjNfxowZI7w+cuRI+e2336RIkSIycOBAM03n+/PPP83fvXr1kg8++MBcHWtmSm/4+MUXX8i4ceMkX758snr1annppZfMeypWrCh9+vSR3bt3y+LFiyVDhgyyf/9+uXr1qlnWxx9/LN9++63MmjXLVDn89ddf5gEEQooUKcxDq7jKlCkTYQyfzZs3S6ZMmWTy5MlSs2ZNs4/adLv++uuv5ZtvvvFMf/755001s277el8wzbxWqVLF7F9a9dykSRN55JFHZOzYseY927dvl8SJE5v3dujQwWSSdH9Knjy52Ye0bEBQCHQEhsDRLEzt2rXN32XKlLFatmwZaQZIMyvVqlXzea9mjPRqMSq7du2yChYsaCVIkMAqWrSo1bZtW5PV8VaxYkWrc+fOPtPsDNC8efM8065du2auTtetW+czr171vvjii+bvWrVqWS1atIi0LJ06dbKefPJJ686dO9GuE+B+0Ixq2rRpTbayXLlyVu/eva0dO3Z4Xtd9QPdDb5oB0ozoiRMnPNPWrFljpUqVyuwj3h566CHr008/NX9r1mfKlCmRlkP3zbtlagE3oxE0DG0HpO0R9uzZE+E1nVa+fHmfafr8999/N+1zIlOoUCH59ddfZcOGDdKyZUs5ceKE1KpVS1q3bu2oPNpuyPuq98qVK1KtWjXP1bM+Pv/8c/njjz/MPNqg9KuvvjLDrvfs2dNkqWyapdKr3vz585ss1/fff+94vQCx1QboyJEjJjOpWZ4ff/xRSpYsKVOmTLnr+3LmzOmTUd2xY4dcunTJZGO9942DBw969g29N5Pud1WrVjUdE+zpSveHQYMGmf1ZR5T+5ZdfYvFbA3ELARCMChUqmF4ovXv39tsyEyRIII8++qjp6aUpez24T5w40Ryco6PpeJse4NWiRYtMIGM/NF0/Z84c89pTTz0lhw4dki5dupgTi1YBdO/e3bymJxb9zHfeecdUi2l1XoMGDfz2PYF77YCgQb1W32rAroG6BiFO9wt738iaNavPfqGPffv2SY8ePcw8WnW9a9cueeaZZ0y1tF6czJ0717ymgdGBAwekadOmsnPnTnPhMWrUqFj81kDcQQAED706XLBggaxfv95nesGCBT3dc236/OGHH/ZpnxAdPfAqvTOw0h4sUWWQwr9P20kcPnxY8ubN6/PInj27Zz69Mta7EGtbIb0D8WeffeZ5LVWqVKb90vjx42XmzJmmHcWZM2cclx2Ibbqd2/uGttFxsm9ocK83nNRekuH3DW0LZ9N9VS8ONPtZr149077IpvtQu3btzEVKt27dzD4CBAMaQcOjaNGipsGkNhr2pgdFzeRoBkWDCA2QtHv7J598EuWyNMOiafVy5cqZBtGagdHskh6IdWwglStXLtm4caNp+Kxpe22wGZmUKVOabI4ewO/cuSNPPPGEnD9/3gRhGtho0KN3Hi5VqpQULlxYrl+/LgsXLjSBm/roo4/MVbI2BNWs1OzZs02Z0qRJ49f1BzihXd214bJWDRcrVsxs3zpExLBhw6R27dqefUO7xes+pMF/VENUaLVW2bJlpU6dOub9un9pBlSzpXXr1jX7g2aCdH/MnTu3/P3336aRtVbBKc3OavZU36dDVKxcudKz3wCuF+hGSIgbjaBt2hVdu7pH1Q1eG2FqN/L333//rsv+7LPPTHfcjBkzmuXpe15++WXT7da2b98+0/g6LCwsQjd47drrTRswjxgxwsqfP78pgy63Ro0a1qpVq8zr77zzjml0rctKly6d+V4HDhzwlKVEiRJW8uTJTYPRKlWqWNu2bfvP6w+4F9pguVevXqY7eurUqU0Df92u3377bevKlStmnm+//dYM5ZAoUaII3eDDu3Dhgmno/8ADD5h9I3v27FaTJk2sw4cPmyEgGjVqZKbpfqjzdOzY0bp69ap5r/6tDaZ1eAjdp5o2bWqdOnXqPq8RIDC4GzwAAAg6tAECAABBhwAIAAAEHQIgAAAQdAiAAABA0CEAAgAAQYcACAAABB0CIAAAEHQIgAAAQNAhAALiIb1xpt7+wFapUiVzW4P7Te9iHhISIufOnbtv3zWulhNA/EIABPjxRK0nWX3ojV71hpQDBw6UW7duxfpn640s9V5tcTEY0Pta6c1pASAu4WaogB/VrFnT3Glbb8j63XffSYcOHcydvfVGsOHduHHDBEr+ENWNZAEAkSMDBPiR3rlb7zSfM2dOad++vblb97fffutTlfPuu+/KAw88IPnz5zfT//rrL2nYsKG5O70GMnpH8D///NOzzNu3b0vXrl3N6+nTp5eePXvqnWp9Pjd8FZgGYG+88YZkz57dlEmzURMnTjTLrVy5splH7zCumSAtl7pz544MGTLE3DU8LCxMihcvLnPmzPH5HA3q9M7h+roux7uc90K/W6tWrTyfqetk5MiRkc47YMAAyZgxo6RKlUratWtnAkibk7IDgDcyQEAs0pPx6dOnPc+XL19uTuDLli0zz2/evCk1atSQsmXLypo1ayRRokQyaNAgk0n65ZdfTIboww8/lClTpsikSZOkYMGC5vncuXPlySefjPJzmzVrJuvXr5ePP/7YBAMHDx6UU6dOmYDo66+/lvr168u+fftMWbSMSgOIL774QsaNGyf58uWT1atXy0svvWSCjooVK5pArV69eiar9corr8iWLVukW7du/2n9aOCSLVs2mT17tgnu1q1bZ5adNWtWExR6r7ekSZOa6jsNulq0aGHm12DSSdkBIIIA3YUecJ3mzZtbtWvXNn/fuXPHWrZsmRUaGmp1797d83rmzJmt69eve94zbdo0K3/+/GZ+m74eFhZmLV261DzPmjWrNWzYMM/rN2/etLJly+b5LFWxYkWrc+fO5u99+/Zpesh8fmRWrlxpXj979qxn2rVr16xkyZJZ69at85m3VatW1osvvmj+7t27t1WoUCGf1994440IywovZ86c1vDhwy2nOnToYNWvX9/zXNdbunTprMuXL3umjR071kqRIoV1+/ZtR2WP7DsDCG5kgAA/WrhwoaRIkcJkdjS70bhxY+nfv7/n9aJFi/q0+9mxY4fs379fUqZM6bOca9euyR9//CHnz5+Xo0ePyuOPP+55TbNEpUuXjlANZtu+fbskTJgwRpkPLcOVK1ekWrVqPtO1mumRRx4xf+/Zs8enHEozV//VmDFjTHbr8OHDcvXqVfOZJUqU8JlHs1jJkiXz+dxLly6ZrJT+H13ZASA8AiDAj7RdzNixY02Qo+18NFjxljx5cp/nevIuVaqUTJ8+PcKytPrmXthVWjGh5VCLFi2SBx980Oc1bUMUW7766ivp3r27qdbToEYDwffff182btwY58sOIH4jAAL8SAMcbXDsVMmSJWXmzJmSKVMm0x4nMtoeRgOCChUqmOfarX7r1q3mvZHRLJNmn1atWmUaYYdnZ6C0AbKtUKFCJljQLExUmSNtf2Q36LZt2LBB/ouffvpJypUrJ6+++qpnmma+wtNMmWaH7OBOP1czbdqmSRuOR1d2AAiPXmBAADVp0kQyZMhgen5pI2htrKwNfV977TX5+++/zTydO3eWoUOHyrx582Tv3r0mWLjbGD467k7z5s2lZcuW5j32MmfNmmVe1x5q2vtLq+tOnjxpMiiaedFMTJcuXWTq1KkmCNm2bZuMGjXKPFfa8+r333+XHj16mAbUM2bMMI2znfjnn39M1Zz34+zZs6bBsjamXrp0qfz222/Sp08f2bx5c4T3a3WW9hbbvXu36YnWr18/6dixoyRIkMBR2QEggkA3QgLc2Ag6Jq8fPXrUatasmZUhQwbTaDpPnjxWmzZtrPPnz3saPWsD51SpUllp0qSxunbtauaPqhG0unr1qtWlSxfTgDpJkiRW3rx5rUmTJnleHzhwoJUlSxYrJCTElEtpQ+wRI0aYRtmJEye2MmbMaNWoUcNatWqV530LFiwwy9Jy/u9//zPLdNIIWucJ/9AG4NqA+eWXX7ZSp05tvlv79u2tXr16WcWLF4+w3vr27WulT5/eNH7W9aPvtUVXdhpBAwgvRP+JGBYBAAC4F1VgAAAg6BAAAQCAoEMABAAAgg4BEAAACDoEQAAAIOgQAAEAgKBDAAQAAIIOARAAAAg6BEAAACDoEAABAICgQwAEAACCDgEQAACQYPP/ALa4hBOidSsaAAAAAElFTkSuQmCC",
689
+ "text/plain": [
690
+ "<Figure size 600x500 with 2 Axes>"
691
+ ]
692
+ },
693
+ "metadata": {},
694
+ "output_type": "display_data"
695
+ }
696
+ ],
697
+ "source": [
698
+ "plt.figure(figsize=(6, 5))\n",
699
+ "sns.heatmap(cm, annot=True, fmt='d', cmap='Purples',\n",
700
+ " xticklabels=['No Stress', 'Stress'],\n",
701
+ " yticklabels=['No Stress', 'Stress'])\n",
702
+ "plt.xlabel('Predicted Label')\n",
703
+ "plt.ylabel('True Label')\n",
704
+ "plt.title('Confusion Matrix - One-Class SVM Stress Detection')\n",
705
+ "plt.tight_layout()\n",
706
+ "plt.show()"
707
+ ]
708
+ },
709
+ {
710
+ "cell_type": "markdown",
711
+ "metadata": {
712
+ "id": "lpmFNKeSfRI3"
713
+ },
714
+ "source": [
715
+ "### 8. Save the Model and Scaler\n",
716
+ "\n",
717
+ "We save the trained One-Class SVM model and the scaler using `joblib` so they can be reused later for new data.\n"
718
+ ]
719
+ },
720
+ {
721
+ "cell_type": "code",
722
+ "execution_count": 13,
723
+ "metadata": {
724
+ "colab": {
725
+ "base_uri": "https://localhost:8080/"
726
+ },
727
+ "id": "RhL9Aqbqzk9x",
728
+ "outputId": "45a2425b-1c47-4211-af42-5b7617252372"
729
+ },
730
+ "outputs": [
731
+ {
732
+ "data": {
733
+ "text/plain": [
734
+ "['scaler.pkl']"
735
+ ]
736
+ },
737
+ "execution_count": 13,
738
+ "metadata": {},
739
+ "output_type": "execute_result"
740
+ }
741
+ ],
742
+ "source": [
743
+ "# Save the trained model to a file\n",
744
+ "joblib.dump(svm, 'one_class_svm_stress_model.pkl')\n",
745
+ "\n",
746
+ "# Save the scaler as well, to use the same scaling on new data\n",
747
+ "joblib.dump(scaler, 'scaler.pkl')\n"
748
+ ]
749
+ },
750
+ {
751
+ "cell_type": "markdown",
752
+ "metadata": {
753
+ "id": "JWvEAt3CfjZu"
754
+ },
755
+ "source": [
756
+ "### 9. Load Saved Model and Scaler\n",
757
+ "\n",
758
+ "We load the previously saved model and scaler for use in prediction.\n"
759
+ ]
760
+ },
761
+ {
762
+ "cell_type": "code",
763
+ "execution_count": 14,
764
+ "metadata": {
765
+ "id": "KaTPWMO2fnYH"
766
+ },
767
+ "outputs": [],
768
+ "source": [
769
+ "try:\n",
770
+ " model = joblib.load(\"one_class_svm_stress_model.pkl\")\n",
771
+ " scaler = joblib.load(\"scaler.pkl\")\n",
772
+ "except Exception as e:\n",
773
+ " print(f\"Error loading model or scaler: {e}\")\n"
774
+ ]
775
+ },
776
+ {
777
+ "cell_type": "markdown",
778
+ "metadata": {
779
+ "id": "4xYXYvpSfoJe"
780
+ },
781
+ "source": [
782
+ "### 10. Define Prediction Function\n",
783
+ "\n",
784
+ "This function generates a random sample of physiological signals and uses the model to classify whether the person is under stress.\n",
785
+ "- Values are scaled using the saved scaler.\n",
786
+ "- One-Class SVM makes the prediction.\n"
787
+ ]
788
+ },
789
+ {
790
+ "cell_type": "code",
791
+ "execution_count": 18,
792
+ "metadata": {
793
+ "id": "rZ-ALqfNfqf-"
794
+ },
795
+ "outputs": [],
796
+ "source": [
797
+ "def predict_stress():\n",
798
+ " try:\n",
799
+ " hr = np.random.randint(60, 120)\n",
800
+ " hrv = np.random.uniform(20, 80)\n",
801
+ " eda = np.random.uniform(0.1, 5.0)\n",
802
+ "\n",
803
+ " sample = np.array([[hr, hrv, eda]])\n",
804
+ " sample_scaled = scaler.transform(sample)\n",
805
+ "\n",
806
+ " pred = model.predict(sample_scaled)\n",
807
+ " label = \"Stress\" if pred[0] == -1 else \"No Stress\"\n",
808
+ "\n",
809
+ " return str(hr), f\"{hrv:.2f}\", f\"{eda:.2f}\", label\n",
810
+ "\n",
811
+ " except Exception as e:\n",
812
+ " return \"Error\", \"Error\", \"Error\", f\"Error: {str(e)}\"\n"
813
+ ]
814
+ },
815
+ {
816
+ "cell_type": "markdown",
817
+ "metadata": {
818
+ "id": "_wPFxQ9LfwaX"
819
+ },
820
+ "source": [
821
+ "### 11. Create Gradio Interface\n",
822
+ "\n",
823
+ "We use Gradio to build a simple web app with a button that:\n",
824
+ "- Simulates a reading\n",
825
+ "- Displays HR, HRV, EDA\n",
826
+ "- Shows the prediction (\"Stress\" or \"No Stress\")\n"
827
+ ]
828
+ },
829
+ {
830
+ "cell_type": "code",
831
+ "execution_count": 19,
832
+ "metadata": {
833
+ "colab": {
834
+ "base_uri": "https://localhost:8080/",
835
+ "height": 646
836
+ },
837
+ "id": "BPta2ttifs3_",
838
+ "outputId": "34740214-7181-4de5-8d3a-404be7841da9"
839
+ },
840
+ "outputs": [
841
+ {
842
+ "name": "stdout",
843
+ "output_type": "stream",
844
+ "text": [
845
+ "* Running on local URL: http://127.0.0.1:7860\n",
846
+ "* To create a public link, set `share=True` in `launch()`.\n"
847
+ ]
848
+ },
849
+ {
850
+ "data": {
851
+ "text/html": [
852
+ "<div><iframe src=\"http://127.0.0.1:7860/\" width=\"100%\" height=\"500\" allow=\"autoplay; camera; microphone; clipboard-read; clipboard-write;\" frameborder=\"0\" allowfullscreen></iframe></div>"
853
+ ],
854
+ "text/plain": [
855
+ "<IPython.core.display.HTML object>"
856
+ ]
857
+ },
858
+ "metadata": {},
859
+ "output_type": "display_data"
860
+ },
861
+ {
862
+ "data": {
863
+ "text/plain": []
864
+ },
865
+ "execution_count": 19,
866
+ "metadata": {},
867
+ "output_type": "execute_result"
868
+ }
869
+ ],
870
+ "source": [
871
+ "gr.Interface(\n",
872
+ " fn=predict_stress,\n",
873
+ " inputs=[],\n",
874
+ " outputs=[\n",
875
+ " gr.Textbox(label=\"Heart Rate (HR)\"),\n",
876
+ " gr.Textbox(label=\"Heart Rate Variability (HRV)\"),\n",
877
+ " gr.Textbox(label=\"Electrodermal Activity (EDA)\"),\n",
878
+ " gr.Textbox(label=\"Prediction\")\n",
879
+ " ],\n",
880
+ " title=\"Stress Detection using One-Class SVM\",\n",
881
+ " description=\"Click to generate random sensor data and detect if the person is under stress.\"\n",
882
+ ").launch()\n"
883
+ ]
884
+ }
885
+ ],
886
+ "metadata": {
887
+ "colab": {
888
+ "provenance": []
889
+ },
890
+ "kernelspec": {
891
+ "display_name": "Python 3",
892
+ "name": "python3"
893
+ },
894
+ "language_info": {
895
+ "codemirror_mode": {
896
+ "name": "ipython",
897
+ "version": 3
898
+ },
899
+ "file_extension": ".py",
900
+ "mimetype": "text/x-python",
901
+ "name": "python",
902
+ "nbconvert_exporter": "python",
903
+ "pygments_lexer": "ipython3",
904
+ "version": "3.13.2"
905
+ }
906
+ },
907
+ "nbformat": 4,
908
+ "nbformat_minor": 0
909
+ }
Image/360_F_1375669005_ebg3mldxps5ZYrQFlY6EX3eCINwVDeoF.jpg ADDED

Git LFS Details

  • SHA256: 9d89ff1045e0ab0427eaa07af4074f887ce8cc654a0f3e3e6775c7a6a955f899
  • Pointer size: 131 Bytes
  • Size of remote file: 118 kB
Image/istockphoto-1329512605-640x640.jpg ADDED
Image/stress-main.png ADDED

Git LFS Details

  • SHA256: e35390be1c75ff5e50dc2c2375a000449249d6701e547c63f66e0b612971b4a4
  • Pointer size: 131 Bytes
  • Size of remote file: 252 kB