CristopherWVSU commited on
Commit
02c4ec3
·
1 Parent(s): aebd19f

Added Model Evaluation Tab

Browse files
app.py CHANGED
@@ -14,30 +14,57 @@ with open("sentimentAnalysis_model.pkl", "rb") as model_file:
14
  with open("vectorizer.pkl", "rb") as vectorizer_file:
15
  vectorizer = joblib.load(vectorizer_file)
16
 
17
- # MAPPING RESULTS
18
- sentiment_mapping = {0: "Neutral", 1: "Positive", 2: "Negative"}
19
-
20
- # FUNCTION TO REDUCE TEXT TO ITS MOST BASIC FORM
21
- def clean_text(text):
22
- text = text.lower()
23
- text = re.sub(r'[^a-zA-Z\s]', '', text)
24
- text = ' '.join([word for word in text.split() if word not in stop_words])
25
- return text
26
-
27
- # STREAMLIT UI
28
- st.title("Sentiment Analysis App")
29
- st.write("Enter text below to analyze its sentiment.")
30
-
31
- user_input = st.text_area("Enter text:")
32
-
33
- if st.button("Analyze Sentiment"):
34
- if user_input:
35
- cleaned_input = clean_text(user_input)
36
- transformed_input = vectorizer.transform([cleaned_input])
37
-
38
- prediction = model.predict(transformed_input)[0]
39
- sentiment = sentiment_mapping[prediction]
40
-
41
- st.write(f"Predicted Sentiment: **{sentiment}**")
42
- else:
43
- st.write("Please enter some text to analyze.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  with open("vectorizer.pkl", "rb") as vectorizer_file:
15
  vectorizer = joblib.load(vectorizer_file)
16
 
17
+
18
+ app, model_eval = st.tabs(["Application", "Model Evaluation"])
19
+ # STREAMLIT APP TAB 1
20
+ with app:
21
+ # MAPPING RESULTS
22
+ sentiment_mapping = {0: "Neutral", 1: "Positive", 2: "Negative"}
23
+
24
+ # FUNCTION TO REDUCE TEXT TO ITS MOST BASIC FORM
25
+ def clean_text(text):
26
+ text = text.lower()
27
+ text = re.sub(r'[^a-zA-Z\s]', '', text)
28
+ text = ' '.join([word for word in text.split() if word not in stop_words])
29
+ return text
30
+
31
+ # STREAMLIT UI
32
+ st.title("Sentiment Analysis App")
33
+ st.write("Enter text below to analyze its sentiment.")
34
+
35
+ user_input = st.text_area("Enter text:")
36
+
37
+ if st.button("Analyze Sentiment"):
38
+ if user_input:
39
+ cleaned_input = clean_text(user_input)
40
+ transformed_input = vectorizer.transform([cleaned_input])
41
+
42
+ prediction = model.predict(transformed_input)[0]
43
+ sentiment = sentiment_mapping[prediction]
44
+
45
+ st.write(f"Predicted Sentiment: **{sentiment}**")
46
+ else:
47
+ st.write("Please enter some text to analyze.")
48
+
49
+ with model_eval:
50
+
51
+ st.header("Model Evaluation")
52
+ st.write("The Sentiment Analysis model was trained in order to detect if a text is positive, negative, or neutral. The dataset was taken from kaggle.")
53
+ st.write("dataset by Dataset by Ismiel Hossen Abir. Link: https://www.kaggle.com/datasets/mdismielhossenabir/sentiment-analysis")
54
+
55
+ # SENTIMENT DISTRIBUTION
56
+ st.header("Sentinment Distribution")
57
+ st.write("The model was trained using a dataset with the total amount of text equivalent to the following labels")
58
+
59
+ # CONFUSION MATRIX
60
+ st.title("Confusion Matrix")
61
+ st.write("The confusion matrix displays the actual values or true labels with the predicted values from the model. With this, we can identify the margin of error the model has.")
62
+ st.image("confusion_matrix.png")
63
+
64
+ # EVALUATION MATRICS
65
+ st.title("Evaluation Metrics")
66
+ st.write("The image below represents the Accuracy, F1 score and the classification report of the model")
67
+ st.image("classification_report.png")
68
+ st.write("The model can be improved by using other models, but logistic regression was used for project purposes")
69
+
70
+
classification_report.png ADDED
confusion_matrix.png ADDED
main.ipynb CHANGED
@@ -13,7 +13,7 @@
13
  },
