liangc40 commited on
Commit
06cad47
1 Parent(s): 3d4e13e

Upload sentimental_analysis_training_pipeline.ipynb

Browse files
sentimental_analysis_training_pipeline.ipynb ADDED
@@ -0,0 +1,1094 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "nbformat": 4,
3
+ "nbformat_minor": 0,
4
+ "metadata": {
5
+ "colab": {
6
+ "provenance": []
7
+ },
8
+ "kernelspec": {
9
+ "name": "python3",
10
+ "display_name": "Python 3"
11
+ },
12
+ "language_info": {
13
+ "name": "python"
14
+ },
15
+ "accelerator": "GPU",
16
+ "gpuClass": "standard",
17
+ "widgets": {
18
+ "application/vnd.jupyter.widget-state+json": {
19
+ "23633252c1024924905ec679b76afcff": {
20
+ "model_module": "@jupyter-widgets/controls",
21
+ "model_name": "HBoxModel",
22
+ "model_module_version": "1.5.0",
23
+ "state": {
24
+ "_dom_classes": [],
25
+ "_model_module": "@jupyter-widgets/controls",
26
+ "_model_module_version": "1.5.0",
27
+ "_model_name": "HBoxModel",
28
+ "_view_count": null,
29
+ "_view_module": "@jupyter-widgets/controls",
30
+ "_view_module_version": "1.5.0",
31
+ "_view_name": "HBoxView",
32
+ "box_style": "",
33
+ "children": [
34
+ "IPY_MODEL_c2388f6069984613b88dc84ddb8e4fde",
35
+ "IPY_MODEL_49e6c1619fdc4e57baf4d981828fc141",
36
+ "IPY_MODEL_67459de96a474b3c89d12c259823fe8f"
37
+ ],
38
+ "layout": "IPY_MODEL_096988fe730241bca5b4647c3f5ac561"
39
+ }
40
+ },
41
+ "c2388f6069984613b88dc84ddb8e4fde": {
42
+ "model_module": "@jupyter-widgets/controls",
43
+ "model_name": "HTMLModel",
44
+ "model_module_version": "1.5.0",
45
+ "state": {
46
+ "_dom_classes": [],
47
+ "_model_module": "@jupyter-widgets/controls",
48
+ "_model_module_version": "1.5.0",
49
+ "_model_name": "HTMLModel",
50
+ "_view_count": null,
51
+ "_view_module": "@jupyter-widgets/controls",
52
+ "_view_module_version": "1.5.0",
53
+ "_view_name": "HTMLView",
54
+ "description": "",
55
+ "description_tooltip": null,
56
+ "layout": "IPY_MODEL_432ca53539984f6f8d38ff46c3afa42c",
57
+ "placeholder": "​",
58
+ "style": "IPY_MODEL_48d442f8e826410da171ab3c54bee0ee",
59
+ "value": "Model export complete: 100%"
60
+ }
61
+ },
62
+ "49e6c1619fdc4e57baf4d981828fc141": {
63
+ "model_module": "@jupyter-widgets/controls",
64
+ "model_name": "FloatProgressModel",
65
+ "model_module_version": "1.5.0",
66
+ "state": {
67
+ "_dom_classes": [],
68
+ "_model_module": "@jupyter-widgets/controls",
69
+ "_model_module_version": "1.5.0",
70
+ "_model_name": "FloatProgressModel",
71
+ "_view_count": null,
72
+ "_view_module": "@jupyter-widgets/controls",
73
+ "_view_module_version": "1.5.0",
74
+ "_view_name": "ProgressView",
75
+ "bar_style": "success",
76
+ "description": "",
77
+ "description_tooltip": null,
78
+ "layout": "IPY_MODEL_2571df81b38e490b8752309bd485b91e",
79
+ "max": 6,
80
+ "min": 0,
81
+ "orientation": "horizontal",
82
+ "style": "IPY_MODEL_02d2d92f6f754d6a9a6b9ed63d5dbed2",
83
+ "value": 6
84
+ }
85
+ },
86
+ "67459de96a474b3c89d12c259823fe8f": {
87
+ "model_module": "@jupyter-widgets/controls",
88
+ "model_name": "HTMLModel",
89
+ "model_module_version": "1.5.0",
90
+ "state": {
91
+ "_dom_classes": [],
92
+ "_model_module": "@jupyter-widgets/controls",
93
+ "_model_module_version": "1.5.0",
94
+ "_model_name": "HTMLModel",
95
+ "_view_count": null,
96
+ "_view_module": "@jupyter-widgets/controls",
97
+ "_view_module_version": "1.5.0",
98
+ "_view_name": "HTMLView",
99
+ "description": "",
100
+ "description_tooltip": null,
101
+ "layout": "IPY_MODEL_918c8791a4cb4fc08f16f49bbd2cd73f",
102
+ "placeholder": "​",
103
+ "style": "IPY_MODEL_3058453f9373468d9f09a5867c834d18",
104
+ "value": " 6/6 [05:03<00:00, 54.56s/it]"
105
+ }
106
+ },
107
+ "096988fe730241bca5b4647c3f5ac561": {
108
+ "model_module": "@jupyter-widgets/base",
109
+ "model_name": "LayoutModel",
110
+ "model_module_version": "1.2.0",
111
+ "state": {
112
+ "_model_module": "@jupyter-widgets/base",
113
+ "_model_module_version": "1.2.0",
114
+ "_model_name": "LayoutModel",
115
+ "_view_count": null,
116
+ "_view_module": "@jupyter-widgets/base",
117
+ "_view_module_version": "1.2.0",
118
+ "_view_name": "LayoutView",
119
+ "align_content": null,
120
+ "align_items": null,
121
+ "align_self": null,
122
+ "border": null,
123
+ "bottom": null,
124
+ "display": null,
125
+ "flex": null,
126
+ "flex_flow": null,
127
+ "grid_area": null,
128
+ "grid_auto_columns": null,
129
+ "grid_auto_flow": null,
130
+ "grid_auto_rows": null,
131
+ "grid_column": null,
132
+ "grid_gap": null,
133
+ "grid_row": null,
134
+ "grid_template_areas": null,
135
+ "grid_template_columns": null,
136
+ "grid_template_rows": null,
137
+ "height": null,
138
+ "justify_content": null,
139
+ "justify_items": null,
140
+ "left": null,
141
+ "margin": null,
142
+ "max_height": null,
143
+ "max_width": null,
144
+ "min_height": null,
145
+ "min_width": null,
146
+ "object_fit": null,
147
+ "object_position": null,
148
+ "order": null,
149
+ "overflow": null,
150
+ "overflow_x": null,
151
+ "overflow_y": null,
152
+ "padding": null,
153
+ "right": null,
154
+ "top": null,
155
+ "visibility": null,
156
+ "width": null
157
+ }
158
+ },
159
+ "432ca53539984f6f8d38ff46c3afa42c": {
160
+ "model_module": "@jupyter-widgets/base",
161
+ "model_name": "LayoutModel",
162
+ "model_module_version": "1.2.0",
163
+ "state": {
164
+ "_model_module": "@jupyter-widgets/base",
165
+ "_model_module_version": "1.2.0",
166
+ "_model_name": "LayoutModel",
167
+ "_view_count": null,
168
+ "_view_module": "@jupyter-widgets/base",
169
+ "_view_module_version": "1.2.0",
170
+ "_view_name": "LayoutView",
171
+ "align_content": null,
172
+ "align_items": null,
173
+ "align_self": null,
174
+ "border": null,
175
+ "bottom": null,
176
+ "display": null,
177
+ "flex": null,
178
+ "flex_flow": null,
179
+ "grid_area": null,
180
+ "grid_auto_columns": null,
181
+ "grid_auto_flow": null,
182
+ "grid_auto_rows": null,
183
+ "grid_column": null,
184
+ "grid_gap": null,
185
+ "grid_row": null,
186
+ "grid_template_areas": null,
187
+ "grid_template_columns": null,
188
+ "grid_template_rows": null,
189
+ "height": null,
190
+ "justify_content": null,
191
+ "justify_items": null,
192
+ "left": null,
193
+ "margin": null,
194
+ "max_height": null,
195
+ "max_width": null,
196
+ "min_height": null,
197
+ "min_width": null,
198
+ "object_fit": null,
199
+ "object_position": null,
200
+ "order": null,
201
+ "overflow": null,
202
+ "overflow_x": null,
203
+ "overflow_y": null,
204
+ "padding": null,
205
+ "right": null,
206
+ "top": null,
207
+ "visibility": null,
208
+ "width": null
209
+ }
210
+ },
211
+ "48d442f8e826410da171ab3c54bee0ee": {
212
+ "model_module": "@jupyter-widgets/controls",
213
+ "model_name": "DescriptionStyleModel",
214
+ "model_module_version": "1.5.0",
215
+ "state": {
216
+ "_model_module": "@jupyter-widgets/controls",
217
+ "_model_module_version": "1.5.0",
218
+ "_model_name": "DescriptionStyleModel",
219
+ "_view_count": null,
220
+ "_view_module": "@jupyter-widgets/base",
221
+ "_view_module_version": "1.2.0",
222
+ "_view_name": "StyleView",
223
+ "description_width": ""
224
+ }
225
+ },
226
+ "2571df81b38e490b8752309bd485b91e": {
227
+ "model_module": "@jupyter-widgets/base",
228
+ "model_name": "LayoutModel",
229
+ "model_module_version": "1.2.0",
230
+ "state": {
231
+ "_model_module": "@jupyter-widgets/base",
232
+ "_model_module_version": "1.2.0",
233
+ "_model_name": "LayoutModel",
234
+ "_view_count": null,
235
+ "_view_module": "@jupyter-widgets/base",
236
+ "_view_module_version": "1.2.0",
237
+ "_view_name": "LayoutView",
238
+ "align_content": null,
239
+ "align_items": null,
240
+ "align_self": null,
241
+ "border": null,
242
+ "bottom": null,
243
+ "display": null,
244
+ "flex": null,
245
+ "flex_flow": null,
246
+ "grid_area": null,
247
+ "grid_auto_columns": null,
248
+ "grid_auto_flow": null,
249
+ "grid_auto_rows": null,
250
+ "grid_column": null,
251
+ "grid_gap": null,
252
+ "grid_row": null,
253
+ "grid_template_areas": null,
254
+ "grid_template_columns": null,
255
+ "grid_template_rows": null,
256
+ "height": null,
257
+ "justify_content": null,
258
+ "justify_items": null,
259
+ "left": null,
260
+ "margin": null,
261
+ "max_height": null,
262
+ "max_width": null,
263
+ "min_height": null,
264
+ "min_width": null,
265
+ "object_fit": null,
266
+ "object_position": null,
267
+ "order": null,
268
+ "overflow": null,
269
+ "overflow_x": null,
270
+ "overflow_y": null,
271
+ "padding": null,
272
+ "right": null,
273
+ "top": null,
274
+ "visibility": null,
275
+ "width": null
276
+ }
277
+ },
278
+ "02d2d92f6f754d6a9a6b9ed63d5dbed2": {
279
+ "model_module": "@jupyter-widgets/controls",
280
+ "model_name": "ProgressStyleModel",
281
+ "model_module_version": "1.5.0",
282
+ "state": {
283
+ "_model_module": "@jupyter-widgets/controls",
284
+ "_model_module_version": "1.5.0",
285
+ "_model_name": "ProgressStyleModel",
286
+ "_view_count": null,
287
+ "_view_module": "@jupyter-widgets/base",
288
+ "_view_module_version": "1.2.0",
289
+ "_view_name": "StyleView",
290
+ "bar_color": null,
291
+ "description_width": ""
292
+ }
293
+ },
294
+ "918c8791a4cb4fc08f16f49bbd2cd73f": {
295
+ "model_module": "@jupyter-widgets/base",
296
+ "model_name": "LayoutModel",
297
+ "model_module_version": "1.2.0",
298
+ "state": {
299
+ "_model_module": "@jupyter-widgets/base",
300
+ "_model_module_version": "1.2.0",
301
+ "_model_name": "LayoutModel",
302
+ "_view_count": null,
303
+ "_view_module": "@jupyter-widgets/base",
304
+ "_view_module_version": "1.2.0",
305
+ "_view_name": "LayoutView",
306
+ "align_content": null,
307
+ "align_items": null,
308
+ "align_self": null,
309
+ "border": null,
310
+ "bottom": null,
311
+ "display": null,
312
+ "flex": null,
313
+ "flex_flow": null,
314
+ "grid_area": null,
315
+ "grid_auto_columns": null,
316
+ "grid_auto_flow": null,
317
+ "grid_auto_rows": null,
318
+ "grid_column": null,
319
+ "grid_gap": null,
320
+ "grid_row": null,
321
+ "grid_template_areas": null,
322
+ "grid_template_columns": null,
323
+ "grid_template_rows": null,
324
+ "height": null,
325
+ "justify_content": null,
326
+ "justify_items": null,
327
+ "left": null,
328
+ "margin": null,
329
+ "max_height": null,
330
+ "max_width": null,
331
+ "min_height": null,
332
+ "min_width": null,
333
+ "object_fit": null,
334
+ "object_position": null,
335
+ "order": null,
336
+ "overflow": null,
337
+ "overflow_x": null,
338
+ "overflow_y": null,
339
+ "padding": null,
340
+ "right": null,
341
+ "top": null,
342
+ "visibility": null,
343
+ "width": null
344
+ }
345
+ },
346
+ "3058453f9373468d9f09a5867c834d18": {
347
+ "model_module": "@jupyter-widgets/controls",
348
+ "model_name": "DescriptionStyleModel",
349
+ "model_module_version": "1.5.0",
350
+ "state": {
351
+ "_model_module": "@jupyter-widgets/controls",
352
+ "_model_module_version": "1.5.0",
353
+ "_model_name": "DescriptionStyleModel",
354
+ "_view_count": null,
355
+ "_view_module": "@jupyter-widgets/base",
356
+ "_view_module_version": "1.2.0",
357
+ "_view_name": "StyleView",
358
+ "description_width": ""
359
+ }
360
+ }
361
+ }
362
+ }
363
+ },
364
+ "cells": [
365
+ {
366
+ "cell_type": "code",
367
+ "execution_count": null,
368
+ "metadata": {
369
+ "id": "KNG3EMWB9woD"
370
+ },
371
+ "outputs": [],
372
+ "source": [
373
+ "!pip install click==8.0.3\n",
374
+ "!pip install cloudml_hypertune==0.1.0.dev6\n",
375
+ "!pip install hypertune==0.0.0\n",
376
+ "!pip uninstall matplotlib\n",
377
+ "!pip install matplotlib==3.1.3\n",
378
+ "!pip install numpy==1.20.3\n",
379
+ "!pip install pandas==1.3.4\n",
380
+ "!pip install protobuf==3.19.3\n",
381
+ "!pip install python-dotenv==0.19.2\n",
382
+ "!pip install cikit_learn==1.0.2\n",
383
+ "!pip install torch==1.10.1\n",
384
+ "!pip install transformers==4.15.0\n",
385
+ "!pip install hopsworks"
386
+ ]
387
+ },
388
+ {
389
+ "cell_type": "code",
390
+ "source": [
391
+ "import warnings\n",
392
+ "warnings.filterwarnings(\"ignore\")"
393
+ ],
394
+ "metadata": {
395
+ "id": "9jQ-nMBYH1mB"
396
+ },
397
+ "execution_count": 2,
398
+ "outputs": []
399
+ },
400
+ {
401
+ "cell_type": "code",
402
+ "source": [
403
+ "import hopsworks\n",
404
+ "project = hopsworks.login()"
405
+ ],
406
+ "metadata": {
407
+ "colab": {
408
+ "base_uri": "https://localhost:8080/"
409
+ },
410
+ "id": "xfOcg7kX_G15",
411
+ "outputId": "764a5c83-0b44-42fa-ec56-f5fea94c35ed"
412
+ },
413
+ "execution_count": 3,
414
+ "outputs": [
415
+ {
416
+ "output_type": "stream",
417
+ "name": "stdout",
418
+ "text": [
419
+ "Copy your Api Key (first register/login): https://c.app.hopsworks.ai/account/api/generated\n",
420
+ "\n",
421
+ "Paste it here: ··········\n",
422
+ "Connected. Call `.close()` to terminate connection gracefully.\n",
423
+ "\n",
424
+ "Multiple projects found. \n",
425
+ "\n",
426
+ "\t (1) liangc40\n",
427
+ "\t (2) Lab1_for_iris\n",
428
+ "\n",
429
+ "Enter project to access: 1\n",
430
+ "\n",
431
+ "Logged in to project, explore it here https://c.app.hopsworks.ai:443/p/5311\n"
432
+ ]
433
+ }
434
+ ]
435
+ },
436
+ {
437
+ "cell_type": "markdown",
438
+ "source": [
439
+ "## Load Feature from Hopsworks"
440
+ ],
441
+ "metadata": {
442
+ "id": "AS56zXEDCeae"
443
+ }
444
+ },
445
+ {
446
+ "cell_type": "code",
447
+ "source": [
448
+ "fs = project.get_feature_store()\n",
449
+ "try: \n",
450
+ " feature_view = fs.get_feature_view(name=\"sentimental_analysis_feature_group\", version=1)\n",
451
+ "except:\n",
452
+ " fg = fs.get_feature_group(name=\"sentimental_analysis_feature_group\", version=1)\n",
453
+ " query = fg.select_all()\n",
454
+ " feature_view = fs.create_feature_view(name=\"sentimental_analysis_feature_group\",\n",
455
+ " version=1,\n",
456
+ " description=\"Read from pre-processed sentimental analysis dataset\",\n",
457
+ " labels=[\"label\"],\n",
458
+ " query=query) "
459
+ ],
460
+ "metadata": {
461
+ "colab": {
462
+ "base_uri": "https://localhost:8080/"
463
+ },
464
+ "id": "ck9vNlZj_cRA",
465
+ "outputId": "1dbcae12-51cf-4a38-d77e-dd94e0201299"
466
+ },
467
+ "execution_count": 4,
468
+ "outputs": [
469
+ {
470
+ "output_type": "stream",
471
+ "name": "stderr",
472
+ "text": [
473
+ "DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3, and in 3.10 it will stop working\n",
474
+ "DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3, and in 3.10 it will stop working\n"
475
+ ]
476
+ },
477
+ {
478
+ "output_type": "stream",
479
+ "name": "stdout",
480
+ "text": [
481
+ "Connected. Call `.close()` to terminate connection gracefully.\n"
482
+ ]
483
+ }
484
+ ]
485
+ },
486
+ {
487
+ "cell_type": "markdown",
488
+ "source": [
489
+ "## Create DataLoader and TweetsDataset"
490
+ ],
491
+ "metadata": {
492
+ "id": "nts7RyyHCmlJ"
493
+ }
494
+ },
495
+ {
496
+ "cell_type": "code",
497
+ "source": [
498
+ "BATCH_SIZE = 16\n",
499
+ "MAX_LEN = 160\n",
500
+ "EPOCHS = 3"
501
+ ],
502
+ "metadata": {
503
+ "id": "zwfWbehIEZWH"
504
+ },
505
+ "execution_count": 35,
506
+ "outputs": []
507
+ },
508
+ {
509
+ "cell_type": "code",
510
+ "source": [
511
+ "from torch.utils.data import Dataset, DataLoader\n",
512
+ "from sklearn.model_selection import train_test_split\n",
513
+ "import torch\n",
514
+ "import numpy as np\n",
515
+ "from transformers import BertModel, BertTokenizer, AdamW, get_linear_schedule_with_warmup\n",
516
+ "\n",
517
+ "class TweetsDataset(Dataset):\n",
518
+ " def __init__(self, message, depression, tokenizer, max_len):\n",
519
+ " self.message = message\n",
520
+ " self.depression = depression\n",
521
+ " self.tokenizer = tokenizer\n",
522
+ " self.max_len = max_len\n",
523
+ " \n",
524
+ " def __len__(self):\n",
525
+ " return len(self.message)\n",
526
+ " \n",
527
+ " def __getitem__(self, item):\n",
528
+ " message = str(self.message[item])\n",
529
+ " depression = self.depression[item]\n",
530
+ "\n",
531
+ " encoding = self.tokenizer.encode_plus(\n",
532
+ " message,\n",
533
+ " add_special_tokens=True,\n",
534
+ " max_length=self.max_len,\n",
535
+ " return_token_type_ids=False,\n",
536
+ " truncation=True,\n",
537
+ " pad_to_max_length=True,\n",
538
+ " return_attention_mask=True,\n",
539
+ " return_tensors='pt',\n",
540
+ " )\n",
541
+ "\n",
542
+ " return {\n",
543
+ " 'tweet_text': message,\n",
544
+ " 'input_ids': encoding['input_ids'].flatten(),\n",
545
+ " 'attention_mask': encoding['attention_mask'].flatten(),\n",
546
+ " 'depression': torch.tensor(depression, dtype=torch.long)\n",
547
+ " }"
548
+ ],
549
+ "metadata": {
550
+ "id": "Icpi3iw7CRBu"
551
+ },
552
+ "execution_count": 6,
553
+ "outputs": []
554
+ },
555
+ {
556
+ "cell_type": "code",
557
+ "source": [
558
+ "def create_data_loader(message, depression, tokenizer, max_len, batch_size):\n",
559
+ " ds = TweetsDataset(\n",
560
+ " message = message['message'].to_numpy(),\n",
561
+ " depression = depression['label'].to_numpy(),\n",
562
+ " tokenizer=tokenizer,\n",
563
+ " max_len=max_len\n",
564
+ " )\n",
565
+ "\n",
566
+ " return DataLoader(\n",
567
+ " ds,\n",
568
+ " batch_size = batch_size,\n",
569
+ " num_workers = 9\n",
570
+ " )"
571
+ ],
572
+ "metadata": {
573
+ "id": "UzKUaFdOCU98"
574
+ },
575
+ "execution_count": 22,
576
+ "outputs": []
577
+ },
578
+ {
579
+ "cell_type": "code",
580
+ "source": [
581
+ "train_message, test_message, train_depression, test_depression = feature_view.train_test_split(0.2)\n",
582
+ "\n",
583
+ "#Creating dataloaders\n",
584
+ "tokenizer = BertTokenizer.from_pretrained('bert-base-cased')\n",
585
+ "train_data_loader = create_data_loader(train_message, train_depression, tokenizer, MAX_LEN, BATCH_SIZE)\n",
586
+ "test_data_loader = create_data_loader(test_message, test_depression, tokenizer, MAX_LEN, BATCH_SIZE)\n",
587
+ "data = next(iter(train_data_loader))"
588
+ ],
589
+ "metadata": {
590
+ "colab": {
591
+ "base_uri": "https://localhost:8080/"
592
+ },
593
+ "id": "QLzTqeQ7DDTs",
594
+ "outputId": "4c4b73fd-1b23-40a2-ca23-39efcfb9db72"
595
+ },
596
+ "execution_count": 23,
597
+ "outputs": [
598
+ {
599
+ "output_type": "stream",
600
+ "name": "stderr",
601
+ "text": [
602
+ "VersionWarning: Incremented version to `39`.\n"
603
+ ]
604
+ }
605
+ ]
606
+ },
607
+ {
608
+ "cell_type": "markdown",
609
+ "source": [
610
+ "## Bert-Based Depression Classier Model"
611
+ ],
612
+ "metadata": {
613
+ "id": "dzDl3HR6MRqf"
614
+ }
615
+ },
616
+ {
617
+ "cell_type": "code",
618
+ "source": [
619
+ "from torch import nn, optim\n",
620
+ "import torch.nn.functional as F\n",
621
+ "import transformers\n",
622
+ "from transformers import BertModel, BertTokenizer, AdamW, get_linear_schedule_with_warmup\n",
623
+ "from collections import defaultdict\n",
624
+ "\n",
625
+ "class DepressionClassifier(nn.Module):\n",
626
+ " def __init__(self, n_classes, pre_trained_model_name):\n",
627
+ " super(DepressionClassifier, self).__init__()\n",
628
+ " self.bert = BertModel.from_pretrained(pre_trained_model_name)\n",
629
+ " self.drop = nn.Dropout(p=0.3)\n",
630
+ " self.out = nn.Linear(self.bert.config.hidden_size, n_classes)\n",
631
+ "\n",
632
+ " def forward(self, input_ids, attention_mask):\n",
633
+ " _, pooled_output = self.bert(\n",
634
+ " input_ids=input_ids,\n",
635
+ " attention_mask=attention_mask,\n",
636
+ " return_dict = False #here\n",
637
+ " )\n",
638
+ " output = self.drop(pooled_output)\n",
639
+ " return self.out(output)"
640
+ ],
641
+ "metadata": {
642
+ "id": "frP5Mk_4NvSe"
643
+ },
644
+ "execution_count": 24,
645
+ "outputs": []
646
+ },
647
+ {
648
+ "cell_type": "code",
649
+ "source": [
650
+ "class_names = ['Not Depressed', 'Depressed']\n",
651
+ "model = DepressionClassifier(len(class_names), 'bert-base-cased')"
652
+ ],
653
+ "metadata": {
654
+ "colab": {
655
+ "base_uri": "https://localhost:8080/"
656
+ },
657
+ "id": "TH0OMDamN32-",
658
+ "outputId": "3ec8d3f7-1dee-4c0f-f004-37bcc2112a16"
659
+ },
660
+ "execution_count": 25,
661
+ "outputs": [
662
+ {
663
+ "output_type": "stream",
664
+ "name": "stderr",
665
+ "text": [
666
+ "Some weights of the model checkpoint at bert-base-cased were not used when initializing BertModel: ['cls.predictions.decoder.weight', 'cls.predictions.transform.dense.weight', 'cls.seq_relationship.weight', 'cls.seq_relationship.bias', 'cls.predictions.transform.dense.bias', 'cls.predictions.transform.LayerNorm.bias', 'cls.predictions.bias', 'cls.predictions.transform.LayerNorm.weight']\n",
667
+ "- This IS expected if you are initializing BertModel from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model).\n",
668
+ "- This IS NOT expected if you are initializing BertModel from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).\n"
669
+ ]
670
+ }
671
+ ]
672
+ },
673
+ {
674
+ "cell_type": "markdown",
675
+ "source": [
676
+ "## Training Functions"
677
+ ],
678
+ "metadata": {
679
+ "id": "wpJdcYItKqnN"
680
+ }
681
+ },
682
+ {
683
+ "cell_type": "code",
684
+ "source": [
685
+ "from torch import nn, optim\n",
686
+ "import torch.nn.functional as F\n",
687
+ "import transformers\n",
688
+ "from transformers import BertModel, BertTokenizer, AdamW, get_linear_schedule_with_warmup\n",
689
+ "from collections import defaultdict\n",
690
+ "import matplotlib.pyplot as plt"
691
+ ],
692
+ "metadata": {
693
+ "id": "czXmMyUzLS7z"
694
+ },
695
+ "execution_count": 26,
696
+ "outputs": []
697
+ },
698
+ {
699
+ "cell_type": "code",
700
+ "source": [
701
+ "def train_epoch(model, data_loader, loss_fn, optimizer, device, scheduler, n_examples):\n",
702
+ " model = model.train()\n",
703
+ "\n",
704
+ " losses = []\n",
705
+ " correct_predictions = 0\n",
706
+ " \n",
707
+ " for d in data_loader:\n",
708
+ " input_ids = d[\"input_ids\"].to(device)\n",
709
+ " attention_mask = d[\"attention_mask\"].to(device)\n",
710
+ " depression = d[\"depression\"].to(device)\n",
711
+ "\n",
712
+ " outputs = model(\n",
713
+ " input_ids = input_ids,\n",
714
+ " attention_mask = attention_mask\n",
715
+ " )\n",
716
+ "\n",
717
+ " _, preds = torch.max(outputs, dim=1)\n",
718
+ " loss = loss_fn(outputs, depression)\n",
719
+ "\n",
720
+ " correct_predictions += torch.sum(preds == depression)\n",
721
+ " losses.append(loss.item())\n",
722
+ "\n",
723
+ " loss.backward()\n",
724
+ " nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)\n",
725
+ " optimizer.step()\n",
726
+ " scheduler.step()\n",
727
+ " optimizer.zero_grad()\n",
728
+ "\n",
729
+ " return correct_predictions.double() / n_examples, np.mean(losses)"
730
+ ],
731
+ "metadata": {
732
+ "id": "OZ9Ykhx9Kv9X"
733
+ },
734
+ "execution_count": 27,
735
+ "outputs": []
736
+ },
737
+ {
738
+ "cell_type": "code",
739
+ "source": [
740
+ "def eval_model(model, data_loader, loss_fn, device, n_examples):\n",
741
+ " model = model.eval()\n",
742
+ " losses = []\n",
743
+ " correct_predictions = 0\n",
744
+ "\n",
745
+ " with torch.no_grad():\n",
746
+ " for d in data_loader:\n",
747
+ " input_ids = d[\"input_ids\"].to(device)\n",
748
+ " attention_mask = d[\"attention_mask\"].to(device)\n",
749
+ " depression = d[\"depression\"].to(device)\n",
750
+ "\n",
751
+ " outputs = model(\n",
752
+ " input_ids = input_ids,\n",
753
+ " attention_mask = attention_mask\n",
754
+ " )\n",
755
+ " _, preds = torch.max(outputs, dim=1)\n",
756
+ "\n",
757
+ " loss = loss_fn(outputs, depression)\n",
758
+ "\n",
759
+ " correct_predictions += torch.sum(preds == depression)\n",
760
+ " losses.append(loss.item())\n",
761
+ "\n",
762
+ " return correct_predictions.double() / n_examples, np.mean(losses)"
763
+ ],
764
+ "metadata": {
765
+ "id": "T6DMQmcrL0t6"
766
+ },
767
+ "execution_count": 28,
768
+ "outputs": []
769
+ },
770
+ {
771
+ "cell_type": "code",
772
+ "source": [
773
+ "def loss_accuracy_plots(history):\n",
774
+ " plt.figure(1)\n",
775
+ " plt.plot(history['train_loss'])\n",
776
+ " plt.plot(history['val_loss'])\n",
777
+ " plt.xlabel(\"Epochs [-]\")\n",
778
+ " plt.ylabel(\"Loss [-]\")\n",
779
+ " plt.legend(['Training loss','Validation loss'])\n",
780
+ " plt.grid()\n",
781
+ " plt.savefig(f\"/content/Training_losses_plot.jpg\")\n",
782
+ " plt.figure(2)\n",
783
+ " plt.plot(history['train_acc'])\n",
784
+ " plt.plot(history['val_acc'])\n",
785
+ " plt.xlabel(\"Epochs [-]\")\n",
786
+ " plt.ylabel(\"Loss [-]\")\n",
787
+ " plt.legend(['Training accuracy','Validation accuracy'])\n",
788
+ " plt.grid()\n",
789
+ " plt.savefig(f\"/content/Training_accuracies_plot.jpg\")"
790
+ ],
791
+ "metadata": {
792
+ "id": "JkAu-va5L34i"
793
+ },
794
+ "execution_count": 51,
795
+ "outputs": []
796
+ },
797
+ {
798
+ "cell_type": "markdown",
799
+ "source": [
800
+ "## Training Data"
801
+ ],
802
+ "metadata": {
803
+ "id": "rfslV1NJL7cj"
804
+ }
805
+ },
806
+ {
807
+ "cell_type": "code",
808
+ "source": [
809
+ "gpu_info = !nvidia-smi\n",
810
+ "gpu_info = '\\n'.join(gpu_info)\n",
811
+ "if gpu_info.find('failed') >= 0:\n",
812
+ " print('Not connected to a GPU')\n",
813
+ "else:\n",
814
+ " print(gpu_info)"
815
+ ],
816
+ "metadata": {
817
+ "colab": {
818
+ "base_uri": "https://localhost:8080/"
819
+ },
820
+ "id": "d_vJG_kuQlTw",
821
+ "outputId": "aff034a1-da7f-4159-f68b-82f6ba10812f"
822
+ },
823
+ "execution_count": 31,
824
+ "outputs": [
825
+ {
826
+ "output_type": "stream",
827
+ "name": "stdout",
828
+ "text": [
829
+ "Wed Jan 11 10:55:48 2023 \n",
830
+ "+-----------------------------------------------------------------------------+\n",
831
+ "| NVIDIA-SMI 460.32.03 Driver Version: 460.32.03 CUDA Version: 11.2 |\n",
832
+ "|-------------------------------+----------------------+----------------------+\n",
833
+ "| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |\n",
834
+ "| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |\n",
835
+ "| | | MIG M. |\n",
836
+ "|===============================+======================+======================|\n",
837
+ "| 0 Tesla T4 Off | 00000000:00:04.0 Off | 0 |\n",
838
+ "| N/A 55C P0 29W / 70W | 10716MiB / 15109MiB | 0% Default |\n",
839
+ "| | | N/A |\n",
840
+ "+-------------------------------+----------------------+----------------------+\n",
841
+ " \n",
842
+ "+-----------------------------------------------------------------------------+\n",
843
+ "| Processes: |\n",
844
+ "| GPU GI CI PID Type Process name GPU Memory |\n",
845
+ "| ID ID Usage |\n",
846
+ "|=============================================================================|\n",
847
+ "+-----------------------------------------------------------------------------+\n"
848
+ ]
849
+ }
850
+ ]
851
+ },
852
+ {
853
+ "cell_type": "code",
854
+ "source": [
855
+ "device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n",
856
+ "model = model.to(device)\n",
857
+ "input_ids = data['input_ids'].to(device)\n",
858
+ "attention_mask = data['attention_mask'].to(device)"
859
+ ],
860
+ "metadata": {
861
+ "id": "ly__rDVkRwB2"
862
+ },
863
+ "execution_count": 32,
864
+ "outputs": []
865
+ },
866
+ {
867
+ "cell_type": "code",
868
+ "source": [
869
+ "F.softmax(model(input_ids, attention_mask), dim=1)"
870
+ ],
871
+ "metadata": {
872
+ "colab": {
873
+ "base_uri": "https://localhost:8080/"
874
+ },
875
+ "id": "uLoWAKm3Wz8K",
876
+ "outputId": "d5713105-5c3d-40b4-82e4-5c6766852e5e"
877
+ },
878
+ "execution_count": 33,
879
+ "outputs": [
880
+ {
881
+ "output_type": "execute_result",
882
+ "data": {
883
+ "text/plain": [
884
+ "tensor([[0.6483, 0.3517],\n",
885
+ " [0.7467, 0.2533],\n",
886
+ " [0.7182, 0.2818],\n",
887
+ " [0.6410, 0.3590],\n",
888
+ " [0.4981, 0.5019],\n",
889
+ " [0.6323, 0.3677],\n",
890
+ " [0.3284, 0.6716],\n",
891
+ " [0.6354, 0.3646],\n",
892
+ " [0.5387, 0.4613],\n",
893
+ " [0.5530, 0.4470],\n",
894
+ " [0.5840, 0.4160],\n",
895
+ " [0.6082, 0.3918],\n",
896
+ " [0.5927, 0.4073],\n",
897
+ " [0.5545, 0.4455],\n",
898
+ " [0.7305, 0.2695],\n",
899
+ " [0.6892, 0.3108]], device='cuda:0', grad_fn=<SoftmaxBackward0>)"
900
+ ]
901
+ },
902
+ "metadata": {},
903
+ "execution_count": 33
904
+ }
905
+ ]
906
+ },
907
+ {
908
+ "cell_type": "code",
909
+ "source": [
910
+ "import gc\n",
911
+ "gc.collect()\n",
912
+ "\n",
913
+ "optimizer = AdamW(model.parameters(), lr = 2e-5, correct_bias = False)\n",
914
+ "total_steps = len(train_data_loader) * EPOCHS\n",
915
+ "scheduler = get_linear_schedule_with_warmup(optimizer,\n",
916
+ " num_warmup_steps = 0,\n",
917
+ " num_training_steps = total_steps)\n",
918
+ "\n",
919
+ "loss_fn = nn.CrossEntropyLoss().to(device)\n",
920
+ "history = defaultdict(list)\n",
921
+ "best_accuracy = 0\n",
922
+ "\n",
923
+ "for epoch in range(EPOCHS):\n",
924
+ " print(f'Epoch {epoch + 1}/{EPOCHS}')\n",
925
+ " print('-' * 10)\n",
926
+ " \n",
927
+ " train_acc, train_loss = train_epoch(model, train_data_loader, loss_fn, optimizer, device, scheduler, len(train_message))\n",
928
+ " \n",
929
+ " print(f'Train loss {train_loss} accuracy {train_acc}')\n",
930
+ " \n",
931
+ " val_acc, val_loss = eval_model(model, test_data_loader, loss_fn, device, len(test_message))\n",
932
+ " \n",
933
+ " print(f'Val loss {val_loss} accuracy {val_acc}')\n",
934
+ " \n",
935
+ " history['train_acc'].append(train_acc)\n",
936
+ " history['train_loss'].append(train_loss)\n",
937
+ " history['val_acc'].append(val_acc)\n",
938
+ " history['val_loss'].append(val_loss)"
939
+ ],
940
+ "metadata": {
941
+ "colab": {
942
+ "base_uri": "https://localhost:8080/"
943
+ },
944
+ "id": "RKbvtLNnW7dh",
945
+ "outputId": "1cc22ebc-bf68-4d97-f976-f37d92bc7993"
946
+ },
947
+ "execution_count": 41,
948
+ "outputs": [
949
+ {
950
+ "output_type": "stream",
951
+ "name": "stdout",
952
+ "text": [
953
+ "Epoch 1/3\n",
954
+ "----------\n",
955
+ "Train loss 0.032615248548951696 accuracy 0.9951367781155015\n",
956
+ "Val loss 0.03613543838475535 accuracy 0.9941662615459407\n",
957
+ "Epoch 2/3\n",
958
+ "----------\n",
959
+ "Train loss 0.021585255281155413 accuracy 0.9958662613981764\n",
960
+ "Val loss 0.008615166831007156 accuracy 0.9990277102576568\n",
961
+ "Epoch 3/3\n",
962
+ "----------\n",
963
+ "Train loss 0.003893426973731551 accuracy 0.9993920972644377\n",
964
+ "Val loss 0.009192386632538158 accuracy 0.9985415653864851\n"
965
+ ]
966
+ }
967
+ ]
968
+ },
969
+ {
970
+ "cell_type": "code",
971
+ "source": [
972
+ "from google.colab import drive\n",
973
+ "drive.mount('/content/drive')\n",
974
+ "torch.save(model.state_dict(), '/content/drive/MyDrive/data/weights.pth')"
975
+ ],
976
+ "metadata": {
977
+ "colab": {
978
+ "base_uri": "https://localhost:8080/"
979
+ },
980
+ "id": "asNHjpLTZOJQ",
981
+ "outputId": "bc24d7ab-e05e-451c-dbe4-52328ccf71ac"
982
+ },
983
+ "execution_count": 55,
984
+ "outputs": [
985
+ {
986
+ "output_type": "stream",
987
+ "name": "stdout",
988
+ "text": [
989
+ "Mounted at /content/drive\n"
990
+ ]
991
+ }
992
+ ]
993
+ },
994
+ {
995
+ "cell_type": "code",
996
+ "source": [
997
+ "import os\n",
998
+ "import joblib\n",
999
+ "from hsml.schema import Schema\n",
1000
+ "from hsml.model_schema import ModelSchema\n",
1001
+ "from sklearn.metrics import classification_report\n",
1002
+ "\n",
1003
+ "# We will now upload our model to the Hopsworks Model Registry. First get an object for the model registry.\n",
1004
+ "mr = project.get_model_registry()\n",
1005
+ " \n",
1006
+ "# The contents of the directory will be saved to the model registry. Create the dir, first.\n",
1007
+ "model_dir=\"sentimental_analysis_model\"\n",
1008
+ "if os.path.isdir(model_dir) == False:\n",
1009
+ " os.mkdir(model_dir)\n",
1010
+ "\n",
1011
+ "# Save both our model and the confusion matrix to 'model_dir', whose contents will be uploaded to the model registry\n",
1012
+ "joblib.dump(model, model_dir + \"/sentimental_analysis_model.pkl\") \n",
1013
+ "\n",
1014
+ "\n",
1015
+ "# Specify the schema of the model's input/output using the features (X_train) and labels (y_train)\n",
1016
+ "input_schema = Schema(train_message)\n",
1017
+ "output_schema = Schema(train_depression)\n",
1018
+ "model_schema = ModelSchema(input_schema, output_schema)\n",
1019
+ "\n",
1020
+ "# Create an entry in the model registry that includes the model's name, desc, metrics\n",
1021
+ "sentimental_analysis_model = mr.python.create_model(\n",
1022
+ " name=\"sentimental_analysis_model\", \n",
1023
+ " model_schema=model_schema,\n",
1024
+ " description=\"Sentimental Analysis Predictor\"\n",
1025
+ ")\n",
1026
+ " \n",
1027
+ "# Upload the model to the model registry, including all files in 'model_dir'\n",
1028
+ "sentimental_analysis_model.save(model_dir)"
1029
+ ],
1030
+ "metadata": {
1031
+ "colab": {
1032
+ "base_uri": "https://localhost:8080/",
1033
+ "height": 103,
1034
+ "referenced_widgets": [
1035
+ "23633252c1024924905ec679b76afcff",
1036
+ "c2388f6069984613b88dc84ddb8e4fde",
1037
+ "49e6c1619fdc4e57baf4d981828fc141",
1038
+ "67459de96a474b3c89d12c259823fe8f",
1039
+ "096988fe730241bca5b4647c3f5ac561",
1040
+ "432ca53539984f6f8d38ff46c3afa42c",
1041
+ "48d442f8e826410da171ab3c54bee0ee",
1042
+ "2571df81b38e490b8752309bd485b91e",
1043
+ "02d2d92f6f754d6a9a6b9ed63d5dbed2",
1044
+ "918c8791a4cb4fc08f16f49bbd2cd73f",
1045
+ "3058453f9373468d9f09a5867c834d18"
1046
+ ]
1047
+ },
1048
+ "id": "PNbxNGUimwj8",
1049
+ "outputId": "2e775988-7d2e-46d7-dba7-30896b30f7ac"
1050
+ },
1051
+ "execution_count": 56,
1052
+ "outputs": [
1053
+ {
1054
+ "output_type": "stream",
1055
+ "name": "stdout",
1056
+ "text": [
1057
+ "Connected. Call `.close()` to terminate connection gracefully.\n"
1058
+ ]
1059
+ },
1060
+ {
1061
+ "output_type": "display_data",
1062
+ "data": {
1063
+ "text/plain": [
1064
+ " 0%| | 0/6 [00:00<?, ?it/s]"
1065
+ ],
1066
+ "application/vnd.jupyter.widget-view+json": {
1067
+ "version_major": 2,
1068
+ "version_minor": 0,
1069
+ "model_id": "23633252c1024924905ec679b76afcff"
1070
+ }
1071
+ },
1072
+ "metadata": {}
1073
+ },
1074
+ {
1075
+ "output_type": "stream",
1076
+ "name": "stdout",
1077
+ "text": [
1078
+ "Model created, explore it at https://c.app.hopsworks.ai:443/p/5311/models/sentimental_analysis_model/1\n"
1079
+ ]
1080
+ },
1081
+ {
1082
+ "output_type": "execute_result",
1083
+ "data": {
1084
+ "text/plain": [
1085
+ "Model(name: 'sentimental_analysis_model', version: 1)"
1086
+ ]
1087
+ },
1088
+ "metadata": {},
1089
+ "execution_count": 56
1090
+ }
1091
+ ]
1092
+ }
1093
+ ]
1094
+ }