Spaces:
Running
Running
Hyperparameter tuning in notebook done
Browse files- notebook.ipynb +142 -507
notebook.ipynb
CHANGED
@@ -9,7 +9,7 @@
|
|
9 |
},
|
10 |
{
|
11 |
"cell_type": "code",
|
12 |
-
"execution_count":
|
13 |
"metadata": {},
|
14 |
"outputs": [],
|
15 |
"source": [
|
@@ -20,16 +20,18 @@
|
|
20 |
"if TYPE_CHECKING:\n",
|
21 |
" from sklearn.base import BaseEstimator\n",
|
22 |
"\n",
|
|
|
23 |
"import re\n",
|
24 |
"import warnings\n",
|
25 |
"from functools import cache\n",
|
|
|
26 |
"\n",
|
|
|
27 |
"import matplotlib.pyplot as plt\n",
|
28 |
"import nltk\n",
|
29 |
"import numpy as np\n",
|
30 |
"import pandas as pd\n",
|
31 |
"import seaborn as sns\n",
|
32 |
-
"from joblib import Memory\n",
|
33 |
"from nltk.corpus import stopwords\n",
|
34 |
"from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer\n",
|
35 |
"from sklearn.linear_model import LogisticRegression\n",
|
@@ -38,7 +40,7 @@
|
|
38 |
"from sklearn.pipeline import Pipeline\n",
|
39 |
"from sklearn.svm import SVC\n",
|
40 |
"\n",
|
41 |
-
"from app.constants import CACHE_DIR, SENTIMENT140_PATH\n",
|
42 |
"from app.model import TextCleaner, TextLemmatizer"
|
43 |
]
|
44 |
},
|
@@ -64,7 +66,7 @@
|
|
64 |
"[nltk_data] Downloading package wordnet to /home/tymec/nltk_data...\n",
|
65 |
"[nltk_data] Package wordnet is already up-to-date!\n",
|
66 |
"[nltk_data] Downloading package stopwords to /home/tymec/nltk_data...\n",
|
67 |
-
"[nltk_data]
|
68 |
]
|
69 |
},
|
70 |
{
|
@@ -99,7 +101,7 @@
|
|
99 |
},
|
100 |
{
|
101 |
"cell_type": "code",
|
102 |
-
"execution_count":
|
103 |
"metadata": {},
|
104 |
"outputs": [
|
105 |
{
|
@@ -141,7 +143,7 @@
|
|
141 |
" <td>NO_QUERY</td>\n",
|
142 |
" <td>_TheSpecialOne_</td>\n",
|
143 |
" <td>@switchfoot http://twitpic.com/2y1zl - Awww, t...</td>\n",
|
144 |
-
" <td>
|
145 |
" </tr>\n",
|
146 |
" <tr>\n",
|
147 |
" <th>1</th>\n",
|
@@ -151,7 +153,7 @@
|
|
151 |
" <td>NO_QUERY</td>\n",
|
152 |
" <td>scotthamilton</td>\n",
|
153 |
" <td>is upset that he can't update his Facebook by ...</td>\n",
|
154 |
-
" <td>
|
155 |
" </tr>\n",
|
156 |
" <tr>\n",
|
157 |
" <th>2</th>\n",
|
@@ -161,7 +163,7 @@
|
|
161 |
" <td>NO_QUERY</td>\n",
|
162 |
" <td>mattycus</td>\n",
|
163 |
" <td>@Kenichan I dived many times for the ball. Man...</td>\n",
|
164 |
-
" <td>
|
165 |
" </tr>\n",
|
166 |
" <tr>\n",
|
167 |
" <th>3</th>\n",
|
@@ -171,7 +173,7 @@
|
|
171 |
" <td>NO_QUERY</td>\n",
|
172 |
" <td>ElleCTF</td>\n",
|
173 |
" <td>my whole body feels itchy and like its on fire</td>\n",
|
174 |
-
" <td>
|
175 |
" </tr>\n",
|
176 |
" <tr>\n",
|
177 |
" <th>4</th>\n",
|
@@ -181,7 +183,7 @@
|
|
181 |
" <td>NO_QUERY</td>\n",
|
182 |
" <td>Karoli</td>\n",
|
183 |
" <td>@nationwideclass no, it's not behaving at all....</td>\n",
|
184 |
-
" <td>
|
185 |
" </tr>\n",
|
186 |
" </tbody>\n",
|
187 |
"</table>\n",
|
@@ -202,15 +204,15 @@
|
|
202 |
"3 ElleCTF my whole body feels itchy and like its on fire \n",
|
203 |
"4 Karoli @nationwideclass no, it's not behaving at all.... \n",
|
204 |
"\n",
|
205 |
-
"
|
206 |
-
"0
|
207 |
-
"1
|
208 |
-
"2
|
209 |
-
"3
|
210 |
-
"4
|
211 |
]
|
212 |
},
|
213 |
-
"execution_count":
|
214 |
"metadata": {},
|
215 |
"output_type": "execute_result"
|
216 |
}
|
@@ -234,7 +236,7 @@
|
|
234 |
"data = data[data[\"target\"] != 2]\n",
|
235 |
"\n",
|
236 |
"# Map the sentiment values\n",
|
237 |
-
"data[\"sentiment\"] = data[\"target\"].map({0:
|
238 |
"\n",
|
239 |
"# Show the first few rows\n",
|
240 |
"data.head()"
|
@@ -249,7 +251,7 @@
|
|
249 |
},
|
250 |
{
|
251 |
"cell_type": "code",
|
252 |
-
"execution_count":
|
253 |
"metadata": {},
|
254 |
"outputs": [],
|
255 |
"source": [
|
@@ -265,7 +267,7 @@
|
|
265 |
},
|
266 |
{
|
267 |
"cell_type": "code",
|
268 |
-
"execution_count":
|
269 |
"metadata": {},
|
270 |
"outputs": [
|
271 |
{
|
@@ -291,7 +293,7 @@
|
|
291 |
},
|
292 |
{
|
293 |
"cell_type": "code",
|
294 |
-
"execution_count":
|
295 |
"metadata": {},
|
296 |
"outputs": [],
|
297 |
"source": [
|
@@ -302,7 +304,7 @@
|
|
302 |
},
|
303 |
{
|
304 |
"cell_type": "code",
|
305 |
-
"execution_count":
|
306 |
"metadata": {},
|
307 |
"outputs": [
|
308 |
{
|
@@ -369,7 +371,7 @@
|
|
369 |
"4 my 314024"
|
370 |
]
|
371 |
},
|
372 |
-
"execution_count":
|
373 |
"metadata": {},
|
374 |
"output_type": "execute_result"
|
375 |
}
|
@@ -384,7 +386,7 @@
|
|
384 |
},
|
385 |
{
|
386 |
"cell_type": "code",
|
387 |
-
"execution_count":
|
388 |
"metadata": {},
|
389 |
"outputs": [
|
390 |
{
|
@@ -430,7 +432,7 @@
|
|
430 |
},
|
431 |
{
|
432 |
"cell_type": "code",
|
433 |
-
"execution_count":
|
434 |
"metadata": {},
|
435 |
"outputs": [],
|
436 |
"source": [
|
@@ -452,12 +454,12 @@
|
|
452 |
"cell_type": "markdown",
|
453 |
"metadata": {},
|
454 |
"source": [
|
455 |
-
"###
|
456 |
]
|
457 |
},
|
458 |
{
|
459 |
"cell_type": "code",
|
460 |
-
"execution_count":
|
461 |
"metadata": {},
|
462 |
"outputs": [],
|
463 |
"source": [
|
@@ -467,497 +469,26 @@
|
|
467 |
" # Text preprocessing\n",
|
468 |
" (\"clean\", TextCleaner()),\n",
|
469 |
" (\"lemma\", TextLemmatizer()),\n",
|
470 |
-
" #
|
471 |
" (\"vectorize\", CountVectorizer(stop_words=stopwords_en, ngram_range=(1, 2), max_features=MAX_FEATURES)),\n",
|
472 |
" (\"tfidf\", TfidfTransformer()),\n",
|
473 |
" ],\n",
|
474 |
-
" memory=Memory(CACHE_DIR, verbose=0),\n",
|
475 |
" verbose=True,\n",
|
476 |
")"
|
477 |
]
|
478 |
},
|
479 |
{
|
480 |
"cell_type": "code",
|
481 |
-
"execution_count":
|
482 |
"metadata": {},
|
483 |
"outputs": [
|
484 |
{
|
485 |
"name": "stdout",
|
486 |
"output_type": "stream",
|
487 |
"text": [
|
488 |
-
"[Pipeline] ......... (step 3 of 4) Processing vectorize, total= 41.9s\n",
|
489 |
"[Pipeline] ............. (step 4 of 4) Processing tfidf, total= 0.0s\n"
|
490 |
]
|
491 |
-
},
|
492 |
-
{
|
493 |
-
"name": "stderr",
|
494 |
-
"output_type": "stream",
|
495 |
-
"text": [
|
496 |
-
"/home/tymec/university/projekt-psi/.venv/lib/python3.12/site-packages/joblib/memory.py:577: UserWarning: Persisting input arguments took 0.55s to run.If this happens often in your code, it can cause performance problems (results will be correct in all cases). The reason for this is probably some large input arguments for a wrapped function.\n",
|
497 |
-
" return self._cached_call(args, kwargs, shelving=False)[0]\n"
|
498 |
-
]
|
499 |
-
},
|
500 |
-
{
|
501 |
-
"data": {
|
502 |
-
"text/html": [
|
503 |
-
"<style>#sk-container-id-1 {\n",
|
504 |
-
" /* Definition of color scheme common for light and dark mode */\n",
|
505 |
-
" --sklearn-color-text: black;\n",
|
506 |
-
" --sklearn-color-line: gray;\n",
|
507 |
-
" /* Definition of color scheme for unfitted estimators */\n",
|
508 |
-
" --sklearn-color-unfitted-level-0: #fff5e6;\n",
|
509 |
-
" --sklearn-color-unfitted-level-1: #f6e4d2;\n",
|
510 |
-
" --sklearn-color-unfitted-level-2: #ffe0b3;\n",
|
511 |
-
" --sklearn-color-unfitted-level-3: chocolate;\n",
|
512 |
-
" /* Definition of color scheme for fitted estimators */\n",
|
513 |
-
" --sklearn-color-fitted-level-0: #f0f8ff;\n",
|
514 |
-
" --sklearn-color-fitted-level-1: #d4ebff;\n",
|
515 |
-
" --sklearn-color-fitted-level-2: #b3dbfd;\n",
|
516 |
-
" --sklearn-color-fitted-level-3: cornflowerblue;\n",
|
517 |
-
"\n",
|
518 |
-
" /* Specific color for light theme */\n",
|
519 |
-
" --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
|
520 |
-
" --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, white)));\n",
|
521 |
-
" --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
|
522 |
-
" --sklearn-color-icon: #696969;\n",
|
523 |
-
"\n",
|
524 |
-
" @media (prefers-color-scheme: dark) {\n",
|
525 |
-
" /* Redefinition of color scheme for dark theme */\n",
|
526 |
-
" --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
|
527 |
-
" --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, #111)));\n",
|
528 |
-
" --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
|
529 |
-
" --sklearn-color-icon: #878787;\n",
|
530 |
-
" }\n",
|
531 |
-
"}\n",
|
532 |
-
"\n",
|
533 |
-
"#sk-container-id-1 {\n",
|
534 |
-
" color: var(--sklearn-color-text);\n",
|
535 |
-
"}\n",
|
536 |
-
"\n",
|
537 |
-
"#sk-container-id-1 pre {\n",
|
538 |
-
" padding: 0;\n",
|
539 |
-
"}\n",
|
540 |
-
"\n",
|
541 |
-
"#sk-container-id-1 input.sk-hidden--visually {\n",
|
542 |
-
" border: 0;\n",
|
543 |
-
" clip: rect(1px 1px 1px 1px);\n",
|
544 |
-
" clip: rect(1px, 1px, 1px, 1px);\n",
|
545 |
-
" height: 1px;\n",
|
546 |
-
" margin: -1px;\n",
|
547 |
-
" overflow: hidden;\n",
|
548 |
-
" padding: 0;\n",
|
549 |
-
" position: absolute;\n",
|
550 |
-
" width: 1px;\n",
|
551 |
-
"}\n",
|
552 |
-
"\n",
|
553 |
-
"#sk-container-id-1 div.sk-dashed-wrapped {\n",
|
554 |
-
" border: 1px dashed var(--sklearn-color-line);\n",
|
555 |
-
" margin: 0 0.4em 0.5em 0.4em;\n",
|
556 |
-
" box-sizing: border-box;\n",
|
557 |
-
" padding-bottom: 0.4em;\n",
|
558 |
-
" background-color: var(--sklearn-color-background);\n",
|
559 |
-
"}\n",
|
560 |
-
"\n",
|
561 |
-
"#sk-container-id-1 div.sk-container {\n",
|
562 |
-
" /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n",
|
563 |
-
" but bootstrap.min.css set `[hidden] { display: none !important; }`\n",
|
564 |
-
" so we also need the `!important` here to be able to override the\n",
|
565 |
-
" default hidden behavior on the sphinx rendered scikit-learn.org.\n",
|
566 |
-
" See: https://github.com/scikit-learn/scikit-learn/issues/21755 */\n",
|
567 |
-
" display: inline-block !important;\n",
|
568 |
-
" position: relative;\n",
|
569 |
-
"}\n",
|
570 |
-
"\n",
|
571 |
-
"#sk-container-id-1 div.sk-text-repr-fallback {\n",
|
572 |
-
" display: none;\n",
|
573 |
-
"}\n",
|
574 |
-
"\n",
|
575 |
-
"div.sk-parallel-item,\n",
|
576 |
-
"div.sk-serial,\n",
|
577 |
-
"div.sk-item {\n",
|
578 |
-
" /* draw centered vertical line to link estimators */\n",
|
579 |
-
" background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));\n",
|
580 |
-
" background-size: 2px 100%;\n",
|
581 |
-
" background-repeat: no-repeat;\n",
|
582 |
-
" background-position: center center;\n",
|
583 |
-
"}\n",
|
584 |
-
"\n",
|
585 |
-
"/* Parallel-specific style estimator block */\n",
|
586 |
-
"\n",
|
587 |
-
"#sk-container-id-1 div.sk-parallel-item::after {\n",
|
588 |
-
" content: \"\";\n",
|
589 |
-
" width: 100%;\n",
|
590 |
-
" border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n",
|
591 |
-
" flex-grow: 1;\n",
|
592 |
-
"}\n",
|
593 |
-
"\n",
|
594 |
-
"#sk-container-id-1 div.sk-parallel {\n",
|
595 |
-
" display: flex;\n",
|
596 |
-
" align-items: stretch;\n",
|
597 |
-
" justify-content: center;\n",
|
598 |
-
" background-color: var(--sklearn-color-background);\n",
|
599 |
-
" position: relative;\n",
|
600 |
-
"}\n",
|
601 |
-
"\n",
|
602 |
-
"#sk-container-id-1 div.sk-parallel-item {\n",
|
603 |
-
" display: flex;\n",
|
604 |
-
" flex-direction: column;\n",
|
605 |
-
"}\n",
|
606 |
-
"\n",
|
607 |
-
"#sk-container-id-1 div.sk-parallel-item:first-child::after {\n",
|
608 |
-
" align-self: flex-end;\n",
|
609 |
-
" width: 50%;\n",
|
610 |
-
"}\n",
|
611 |
-
"\n",
|
612 |
-
"#sk-container-id-1 div.sk-parallel-item:last-child::after {\n",
|
613 |
-
" align-self: flex-start;\n",
|
614 |
-
" width: 50%;\n",
|
615 |
-
"}\n",
|
616 |
-
"\n",
|
617 |
-
"#sk-container-id-1 div.sk-parallel-item:only-child::after {\n",
|
618 |
-
" width: 0;\n",
|
619 |
-
"}\n",
|
620 |
-
"\n",
|
621 |
-
"/* Serial-specific style estimator block */\n",
|
622 |
-
"\n",
|
623 |
-
"#sk-container-id-1 div.sk-serial {\n",
|
624 |
-
" display: flex;\n",
|
625 |
-
" flex-direction: column;\n",
|
626 |
-
" align-items: center;\n",
|
627 |
-
" background-color: var(--sklearn-color-background);\n",
|
628 |
-
" padding-right: 1em;\n",
|
629 |
-
" padding-left: 1em;\n",
|
630 |
-
"}\n",
|
631 |
-
"\n",
|
632 |
-
"\n",
|
633 |
-
"/* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is\n",
|
634 |
-
"clickable and can be expanded/collapsed.\n",
|
635 |
-
"- Pipeline and ColumnTransformer use this feature and define the default style\n",
|
636 |
-
"- Estimators will overwrite some part of the style using the `sk-estimator` class\n",
|
637 |
-
"*/\n",
|
638 |
-
"\n",
|
639 |
-
"/* Pipeline and ColumnTransformer style (default) */\n",
|
640 |
-
"\n",
|
641 |
-
"#sk-container-id-1 div.sk-toggleable {\n",
|
642 |
-
" /* Default theme specific background. It is overwritten whether we have a\n",
|
643 |
-
" specific estimator or a Pipeline/ColumnTransformer */\n",
|
644 |
-
" background-color: var(--sklearn-color-background);\n",
|
645 |
-
"}\n",
|
646 |
-
"\n",
|
647 |
-
"/* Toggleable label */\n",
|
648 |
-
"#sk-container-id-1 label.sk-toggleable__label {\n",
|
649 |
-
" cursor: pointer;\n",
|
650 |
-
" display: block;\n",
|
651 |
-
" width: 100%;\n",
|
652 |
-
" margin-bottom: 0;\n",
|
653 |
-
" padding: 0.5em;\n",
|
654 |
-
" box-sizing: border-box;\n",
|
655 |
-
" text-align: center;\n",
|
656 |
-
"}\n",
|
657 |
-
"\n",
|
658 |
-
"#sk-container-id-1 label.sk-toggleable__label-arrow:before {\n",
|
659 |
-
" /* Arrow on the left of the label */\n",
|
660 |
-
" content: \"▸\";\n",
|
661 |
-
" float: left;\n",
|
662 |
-
" margin-right: 0.25em;\n",
|
663 |
-
" color: var(--sklearn-color-icon);\n",
|
664 |
-
"}\n",
|
665 |
-
"\n",
|
666 |
-
"#sk-container-id-1 label.sk-toggleable__label-arrow:hover:before {\n",
|
667 |
-
" color: var(--sklearn-color-text);\n",
|
668 |
-
"}\n",
|
669 |
-
"\n",
|
670 |
-
"/* Toggleable content - dropdown */\n",
|
671 |
-
"\n",
|
672 |
-
"#sk-container-id-1 div.sk-toggleable__content {\n",
|
673 |
-
" max-height: 0;\n",
|
674 |
-
" max-width: 0;\n",
|
675 |
-
" overflow: hidden;\n",
|
676 |
-
" text-align: left;\n",
|
677 |
-
" /* unfitted */\n",
|
678 |
-
" background-color: var(--sklearn-color-unfitted-level-0);\n",
|
679 |
-
"}\n",
|
680 |
-
"\n",
|
681 |
-
"#sk-container-id-1 div.sk-toggleable__content.fitted {\n",
|
682 |
-
" /* fitted */\n",
|
683 |
-
" background-color: var(--sklearn-color-fitted-level-0);\n",
|
684 |
-
"}\n",
|
685 |
-
"\n",
|
686 |
-
"#sk-container-id-1 div.sk-toggleable__content pre {\n",
|
687 |
-
" margin: 0.2em;\n",
|
688 |
-
" border-radius: 0.25em;\n",
|
689 |
-
" color: var(--sklearn-color-text);\n",
|
690 |
-
" /* unfitted */\n",
|
691 |
-
" background-color: var(--sklearn-color-unfitted-level-0);\n",
|
692 |
-
"}\n",
|
693 |
-
"\n",
|
694 |
-
"#sk-container-id-1 div.sk-toggleable__content.fitted pre {\n",
|
695 |
-
" /* unfitted */\n",
|
696 |
-
" background-color: var(--sklearn-color-fitted-level-0);\n",
|
697 |
-
"}\n",
|
698 |
-
"\n",
|
699 |
-
"#sk-container-id-1 input.sk-toggleable__control:checked~div.sk-toggleable__content {\n",
|
700 |
-
" /* Expand drop-down */\n",
|
701 |
-
" max-height: 200px;\n",
|
702 |
-
" max-width: 100%;\n",
|
703 |
-
" overflow: auto;\n",
|
704 |
-
"}\n",
|
705 |
-
"\n",
|
706 |
-
"#sk-container-id-1 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n",
|
707 |
-
" content: \"▾\";\n",
|
708 |
-
"}\n",
|
709 |
-
"\n",
|
710 |
-
"/* Pipeline/ColumnTransformer-specific style */\n",
|
711 |
-
"\n",
|
712 |
-
"#sk-container-id-1 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
|
713 |
-
" color: var(--sklearn-color-text);\n",
|
714 |
-
" background-color: var(--sklearn-color-unfitted-level-2);\n",
|
715 |
-
"}\n",
|
716 |
-
"\n",
|
717 |
-
"#sk-container-id-1 div.sk-label.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
|
718 |
-
" background-color: var(--sklearn-color-fitted-level-2);\n",
|
719 |
-
"}\n",
|
720 |
-
"\n",
|
721 |
-
"/* Estimator-specific style */\n",
|
722 |
-
"\n",
|
723 |
-
"/* Colorize estimator box */\n",
|
724 |
-
"#sk-container-id-1 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
|
725 |
-
" /* unfitted */\n",
|
726 |
-
" background-color: var(--sklearn-color-unfitted-level-2);\n",
|
727 |
-
"}\n",
|
728 |
-
"\n",
|
729 |
-
"#sk-container-id-1 div.sk-estimator.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
|
730 |
-
" /* fitted */\n",
|
731 |
-
" background-color: var(--sklearn-color-fitted-level-2);\n",
|
732 |
-
"}\n",
|
733 |
-
"\n",
|
734 |
-
"#sk-container-id-1 div.sk-label label.sk-toggleable__label,\n",
|
735 |
-
"#sk-container-id-1 div.sk-label label {\n",
|
736 |
-
" /* The background is the default theme color */\n",
|
737 |
-
" color: var(--sklearn-color-text-on-default-background);\n",
|
738 |
-
"}\n",
|
739 |
-
"\n",
|
740 |
-
"/* On hover, darken the color of the background */\n",
|
741 |
-
"#sk-container-id-1 div.sk-label:hover label.sk-toggleable__label {\n",
|
742 |
-
" color: var(--sklearn-color-text);\n",
|
743 |
-
" background-color: var(--sklearn-color-unfitted-level-2);\n",
|
744 |
-
"}\n",
|
745 |
-
"\n",
|
746 |
-
"/* Label box, darken color on hover, fitted */\n",
|
747 |
-
"#sk-container-id-1 div.sk-label.fitted:hover label.sk-toggleable__label.fitted {\n",
|
748 |
-
" color: var(--sklearn-color-text);\n",
|
749 |
-
" background-color: var(--sklearn-color-fitted-level-2);\n",
|
750 |
-
"}\n",
|
751 |
-
"\n",
|
752 |
-
"/* Estimator label */\n",
|
753 |
-
"\n",
|
754 |
-
"#sk-container-id-1 div.sk-label label {\n",
|
755 |
-
" font-family: monospace;\n",
|
756 |
-
" font-weight: bold;\n",
|
757 |
-
" display: inline-block;\n",
|
758 |
-
" line-height: 1.2em;\n",
|
759 |
-
"}\n",
|
760 |
-
"\n",
|
761 |
-
"#sk-container-id-1 div.sk-label-container {\n",
|
762 |
-
" text-align: center;\n",
|
763 |
-
"}\n",
|
764 |
-
"\n",
|
765 |
-
"/* Estimator-specific */\n",
|
766 |
-
"#sk-container-id-1 div.sk-estimator {\n",
|
767 |
-
" font-family: monospace;\n",
|
768 |
-
" border: 1px dotted var(--sklearn-color-border-box);\n",
|
769 |
-
" border-radius: 0.25em;\n",
|
770 |
-
" box-sizing: border-box;\n",
|
771 |
-
" margin-bottom: 0.5em;\n",
|
772 |
-
" /* unfitted */\n",
|
773 |
-
" background-color: var(--sklearn-color-unfitted-level-0);\n",
|
774 |
-
"}\n",
|
775 |
-
"\n",
|
776 |
-
"#sk-container-id-1 div.sk-estimator.fitted {\n",
|
777 |
-
" /* fitted */\n",
|
778 |
-
" background-color: var(--sklearn-color-fitted-level-0);\n",
|
779 |
-
"}\n",
|
780 |
-
"\n",
|
781 |
-
"/* on hover */\n",
|
782 |
-
"#sk-container-id-1 div.sk-estimator:hover {\n",
|
783 |
-
" /* unfitted */\n",
|
784 |
-
" background-color: var(--sklearn-color-unfitted-level-2);\n",
|
785 |
-
"}\n",
|
786 |
-
"\n",
|
787 |
-
"#sk-container-id-1 div.sk-estimator.fitted:hover {\n",
|
788 |
-
" /* fitted */\n",
|
789 |
-
" background-color: var(--sklearn-color-fitted-level-2);\n",
|
790 |
-
"}\n",
|
791 |
-
"\n",
|
792 |
-
"/* Specification for estimator info (e.g. \"i\" and \"?\") */\n",
|
793 |
-
"\n",
|
794 |
-
"/* Common style for \"i\" and \"?\" */\n",
|
795 |
-
"\n",
|
796 |
-
".sk-estimator-doc-link,\n",
|
797 |
-
"a:link.sk-estimator-doc-link,\n",
|
798 |
-
"a:visited.sk-estimator-doc-link {\n",
|
799 |
-
" float: right;\n",
|
800 |
-
" font-size: smaller;\n",
|
801 |
-
" line-height: 1em;\n",
|
802 |
-
" font-family: monospace;\n",
|
803 |
-
" background-color: var(--sklearn-color-background);\n",
|
804 |
-
" border-radius: 1em;\n",
|
805 |
-
" height: 1em;\n",
|
806 |
-
" width: 1em;\n",
|
807 |
-
" text-decoration: none !important;\n",
|
808 |
-
" margin-left: 1ex;\n",
|
809 |
-
" /* unfitted */\n",
|
810 |
-
" border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
|
811 |
-
" color: var(--sklearn-color-unfitted-level-1);\n",
|
812 |
-
"}\n",
|
813 |
-
"\n",
|
814 |
-
".sk-estimator-doc-link.fitted,\n",
|
815 |
-
"a:link.sk-estimator-doc-link.fitted,\n",
|
816 |
-
"a:visited.sk-estimator-doc-link.fitted {\n",
|
817 |
-
" /* fitted */\n",
|
818 |
-
" border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
|
819 |
-
" color: var(--sklearn-color-fitted-level-1);\n",
|
820 |
-
"}\n",
|
821 |
-
"\n",
|
822 |
-
"/* On hover */\n",
|
823 |
-
"div.sk-estimator:hover .sk-estimator-doc-link:hover,\n",
|
824 |
-
".sk-estimator-doc-link:hover,\n",
|
825 |
-
"div.sk-label-container:hover .sk-estimator-doc-link:hover,\n",
|
826 |
-
".sk-estimator-doc-link:hover {\n",
|
827 |
-
" /* unfitted */\n",
|
828 |
-
" background-color: var(--sklearn-color-unfitted-level-3);\n",
|
829 |
-
" color: var(--sklearn-color-background);\n",
|
830 |
-
" text-decoration: none;\n",
|
831 |
-
"}\n",
|
832 |
-
"\n",
|
833 |
-
"div.sk-estimator.fitted:hover .sk-estimator-doc-link.fitted:hover,\n",
|
834 |
-
".sk-estimator-doc-link.fitted:hover,\n",
|
835 |
-
"div.sk-label-container:hover .sk-estimator-doc-link.fitted:hover,\n",
|
836 |
-
".sk-estimator-doc-link.fitted:hover {\n",
|
837 |
-
" /* fitted */\n",
|
838 |
-
" background-color: var(--sklearn-color-fitted-level-3);\n",
|
839 |
-
" color: var(--sklearn-color-background);\n",
|
840 |
-
" text-decoration: none;\n",
|
841 |
-
"}\n",
|
842 |
-
"\n",
|
843 |
-
"/* Span, style for the box shown on hovering the info icon */\n",
|
844 |
-
".sk-estimator-doc-link span {\n",
|
845 |
-
" display: none;\n",
|
846 |
-
" z-index: 9999;\n",
|
847 |
-
" position: relative;\n",
|
848 |
-
" font-weight: normal;\n",
|
849 |
-
" right: .2ex;\n",
|
850 |
-
" padding: .5ex;\n",
|
851 |
-
" margin: .5ex;\n",
|
852 |
-
" width: min-content;\n",
|
853 |
-
" min-width: 20ex;\n",
|
854 |
-
" max-width: 50ex;\n",
|
855 |
-
" color: var(--sklearn-color-text);\n",
|
856 |
-
" box-shadow: 2pt 2pt 4pt #999;\n",
|
857 |
-
" /* unfitted */\n",
|
858 |
-
" background: var(--sklearn-color-unfitted-level-0);\n",
|
859 |
-
" border: .5pt solid var(--sklearn-color-unfitted-level-3);\n",
|
860 |
-
"}\n",
|
861 |
-
"\n",
|
862 |
-
".sk-estimator-doc-link.fitted span {\n",
|
863 |
-
" /* fitted */\n",
|
864 |
-
" background: var(--sklearn-color-fitted-level-0);\n",
|
865 |
-
" border: var(--sklearn-color-fitted-level-3);\n",
|
866 |
-
"}\n",
|
867 |
-
"\n",
|
868 |
-
".sk-estimator-doc-link:hover span {\n",
|
869 |
-
" display: block;\n",
|
870 |
-
"}\n",
|
871 |
-
"\n",
|
872 |
-
"/* \"?\"-specific style due to the `<a>` HTML tag */\n",
|
873 |
-
"\n",
|
874 |
-
"#sk-container-id-1 a.estimator_doc_link {\n",
|
875 |
-
" float: right;\n",
|
876 |
-
" font-size: 1rem;\n",
|
877 |
-
" line-height: 1em;\n",
|
878 |
-
" font-family: monospace;\n",
|
879 |
-
" background-color: var(--sklearn-color-background);\n",
|
880 |
-
" border-radius: 1rem;\n",
|
881 |
-
" height: 1rem;\n",
|
882 |
-
" width: 1rem;\n",
|
883 |
-
" text-decoration: none;\n",
|
884 |
-
" /* unfitted */\n",
|
885 |
-
" color: var(--sklearn-color-unfitted-level-1);\n",
|
886 |
-
" border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
|
887 |
-
"}\n",
|
888 |
-
"\n",
|
889 |
-
"#sk-container-id-1 a.estimator_doc_link.fitted {\n",
|
890 |
-
" /* fitted */\n",
|
891 |
-
" border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
|
892 |
-
" color: var(--sklearn-color-fitted-level-1);\n",
|
893 |
-
"}\n",
|
894 |
-
"\n",
|
895 |
-
"/* On hover */\n",
|
896 |
-
"#sk-container-id-1 a.estimator_doc_link:hover {\n",
|
897 |
-
" /* unfitted */\n",
|
898 |
-
" background-color: var(--sklearn-color-unfitted-level-3);\n",
|
899 |
-
" color: var(--sklearn-color-background);\n",
|
900 |
-
" text-decoration: none;\n",
|
901 |
-
"}\n",
|
902 |
-
"\n",
|
903 |
-
"#sk-container-id-1 a.estimator_doc_link.fitted:hover {\n",
|
904 |
-
" /* fitted */\n",
|
905 |
-
" background-color: var(--sklearn-color-fitted-level-3);\n",
|
906 |
-
"}\n",
|
907 |
-
"</style><div id=\"sk-container-id-1\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>Pipeline(memory=Memory(location=.cache),\n",
|
908 |
-
" steps=[('clean', TextCleaner()), ('lemma', TextLemmatizer()),\n",
|
909 |
-
" ('vectorize',\n",
|
910 |
-
" CountVectorizer(max_features=20000, ngram_range=(1, 2),\n",
|
911 |
-
" stop_words=['i', 'me', 'my', 'myself', 'we',\n",
|
912 |
-
" 'our', 'ours', 'ourselves', 'you',\n",
|
913 |
-
" "you're", "you've", "you'll",\n",
|
914 |
-
" "you'd", 'your', 'yours',\n",
|
915 |
-
" 'yourself', 'yourselves', 'he',\n",
|
916 |
-
" 'him', 'his', 'himself', 'she',\n",
|
917 |
-
" "she's", 'her', 'hers', 'herself',\n",
|
918 |
-
" 'it', "it's", 'its', 'itself', ...])),\n",
|
919 |
-
" ('tfidf', TfidfTransformer())],\n",
|
920 |
-
" verbose=True)</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 sk-dashed-wrapped\"><div class=\"sk-label-container\"><div class=\"sk-label fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-1\" type=\"checkbox\" ><label for=\"sk-estimator-id-1\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\"> Pipeline<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.4/modules/generated/sklearn.pipeline.Pipeline.html\">?<span>Documentation for Pipeline</span></a><span class=\"sk-estimator-doc-link fitted\">i<span>Fitted</span></span></label><div class=\"sk-toggleable__content fitted\"><pre>Pipeline(memory=Memory(location=.cache),\n",
|
921 |
-
" steps=[('clean', TextCleaner()), ('lemma', TextLemmatizer()),\n",
|
922 |
-
" ('vectorize',\n",
|
923 |
-
" CountVectorizer(max_features=20000, ngram_range=(1, 2),\n",
|
924 |
-
" stop_words=['i', 'me', 'my', 'myself', 'we',\n",
|
925 |
-
" 'our', 'ours', 'ourselves', 'you',\n",
|
926 |
-
" "you're", "you've", "you'll",\n",
|
927 |
-
" "you'd", 'your', 'yours',\n",
|
928 |
-
" 'yourself', 'yourselves', 'he',\n",
|
929 |
-
" 'him', 'his', 'himself', 'she',\n",
|
930 |
-
" "she's", 'her', 'hers', 'herself',\n",
|
931 |
-
" 'it', "it's", 'its', 'itself', ...])),\n",
|
932 |
-
" ('tfidf', TfidfTransformer())],\n",
|
933 |
-
" verbose=True)</pre></div> </div></div><div class=\"sk-serial\"><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-2\" type=\"checkbox\" ><label for=\"sk-estimator-id-2\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\">TextCleaner</label><div class=\"sk-toggleable__content fitted\"><pre>TextCleaner()</pre></div> </div></div><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-3\" type=\"checkbox\" ><label for=\"sk-estimator-id-3\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\">TextLemmatizer</label><div class=\"sk-toggleable__content fitted\"><pre>TextLemmatizer()</pre></div> </div></div><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-4\" type=\"checkbox\" ><label for=\"sk-estimator-id-4\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\"> CountVectorizer<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.4/modules/generated/sklearn.feature_extraction.text.CountVectorizer.html\">?<span>Documentation for CountVectorizer</span></a></label><div class=\"sk-toggleable__content fitted\"><pre>CountVectorizer(max_features=20000, ngram_range=(1, 2),\n",
|
934 |
-
" stop_words=['i', 'me', 'my', 'myself', 'we', 'our', 'ours',\n",
|
935 |
-
" 'ourselves', 'you', "you're", "you've", "you'll",\n",
|
936 |
-
" "you'd", 'your', 'yours', 'yourself', 'yourselves',\n",
|
937 |
-
" 'he', 'him', 'his', 'himself', 'she', "she's",\n",
|
938 |
-
" 'her', 'hers', 'herself', 'it', "it's", 'its',\n",
|
939 |
-
" 'itself', ...])</pre></div> </div></div><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-5\" type=\"checkbox\" ><label for=\"sk-estimator-id-5\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\"> TfidfTransformer<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.4/modules/generated/sklearn.feature_extraction.text.TfidfTransformer.html\">?<span>Documentation for TfidfTransformer</span></a></label><div class=\"sk-toggleable__content fitted\"><pre>TfidfTransformer()</pre></div> </div></div></div></div></div></div>"
|
940 |
-
],
|
941 |
-
"text/plain": [
|
942 |
-
"Pipeline(memory=Memory(location=.cache),\n",
|
943 |
-
" steps=[('clean', TextCleaner()), ('lemma', TextLemmatizer()),\n",
|
944 |
-
" ('vectorize',\n",
|
945 |
-
" CountVectorizer(max_features=20000, ngram_range=(1, 2),\n",
|
946 |
-
" stop_words=['i', 'me', 'my', 'myself', 'we',\n",
|
947 |
-
" 'our', 'ours', 'ourselves', 'you',\n",
|
948 |
-
" \"you're\", \"you've\", \"you'll\",\n",
|
949 |
-
" \"you'd\", 'your', 'yours',\n",
|
950 |
-
" 'yourself', 'yourselves', 'he',\n",
|
951 |
-
" 'him', 'his', 'himself', 'she',\n",
|
952 |
-
" \"she's\", 'her', 'hers', 'herself',\n",
|
953 |
-
" 'it', \"it's\", 'its', 'itself', ...])),\n",
|
954 |
-
" ('tfidf', TfidfTransformer())],\n",
|
955 |
-
" verbose=True)"
|
956 |
-
]
|
957 |
-
},
|
958 |
-
"execution_count": 24,
|
959 |
-
"metadata": {},
|
960 |
-
"output_type": "execute_result"
|
961 |
}
|
962 |
],
|
963 |
"source": [
|
@@ -969,7 +500,7 @@
|
|
969 |
},
|
970 |
{
|
971 |
"cell_type": "code",
|
972 |
-
"execution_count":
|
973 |
"metadata": {},
|
974 |
"outputs": [],
|
975 |
"source": [
|
@@ -978,11 +509,33 @@
|
|
978 |
"X_test_preprocessed = preprocess_pipeline.transform(X_test)"
|
979 |
]
|
980 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
981 |
{
|
982 |
"cell_type": "markdown",
|
983 |
"metadata": {},
|
984 |
"source": [
|
985 |
-
"###
|
986 |
]
|
987 |
},
|
988 |
{
|
@@ -990,6 +543,24 @@
|
|
990 |
"execution_count": null,
|
991 |
"metadata": {},
|
992 |
"outputs": [],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
993 |
"source": [
|
994 |
"def evaluate_model(clf: BaseEstimator) -> None:\n",
|
995 |
" # Calculate the accuracy\n",
|
@@ -1027,7 +598,7 @@
|
|
1027 |
},
|
1028 |
{
|
1029 |
"cell_type": "code",
|
1030 |
-
"execution_count":
|
1031 |
"metadata": {},
|
1032 |
"outputs": [],
|
1033 |
"source": [
|
@@ -1055,12 +626,20 @@
|
|
1055 |
},
|
1056 |
{
|
1057 |
"cell_type": "code",
|
1058 |
-
"execution_count":
|
1059 |
"metadata": {},
|
1060 |
"outputs": [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1061 |
{
|
1062 |
"data": {
|
1063 |
-
"image/png": "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",
|
1064 |
"text/plain": [
|
1065 |
"<Figure size 800x600 with 1 Axes>"
|
1066 |
]
|
@@ -1078,7 +657,7 @@
|
|
1078 |
" lr_clf,\n",
|
1079 |
" {\n",
|
1080 |
" \"C\": np.logspace(-4, 4, 20),\n",
|
1081 |
-
" \"solver\": [\"liblinear\", \"saga\"]
|
1082 |
" \"penalty\": [\"l1\", \"l2\"],\n",
|
1083 |
" },\n",
|
1084 |
")\n",
|
@@ -1109,6 +688,62 @@
|
|
1109 |
"# Evaluate the model\n",
|
1110 |
"evaluate_model(best_svm_clf)"
|
1111 |
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1112 |
}
|
1113 |
],
|
1114 |
"metadata": {
|
|
|
9 |
},
|
10 |
{
|
11 |
"cell_type": "code",
|
12 |
+
"execution_count": 1,
|
13 |
"metadata": {},
|
14 |
"outputs": [],
|
15 |
"source": [
|
|
|
20 |
"if TYPE_CHECKING:\n",
|
21 |
" from sklearn.base import BaseEstimator\n",
|
22 |
"\n",
|
23 |
+
"import json\n",
|
24 |
"import re\n",
|
25 |
"import warnings\n",
|
26 |
"from functools import cache\n",
|
27 |
+
"from pathlib import Path\n",
|
28 |
"\n",
|
29 |
+
"import joblib\n",
|
30 |
"import matplotlib.pyplot as plt\n",
|
31 |
"import nltk\n",
|
32 |
"import numpy as np\n",
|
33 |
"import pandas as pd\n",
|
34 |
"import seaborn as sns\n",
|
|
|
35 |
"from nltk.corpus import stopwords\n",
|
36 |
"from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer\n",
|
37 |
"from sklearn.linear_model import LogisticRegression\n",
|
|
|
40 |
"from sklearn.pipeline import Pipeline\n",
|
41 |
"from sklearn.svm import SVC\n",
|
42 |
"\n",
|
43 |
+
"from app.constants import CACHE_DIR, MODELS_DIR, SENTIMENT140_PATH\n",
|
44 |
"from app.model import TextCleaner, TextLemmatizer"
|
45 |
]
|
46 |
},
|
|
|
66 |
"[nltk_data] Downloading package wordnet to /home/tymec/nltk_data...\n",
|
67 |
"[nltk_data] Package wordnet is already up-to-date!\n",
|
68 |
"[nltk_data] Downloading package stopwords to /home/tymec/nltk_data...\n",
|
69 |
+
"[nltk_data] Package stopwords is already up-to-date!\n"
|
70 |
]
|
71 |
},
|
72 |
{
|
|
|
101 |
},
|
102 |
{
|
103 |
"cell_type": "code",
|
104 |
+
"execution_count": 4,
|
105 |
"metadata": {},
|
106 |
"outputs": [
|
107 |
{
|
|
|
143 |
" <td>NO_QUERY</td>\n",
|
144 |
" <td>_TheSpecialOne_</td>\n",
|
145 |
" <td>@switchfoot http://twitpic.com/2y1zl - Awww, t...</td>\n",
|
146 |
+
" <td>0</td>\n",
|
147 |
" </tr>\n",
|
148 |
" <tr>\n",
|
149 |
" <th>1</th>\n",
|
|
|
153 |
" <td>NO_QUERY</td>\n",
|
154 |
" <td>scotthamilton</td>\n",
|
155 |
" <td>is upset that he can't update his Facebook by ...</td>\n",
|
156 |
+
" <td>0</td>\n",
|
157 |
" </tr>\n",
|
158 |
" <tr>\n",
|
159 |
" <th>2</th>\n",
|
|
|
163 |
" <td>NO_QUERY</td>\n",
|
164 |
" <td>mattycus</td>\n",
|
165 |
" <td>@Kenichan I dived many times for the ball. Man...</td>\n",
|
166 |
+
" <td>0</td>\n",
|
167 |
" </tr>\n",
|
168 |
" <tr>\n",
|
169 |
" <th>3</th>\n",
|
|
|
173 |
" <td>NO_QUERY</td>\n",
|
174 |
" <td>ElleCTF</td>\n",
|
175 |
" <td>my whole body feels itchy and like its on fire</td>\n",
|
176 |
+
" <td>0</td>\n",
|
177 |
" </tr>\n",
|
178 |
" <tr>\n",
|
179 |
" <th>4</th>\n",
|
|
|
183 |
" <td>NO_QUERY</td>\n",
|
184 |
" <td>Karoli</td>\n",
|
185 |
" <td>@nationwideclass no, it's not behaving at all....</td>\n",
|
186 |
+
" <td>0</td>\n",
|
187 |
" </tr>\n",
|
188 |
" </tbody>\n",
|
189 |
"</table>\n",
|
|
|
204 |
"3 ElleCTF my whole body feels itchy and like its on fire \n",
|
205 |
"4 Karoli @nationwideclass no, it's not behaving at all.... \n",
|
206 |
"\n",
|
207 |
+
" sentiment \n",
|
208 |
+
"0 0 \n",
|
209 |
+
"1 0 \n",
|
210 |
+
"2 0 \n",
|
211 |
+
"3 0 \n",
|
212 |
+
"4 0 "
|
213 |
]
|
214 |
},
|
215 |
+
"execution_count": 4,
|
216 |
"metadata": {},
|
217 |
"output_type": "execute_result"
|
218 |
}
|
|
|
236 |
"data = data[data[\"target\"] != 2]\n",
|
237 |
"\n",
|
238 |
"# Map the sentiment values\n",
|
239 |
+
"data[\"sentiment\"] = data[\"target\"].map({0: 0, 4: 1})\n",
|
240 |
"\n",
|
241 |
"# Show the first few rows\n",
|
242 |
"data.head()"
|
|
|
251 |
},
|
252 |
{
|
253 |
"cell_type": "code",
|
254 |
+
"execution_count": 5,
|
255 |
"metadata": {},
|
256 |
"outputs": [],
|
257 |
"source": [
|
|
|
267 |
},
|
268 |
{
|
269 |
"cell_type": "code",
|
270 |
+
"execution_count": 6,
|
271 |
"metadata": {},
|
272 |
"outputs": [
|
273 |
{
|
|
|
293 |
},
|
294 |
{
|
295 |
"cell_type": "code",
|
296 |
+
"execution_count": 7,
|
297 |
"metadata": {},
|
298 |
"outputs": [],
|
299 |
"source": [
|
|
|
304 |
},
|
305 |
{
|
306 |
"cell_type": "code",
|
307 |
+
"execution_count": 8,
|
308 |
"metadata": {},
|
309 |
"outputs": [
|
310 |
{
|
|
|
371 |
"4 my 314024"
|
372 |
]
|
373 |
},
|
374 |
+
"execution_count": 8,
|
375 |
"metadata": {},
|
376 |
"output_type": "execute_result"
|
377 |
}
|
|
|
386 |
},
|
387 |
{
|
388 |
"cell_type": "code",
|
389 |
+
"execution_count": 9,
|
390 |
"metadata": {},
|
391 |
"outputs": [
|
392 |
{
|
|
|
432 |
},
|
433 |
{
|
434 |
"cell_type": "code",
|
435 |
+
"execution_count": 10,
|
436 |
"metadata": {},
|
437 |
"outputs": [],
|
438 |
"source": [
|
|
|
454 |
"cell_type": "markdown",
|
455 |
"metadata": {},
|
456 |
"source": [
|
457 |
+
"### Create a tokenizer and transform the data"
|
458 |
]
|
459 |
},
|
460 |
{
|
461 |
"cell_type": "code",
|
462 |
+
"execution_count": 11,
|
463 |
"metadata": {},
|
464 |
"outputs": [],
|
465 |
"source": [
|
|
|
469 |
" # Text preprocessing\n",
|
470 |
" (\"clean\", TextCleaner()),\n",
|
471 |
" (\"lemma\", TextLemmatizer()),\n",
|
472 |
+
" # Tokenize (NOTE: Can be replaced with TfidfVectorizer, but left for clarity)\n",
|
473 |
" (\"vectorize\", CountVectorizer(stop_words=stopwords_en, ngram_range=(1, 2), max_features=MAX_FEATURES)),\n",
|
474 |
" (\"tfidf\", TfidfTransformer()),\n",
|
475 |
" ],\n",
|
476 |
+
" memory=joblib.Memory(CACHE_DIR, verbose=0),\n",
|
477 |
" verbose=True,\n",
|
478 |
")"
|
479 |
]
|
480 |
},
|
481 |
{
|
482 |
"cell_type": "code",
|
483 |
+
"execution_count": 12,
|
484 |
"metadata": {},
|
485 |
"outputs": [
|
486 |
{
|
487 |
"name": "stdout",
|
488 |
"output_type": "stream",
|
489 |
"text": [
|
|
|
490 |
"[Pipeline] ............. (step 4 of 4) Processing tfidf, total= 0.0s\n"
|
491 |
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
492 |
}
|
493 |
],
|
494 |
"source": [
|
|
|
500 |
},
|
501 |
{
|
502 |
"cell_type": "code",
|
503 |
+
"execution_count": 13,
|
504 |
"metadata": {},
|
505 |
"outputs": [],
|
506 |
"source": [
|
|
|
509 |
"X_test_preprocessed = preprocess_pipeline.transform(X_test)"
|
510 |
]
|
511 |
},
|
512 |
+
{
|
513 |
+
"cell_type": "code",
|
514 |
+
"execution_count": 14,
|
515 |
+
"metadata": {},
|
516 |
+
"outputs": [
|
517 |
+
{
|
518 |
+
"data": {
|
519 |
+
"text/plain": [
|
520 |
+
"['.cache/X_test_preprocessed.pkl']"
|
521 |
+
]
|
522 |
+
},
|
523 |
+
"execution_count": 14,
|
524 |
+
"metadata": {},
|
525 |
+
"output_type": "execute_result"
|
526 |
+
}
|
527 |
+
],
|
528 |
+
"source": [
|
529 |
+
"# Cache the preprocessed data\n",
|
530 |
+
"joblib.dump(X_train_preprocessed, CACHE_DIR / \"X_train_preprocessed.pkl\")\n",
|
531 |
+
"joblib.dump(X_test_preprocessed, CACHE_DIR / \"X_test_preprocessed.pkl\")"
|
532 |
+
]
|
533 |
+
},
|
534 |
{
|
535 |
"cell_type": "markdown",
|
536 |
"metadata": {},
|
537 |
"source": [
|
538 |
+
"### Or load cached data"
|
539 |
]
|
540 |
},
|
541 |
{
|
|
|
543 |
"execution_count": null,
|
544 |
"metadata": {},
|
545 |
"outputs": [],
|
546 |
+
"source": [
|
547 |
+
"# Load the transformed data\n",
|
548 |
+
"X_train_preprocessed = joblib.load(CACHE_DIR / \"X_train_preprocessed.pkl\")\n",
|
549 |
+
"X_test_preprocessed = joblib.load(CACHE_DIR / \"X_test_preprocessed.pkl\")"
|
550 |
+
]
|
551 |
+
},
|
552 |
+
{
|
553 |
+
"cell_type": "markdown",
|
554 |
+
"metadata": {},
|
555 |
+
"source": [
|
556 |
+
"### Pick the classifier"
|
557 |
+
]
|
558 |
+
},
|
559 |
+
{
|
560 |
+
"cell_type": "code",
|
561 |
+
"execution_count": 15,
|
562 |
+
"metadata": {},
|
563 |
+
"outputs": [],
|
564 |
"source": [
|
565 |
"def evaluate_model(clf: BaseEstimator) -> None:\n",
|
566 |
" # Calculate the accuracy\n",
|
|
|
598 |
},
|
599 |
{
|
600 |
"cell_type": "code",
|
601 |
+
"execution_count": 16,
|
602 |
"metadata": {},
|
603 |
"outputs": [],
|
604 |
"source": [
|
|
|
626 |
},
|
627 |
{
|
628 |
"cell_type": "code",
|
629 |
+
"execution_count": 19,
|
630 |
"metadata": {},
|
631 |
"outputs": [
|
632 |
+
{
|
633 |
+
"name": "stdout",
|
634 |
+
"output_type": "stream",
|
635 |
+
"text": [
|
636 |
+
"Fitting 3 folds for each of 10 candidates, totalling 30 fits\n",
|
637 |
+
"Best parameters: {'solver': 'liblinear', 'penalty': 'l2', 'C': 1438.44988828766}\n"
|
638 |
+
]
|
639 |
+
},
|
640 |
{
|
641 |
"data": {
|
642 |
+
"image/png": "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",
|
643 |
"text/plain": [
|
644 |
"<Figure size 800x600 with 1 Axes>"
|
645 |
]
|
|
|
657 |
" lr_clf,\n",
|
658 |
" {\n",
|
659 |
" \"C\": np.logspace(-4, 4, 20),\n",
|
660 |
+
" \"solver\": [\"liblinear\", \"saga\"], # lbfgs takes too long\n",
|
661 |
" \"penalty\": [\"l1\", \"l2\"],\n",
|
662 |
" },\n",
|
663 |
")\n",
|
|
|
688 |
"# Evaluate the model\n",
|
689 |
"evaluate_model(best_svm_clf)"
|
690 |
]
|
691 |
+
},
|
692 |
+
{
|
693 |
+
"cell_type": "markdown",
|
694 |
+
"metadata": {},
|
695 |
+
"source": [
|
696 |
+
"## Export the final model"
|
697 |
+
]
|
698 |
+
},
|
699 |
+
{
|
700 |
+
"cell_type": "code",
|
701 |
+
"execution_count": 20,
|
702 |
+
"metadata": {},
|
703 |
+
"outputs": [],
|
704 |
+
"source": [
|
705 |
+
"best_clf = best_lr_clf # TODO: Pick the best classifier\n",
|
706 |
+
"best_params = lr_params # TODO: Pick the best parameters"
|
707 |
+
]
|
708 |
+
},
|
709 |
+
{
|
710 |
+
"cell_type": "code",
|
711 |
+
"execution_count": 21,
|
712 |
+
"metadata": {},
|
713 |
+
"outputs": [],
|
714 |
+
"source": [
|
715 |
+
"# Merge the tokenizer and the best classifier\n",
|
716 |
+
"model = Pipeline(\n",
|
717 |
+
" [\n",
|
718 |
+
" (\"preprocess\", preprocess_pipeline),\n",
|
719 |
+
" (\"clf\", best_clf),\n",
|
720 |
+
" ],\n",
|
721 |
+
")"
|
722 |
+
]
|
723 |
+
},
|
724 |
+
{
|
725 |
+
"cell_type": "code",
|
726 |
+
"execution_count": 22,
|
727 |
+
"metadata": {},
|
728 |
+
"outputs": [],
|
729 |
+
"source": [
|
730 |
+
"# Export the model and the parameters\n",
|
731 |
+
"joblib.dump(model, MODELS_DIR / \"best_model.pkl\")\n",
|
732 |
+
"with Path.open(MODELS_DIR / \"best_params.json\", \"w\") as f:\n",
|
733 |
+
" json.dump(best_params, f, indent=2)"
|
734 |
+
]
|
735 |
+
},
|
736 |
+
{
|
737 |
+
"cell_type": "code",
|
738 |
+
"execution_count": 23,
|
739 |
+
"metadata": {},
|
740 |
+
"outputs": [],
|
741 |
+
"source": [
|
742 |
+
"# Import and test the model\n",
|
743 |
+
"model = joblib.load(MODELS_DIR / \"best_model.pkl\")\n",
|
744 |
+
"assert model.predict([\"I love this!\"])[0] == 1 # noqa: S101\n",
|
745 |
+
"assert model.predict([\"I hate this!\"])[0] == 0 # noqa: S101"
|
746 |
+
]
|
747 |
}
|
748 |
],
|
749 |
"metadata": {
|