14
  {
15
  "cell_type": "code",
16
- "execution_count": 496,
17
  "metadata": {},
18
  "outputs": [
19
  {
@@ -34,7 +34,7 @@
34
  "from sklearn.model_selection import train_test_split\n",
35
  "from sklearn.feature_extraction.text import TfidfVectorizer\n",
36
  "from sklearn.linear_model import LogisticRegression\n",
37
- "from sklearn.metrics import accuracy_score, classification_report, confusion_matrix\n",
38
  "import nltk\n",
39
  "from nltk.corpus import stopwords\n",
40
  "import re\n",
@@ -55,7 +55,7 @@
55
  },
56
  {
57
  "cell_type": "code",
58
- "execution_count": 497,
59
  "metadata": {},
60
  "outputs": [],
61
  "source": [
@@ -65,7 +65,7 @@
65
  },
66
  {
67
  "cell_type": "code",
68
- "execution_count": 498,
69
  "metadata": {},
70
  "outputs": [],
71
  "source": [
@@ -75,7 +75,7 @@
75
  },
76
  {
77
  "cell_type": "code",
78
- "execution_count": 499,
79
  "metadata": {},
80
  "outputs": [
81
  {
@@ -100,7 +100,7 @@
100
  },
101
  {
102
  "cell_type": "code",
103
- "execution_count": 500,
104
  "metadata": {},
105
  "outputs": [
106
  {
@@ -119,7 +119,7 @@
119
  },
120
  {
121
  "cell_type": "code",
122
- "execution_count": 501,
123
  "metadata": {},
124
  "outputs": [
125
  {
@@ -132,7 +132,7 @@
132
  "Name: count, dtype: int64"
133
  ]
134
  },
135
- "execution_count": 501,
136
  "metadata": {},
137
  "output_type": "execute_result"
138
  }
@@ -143,7 +143,7 @@
143
  },
144
  {
145
  "cell_type": "code",
146
- "execution_count": 502,
147
  "metadata": {},
148
  "outputs": [
149
  {
@@ -158,10 +158,11 @@
158
  }
159
  ],
160
  "source": [
161
- "# Data Visualization\n",
162
  "sns.countplot(x=df[\"sentiment\"])\n",
163
  "plt.title(\"Sentiment Distribution\")\n",
164
- "plt.show()"
 
 
165
  ]
166
  },
167
  {
@@ -174,7 +175,7 @@
174
  },
175
  {
176
  "cell_type": "code",
177
- "execution_count": 503,
178
  "metadata": {},
179
  "outputs": [],
180
  "source": [
@@ -187,7 +188,7 @@
187
  },
188
  {
189
  "cell_type": "code",
190
- "execution_count": 504,
191
  "metadata": {},
192
  "outputs": [],
193
  "source": [
@@ -203,7 +204,7 @@
203
  },
204
  {
205
  "cell_type": "code",
206
- "execution_count": 505,
207
  "metadata": {},
208
  "outputs": [],
209
  "source": [
@@ -222,7 +223,7 @@
222
  },
223
  {
224
  "cell_type": "code",
225
- "execution_count": 506,
226
  "metadata": {},
227
  "outputs": [],
228
  "source": [
@@ -231,7 +232,7 @@
231
  },
232
  {
233
  "cell_type": "code",
234
- "execution_count": 507,
235
  "metadata": {},
236
  "outputs": [],
237
  "source": [
@@ -249,13 +250,13 @@
249
  },
250
  {
251
  "cell_type": "code",
252
- "execution_count": 508,
253
  "metadata": {},
254
  "outputs": [
255
  {
256
  "data": {
257
  "text/html": [
258
- "<style>#sk-container-id-21 {\n",
259
  " /* Definition of color scheme common for light and dark mode */\n",
260
  " --sklearn-color-text: black;\n",
261
  " --sklearn-color-line: gray;\n",
@@ -285,15 +286,15 @@
285
  " }\n",
286
  "}\n",
287
  "\n",
288
- "#sk-container-id-21 {\n",
289
  " color: var(--sklearn-color-text);\n",
290
  "}\n",
291
  "\n",
292
- "#sk-container-id-21 pre {\n",
293
  " padding: 0;\n",
294
  "}\n",
295
  "\n",
296
- "#sk-container-id-21 input.sk-hidden--visually {\n",
297
  " border: 0;\n",
298
  " clip: rect(1px 1px 1px 1px);\n",
299
  " clip: rect(1px, 1px, 1px, 1px);\n",
@@ -305,7 +306,7 @@
305
  " width: 1px;\n",
306
  "}\n",
307
  "\n",
308
- "#sk-container-id-21 div.sk-dashed-wrapped {\n",
309
  " border: 1px dashed var(--sklearn-color-line);\n",
310
  " margin: 0 0.4em 0.5em 0.4em;\n",
311
  " box-sizing: border-box;\n",
@@ -313,7 +314,7 @@
313
  " background-color: var(--sklearn-color-background);\n",
314
  "}\n",
315
  "\n",
316
- "#sk-container-id-21 div.sk-container {\n",
317
  " /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n",
318
  " but bootstrap.min.css set `[hidden] { display: none !important; }`\n",
319
  " so we also need the `!important` here to be able to override the\n",
@@ -323,7 +324,7 @@
323
  " position: relative;\n",
324
  "}\n",
325
  "\n",
326
- "#sk-container-id-21 div.sk-text-repr-fallback {\n",
327
  " display: none;\n",
328
  "}\n",
329
  "\n",
@@ -339,14 +340,14 @@
339
  "\n",
340
  "/* Parallel-specific style estimator block */\n",
341
  "\n",
342
- "#sk-container-id-21 div.sk-parallel-item::after {\n",
343
  " content: \"\";\n",
344
  " width: 100%;\n",
345
  " border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n",
346
  " flex-grow: 1;\n",
347
  "}\n",
348
  "\n",
349
- "#sk-container-id-21 div.sk-parallel {\n",
350
  " display: flex;\n",
351
  " align-items: stretch;\n",
352
  " justify-content: center;\n",
@@ -354,28 +355,28 @@
354
  " position: relative;\n",
355
  "}\n",
356
  "\n",
357
- "#sk-container-id-21 div.sk-parallel-item {\n",
358
  " display: flex;\n",
359
  " flex-direction: column;\n",
360
  "}\n",
361
  "\n",
362
- "#sk-container-id-21 div.sk-parallel-item:first-child::after {\n",
363
  " align-self: flex-end;\n",
364
  " width: 50%;\n",
365
  "}\n",
366
  "\n",
367
- "#sk-container-id-21 div.sk-parallel-item:last-child::after {\n",
368
  " align-self: flex-start;\n",
369
  " width: 50%;\n",
370
  "}\n",
371
  "\n",
372
- "#sk-container-id-21 div.sk-parallel-item:only-child::after {\n",
373
  " width: 0;\n",
374
  "}\n",
375
  "\n",
376
  "/* Serial-specific style estimator block */\n",
377
  "\n",
378
- "#sk-container-id-21 div.sk-serial {\n",
379
  " display: flex;\n",
380
  " flex-direction: column;\n",
381
  " align-items: center;\n",
@@ -393,14 +394,14 @@
393
  "\n",
394
  "/* Pipeline and ColumnTransformer style (default) */\n",
395
  "\n",
396
- "#sk-container-id-21 div.sk-toggleable {\n",
397
  " /* Default theme specific background. It is overwritten whether we have a\n",
398
  " specific estimator or a Pipeline/ColumnTransformer */\n",
399
  " background-color: var(--sklearn-color-background);\n",
400
  "}\n",
401
  "\n",
402
  "/* Toggleable label */\n",
403
- "#sk-container-id-21 label.sk-toggleable__label {\n",
404
  " cursor: pointer;\n",
405
  " display: block;\n",
406
  " width: 100%;\n",
@@ -410,7 +411,7 @@
410
  " text-align: center;\n",
411
  "}\n",
412
  "\n",
413
- "#sk-container-id-21 label.sk-toggleable__label-arrow:before {\n",
414
  " /* Arrow on the left of the label */\n",
415
  " content: \"▸\";\n",
416
  " float: left;\n",
@@ -418,13 +419,13 @@
418
  " color: var(--sklearn-color-icon);\n",
419
  "}\n",
420
  "\n",
421
- "#sk-container-id-21 label.sk-toggleable__label-arrow:hover:before {\n",
422
  " color: var(--sklearn-color-text);\n",
423
  "}\n",
424
  "\n",
425
  "/* Toggleable content - dropdown */\n",
426
  "\n",
427
- "#sk-container-id-21 div.sk-toggleable__content {\n",
428
  " max-height: 0;\n",
429
  " max-width: 0;\n",
430
  " overflow: hidden;\n",
@@ -433,12 +434,12 @@
433
  " background-color: var(--sklearn-color-unfitted-level-0);\n",
434
  "}\n",
435
  "\n",
436
- "#sk-container-id-21 div.sk-toggleable__content.fitted {\n",
437
  " /* fitted */\n",
438
  " background-color: var(--sklearn-color-fitted-level-0);\n",
439
  "}\n",
440
  "\n",
441
- "#sk-container-id-21 div.sk-toggleable__content pre {\n",
442
  " margin: 0.2em;\n",
443
  " border-radius: 0.25em;\n",
444
  " color: var(--sklearn-color-text);\n",
@@ -446,79 +447,79 @@
446
  " background-color: var(--sklearn-color-unfitted-level-0);\n",
447
  "}\n",
448
  "\n",
449
- "#sk-container-id-21 div.sk-toggleable__content.fitted pre {\n",
450
  " /* unfitted */\n",
451
  " background-color: var(--sklearn-color-fitted-level-0);\n",
452
  "}\n",
453
  "\n",
454
- "#sk-container-id-21 input.sk-toggleable__control:checked~div.sk-toggleable__content {\n",
455
  " /* Expand drop-down */\n",
456
  " max-height: 200px;\n",
457
  " max-width: 100%;\n",
458
  " overflow: auto;\n",
459
  "}\n",
460
  "\n",
461
- "#sk-container-id-21 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n",
462
  " content: \"▾\";\n",
463
  "}\n",
464
  "\n",
465
  "/* Pipeline/ColumnTransformer-specific style */\n",
466
  "\n",
467
- "#sk-container-id-21 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
468
  " color: var(--sklearn-color-text);\n",
469
  " background-color: var(--sklearn-color-unfitted-level-2);\n",
470
  "}\n",
471
  "\n",
472
- "#sk-container-id-21 div.sk-label.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
473
  " background-color: var(--sklearn-color-fitted-level-2);\n",
474
  "}\n",
475
  "\n",
476
  "/* Estimator-specific style */\n",
477
  "\n",
478
  "/* Colorize estimator box */\n",
479
- "#sk-container-id-21 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
480
  " /* unfitted */\n",
481
  " background-color: var(--sklearn-color-unfitted-level-2);\n",
482
  "}\n",
483
  "\n",
484
- "#sk-container-id-21 div.sk-estimator.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
485
  " /* fitted */\n",
486
  " background-color: var(--sklearn-color-fitted-level-2);\n",
487
  "}\n",
488
  "\n",
489
- "#sk-container-id-21 div.sk-label label.sk-toggleable__label,\n",
490
- "#sk-container-id-21 div.sk-label label {\n",
491
  " /* The background is the default theme color */\n",
492
  " color: var(--sklearn-color-text-on-default-background);\n",
493
  "}\n",
494
  "\n",
495
  "/* On hover, darken the color of the background */\n",
496
- "#sk-container-id-21 div.sk-label:hover label.sk-toggleable__label {\n",
497
  " color: var(--sklearn-color-text);\n",
498
  " background-color: var(--sklearn-color-unfitted-level-2);\n",
499
  "}\n",
500
  "\n",
501
  "/* Label box, darken color on hover, fitted */\n",
502
- "#sk-container-id-21 div.sk-label.fitted:hover label.sk-toggleable__label.fitted {\n",
503
  " color: var(--sklearn-color-text);\n",
504
  " background-color: var(--sklearn-color-fitted-level-2);\n",
505
  "}\n",
506
  "\n",
507
  "/* Estimator label */\n",
508
  "\n",
509
- "#sk-container-id-21 div.sk-label label {\n",
510
  " font-family: monospace;\n",
511
  " font-weight: bold;\n",
512
  " display: inline-block;\n",
513
  " line-height: 1.2em;\n",
514
  "}\n",
515
  "\n",
516
- "#sk-container-id-21 div.sk-label-container {\n",
517
  " text-align: center;\n",
518
  "}\n",
519
  "\n",
520
  "/* Estimator-specific */\n",
521
- "#sk-container-id-21 div.sk-estimator {\n",
522
  " font-family: monospace;\n",
523
  " border: 1px dotted var(--sklearn-color-border-box);\n",
524
  " border-radius: 0.25em;\n",
@@ -528,18 +529,18 @@
528
  " background-color: var(--sklearn-color-unfitted-level-0);\n",
529
  "}\n",
530
  "\n",
531
- "#sk-container-id-21 div.sk-estimator.fitted {\n",
532
  " /* fitted */\n",
533
  " background-color: var(--sklearn-color-fitted-level-0);\n",
534
  "}\n",
535
  "\n",
536
  "/* on hover */\n",
537
- "#sk-container-id-21 div.sk-estimator:hover {\n",
538
  " /* unfitted */\n",
539
  " background-color: var(--sklearn-color-unfitted-level-2);\n",
540
  "}\n",
541
  "\n",
542
- "#sk-container-id-21 div.sk-estimator.fitted:hover {\n",
543
  " /* fitted */\n",
544
  " background-color: var(--sklearn-color-fitted-level-2);\n",
545
  "}\n",
@@ -626,7 +627,7 @@
626
  "\n",
627
  "/* \"?\"-specific style due to the `<a>` HTML tag */\n",
628
  "\n",
629
- "#sk-container-id-21 a.estimator_doc_link {\n",
630
  " float: right;\n",
631
  " font-size: 1rem;\n",
632
  " line-height: 1em;\n",
@@ -641,31 +642,31 @@
641
  " border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
642
  "}\n",
643
  "\n",
644
- "#sk-container-id-21 a.estimator_doc_link.fitted {\n",
645
  " /* fitted */\n",
646
  " border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
647
  " color: var(--sklearn-color-fitted-level-1);\n",
648
  "}\n",
649
  "\n",
650
  "/* On hover */\n",
651
- "#sk-container-id-21 a.estimator_doc_link:hover {\n",
652
  " /* unfitted */\n",
653
  " background-color: var(--sklearn-color-unfitted-level-3);\n",
654
  " color: var(--sklearn-color-background);\n",
655
  " text-decoration: none;\n",
656
  "}\n",
657
  "\n",
658
- "#sk-container-id-21 a.estimator_doc_link.fitted:hover {\n",
659
  " /* fitted */\n",
660
  " background-color: var(--sklearn-color-fitted-level-3);\n",
661
  "}\n",
662
- "</style><div id=\"sk-container-id-21\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>LogisticRegression()</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-21\" type=\"checkbox\" checked><label for=\"sk-estimator-id-21\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\">&nbsp;&nbsp;LogisticRegression<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.5/modules/generated/sklearn.linear_model.LogisticRegression.html\">?<span>Documentation for LogisticRegression</span></a><span class=\"sk-estimator-doc-link fitted\">i<span>Fitted</span></span></label><div class=\"sk-toggleable__content fitted\"><pre>LogisticRegression()</pre></div> </div></div></div></div>"
663
  ],
664
  "text/plain": [
665
  "LogisticRegression()"
666
  ]
667
  },
668
- "execution_count": 508,
669
  "metadata": {},
670
  "output_type": "execute_result"
671
  }
@@ -678,7 +679,7 @@
678
  },
679
  {
680
  "cell_type": "code",
681
- "execution_count": 509,
682
  "metadata": {},
683
  "outputs": [],
684
  "source": [
@@ -697,7 +698,7 @@
697
  },
698
  {
699
  "cell_type": "code",
700
- "execution_count": 510,
701
  "metadata": {},
702
  "outputs": [
703
  {
@@ -717,13 +718,35 @@
717
  "weighted avg 0.76 0.76 0.76 50\n",
718
  "\n"
719
  ]
 
 
 
 
 
 
 
 
 
 
720
  }
721
  ],
722
  "source": [
723
- "# Model Evaluation\n",
724
  "accuracy = accuracy_score(y_test, y_pred)\n",
 
 
 
725
  "print(f\"Accuracy: {accuracy:.4f}\")\n",
726
- "print(\"Classification Report:\\n\", classification_report(y_test, y_pred))"
 
 
 
 
 
 
 
 
 
727
  ]
728
  },
729
  {
@@ -735,7 +758,7 @@
735
  },
736
  {
737
  "cell_type": "code",
738
- "execution_count": 511,
739
  "metadata": {},
740
  "outputs": [
741
  {
@@ -750,18 +773,18 @@
750
  }
751
  ],
752
  "source": [
753
- "# Confusion Matrix\n",
754
  "cm = confusion_matrix(y_test, y_pred)\n",
755
  "sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=sentiment_mapping.keys(), yticklabels=sentiment_mapping.keys())\n",
756
  "plt.xlabel(\"Predicted\")\n",
757
  "plt.ylabel(\"Actual\")\n",
758
  "plt.title(\"Confusion Matrix\")\n",
 
759
  "plt.show()"
760
  ]
761
  },
762
  {
763
  "cell_type": "code",
764
- "execution_count": 512,
765
  "metadata": {},
766
  "outputs": [
767
  {
@@ -773,6 +796,7 @@
773
  }
774
  ],
775
  "source": [
 
776
  "joblib.dump(model, \"sentimentAnalysis_model.pkl\")\n",
777
  "joblib.dump(vectorizer, \"vectorizer.pkl\")\n",
778
  "print(\"Model saved successfully\")"
 
13
  },
14
  {
15
  "cell_type": "code",
16
+ "execution_count": 48,
17
  "metadata": {},
18
  "outputs": [
19
  {
 
34
  "from sklearn.model_selection import train_test_split\n",
35
  "from sklearn.feature_extraction.text import TfidfVectorizer\n",
36
  "from sklearn.linear_model import LogisticRegression\n",
37
+ "from sklearn.metrics import accuracy_score, classification_report, confusion_matrix, f1_score\n",
38
  "import nltk\n",
39
  "from nltk.corpus import stopwords\n",
40
  "import re\n",
 
55
  },
56
  {
57
  "cell_type": "code",
58
+ "execution_count": 49,
59
  "metadata": {},
60
  "outputs": [],
61
  "source": [
 
65
  },
66
  {
67
  "cell_type": "code",
68
+ "execution_count": 50,
69
  "metadata": {},
70
  "outputs": [],
71
  "source": [
 
75
  },
76
  {
77
  "cell_type": "code",
78
+ "execution_count": 51,
79
  "metadata": {},
80
  "outputs": [
81
  {
 
100
  },
101
  {
102
  "cell_type": "code",
103
+ "execution_count": 52,
104
  "metadata": {},
105
  "outputs": [
106
  {
 
119
  },
120
  {
121
  "cell_type": "code",
122
+ "execution_count": 53,
123
  "metadata": {},
124
  "outputs": [
125
  {
 
132
  "Name: count, dtype: int64"
133
  ]
134
  },
135
+ "execution_count": 53,
136
  "metadata": {},
137
  "output_type": "execute_result"
138
  }
 
143
  },
144
  {
145
  "cell_type": "code",
146
+ "execution_count": 54,
147
  "metadata": {},
148
  "outputs": [
149
  {
 
158
  }
159
  ],
160
  "source": [
 
161
  "sns.countplot(x=df[\"sentiment\"])\n",
162
  "plt.title(\"Sentiment Distribution\")\n",
163
+ "plt.savefig(\"sentiment_distribution.png\")\n",
164
+ "plt.show()\n",
165
+ "plt.close() "
166
  ]
167
  },
168
  {
 
175
  },
176
  {
177
  "cell_type": "code",
178
+ "execution_count": 55,
179
  "metadata": {},
180
  "outputs": [],
181
  "source": [
 
188
  },
189
  {
190
  "cell_type": "code",
191
+ "execution_count": 56,
192
  "metadata": {},
193
  "outputs": [],
194
  "source": [
 
204
  },
205
  {
206
  "cell_type": "code",
207
+ "execution_count": 57,
208
  "metadata": {},
209
  "outputs": [],
210
  "source": [
 
223
  },
224
  {
225
  "cell_type": "code",
226
+ "execution_count": 58,
227
  "metadata": {},
228
  "outputs": [],
229
  "source": [
 
232
  },
233
  {
234
  "cell_type": "code",
235
+ "execution_count": 59,
236
  "metadata": {},
237
  "outputs": [],
238
  "source": [
 
250
  },
251
  {
252
  "cell_type": "code",
253
+ "execution_count": 60,
254
  "metadata": {},
255
  "outputs": [
256
  {
257
  "data": {
258
  "text/html": [
259
+ "<style>#sk-container-id-4 {\n",
260
  " /* Definition of color scheme common for light and dark mode */\n",
261
  " --sklearn-color-text: black;\n",
262
  " --sklearn-color-line: gray;\n",
 
286
  " }\n",
287
  "}\n",
288
  "\n",
289
+ "#sk-container-id-4 {\n",
290
  " color: var(--sklearn-color-text);\n",
291
  "}\n",
292
  "\n",
293
+ "#sk-container-id-4 pre {\n",
294
  " padding: 0;\n",
295
  "}\n",
296
  "\n",
297
+ "#sk-container-id-4 input.sk-hidden--visually {\n",
298
  " border: 0;\n",
299
  " clip: rect(1px 1px 1px 1px);\n",
300
  " clip: rect(1px, 1px, 1px, 1px);\n",
 
306
  " width: 1px;\n",
307
  "}\n",
308
  "\n",
309
+ "#sk-container-id-4 div.sk-dashed-wrapped {\n",
310
  " border: 1px dashed var(--sklearn-color-line);\n",
311
  " margin: 0 0.4em 0.5em 0.4em;\n",
312
  " box-sizing: border-box;\n",
 
314
  " background-color: var(--sklearn-color-background);\n",
315
  "}\n",
316
  "\n",
317
+ "#sk-container-id-4 div.sk-container {\n",
318
  " /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n",
319
  " but bootstrap.min.css set `[hidden] { display: none !important; }`\n",
320
  " so we also need the `!important` here to be able to override the\n",
 
324
  " position: relative;\n",
325
  "}\n",
326
  "\n",
327
+ "#sk-container-id-4 div.sk-text-repr-fallback {\n",
328
  " display: none;\n",
329
  "}\n",
330
  "\n",
 
340
  "\n",
341
  "/* Parallel-specific style estimator block */\n",
342
  "\n",
343
+ "#sk-container-id-4 div.sk-parallel-item::after {\n",
344
  " content: \"\";\n",
345
  " width: 100%;\n",
346
  " border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n",
347
  " flex-grow: 1;\n",
348
  "}\n",
349
  "\n",
350
+ "#sk-container-id-4 div.sk-parallel {\n",
351
  " display: flex;\n",
352
  " align-items: stretch;\n",
353
  " justify-content: center;\n",
 
355
  " position: relative;\n",
356
  "}\n",
357
  "\n",
358
+ "#sk-container-id-4 div.sk-parallel-item {\n",
359
  " display: flex;\n",
360
  " flex-direction: column;\n",
361
  "}\n",
362
  "\n",
363
+ "#sk-container-id-4 div.sk-parallel-item:first-child::after {\n",
364
  " align-self: flex-end;\n",
365
  " width: 50%;\n",
366
  "}\n",
367
  "\n",
368
+ "#sk-container-id-4 div.sk-parallel-item:last-child::after {\n",
369
  " align-self: flex-start;\n",
370
  " width: 50%;\n",
371
  "}\n",
372
  "\n",
373
+ "#sk-container-id-4 div.sk-parallel-item:only-child::after {\n",
374
  " width: 0;\n",
375
  "}\n",
376
  "\n",
377
  "/* Serial-specific style estimator block */\n",
378
  "\n",
379
+ "#sk-container-id-4 div.sk-serial {\n",
380
  " display: flex;\n",
381
  " flex-direction: column;\n",
382
  " align-items: center;\n",
 
394
  "\n",
395
  "/* Pipeline and ColumnTransformer style (default) */\n",
396
  "\n",
397
+ "#sk-container-id-4 div.sk-toggleable {\n",
398
  " /* Default theme specific background. It is overwritten whether we have a\n",
399
  " specific estimator or a Pipeline/ColumnTransformer */\n",
400
  " background-color: var(--sklearn-color-background);\n",
401
  "}\n",
402
  "\n",
403
  "/* Toggleable label */\n",
404
+ "#sk-container-id-4 label.sk-toggleable__label {\n",
405
  " cursor: pointer;\n",
406
  " display: block;\n",
407
  " width: 100%;\n",
 
411
  " text-align: center;\n",
412
  "}\n",
413
  "\n",
414
+ "#sk-container-id-4 label.sk-toggleable__label-arrow:before {\n",
415
  " /* Arrow on the left of the label */\n",
416
  " content: \"▸\";\n",
417
  " float: left;\n",
 
419
  " color: var(--sklearn-color-icon);\n",
420
  "}\n",
421
  "\n",
422
+ "#sk-container-id-4 label.sk-toggleable__label-arrow:hover:before {\n",
423
  " color: var(--sklearn-color-text);\n",
424
  "}\n",
425
  "\n",
426
  "/* Toggleable content - dropdown */\n",
427
  "\n",
428
+ "#sk-container-id-4 div.sk-toggleable__content {\n",
429
  " max-height: 0;\n",
430
  " max-width: 0;\n",
431
  " overflow: hidden;\n",
 
434
  " background-color: var(--sklearn-color-unfitted-level-0);\n",
435
  "}\n",
436
  "\n",
437
+ "#sk-container-id-4 div.sk-toggleable__content.fitted {\n",
438
  " /* fitted */\n",
439
  " background-color: var(--sklearn-color-fitted-level-0);\n",
440
  "}\n",
441
  "\n",
442
+ "#sk-container-id-4 div.sk-toggleable__content pre {\n",
443
  " margin: 0.2em;\n",
444
  " border-radius: 0.25em;\n",
445
  " color: var(--sklearn-color-text);\n",
 
447
  " background-color: var(--sklearn-color-unfitted-level-0);\n",
448
  "}\n",
449
  "\n",
450
+ "#sk-container-id-4 div.sk-toggleable__content.fitted pre {\n",
451
  " /* unfitted */\n",
452
  " background-color: var(--sklearn-color-fitted-level-0);\n",
453
  "}\n",
454
  "\n",
455
+ "#sk-container-id-4 input.sk-toggleable__control:checked~div.sk-toggleable__content {\n",
456
  " /* Expand drop-down */\n",
457
  " max-height: 200px;\n",
458
  " max-width: 100%;\n",
459
  " overflow: auto;\n",
460
  "}\n",
461
  "\n",
462
+ "#sk-container-id-4 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n",
463
  " content: \"▾\";\n",
464
  "}\n",
465
  "\n",
466
  "/* Pipeline/ColumnTransformer-specific style */\n",
467
  "\n",
468
+ "#sk-container-id-4 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
469
  " color: var(--sklearn-color-text);\n",
470
  " background-color: var(--sklearn-color-unfitted-level-2);\n",
471
  "}\n",
472
  "\n",
473
+ "#sk-container-id-4 div.sk-label.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
474
  " background-color: var(--sklearn-color-fitted-level-2);\n",
475
  "}\n",
476
  "\n",
477
  "/* Estimator-specific style */\n",
478
  "\n",
479
  "/* Colorize estimator box */\n",
480
+ "#sk-container-id-4 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
481
  " /* unfitted */\n",
482
  " background-color: var(--sklearn-color-unfitted-level-2);\n",
483
  "}\n",
484
  "\n",
485
+ "#sk-container-id-4 div.sk-estimator.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
486
  " /* fitted */\n",
487
  " background-color: var(--sklearn-color-fitted-level-2);\n",
488
  "}\n",
489
  "\n",
490
+ "#sk-container-id-4 div.sk-label label.sk-toggleable__label,\n",
491
+ "#sk-container-id-4 div.sk-label label {\n",
492
  " /* The background is the default theme color */\n",
493
  " color: var(--sklearn-color-text-on-default-background);\n",
494
  "}\n",
495
  "\n",
496
  "/* On hover, darken the color of the background */\n",
497
+ "#sk-container-id-4 div.sk-label:hover label.sk-toggleable__label {\n",
498
  " color: var(--sklearn-color-text);\n",
499
  " background-color: var(--sklearn-color-unfitted-level-2);\n",
500
  "}\n",
501
  "\n",
502
  "/* Label box, darken color on hover, fitted */\n",
503
+ "#sk-container-id-4 div.sk-label.fitted:hover label.sk-toggleable__label.fitted {\n",
504
  " color: var(--sklearn-color-text);\n",
505
  " background-color: var(--sklearn-color-fitted-level-2);\n",
506
  "}\n",
507
  "\n",
508
  "/* Estimator label */\n",
509
  "\n",
510
+ "#sk-container-id-4 div.sk-label label {\n",
511
  " font-family: monospace;\n",
512
  " font-weight: bold;\n",
513
  " display: inline-block;\n",
514
  " line-height: 1.2em;\n",
515
  "}\n",
516
  "\n",
517
+ "#sk-container-id-4 div.sk-label-container {\n",
518
  " text-align: center;\n",
519
  "}\n",
520
  "\n",
521
  "/* Estimator-specific */\n",
522
+ "#sk-container-id-4 div.sk-estimator {\n",
523
  " font-family: monospace;\n",
524
  " border: 1px dotted var(--sklearn-color-border-box);\n",
525
  " border-radius: 0.25em;\n",
 
529
  " background-color: var(--sklearn-color-unfitted-level-0);\n",
530
  "}\n",
531
  "\n",
532
+ "#sk-container-id-4 div.sk-estimator.fitted {\n",
533
  " /* fitted */\n",
534
  " background-color: var(--sklearn-color-fitted-level-0);\n",
535
  "}\n",
536
  "\n",
537
  "/* on hover */\n",
538
+ "#sk-container-id-4 div.sk-estimator:hover {\n",
539
  " /* unfitted */\n",
540
  " background-color: var(--sklearn-color-unfitted-level-2);\n",
541
  "}\n",
542
  "\n",
543
+ "#sk-container-id-4 div.sk-estimator.fitted:hover {\n",
544
  " /* fitted */\n",
545
  " background-color: var(--sklearn-color-fitted-level-2);\n",
546
  "}\n",
 
627
  "\n",
628
  "/* \"?\"-specific style due to the `<a>` HTML tag */\n",
629
  "\n",
630
+ "#sk-container-id-4 a.estimator_doc_link {\n",
631
  " float: right;\n",
632
  " font-size: 1rem;\n",
633
  " line-height: 1em;\n",
 
642
  " border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
643
  "}\n",
644
  "\n",
645
+ "#sk-container-id-4 a.estimator_doc_link.fitted {\n",
646
  " /* fitted */\n",
647
  " border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
648
  " color: var(--sklearn-color-fitted-level-1);\n",
649
  "}\n",
650
  "\n",
651
  "/* On hover */\n",
652
+ "#sk-container-id-4 a.estimator_doc_link:hover {\n",
653
  " /* unfitted */\n",
654
  " background-color: var(--sklearn-color-unfitted-level-3);\n",
655
  " color: var(--sklearn-color-background);\n",
656
  " text-decoration: none;\n",
657
  "}\n",
658
  "\n",
659
+ "#sk-container-id-4 a.estimator_doc_link.fitted:hover {\n",
660
  " /* fitted */\n",
661
  " background-color: var(--sklearn-color-fitted-level-3);\n",
662
  "}\n",
663
+ "</style><div id=\"sk-container-id-4\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>LogisticRegression()</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-4\" type=\"checkbox\" checked><label for=\"sk-estimator-id-4\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\">&nbsp;&nbsp;LogisticRegression<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.5/modules/generated/sklearn.linear_model.LogisticRegression.html\">?<span>Documentation for LogisticRegression</span></a><span class=\"sk-estimator-doc-link fitted\">i<span>Fitted</span></span></label><div class=\"sk-toggleable__content fitted\"><pre>LogisticRegression()</pre></div> </div></div></div></div>"
664
  ],
665
  "text/plain": [
666
  "LogisticRegression()"
667
  ]
668
  },
669
+ "execution_count": 60,
670
  "metadata": {},
671
  "output_type": "execute_result"
672
  }
 
679
  },
680
  {
681
  "cell_type": "code",
682
+ "execution_count": 61,
683
  "metadata": {},
684
  "outputs": [],
685
  "source": [
 
698
  },
699
  {
700
  "cell_type": "code",
701
+ "execution_count": 62,
702
  "metadata": {},
703
  "outputs": [
704
  {
 
718
  "weighted avg 0.76 0.76 0.76 50\n",
719
  "\n"
720
  ]
721
+ },
722
+ {
723
+ "data": {
724
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAoAAAAHiCAYAAAB4GX3vAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy80BEi2AAAACXBIWXMAAA9hAAAPYQGoP6dpAABkKElEQVR4nO3de1xUZf4H8M+AMCAMqFxEjZsoYutoXkpzFShGFDUVC01LZd1drYzWLe2XbKX+bFPXDC1bTfMnu9gaWd4Lky3wEiaFqaz3AkTygqCCN5DL9/eHP87PaQZlYHDA83m/XryS5zzzPM85z5nh07mNRkQERERERKQadrYeABERERHdWwyARERERCrDAEhERESkMgyARERERCrDAEhERESkMgyARERERCrDAEhERESkMgyARERERCrDAEhERESkMgyARERERCrDAEhERESkMgyARERERCrDAEhERESkMgyARERERCrDAEhERESkMlYNgLm5udBoNNBoNPjpp5+s2TRZ6NKlS4iNjUXr1q3h7u6OsWPHorCwsF5tBQQEKPP6659BgwYZ1RURrFixAt27d4ezszO8vb0xYsQIXL16tV7js+Z6EBER0S0trNlYSkoKPDw8AADbt2/Hiy++aM3myQLR0dHIysrCrFmz4ODggIULFyIqKgqZmZmwt7e3qK0lS5aYBLi8vDy88cYbJgEwPj4eCxYsQExMDOLi4nD16lXs2bMHN27cgKurq8Xjs+Z6EBER0f8RKxo+fLg89dRT8uSTT8rQoUOt2TRZYMeOHQJAEhMTlbJt27YJAElOTrZKH3PnzhWNRiP5+flK2dGjR8Xe3l7i4+OtMr57sR5ERERqZLVTwOXl5UhLS0NERAQiIiKQlpaGsrIys3V37dqFyMhIuLu7w93dHeHh4dixY4fF9RITE6HRaJCXl2f0uoCAAMTGxpq0p9FoMGfOHGzatAl6vR5OTk4ICgrCl19+CQC4ePEiZsyYge7du0On08HNzQ0GgwEZGRkWr8eNGzfg5uaGP/7xjyavW716NTQaDQ4ePGi23YbaunUrtFotxo4dq5RFRUXBw8MDW7ZssUofa9euxYABA+Dr66uUrVu3Dg4ODpg1axYAmBw1tHR892I9iIiI1MhqAXDnzp24du2aEgBv3LiBnTt3mtTbunUrHn/8ceTn5+PVV1/FO++8gw4dOmDl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u+h0OomJiZGzZ8/WWv9u/ebl5YlGo5GpU6fesd/CwkKZOHGitGnTRrRarfTr18/so342bNgg/fr1Ezc3N3FxcRGDwSD79u0zqvO3v/1N+vfvL15eXuLo6CiBgYESGxsrp06duvPKExER0R1Z5QggERERETUfzfoaQCIiIiKyHAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpzD0NgM8++yw0Go3yk56efi+7t8icOXOg0WjuWu+XX37B8OHD4e7uDo1Gg9jY2Aa1ZytNfXxERERkPVYNgF999RUee+wxuLm5oVWrVhgwYAA2b96sLH/hhReQlJSE+Ph4a3ZrUy+//DK+++47/Pd//zeSkpIwdepUWw9JsWnTJixZssTWw6i3gIAA5X8WHBwc0KlTJ/zhD3/AL7/8Yuuh1Utznw8iIrp/aERErNFQYmIiJk+ejN69e2PixIlo0aIFvvrqK9jZ2WHDhg1GddPT0/HYY48hLS0N4eHh1uje6iorK1FZWQknJ6c71mvbti3GjRt31z/sdW3PmmJjY5Geno68vLy71rXF+O4mICAArVu3xiuvvIKKigocPHgQK1asQJs2bZCdnQ0PDw9bD9EilswHERFRY2phjUbOnz+PuLg4PProo9i5cydatLjV7PPPP4+CggJrdHHPtWjRQlmPO7lw4QJatWpltfZspamOr0OHDnj22WeV3zt16oS4uDj84x//wMsvv2zDkRERETVfVjkFvHbtWly9ehWvv/66SYh44IEHLG7v4sWLmDFjBrp37w6dTgc3NzcYDAZkZGSY1D169ChGjhwJb29vuLi4oFu3bpgzZ06963Xq1MnoOkVzEhMTleUigrlz5yq///oawLq0V2PXrl2IjIyEu7s73N3dER4ejh07dli8XWr6+sc//oFTp04Z9Z+YmFiv8R05cgRDhw6FTqeDTqfDsGHDcOzYMbPbJTMzE9HR0dDpdAgKCsLq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Ll26oLi4GO+//z78/PyMHm9Q1/ZeeOEFfPDBBxg1ahSmT58OAEhISIC3tzdeeOEFi7fL/cLa8ztixAjMmTMHzz33HHr16oUff/wRmzdvNvt4C+DWtU+PPPII5s2bh+rqari5uaFPnz4m1z3VtZ4tLFu2DJcvX8bhw4cB3Ho0x549e9CqVSu8+OKLFrVV1/2+rvNh7f2+rvuLrdR1+/Xr1w+enp54+eWXcfr0aVy/fh3JycnKJQu/VtfP07vVa6zPof79++P999/HlClTMGrUKDg6OkKv1ytBl2zA1rchk/rUPGZg586d0q1bN9FqtdKzZ09JT083Wx91eMRFUVGRTJs2TR544AFxdHQUX19fiYmJkdTUVJO66enpYjAYRKfTiU6nk9DQUNm+fbvJ+Mz93P4Yg5ycHImNjZWAgADRarXi4+MjMTExcvz4cbPre7f2REQOHz4sQ4YMERcXF3FxcZEhQ4bIkSNHjOrU9fEQzcW9nt/y8nKZOXOmtG/fXpydnSUsLEwOHjwoQUFBMmzYMLP9//TTTxIWFiZarVYASEJCQoPqWdvdtqG/v3+d9r+6qOt+X+Nu8yFSt/2+rusqYtn+cq9Zsv327t0rDz30kDg7O0vfvn0lKyur1sfA3O3z1JLPXWvPh8itR/G88sor0rZtW9FoNAJA1qxZc9fXUePhdwHTPTdnzhzMnTtX9RfcExE1VF0/T/m5S7/GawCJiIiIVIYBkIiIiEhlGACJiIiIVIbXABIRERGpDI8AEhEREakMAyARERGRyjAAEhEREakMAyARERGRyjAAEhEREakMAyARERGRyjAAEhEREakMAyARERGRyjAAEhEREakMAyARERGRyjAAEhEREakMAyARERGRyjAAEhEREakMAyARERGRyjAAEhEREakMAyARERGRyjAAEhEREakMAyARERGRyjAAEhEREakMAyARERGRyjAAEhEREakMAyARERGRyjAAEhEREakMA6DKXbp0CbGxsWjdujXc3d0xduxYFBYW2npYzYY1t19AQAA0Go3Zn0GDBjVav/cTW83H7t278dhjj6F169bw9PREZGQk9u3bZ41VatZsNR+3mzFjBjQaDV588cX6rgaZUVFRgXnz5iEyMhJubm7QaDRIT083W5fvj6apha0HQLYVHR2NrKwszJo1Cw4ODli4cCGioqKQmZkJe3t7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kcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpDAMgERERkcowABIRERGpzP8Cp3cD0bgnZQcAAAAASUVORK5CYII=",
725
+ "text/plain": [
726
+ "<Figure size 800x600 with 1 Axes>"
727
+ ]
728
+ },
729
+ "metadata": {},
730
+ "output_type": "display_data"
731
  }
732
  ],
733
  "source": [
734
+ "# MODEL EVALUATION\n",
735
  "accuracy = accuracy_score(y_test, y_pred)\n",
736
+ "f1 = f1_score(y_test, y_pred, average=\"macro\")\n",
737
+ "report = classification_report(y_test, y_pred)\n",
738
+ "\n",
739
  "print(f\"Accuracy: {accuracy:.4f}\")\n",
740
+ "print(\"Classification Report:\\n\", classification_report(y_test, y_pred))\n",
741
+ "\n",
742
+ "text_output = f\"Accuracy: {accuracy:.4f}\\nF1 Score: {f1:.4f}\\n\\nClassification Report:\\n{report}\"\n",
743
+ "\n",
744
+ "plt.figure(figsize=(8, 6))\n",
745
+ "plt.text(0.01, 0.99, text_output, fontsize=12, ha='left', va='top', family=\"monospace\")\n",
746
+ "plt.axis(\"off\")\n",
747
+ "\n",
748
+ "plt.savefig(\"classification_report.png\", bbox_inches=\"tight\", dpi=300)\n",
749
+ "plt.show()"
750
  ]
751
  },
752
  {
 
758
  },
759
  {
760
  "cell_type": "code",
761
+ "execution_count": 63,
762
  "metadata": {},
763
  "outputs": [
764
  {
 
773
  }
774
  ],
775
  "source": [
 
776
  "cm = confusion_matrix(y_test, y_pred)\n",
777
  "sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=sentiment_mapping.keys(), yticklabels=sentiment_mapping.keys())\n",
778
  "plt.xlabel(\"Predicted\")\n",
779
  "plt.ylabel(\"Actual\")\n",
780
  "plt.title(\"Confusion Matrix\")\n",
781
+ "plt.savefig(\"confusion_matrix.png\")\n",
782
  "plt.show()"
783
  ]
784
  },
785
  {
786
  "cell_type": "code",
787
+ "execution_count": 64,
788
  "metadata": {},
789
  "outputs": [
790
  {
 
796
  }
797
  ],
798
  "source": [
799
+ "# SAVING THE MODEL AS A .pkl FILE\n",
800
  "joblib.dump(model, \"sentimentAnalysis_model.pkl\")\n",
801
  "joblib.dump(vectorizer, \"vectorizer.pkl\")\n",
802
  "print(\"Model saved successfully\")"
sentiment_distribution.png ADDED
vectorizer.pkl CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:58104b1bcbeb9aa47573a7700b81da612a477282c0402d0b9d8f7d4af8f4164d
3
  size 39183
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:005669f3aa2e6881f76c8ac6b49fed721f3ed10ac15622a25439da31c0716753
3
  size 39183