Ashwin B commited on
Commit
0b6b733
·
1 Parent(s): 9afcdc1

Move project to Hugging Space

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .DS_Store +0 -0
  2. README.md +135 -9
  3. app/.DS_Store +0 -0
  4. app/app.py +62 -0
  5. notebooks/.DS_Store +0 -0
  6. notebooks/.ipynb_checkpoints/01_exploration-checkpoint.ipynb +358 -0
  7. notebooks/.ipynb_checkpoints/02_training-checkpoint.ipynb +368 -0
  8. notebooks/.ipynb_checkpoints/03_evaluation-checkpoint.ipynb +0 -0
  9. notebooks/.ipynb_checkpoints/04_model_comparison-checkpoint.ipynb +290 -0
  10. notebooks/01_exploration.ipynb +358 -0
  11. notebooks/02_training.ipynb +368 -0
  12. notebooks/03_evaluation.ipynb +0 -0
  13. notebooks/04_model_comparison.ipynb +290 -0
  14. outputs/.DS_Store +0 -0
  15. outputs/interpretations/.DS_Store +0 -0
  16. outputs/interpretations/sample_1_disapproval_bar.png +0 -0
  17. outputs/interpretations/sample_1_disapproval_heatmap.png +0 -0
  18. outputs/interpretations/sample_2_neutral_bar.png +0 -0
  19. outputs/interpretations/sample_2_neutral_heatmap.png +0 -0
  20. outputs/interpretations/sample_3_neutral_bar.png +0 -0
  21. outputs/interpretations/sample_3_neutral_heatmap.png +0 -0
  22. outputs/interpretations/sample_4_sadness_bar.png +0 -0
  23. outputs/interpretations/sample_4_sadness_heatmap.png +0 -0
  24. outputs/interpretations/sample_5_neutral_bar.png +0 -0
  25. outputs/interpretations/sample_5_neutral_heatmap.png +0 -0
  26. outputs/metrics/.DS_Store +0 -0
  27. outputs/metrics/.gitkeep +0 -0
  28. outputs/metrics/.ipynb_checkpoints/confusion_matrix-checkpoint.png +0 -0
  29. outputs/metrics/.ipynb_checkpoints/report-checkpoint.json +183 -0
  30. outputs/metrics/report.json +183 -0
  31. outputs/model-old/.gitkeep +0 -0
  32. outputs/model-old/.ipynb_checkpoints/special_tokens_map-checkpoint.json +7 -0
  33. outputs/model-old/config.json +87 -0
  34. outputs/model-old/model.safetensors +3 -0
  35. outputs/model-old/special_tokens_map.json +7 -0
  36. outputs/model-old/tokenizer_config.json +57 -0
  37. outputs/model-old/vocab.txt +0 -0
  38. outputs/model/config.json +87 -0
  39. outputs/model/model.safetensors +3 -0
  40. outputs/model/special_tokens_map.json +37 -0
  41. outputs/model/tokenizer.json +0 -0
  42. outputs/model/tokenizer_config.json +57 -0
  43. outputs/model/vocab.txt +0 -0
  44. requirements.txt +9 -0
  45. save_clean_model.py +12 -0
  46. src/__pycache__/data_loader.cpython-312.pyc +0 -0
  47. src/__pycache__/evaluate.cpython-312.pyc +0 -0
  48. src/__pycache__/model.cpython-312.pyc +0 -0
  49. src/__pycache__/model_custom.cpython-312.pyc +0 -0
  50. src/__pycache__/model_hartmann.cpython-312.pyc +0 -0
.DS_Store ADDED
Binary file (6.15 kB). View file
 
README.md CHANGED
@@ -1,12 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
- title: Emotion Classifier Nlp
3
- emoji: 📚
4
- colorFrom: indigo
5
- colorTo: gray
6
- sdk: gradio
7
- sdk_version: 5.29.0
8
- app_file: app.py
9
- pinned: false
 
 
10
  ---
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Emotion Classifier (NLP)
2
+
3
+ A simple NLP-based emotion classification app that uses a fine-tuned transformer model on the GoEmotions dataset to predict the emotion conveyed in a given sentence.
4
+
5
+ ## Project Structure
6
+
7
+ Emotion-Classifier-NLP/
8
+ ├── notebooks/
9
+ │ ├── 01_exploration.ipynb
10
+ │ ├── 02_training.ipynb
11
+ │ ├── 03_evaluation.ipynb
12
+ │ └── 04_comparison.ipynb
13
+ ├── src/
14
+ │ ├── data_loader.py
15
+ │ ├── model.py
16
+ │ ├── model_hartmann.py
17
+ │ ├── model_custom.py
18
+ │ ├── train.py
19
+ │ └── evaluate.py
20
+ ├── app/
21
+ │ └── app.py
22
+ ├── outputs/
23
+ │ ├── model/ # Trained model
24
+ │ ├── metrics/ # Evaluation metrics
25
+ │ └── interpretations/ # Integrated gradients visualization plots
26
+ ├── requirements.txt
27
+ ├── README.md
28
+ └── .gitignore
29
+
30
+ ## Features
31
+ - Uses Hugging Face Transformers with a fine-tuned model
32
+ - Classifies emotion from text across 28 GoEmotions labels
33
+ - Streamlit frontend for interactive use
34
+ - Displays model prediction probabilities
35
+ - Shows sample integrated gradients visualizations per label (optional)
36
+
37
+ ## Running the App Locally
38
+ ### Make sure you have Streamlit and other dependencies installed:
39
+
40
+ pip install -r requirements.txt
41
+
42
+ ### Then start the app using:
43
+
44
+ streamlit run app/app.py
45
+
46
+ ## Running the App on a web browser
47
+
48
+ You can visit https://emotion-classifier-nlp.streamlit.app/ to run the app online
49
+
50
+ ## Example Output
51
+ - Input: "I find this funny"
52
+ - Output: Predicted Emotion: `amusement`
53
+ - Shows prediction probabilities across all 28 classes
54
+
55
+ ## Notes
56
+ - Pretrained model is saved in `outputs/model/`
57
+ - Integrated Gradients plots should be saved under `outputs/interpretations/` and named using the format: `sample_{n}_{label}.png`
58
+
59
+
60
+ # Performance Metrics
61
+
62
+ | Metric | Score |
63
+ |------------|-------|
64
+ | Accuracy | 60.2% |
65
+ | Macro F1 | 48.3% |
66
+ | Weighted F1| 59.6% |
67
+
68
+ ### Confusion matrix
69
+
70
+ ![confusion_matrix](https://github.com/user-attachments/assets/f571bafa-daa9-4cf2-88cd-2bad069d187a)
71
+
72
+
73
+
74
+ # Model Comparison (Hartmann vs Custom Model)
75
+
76
+ | Sample Sentence | Hartmann Prediction(s) | Custom Model Prediction(s) |
77
+ |-----------------------------------------------------|-----------------------------|-----------------------------|
78
+ | I love spending time with my family. | joy, sadness, disgust | love, joy, admiration |
79
+ | This is the worst day of my life. | disgust, anger, sadness | anger, surprise, disgust |
80
+ | I'm feeling very nervous about the exam. | fear, sadness, joy | nervousness, fear, embarrassment |
81
+ | What a beautiful sunset! | joy, surprise, neutral | admiration, excitement, joy |
82
+ | I feel so disappointed and frustrated. | sadness, anger, disgust | disappointment, annoyance, anger |
83
+ | I'm not sure how to feel about this. | neutral, disgust, sadness | confusion, optimism, disapproval |
84
+ | That was hilarious, I can't stop laughing! | joy, surprise, neutral | amusement, joy, optimism |
85
+ | I feel completely empty and lost. | sadness, neutral, disgust | surprise, disappointment, optimism |
86
+
87
+ **Insights**:
88
+ - The custom model captured more nuanced emotions, while Hartmann’s model tended to favor high-level emotions.
89
+ - Some variance due to differences in label granularity between the models.
90
+ - The custom model showed stronger performance in emotions like admiration, amusement, and disappointment.
91
+
92
+ ---
93
+
94
+ # Known Limitations
95
+
96
+ - **Single-label restriction**: While the data supports multi-label emotion classification, the model currently predicts only the highest probability emotion.
97
+ - **Low support for some classes**: Emotions like grief and pride had low representation in the training data.
98
+ - **Data bias**: Results reflect Reddit comment biases present in the GoEmotions dataset.
99
+
100
  ---
101
+
102
+ # Confidence Threshold
103
+
104
+ A **confidence threshold of 0.6** is applied in the app.
105
+ If the top emotion’s probability is below this value, the app returns:
106
+
107
+ "Unclear / Not enough signal"
108
+
109
+ This prevents overconfident predictions on uncertain or ambiguous text.
110
+
111
  ---
112
 
113
+ # Future Work
114
+
115
+ - Expand to multi-label predictions to better capture complex emotions.
116
+ - Improve minority class performance via data augmentation or rebalancing.
117
+ - Incorporate explainability methods directly into the Streamlit app.
118
+ - Deploy the app to Streamlit Cloud or Hugging Face Spaces.
119
+ - Collect user feedback for real-world validation.
120
+
121
+ ---
122
+
123
+ # Credits
124
+
125
+ - **Model architecture**: [RoBERTa](https://huggingface.co/roberta-base) (Hugging Face)
126
+ - **Training dataset**: [GoEmotions](https://huggingface.co/datasets/go_emotions)
127
+ - **Reference model**: [Hartmann et al. (2023)](https://arxiv.org/abs/2305.05894)
128
+ - **Streamlit App Framework**: [Streamlit](https://streamlit.io/)
129
+ - **Berta Emotion Model**: [BERTa](https://huggingface.co/bhadresh-savani/bert-base-uncased-emotion)
130
+ - **Transformers Library**: [Hugging Face Transformers](https://huggingface.co/docs/transformers/index)
131
+
132
+ ---
133
+
134
+ # License
135
+
136
+ This project is licensed under the MIT License.
137
+ You can use, modify, and distribute the software freely, but there is no warranty.
138
+
app/.DS_Store ADDED
Binary file (6.15 kB). View file
 
app/app.py ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ os.system("git lfs pull")
3
+
4
+ import streamlit as st
5
+ import torch
6
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
7
+ import numpy as np
8
+
9
+ st.set_page_config(page_title="Emotion Classifier", layout="centered")
10
+
11
+ # Load GoEmotions label names
12
+ GOEMOTIONS_LABELS = [
13
+ "admiration", "amusement", "anger", "annoyance", "approval", "caring",
14
+ "confusion", "curiosity", "desire", "disappointment", "disapproval",
15
+ "disgust", "embarrassment", "excitement", "fear", "gratitude", "grief",
16
+ "joy", "love", "nervousness", "optimism", "pride", "realization", "relief",
17
+ "remorse", "sadness", "surprise", "neutral"
18
+ ]
19
+
20
+ # -----------------------------
21
+ # Load model and tokenizer
22
+ # -----------------------------
23
+ MODEL_PATH = "/mount/src/emotion-classifier-nlp/outputs/model"
24
+ model = AutoModelForSequenceClassification.from_pretrained(MODEL_PATH, device_map="auto", low_cpu_mem_usage=True)
25
+ tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH)
26
+ print("Model device:", next(model.parameters()).device)
27
+
28
+ # -----------------------------
29
+ # Streamlit UI
30
+ # -----------------------------
31
+ st.title("🧠 Emotion Classifier (NLP)")
32
+ st.markdown("Enter a sentence to analyze:")
33
+
34
+ input_text = st.text_area(" ", height=100)
35
+
36
+ if st.button("Classify") and input_text.strip():
37
+
38
+ with torch.no_grad():
39
+ inputs = tokenizer(input_text, return_tensors="pt", truncation=True, padding=True)
40
+ outputs = model(**inputs)
41
+ probs = torch.nn.functional.softmax(outputs.logits, dim=1)[0]
42
+
43
+ pred_label_idx = torch.argmax(probs).cpu().item()
44
+ pred_score = probs[pred_label_idx].cpu().item()
45
+ pred_emotion = GOEMOTIONS_LABELS[pred_label_idx]
46
+
47
+ # -----------------------------
48
+ # Confidence threshold logic
49
+ # -----------------------------
50
+ threshold = 0.6
51
+ if pred_score < threshold:
52
+ st.warning(f"**Predicted Emotion:** Unclear / Not enough signal (Confidence: {pred_score:.0%})")
53
+ else:
54
+ st.success(f"**Predicted Emotion:** {pred_emotion} (Confidence: {pred_score:.0%})")
55
+
56
+ # -----------------------------
57
+ # Show all probabilities
58
+ # -----------------------------
59
+ st.markdown("### Prediction Probabilities:")
60
+ for i, prob in enumerate(probs):
61
+ st.write(f"- {GOEMOTIONS_LABELS[i]}: {prob.item():.4f}")
62
+
notebooks/.DS_Store ADDED
Binary file (6.15 kB). View file
 
notebooks/.ipynb_checkpoints/01_exploration-checkpoint.ipynb ADDED
@@ -0,0 +1,358 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": 1,
6
+ "id": "ec88103e-4da3-4eb9-9ed5-8aab3f7745a5",
7
+ "metadata": {},
8
+ "outputs": [],
9
+ "source": [
10
+ "from datasets import load_dataset\n",
11
+ "\n",
12
+ "dataset = load_dataset(\"go_emotions\")"
13
+ ]
14
+ },
15
+ {
16
+ "cell_type": "code",
17
+ "execution_count": 2,
18
+ "id": "9e38e4c1-5c32-4e1b-8612-e723645e34bb",
19
+ "metadata": {},
20
+ "outputs": [],
21
+ "source": [
22
+ "import pandas as pd\n",
23
+ "import matplotlib.pyplot as plt\n",
24
+ "from collections import Counter"
25
+ ]
26
+ },
27
+ {
28
+ "cell_type": "markdown",
29
+ "id": "169cb7bc-8ac6-41d4-a109-c30ca1688899",
30
+ "metadata": {},
31
+ "source": [
32
+ "### Converting the dataset to a dataframe for ease"
33
+ ]
34
+ },
35
+ {
36
+ "cell_type": "code",
37
+ "execution_count": 4,
38
+ "id": "fadfe4cd-e0a3-4f09-a411-56db306fbd0b",
39
+ "metadata": {},
40
+ "outputs": [
41
+ {
42
+ "data": {
43
+ "text/html": [
44
+ "<div>\n",
45
+ "<style scoped>\n",
46
+ " .dataframe tbody tr th:only-of-type {\n",
47
+ " vertical-align: middle;\n",
48
+ " }\n",
49
+ "\n",
50
+ " .dataframe tbody tr th {\n",
51
+ " vertical-align: top;\n",
52
+ " }\n",
53
+ "\n",
54
+ " .dataframe thead th {\n",
55
+ " text-align: right;\n",
56
+ " }\n",
57
+ "</style>\n",
58
+ "<table border=\"1\" class=\"dataframe\">\n",
59
+ " <thead>\n",
60
+ " <tr style=\"text-align: right;\">\n",
61
+ " <th></th>\n",
62
+ " <th>text</th>\n",
63
+ " <th>labels</th>\n",
64
+ " <th>id</th>\n",
65
+ " </tr>\n",
66
+ " </thead>\n",
67
+ " <tbody>\n",
68
+ " <tr>\n",
69
+ " <th>0</th>\n",
70
+ " <td>My favourite food is anything I didn't have to...</td>\n",
71
+ " <td>[27]</td>\n",
72
+ " <td>eebbqej</td>\n",
73
+ " </tr>\n",
74
+ " <tr>\n",
75
+ " <th>1</th>\n",
76
+ " <td>Now if he does off himself, everyone will thin...</td>\n",
77
+ " <td>[27]</td>\n",
78
+ " <td>ed00q6i</td>\n",
79
+ " </tr>\n",
80
+ " <tr>\n",
81
+ " <th>2</th>\n",
82
+ " <td>WHY THE FUCK IS BAYLESS ISOING</td>\n",
83
+ " <td>[2]</td>\n",
84
+ " <td>eezlygj</td>\n",
85
+ " </tr>\n",
86
+ " <tr>\n",
87
+ " <th>3</th>\n",
88
+ " <td>To make her feel threatened</td>\n",
89
+ " <td>[14]</td>\n",
90
+ " <td>ed7ypvh</td>\n",
91
+ " </tr>\n",
92
+ " <tr>\n",
93
+ " <th>4</th>\n",
94
+ " <td>Dirty Southern Wankers</td>\n",
95
+ " <td>[3]</td>\n",
96
+ " <td>ed0bdzj</td>\n",
97
+ " </tr>\n",
98
+ " </tbody>\n",
99
+ "</table>\n",
100
+ "</div>"
101
+ ],
102
+ "text/plain": [
103
+ " text labels id\n",
104
+ "0 My favourite food is anything I didn't have to... [27] eebbqej\n",
105
+ "1 Now if he does off himself, everyone will thin... [27] ed00q6i\n",
106
+ "2 WHY THE FUCK IS BAYLESS ISOING [2] eezlygj\n",
107
+ "3 To make her feel threatened [14] ed7ypvh\n",
108
+ "4 Dirty Southern Wankers [3] ed0bdzj"
109
+ ]
110
+ },
111
+ "execution_count": 4,
112
+ "metadata": {},
113
+ "output_type": "execute_result"
114
+ }
115
+ ],
116
+ "source": [
117
+ "df = pd.DataFrame(dataset[\"train\"])\n",
118
+ "df.head()"
119
+ ]
120
+ },
121
+ {
122
+ "cell_type": "code",
123
+ "execution_count": 5,
124
+ "id": "20a1d0af-1cd6-45c9-8128-29be160713d4",
125
+ "metadata": {},
126
+ "outputs": [],
127
+ "source": [
128
+ "label_counts = Counter() # counts number of occurences\n",
129
+ "\n",
130
+ "# Looping through all label lists and counting each label's total occurrences\n",
131
+ "for labels in df[\"labels\"]:\n",
132
+ " label_counts.update(labels)"
133
+ ]
134
+ },
135
+ {
136
+ "cell_type": "code",
137
+ "execution_count": 6,
138
+ "id": "11c20083-c1a7-412d-9f98-e51defaded84",
139
+ "metadata": {},
140
+ "outputs": [],
141
+ "source": [
142
+ "# Mapping indices to label names\n",
143
+ "label_names = dataset[\"train\"].features[\"labels\"].feature.names\n",
144
+ "label_distribution = {label_names[i]: count for i, count in label_counts.items()}"
145
+ ]
146
+ },
147
+ {
148
+ "cell_type": "markdown",
149
+ "id": "967e6d78-3dec-4dc5-b035-8ff263e689c8",
150
+ "metadata": {},
151
+ "source": [
152
+ "### Plot for the number of occurences of each emotion in the training set"
153
+ ]
154
+ },
155
+ {
156
+ "cell_type": "code",
157
+ "execution_count": 8,
158
+ "id": "91e04be4-4132-4c78-8e4e-6d4c1b29fd6c",
159
+ "metadata": {},
160
+ "outputs": [
161
+ {
162
+ "data": {
163
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAABKUAAAJOCAYAAABm7rQwAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAAC+y0lEQVR4nOzdd3gUVf/+8XtJISEkS01CkN5DUYpCwK/0IiBig8dgAEEQUZCmwmOhqCCgFMUCitIULAiiYAARUQSkBqQLhqIQghASSkhCcn5/8Ms+LAkthpkF3q/r2uvKzpydvXezZfYzZ85xGGOMAAAAAAAAAAvlsTsAAAAAAAAAbj0UpQAAAAAAAGA5ilIAAAAAAACwHEUpAAAAAAAAWI6iFAAAAAAAACxHUQoAAAAAAACWoygFAAAAAAAAy1GUAgAAAAAAgOUoSgEAAAAAAMByFKUAALgFbNmyRd27d1e5cuXk7+8vf39/VahQQU8++aTWr1+fo21OmzZNDofjkpeffvopdx/EVVi0aJGGDRuW7brSpUura9eulua5WsOGDZPD4dA///zzr7e1b98+ORwOvfnmm7mQzH2b06ZNu6p2mRcfHx8VLlxYd955p/r3769t27Zluc1PP/2Uo9fLe++9d8U8V3NfXbt2Vf78+a9pO1eyatUqDRs2TCdOnMiyrlGjRmrUqFGu3h8AADcqb7sDAACA62vy5Ml65plnVKlSJT377LOqWrWqHA6HduzYodmzZ+vOO+/Unj17VK5cuRxt/5NPPlHlypWzLA8PD/+30a/ZokWL9O6772ZbmJo3b56CgoIsz3Qr6tOnjyIjI5WRkaETJ05o06ZN+vjjj/XOO+9o1KhReu6551xta9WqpdWrV1/z6+W9995TkSJFrqnQmNP7ularVq3S8OHD1bVrVxUoUMBt3XvvvXdd7xsAgBsJRSkAAG5iv/76q3r37q02bdroq6++kq+vr2tdkyZN9PTTT+vLL7+Uv79/ju+jWrVqqlOnTm7Eva5q1qxpd4RbRsmSJVWvXj3X9datW2vAgAF68MEH9fzzz6tatWq69957JUlBQUFuba+HtLQ0ORwOS+7rSuwo1gIA4Kk4fQ8AgJvYyJEj5eXlpcmTJ7sVpC70yCOPKCwszG3ZggULFBERoXz58ikwMFDNmzfX6tWrc5zD4XDomWee0SeffKJKlSrJ399fderU0Zo1a2SM0dixY1WmTBnlz59fTZo00Z49e7Js4+OPP9btt98uPz8/FSpUSA888IB27NjhWt+1a1e9++67rvvLvOzbt09S9qfvHThwQI899piCg4OVN29eValSRW+99ZYyMjJcbS48HW7cuHGunBEREVqzZo3b9v7880/95z//UVhYmPLmzauQkBA1bdpUMTExOX7uMh09elS9e/dWeHi48ufPr+DgYDVp0kS//PJLtu0zMjL0+uuvq2TJkvLz81OdOnW0bNmyLO3++OMPRUZGuj0Hmc9jbvL399fUqVPl4+OjsWPHupZnd0rdlZ7H0qVLa9u2bVqxYoXr/1y6dGm37c2cOVMDBw5U8eLFlTdvXu3Zs+eypwpu27ZNTZs2VUBAgIoWLapnnnlGZ86cca2/3CmMDofD1Ttv2LBhrp5gZcqUyXI6a3an7x0/fly9e/dW8eLF5evrq7Jly+rFF19USkpKlvt55plnNHPmTFWpUkX58uXT7bffru++++7K/wAAADwQPaUAALhJpaena/ny5apTp46KFSt21bf77LPP1KlTJ7Vo0UKzZ89WSkqKxowZo0aNGmnZsmW6++67s9zPuXPn3JY5HA55eXm5Lfvuu++0adMmvfHGG3I4HHrhhRfUpk0bdenSRX/++acmTZqkxMREDRgwQA899JBiYmLkcDgkSaNGjdJ///tfPfrooxo1apSOHTumYcOGKSIiQuvWrVOFChX08ssv6/Tp0/rqq6/cCmiXeuxHjx5V/fr1lZqaqldffVWlS5fWd999p0GDBmnv3r1ZTrN69913VblyZU2YMEGS9PLLL6t169aKjY2V0+mUdL5HUHp6usaMGaOSJUvqn3/+0apVq7IdW+haHT9+XJI0dOhQhYaG6tSpU5o3b57r/3JxoWPSpEkqVaqUJkyYoIyMDI0ZM0b33nuvVqxYoYiICEnS9u3bVb9+fZUsWVJvvfWWQkNDtXjxYvXt21f//POPhg4d+q9zXygsLEy1a9fWqlWrdO7cOXl7Z78reqXncd68eXr44YfldDpd/6e8efO6bWPIkCGKiIjQBx98oDx58ig4OFhxcXHZ3l9aWppat26tJ598UoMHD9aqVav02muvaf/+/fr222+v6TE+8cQTOn78uN555x19/fXXrtffpXpInT17Vo0bN9bevXs1fPhw1ahRQ7/88otGjRql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euqpp1SxYsVryrllyxY988wzeuSRR1ShQgX5+vrqxx9/1JYtWzR48OCr2sa3337rNl5Qpocfflht27bVq6++qqFDh6phw4batWuXRowYoTJlymT7/Ht5eal58+YaMGCAMjIyNHr0aCUlJWn48OGuNhMnTtTdd9+t//u//9NTTz2l0qVL6+TJk9qzZ4++/fbbLONqXa0DBw5ozZo1ysjIUGJiojZt2qSPP/5Y+/fv11tvvaUWLVpc8rZX+zxWr15dc+bM0eeff66yZcvKz8/P9f+/Vr6+vnrrrbd06tQp3Xnnna7Z9+69917XbJMOh0OPPfaYPv74Y5UrV06333671q5d6ypeXSgzx8SJE9WlSxf5+PioUqVK2f5vO3furHfffVddunTRvn37VL16da1cuVIjR45U69at1axZsxw9JgAAbgj2jrMOAACsEBMTYx5//HFTpkwZkzdvXuPn52fKly9vOnfubJYtW5al/fz5803dunWNn5+fCQgIME2bNjW//vqrW5vLzb4nyXz44YeutpLM008/7Xb7S83UljlD2pdffum2/KOPPjI1atQwvr6+xul0mvvvv99s27bNrU1KSop54oknTNGiRY3D4XCbAe3i2feMMWb//v0mMjLSFC5c2Pj4+JhKlSqZsWPHus08eLkZ5XTBrGtHjhwxXbt2NZUrVzYBAQEmf/78pkaNGmb8+PFus/ZlJ3P2vUtdMh/boEGDTPHixY2fn5+pVauWmT9/vunSpYspVapUlryjR482w4cPN7fddpvx9fU1NWvWNIsXL85y37GxsaZbt26mePHixsfHxxQtWtTUr1/fvPbaa1m2ebWz72VevLy8TMGCBU3t2rVNv379svy/jMk6I97VPo/79u0zLVq0MIGBgUaS6zm41Osnu/sy5vzsewEBAWbLli2mUaNGxt/f3xQqVMg89dRTbrNFGmNMYmKieeKJJ0xISIgJCAgw9913n9m3b1+W2feMMWbIkCEmLCzM5MmTx+0+L559zxhjjh07Znr16mWKFStmvL29TalSpcyQIUPM2bNn3dpl9z4yJvvXNgAANwKHMVeYAgUAAAAAAADIZYwpBQAAAAAAAMtRlAIAAAAAAIDlKEoBAAAAAADAchSlAAAAAAAAYDmKUgAAAAAAALAcRSkAAAAAAABYztvuADeTjIwMHTp0SIGBgXI4HHbHAQAA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fdq1a5fKli2rl19+Wfv377e9uLJixQrde++9atCggX7++Wft2LFDZcuW1ZgxY7R27Vp99dVXtmXz8vLS4cOHFRwc7Lb82LFjCg4OVnp6uk3JpIceekgLFy5UiRIl9Pjjj6tLly4qXry4bXmyc+7cOf3000/au3evIiMjFRgYqEOHDikoKEj58+e3LMeDDz541W2//vrr65jkytauXauffvop28+4cePG2ZTqvPz582vr1q0qXbq0rTkutnXrVn388cf69NNPlZKSoo4dO6p79+6666677I4myfO+uy7UokULPfjgg+rVq5dOnDihypUry8fHR//884/GjRunp556yrZsefLkUVxcXJbP3/j4eBUvXlxpaWk2JfNsW7ZsyXa5w+GQn5+fSpYsqbx581qc6n8yMjL0+uuv64MPPtCRI0e0e/du1z5J6dKl1b17d9uyXeo7/59//lFoaKjOnTtnUzLPfj948n5c8eLF9cMPP6hKlSq2ZbhRefI+cHJysowxypcvn6TzB1TmzZun8PBwtWjRwvI83t7eOnTokIKDgy/5vHma1NRUxcbGqly5cvL29rYlQ+HChbVo0SLVrVtXefLk0ZEjR1S0aFFbskiSPc8CXN5+++2rbtu3b9/rmOTynn32WU2bNk1t2rRRtWrVrrogdL20b9/e1vu/WgMGDFDXrl01ZswYBQYGupbfe++9ioyMtDHZeYMHD9Zrr72mAQMGuOVr3LixJk6caGMyyRiT7evsr7/+ktPptCHR/8ydO1fHjh3TrFmzNG3aNA0dOlTNmjVT9+7ddf/998vHx8fWfPv371erVq104MABpaSkqHnz5goMDNSYMWN09uxZffDBB5Zlsft/dbVGjhypl156SZUqVVJISIjba8/uzztJatasmX766Sd17drV7ihuqlWrpnHjxmnMmDH69ttvNW3aNN19992qUKGCunfvrqioKFt3cjztu+tCGzdu1Pjx4yVJX331lUJCQrRp0ybNnTtXr7zyii1FqQuLKtu3b1dcXJzrenp6uqKjoz2iAH/69Gm98cYblyw2/vnnn7bkuuOOOy77GvPx8VHHjh01efJk+fn5WZjsvNdee03Tp0/XmDFj1KNHD9fy6tWra/z48bYUpZKSkmSMkTFGJ0+edHte0tPTtWjRItt+YN4I7wdP3o/r06ePRo8erY8++si2H95Xsnfv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+uuv25pNOn9Ut2vXripevLiMMQoPD1d6eroiIyP10ksv2ZqtS5cuks4PBpjdmCF2nhderFgxZWRk6NFHH9XatWt1xx13ZGnTsmVLFShQwPJsktS8eXNNmDBBU6ZMkXS+J82pU6c0dOhQW09jevvtt/Xiiy+qS5cu+uabb/T4449r7969WrdunZ5++mnbcknSoEGD1KZNG5UrV07h4eEe9Rl3sbNnz9oyHk123n//fXXr1k2PP/64QkNDs21TsmRJTZ061eJk53nyd9fDDz+su+++W4cPH9btt9/uWt60aVM98MADtuXKtHv37ksO/G/3d+urr76qV155RdOnT3cNtusJKleurDfeeENTpkxx9VRNS0vTG2+8ocqVK0s631spJCTElnxDhw5VVFSU/v77b2VkZOjrr7/Wrl27NGPGDH333Xe2ZMpUqlQpnThxQmvXrs32Nde5c2ebkknTp09XkSJF1KZNG0nS888/rylTpig8PFyzZ89WqVKlbMvmyftxns6Te5k1bNhQGRkZ2r17d7bvh3vuucemZOc//yMjI9W/f381bdrU1XNryZIlqlmzpm25pPO/HU6cOKGZM2dq7969eu6551SoUCFt3LhRISEhtv9f77zzTi1cuFB9+vSR9L8xSz/88ENbe8AdP35cjzzyiJYvXy6Hw6E//vhDZcuW1RNPPKECBQrorbfeuu4ZGFPKgyxbtkzt2rVTmTJltGvXLlWrVk379u2TMUa1atWydZagxx9//LLrP/nkE4uSZFWuXDm9/fbbatOmjQIDAxUTE+NatmbNGn322We2Zcv0448/auPGjcrIyFCtWrXUrFkzuyO5+fPPP135atasadtYSBf6448/1K1bN61atcptufGA88JnzpypRx55xGMKAxc7dOiQGjduLC8vL/3xxx+qU6eO/vjjDxUpUkQ///yzbYPGVq5cWUOHDtWjjz7qNvbFK6+8ouPHj2vSpEm25JKkp59+WlOnTlXjxo2zDHQu2fsZJ50fS2LkyJEeOWuWJ/Pk766LJSUl6ccff1SlSpVsn63qww8/1FNPPaUiRYooNDQ0y8D/ds5qK50fe3Dv3r0yxqh06dJZio125Vu1apXatWunPHnyqEaNGnI4HNqyZYvS09P13XffqV69epo5c6bi4uL03HPP2ZJx8eLFGjlypDZs2ODaJ3nllVdsmTXrQt9++606deqk06dPKzAwMMtr7vjx47Zlq1Spkt5//301adJEq1evVtOmTTVhwgR999138vb2tq24bYzRgQMHVLRoUcXFxXncfpx0fhKHL774ItuD7XZ/jjz//PNavXq1vvzyS1WsWFEbN27UkSNH1LlzZ3Xu3FlDhw61LduaNWsUGRmp/fv3ZxnPzO59YEmKi4tzHVDJkyePpPMzGAcFBbkK8Hbw9FnPV61apVatWqlTp06aNm2annzySW3btk2rV6/WihUrVLt2bVtyde7cWfHx8froo49UpUoV1/75kiVL1L9/f23btu26Z6Ao5UHuuusutWrVyjXQ2ObNmxUcHKxOnTqpVatWtk4P7ckCAgK0Y8cOlSxZUsWKFdPChQtVq1Yt/fnnn6pZs6YSExPtjogcaNCggby9vTV48OBsB7K9sGeB1bp166aJEydmOff69OnT6tOnjz7++GObkv1PcnKyZs+e7VYM7dSpk/z9/W3LlC9fPu3YsUOlSpVScHCwli5dqttvv11//PGH6tWrp2PHjtmWLTAwUHPmzHEdCfc0I0aM0PTp0zVixAj16NFDW7duVdmyZfXFF19o/PjxWr16tW3ZTpw4oalTp2rHjh1yOByqUqWKunfvfsPMvGiXDh066J577tEzzzyj5ORk3X777a4DUXPmzLF1LJZSpUqpd+/eeuGFF2zLcDnDhw+/7Ho7f0yeOnVKs2bN0u7du2WMUeXKlRUZGWnvWB03gIoVK6p169YaOXKkR/V+k9wnJXjhhRd0+PBhzZgxQ9u2bVOjRo109OhRW3JlZGTIz89P27Zt85gi1IUu7B394YcfZukdbfcZA2lpaeratavmzJkjY4y8vb1dvcymTZtm63hhd9xxhypWrKjhw4dnuw/sSd+vnnRApWnTpqpdu7Zr1vPM4sqqVasUGRmpffv22ZpPkn7//Xe9+eabbgcGXnjhBVWvXt22TKGhoVq8eLFuv/12t+ctNjZW1atX16lTp65/CMtOFMQV5c+f3+zZs8cYY0yBAgXM1q1bjTHnzzMtVaqUjcn+Jz4+3vzyyy9m5cqVJj4+3u44xhhjKlasaNasWWOMMebuu+82o0aNMsYYM2fOHFO0aFHL80ycOPGqL3Z76KGHXM/XhcaMGWMefvhhGxL9T758+bIdm8MT5MmTxxw5ciTL8qNHj9o2ds6FTp8+bXeEbJUpU8Zs2LDBGGNMnTp1zAcffGCMMWbx4sW2j/9WsmRJj329GWNMuXLlzA8//GCMcR+HYMeOHbaNXWaMMevWrTOFChUyxYsXNw888IBp3769ue2220zhwoVd/2tP4InfXSEhISYmJsYYY8ynn35qypcvb06fPm3ee+89c8cdd9iaLTAw0PUaw83jwIED5uDBg67rv/32m3n22WfN5MmTbUx1Xr58+Tz2NVe0aFGzceNGY4wxd9xxh5k+fboxxpg9e/aYgIAAO6OZ8PBws3r1alszXEqlSpXMZ599Zoxx/956+eWXzdNPP21nNDd79+41X375pfn888/N7t277Y5jjDn/fvjjjz/sjpGtRx55xLzzzjvGGGPOnDljKlSoYHx8fIy3t7f56quvbM0WFBTk+i194Wtu3759to8T5sny58/veu1f+LytXbvWFCpUyJIMFKU8SEhIiGtw4vDwcPPNN98YY84Xpez+0jt16pR5/PHHjZeXl3E4HMbhcBhvb2/TrVs3238Av/DCC+b11183xpwfONbb29uUL1/e+Pr6mhdeeMHyPKVLl3a7BAQEGIfD4Rp43eFwmICAAFOmTBnLs12sSJEiZsuWLVmWb9myxfYBsevUqWN++eUXWzNcLDEx0Zw4ccI4HA6zZ88ek5iY6LocP37cTJ8+3RQrVszumCYgIMB06tTJREdHe9TAsd27d3cNvPr+++8bf39/06xZM1OgQAHTrVs3W7N9/PHHpkOHDrZ/nl2Kn5+f2bdvnzHGfYdh27Zttn4/3H333aZr164mLS3NtSwtLc106dLF/N///Z9tuTJ58neXn5+fOXDggDHGmKioKNf31f79+23/zu/WrZt5//33bc1wNdavX29mzpxpZs2a5Soa2G3Xrl1m8uTJ5tVXXzXDhw93u9jt7rvvNjNmzDDGGNfA2BEREaZw4cK253vggQfM559/bmuGS4mMjDS1atUy3bt3N/ny5TP//POPMcaYb775xlStWtXWbN999525++67ze+//25rjuz4+/u7vreKFi3qKsLv3r3bsh+61+LcuXNm06ZN5vjx43ZHMY0bNzbff/+93TGy5ckHVIKDg13fBRfuKy1evNjcdttttmS68LfClS52ad26tXnppZeMMcY1MVd6erp55JFHzEMPPWRJBopSHuT+++83U6ZMMcacn02jfPny5rXXXjO1atUyTZs2tTVbz549TdmyZc2iRYtcb5yFCxeacuXKmV69etma7WJr1qwxb731lquoZ6dPP/3UNGjQwOzcudO1bOfOneb//u//zKxZs2xMdp6fn59btkwXzhRkl2XLlpmIiAizfPly888//3jEB7fD4TB58uS55MXLy8u89tprtmS70Ny5c83DDz9s/P39TUhIiOnbt69Zu3at3bFMenq6W/Hi888/N3369DETJ040KSkpNiY7f/Q7MDDQ5M+f31SrVs2jZgY0xnNnzbrUbGPbtm2zbYaxC3nyd1eFChXM559/bk6dOmWKFi1qli1bZow5fyCqcOHCtmYbOXKkKVKkiOnSpYt58803Pa6X75EjR0zjxo1dB3wKFChgHA6HadKkia094aZMmWK8vLxMSEiIuf32280dd9zhunjC50iBAgVc3/kTJ0409evXN8ac/8Fm94Gyjz76yJQsWdIMHTrUfPXVV+abb75xu9gpISHBPP3006Zdu3ZuhYJXXnnF9u/8AgUKGF9fX5MnTx7j5+fnUTNQe3LvaGOMefbZZ81HH31kjDlfkGrQoIHrwPHy5cttzfb111+b8PBw88knn5j169ebzZs3u13s5MkHVDxx1vMr/Xa48GKXbdu2maJFi5pWrVoZX19f8/DDD5sqVaqYkJAQV8+z640xpTzIn3/+qVOnTqlGjRo6c+aMBg0apJUrV6p8+fIaP368rbN7FClSRF999ZUaNWrktnz58uXq0KGDbefTS9KZM2c8bvyBTOXKldNXX32VZTaKDRs26OGHH1ZsbKxNyc678847dd9992WZSWnYsGH69ttvtWHDBpuSyTVw4sXn0RsbBzpfsWKFjDFq0qSJ5s6dq0KFCrnW+fr6qlSpUgoLC7M816WcPHlSX331lWbPnq3ly5erTJkyeuyxx2yfOcsTefIYNdL5QYCjoqI0ZMgQjRgxQsOHD3ebNat58+a25AoJCdHMmTOzDJK8ePFide7cWUeOHLElVyZP/u5677339Oyzzyp//vwqWbKkNm3apDx58uidd97R119/reXLl9uW7eLZqC7kcDj0559/Wpgmq44dO2rv3r2aOXOmawyT7du3q0uXLipfvrxmz55tSy5PH4srf/782rp1q0qXLq127dqpQYMGeuGFF3TgwAFVqlRJycnJtmXL/M7PjicM7Oyppk+fftn1mTMZ2+GJJ55QiRIlNHToUH3wwQcaMGCAGjRooPXr1+vBBx+0bVbWTLfddpvmz5+vOnXqaP78+erdu7d++uknzZgxQ8uXL9evv/5qW7bs3g8Oh8MjJvupWLGiXnvtNbVp00ZlypTRnDlz1KRJE23evFlNmzbVP//8Y1u2pKQktW7dWtu2bdPJkycVFhbmmvV80aJFCggIsDzTihUrXH/v27dPgwcPVteuXV2z7a1evVrTp0/XqFGjbH2/xsXF6f3333cb6+rpp59WsWLFLLl/ilIeIj09XStXrlSNGjVUsGBBu+NkkS9fPm3YsCHLAHbbtm3TXXfdpdOnT9uU7PxOVvv27RUVFaXmzZtfdsfGavny5dNPP/2ku+66y2352rVr1ahRI505c8amZOctWLBADz30kCIjI9WkSRNJ52eBnD17tr788ku1b9/etmwXfohnp2HDhhYlyWr//v0qWbJkloKZJ9u+fbs6derkmgnKDplFsU6dOtk6O8uNyhNnzerbt6/mzZunN998U/Xr15fD4dDKlSv13HPP6aGHHtKECRNsyyZ59neXJK1fv14HDx5U8+bNlT9/fknSwoULVaBAATVo0MDWbJ7M6XTqhx9+0J133um2fO3atWrRooVOnDhhS66goCDFxMSobNmyttz/ldStW1eNGzdWmzZt1KJFC61Zs0a333671qxZo4cfflh//fWX3RE90s8//3zZ9ffcc49FSW4sGRkZysjIkLe3tyTpiy++cB1s79Wrl3x9fW3N5+fnpz179ui2225Tz549lS9fPk2YMEGxsbG6/fbblZSUZFu2/fv3X3a9nR0VPPmASiZPnfW8adOmeuKJJ/Too4+6Lf/ss880ZcoU/fTTT/YE8wAUpTyIn5+fduzYcdkjlHZp2rSpChcurBkzZsjPz0/S+dm9unTpouPHj+uHH36wLdvXX3+t2bNna+HChQoKClLHjh312GOPZdlZtcN9992nAwcOaOrUqapdu7YcDofWr1+vHj16qESJElqwYIHdEbVw4UKNHDlSMTEx8vf3V40aNTR06FBbiz6eaMuWLapWrZry5MmjLVu2XLZtjRo1LEp1eWfPntWCBQv02WefKTo6WsHBwXr00Uc1evRoW/KMGzdOs2fP1oYNG1SzZk1FRUWpY8eOlh2FuZyDBw/K4XDotttuk3T+x+1nn32m8PBw9ezZ0+Z0nis1NVXPPfecPvjgA507d07GGPn6+uqpp57SG2+8obx589qaz5O/uzKlpqYqNjZW5cqVc/148xSemi0wMFC//PKL7rjjDrflmzZtUsOGDW37Mdm9e3fdeeed6tWrly33fyU//fSTHnjgASUlJalLly6umWL/+9//aufOnfr6669tTnje2bNnXe9XT3CpXiuZrD7Qk5SUpKCgINffl5PZDlmVKlVKH374oZo2baoyZcrovffeU9u2bbVt2zbdfffdSkhIsDuix+KASs7ky5dPmzdvzjJb5u7du3XHHXdY2lnB437XWHKSIK5KnTp1XLMreZrff//dFC9e3BQuXNg0adLENG3a1BQuXNgUL17cNUug3ZKSkszHH39smjdvbry9vU2FChVsH7gzPj7e3HvvvcbhcBhfX1/Xef/33ntvtrO3wd3PP/9sOnXqZCIiIsxff/1ljDFmxowZtgyA7nA4XP+zzPPDMwdOvvBi5znhmRYvXmw6d+5sgoKCTMGCBU2PHj3MTz/9ZHcsl127dplXXnnFVKxY0Xh7e5vmzZu7ZjOyiycPAHwjOH36tNmyZYvZvHmz7QOIX8iTv7tOnz5tunXrZry8vIyXl5drnLA+ffpkOysq2f6nXbt25p577jF///23a9lff/1lGjZsaNq3b29bLk8fi8uY82PnXDyQc2xsrO37JOfOnTMjRowwYWFhbq+5l156yTXuj11OnDjhdjl69KhZsmSJqVu3ri377RfOAHyp8Wo8ZX8kcz+uXr16tu/HXWzo0KHG6XSaypUrm5IlS5qzZ88aY4yZOnWqqVevns3pzj9P9evXN8WKFXMNGD9+/Hgzf/58m5Odl5KSYnbu3Ok2VqgdJk6caJKTk11/e/Ks5xUrVjQDBgzIsnzAgAGmYsWKlmbxtN819JTyIEuWLNELL7ygV199VbVr185y3qvdRzuSk5M1a9Ys7dy5U8YYhYeHq1OnTvL397c1V3Y84VSlC+3evdv1vFWpUkUVK1a0O5Kb1NRUxcfHKyMjw215yZIlbUokzZ07V1FRUerUqZNmzpyp7du3q2zZsnrvvff03XffadGiRZbmufCUPU/uVi2dPxLTpk0bderUSW3atJGPj4+teS5nzZo1euqpp2x/rxYsWFBr1qxRpUqV9Pbbb+vzzz/Xr7/+qiVLlqhXr162j6FTsGDBbE8XdTgc8vPzU/ny5dW1a1c9/vjj1z3Lgw8+qGnTpikoKEgPPvjgZdvmz59fVatWVa9eveR0Oq97tux46nfXs88+q19//VUTJkxQq1attGXLFpUtW1YLFizQ0KFDtWnTJrJdwsGDB3X//fdr69atKlGihBwOhw4cOKDq1avrm2++cfV4tJqnj8XlyUaMGKHp06drxIgR6tGjh7Zu3aqyZcvqiy++0Pjx47V69Wq7I2bx888/q3///paPv7lixQo1aNBA3t7eHj3Ugaftx10q44EDB/TII4+4PjemT5+uAgUK6P7777ct1/vvv69XXnlF/fr10+uvv+56P0ybNk3Tp0+39RS5M2fOqE+fPq7xzHbv3q2yZcuqb9++CgsL0+DBgy3NU6ZMGa1fv16FCxf2+M/gRYsW6aGHHlK5cuVUr149Sef3g/fu3au5c+eqdevWlmXxtN81FKU8yIXdgy/88WE8YFC7G4Gnnap0I/jjjz/UrVs3rVq1ym25J7zmatasqf79+6tz584KDAzU5s2bVbZsWcXExKhVq1aKi4uzLZunu7Brv6fKPD3u888/V2Jiou677z59/vnntuXx5AGAJWn8+PF6/fXXde+99+quu+6SMUbr1q1TdHS0+vfvr9jYWM2cOVPvvPOOevTocV2zPP7443r77bcVGBh4xSJYSkqKVq9ererVq3vE6cqepFSpUvr8889Vr149t8+4PXv2qFatWraOZ+LJ2S60dOlSt2Kjp4wb4klq1aqlZcuWqWDBgqpZs+Zlx0LcuHGjhcnclS9fXpMnT1bTpk3dXnM7d+5URESER55KtWPHDt155506deqU3VE8kifvx6WlpalFixaaPHmyxx0olqTw8HCNHDlS7du3d3vutm7dqkaNGtk6mLinH7TwdAcPHtT777/v9t3Vq1cvlShRwpY8aWlp6tmzp15++WVbx0P0nAEC4BEDw11owYIFuvfee+Xj43PFHxPt2rWzKFVWS5Ys0aeffqr58+fLy8tLDz/8sBYvXuwRYyJ169btsuszx3OwS9euXeXt7a3vvvtOxYoV86iBu3ft2pXt4KFBQUG2DWKbafr06SpSpIjatGkjSXr++ec1ZcoUhYeHa/bs2bb3lAoKClJ6errmz5+vHTt2yOFwqEqVKrr//vvl5eVlW67du3fr008/1WeffaZ9+/apcePGeuONN/Tggw8qMDDQtlySVLVqVX3wwQdq06aNli5dqldffVWSdOjQIRUuXNjWbJK0cuVKvfbaa1nGqpk8ebKWLFmiuXPnqkaNGnr77beve1Hqk08+yfbvS9m+fbulY/zdKN9dR48eVXBwcJblp0+ftv2z2JOzXah58+a2zTx5o7j//vtdY7vZOXnJlfz9998qX758luUZGRlKS0uzIdH/XDzeijFGhw8f1htvvKHbb7/dplTnRUdHK3/+/Lr77rslSe+++64+/PBDhYeH691337V18iRP3o/z8fHR1q1bPerz7EKxsbFZZu6WpLx589o+Qcf8+fNdBy0ufP7Cw8O1d+9eG5PdGEqUKKGRI0faHcPFx8dH8+bN08svv2xrDopSHqRMmTKubugXMsbo4MGDludp37694uLiFBwcfNkdGbt71LRv315t2rTR9OnTPe5UpYuP7KWlpWnr1q06ceKEa7Y7O8XExGjDhg0eORNasWLFtGfPHpUuXdpt+cqVK22f2WjkyJF6//33JZ2fynXSpEmaMGGCvvvuO/Xv39/2wWL37Nmj1q1b6++//1alSpVkjNHu3btVokQJLVy4UOXKlbMlV+XKlVWnTh09/fTT+s9//qPQ0FBbcmRn9OjReuCBBzR27Fh16dLF9UNjwYIFWWbPtMPixYuz7fXZtGlTDRw4UJLUunVry7vNX41KlSpl6Y15Pd0o31133nmnFi5cqD59+rjySNKHH37omiraLp6Y7e2331bPnj3l5+ent99++7Jt+/bta1EqacCAAXr11VcVEBCgAQMGXLbtuHHjLEr1P0OHDpV0fjDuRo0aeewsz1WrVtUvv/yS5aDOl19+me2Pcyvdcccdcjgcuvjkknr16tl+cPG5555zfTf8/vvvGjBggAYOHKgff/xRAwYMuKoDB9eLJ+/HSVLnzp01depUvfHGG3ZHyaJMmTKKiYnJ8n74/vvvFR4eblOq8zztoMWVPncvZMdnsMcNKJ6NBx54QPPnz7+m5zK3UZTyIGXKlNHhw4ezvNGPHz+uMmXKWL7zfOH4QhePNeRJ4uLiPPZUpXnz5mVZlpGRod69e3vEF3J4eLitXYAv58knn9Szzz6rjz/+WA6HQ4cOHdLq1as1aNAgvfLKK7ZmO3jwoOuI7vz58/Xwww+rZ8+eatCggRo1amRrNun8D7Jy5cppzZo1KlSokCTp2LFjeuyxx9S3b18tXLjQllw7d+70yG7yklzd4ZOSktx+sGVOE223QoUK6dtvv1X//v3dln/77beu//Hp06dt73GWHS8vL0t7E9wo312jRo1Sq1attH37dp07d04TJ07Utm3btHr16iuOE3MrZhs/frw6deokPz8/jR8//pLtHA6HpUWpTZs2uXrybNy48ZI/yuzukeHl5aWWLVtqx44dHlmUGjp0qKKiovT3338rIyNDX3/9tXbt2qUZM2bou+++szVbbGys2/U8efKoaNGiHjFDYGxsrKtIMXfuXN13330aOXKkNm7caOn4NNnx5P046fx4qh999JGWLl2qOnXqZBnL144CRqbnnntOTz/9tM6ePStjjNauXavZs2dr1KhR+uijj2zLJXneQYurPV3Qrs/gO+64w3Wg7FIFbsneA2Xly5fXq6++qlWrVmU7rrUl36mWDKeOq+JwOEx8fHyW5fv27TP58uWzIdH/TJ8+3TUrxYVSUlJsnzXLmPOztnz11Vfm1VdfNa+99pqZO3euOXfunN2xLmnnzp0mNDTU7hhm2bJlJiIiwixfvtz8888/JjEx0e1it//+97/G39/fNQOEn5+feemll+yOZYoWLWo2btxojDHmjjvucL0H9uzZYwICAuyMZowxJl++fGbLli1ZlsfExHhEvvXr15uZM2eaWbNmmQ0bNtgd54YwZcoU4+XlZe677z7X51y7du2Mt7e3a2aqN99803To0MHmpJ4vISHB7gguW7ZsMZ07dzZVq1Y1VapUMZ06dcr2vWsHT86GnPHkWZ6NMSY6Otrcc889JiAgwPj7+5sGDRqYxYsX2x3LoxUsWNBs27bNGGNMgwYNzOTJk40x52dU9Pf3tzzP5s2bTXp6uuu6p+7HGWNMo0aNLnlp3Lix3fHMlClTTMmSJV3P3W233Wb7TJTGGPPrr7+awMBA06tXL+Pn52eeffZZ06xZMxMQEGDWr19vdzyPs2/fPpORkeH6+3IXu5QuXfqSlzJlyliSgYHOPUBmV7mJEyeqR48ebkfl09PT9dtvv8nLy0u//vqrXRHl5eWVbS+uY8eOKTg42NZTIDz1VKXLWbRokbp06aKjR4/amiNzcP3sThm1+9SWTGfOnNH27duVkZGh8PBw5c+f3+5I6tSpk3bu3KmaNWtq9uzZOnDggAoXLqwFCxbov//9r7Zu3WprvkKFCum7775T/fr13Zb/+uuv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",
164
+ "text/plain": [
165
+ "<Figure size 1200x600 with 1 Axes>"
166
+ ]
167
+ },
168
+ "metadata": {},
169
+ "output_type": "display_data"
170
+ }
171
+ ],
172
+ "source": [
173
+ "# Plot for the number of occurences of each emotion in the training set\n",
174
+ "plt.figure(figsize=(12, 6))\n",
175
+ "pd.Series(label_distribution).sort_values(ascending=False).plot(kind='bar')\n",
176
+ "plt.title(\"GoEmotions Label Distribution\")\n",
177
+ "plt.ylabel(\"Count\")\n",
178
+ "plt.xticks(rotation=90)\n",
179
+ "plt.tight_layout()\n",
180
+ "plt.show()"
181
+ ]
182
+ },
183
+ {
184
+ "cell_type": "code",
185
+ "execution_count": 9,
186
+ "id": "6d28b28c-d87f-41e5-afd2-cc3257dd974b",
187
+ "metadata": {},
188
+ "outputs": [
189
+ {
190
+ "data": {
191
+ "text/html": [
192
+ "<div>\n",
193
+ "<style scoped>\n",
194
+ " .dataframe tbody tr th:only-of-type {\n",
195
+ " vertical-align: middle;\n",
196
+ " }\n",
197
+ "\n",
198
+ " .dataframe tbody tr th {\n",
199
+ " vertical-align: top;\n",
200
+ " }\n",
201
+ "\n",
202
+ " .dataframe thead th {\n",
203
+ " text-align: right;\n",
204
+ " }\n",
205
+ "</style>\n",
206
+ "<table border=\"1\" class=\"dataframe\">\n",
207
+ " <thead>\n",
208
+ " <tr style=\"text-align: right;\">\n",
209
+ " <th></th>\n",
210
+ " <th>text</th>\n",
211
+ " <th>labels</th>\n",
212
+ " <th>id</th>\n",
213
+ " <th>clean_text</th>\n",
214
+ " </tr>\n",
215
+ " </thead>\n",
216
+ " <tbody>\n",
217
+ " <tr>\n",
218
+ " <th>0</th>\n",
219
+ " <td>My favourite food is anything I didn't have to...</td>\n",
220
+ " <td>[27]</td>\n",
221
+ " <td>eebbqej</td>\n",
222
+ " <td>my favourite food is anything i didnt have to ...</td>\n",
223
+ " </tr>\n",
224
+ " <tr>\n",
225
+ " <th>1</th>\n",
226
+ " <td>Now if he does off himself, everyone will thin...</td>\n",
227
+ " <td>[27]</td>\n",
228
+ " <td>ed00q6i</td>\n",
229
+ " <td>now if he does off himself everyone will think...</td>\n",
230
+ " </tr>\n",
231
+ " <tr>\n",
232
+ " <th>2</th>\n",
233
+ " <td>WHY THE FUCK IS BAYLESS ISOING</td>\n",
234
+ " <td>[2]</td>\n",
235
+ " <td>eezlygj</td>\n",
236
+ " <td>why the fuck is bayless isoing</td>\n",
237
+ " </tr>\n",
238
+ " <tr>\n",
239
+ " <th>3</th>\n",
240
+ " <td>To make her feel threatened</td>\n",
241
+ " <td>[14]</td>\n",
242
+ " <td>ed7ypvh</td>\n",
243
+ " <td>to make her feel threatened</td>\n",
244
+ " </tr>\n",
245
+ " <tr>\n",
246
+ " <th>4</th>\n",
247
+ " <td>Dirty Southern Wankers</td>\n",
248
+ " <td>[3]</td>\n",
249
+ " <td>ed0bdzj</td>\n",
250
+ " <td>dirty southern wankers</td>\n",
251
+ " </tr>\n",
252
+ " <tr>\n",
253
+ " <th>5</th>\n",
254
+ " <td>OmG pEyToN iSn'T gOoD eNoUgH tO hElP uS iN tHe...</td>\n",
255
+ " <td>[26]</td>\n",
256
+ " <td>edvnz26</td>\n",
257
+ " <td>omg peyton isnt good enough to help us in the ...</td>\n",
258
+ " </tr>\n",
259
+ " <tr>\n",
260
+ " <th>6</th>\n",
261
+ " <td>Yes I heard abt the f bombs! That has to be wh...</td>\n",
262
+ " <td>[15]</td>\n",
263
+ " <td>ee3b6wu</td>\n",
264
+ " <td>yes i heard abt the f bombs that has to be why...</td>\n",
265
+ " </tr>\n",
266
+ " <tr>\n",
267
+ " <th>7</th>\n",
268
+ " <td>We need more boards and to create a bit more s...</td>\n",
269
+ " <td>[8, 20]</td>\n",
270
+ " <td>ef4qmod</td>\n",
271
+ " <td>we need more boards and to create a bit more s...</td>\n",
272
+ " </tr>\n",
273
+ " <tr>\n",
274
+ " <th>8</th>\n",
275
+ " <td>Damn youtube and outrage drama is super lucrat...</td>\n",
276
+ " <td>[0]</td>\n",
277
+ " <td>ed8wbdn</td>\n",
278
+ " <td>damn youtube and outrage drama is super lucrat...</td>\n",
279
+ " </tr>\n",
280
+ " <tr>\n",
281
+ " <th>9</th>\n",
282
+ " <td>It might be linked to the trust factor of your...</td>\n",
283
+ " <td>[27]</td>\n",
284
+ " <td>eczgv1o</td>\n",
285
+ " <td>it might be linked to the trust factor of your...</td>\n",
286
+ " </tr>\n",
287
+ " </tbody>\n",
288
+ "</table>\n",
289
+ "</div>"
290
+ ],
291
+ "text/plain": [
292
+ " text labels id \\\n",
293
+ "0 My favourite food is anything I didn't have to... [27] eebbqej \n",
294
+ "1 Now if he does off himself, everyone will thin... [27] ed00q6i \n",
295
+ "2 WHY THE FUCK IS BAYLESS ISOING [2] eezlygj \n",
296
+ "3 To make her feel threatened [14] ed7ypvh \n",
297
+ "4 Dirty Southern Wankers [3] ed0bdzj \n",
298
+ "5 OmG pEyToN iSn'T gOoD eNoUgH tO hElP uS iN tHe... [26] edvnz26 \n",
299
+ "6 Yes I heard abt the f bombs! That has to be wh... [15] ee3b6wu \n",
300
+ "7 We need more boards and to create a bit more s... [8, 20] ef4qmod \n",
301
+ "8 Damn youtube and outrage drama is super lucrat... [0] ed8wbdn \n",
302
+ "9 It might be linked to the trust factor of your... [27] eczgv1o \n",
303
+ "\n",
304
+ " clean_text \n",
305
+ "0 my favourite food is anything i didnt have to ... \n",
306
+ "1 now if he does off himself everyone will think... \n",
307
+ "2 why the fuck is bayless isoing \n",
308
+ "3 to make her feel threatened \n",
309
+ "4 dirty southern wankers \n",
310
+ "5 omg peyton isnt good enough to help us in the ... \n",
311
+ "6 yes i heard abt the f bombs that has to be why... \n",
312
+ "7 we need more boards and to create a bit more s... \n",
313
+ "8 damn youtube and outrage drama is super lucrat... \n",
314
+ "9 it might be linked to the trust factor of your... "
315
+ ]
316
+ },
317
+ "execution_count": 9,
318
+ "metadata": {},
319
+ "output_type": "execute_result"
320
+ }
321
+ ],
322
+ "source": [
323
+ "import re\n",
324
+ "\n",
325
+ "def clean_text(text):\n",
326
+ " text = text.lower() # this makes every character in the text lower-cased\n",
327
+ " text = re.sub(r\"http\\S+|www\\S+|https\\S+\", '', text) # this removes links\n",
328
+ " text = re.sub(r'[^A-Za-z0-9\\s]+', '', text) # this removes special characters\n",
329
+ " text = re.sub(r'\\s+', ' ', text).strip() # this normalizes whitespace\n",
330
+ " return text\n",
331
+ "\n",
332
+ "df[\"clean_text\"] = df[\"text\"].apply(clean_text)\n",
333
+ "df.head(10)"
334
+ ]
335
+ }
336
+ ],
337
+ "metadata": {
338
+ "kernelspec": {
339
+ "display_name": "Python 3 (ipykernel)",
340
+ "language": "python",
341
+ "name": "python3"
342
+ },
343
+ "language_info": {
344
+ "codemirror_mode": {
345
+ "name": "ipython",
346
+ "version": 3
347
+ },
348
+ "file_extension": ".py",
349
+ "mimetype": "text/x-python",
350
+ "name": "python",
351
+ "nbconvert_exporter": "python",
352
+ "pygments_lexer": "ipython3",
353
+ "version": "3.12.2"
354
+ }
355
+ },
356
+ "nbformat": 4,
357
+ "nbformat_minor": 5
358
+ }
notebooks/.ipynb_checkpoints/02_training-checkpoint.ipynb ADDED
@@ -0,0 +1,368 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "id": "80f816c1-0839-41cb-847b-c79a62ca1465",
6
+ "metadata": {},
7
+ "source": [
8
+ "### Load all required modules for loading data, model setup, training, and metric evaluation"
9
+ ]
10
+ },
11
+ {
12
+ "cell_type": "code",
13
+ "execution_count": 1,
14
+ "id": "2554d05b-f08a-4c21-953f-4f507407e426",
15
+ "metadata": {},
16
+ "outputs": [],
17
+ "source": [
18
+ "import sys\n",
19
+ "import os\n",
20
+ "sys.path.append(os.path.abspath(os.path.join(os.getcwd(), \"..\", \"src\")))\n",
21
+ "from data_loader import load_and_prepare_data \n",
22
+ "from model import get_model, get_tokenizer \n",
23
+ "from train import get_training_args, train_model \n",
24
+ "from evaluate import compute_metrics \n",
25
+ "from torch.utils.data import Dataset \n",
26
+ "import torch"
27
+ ]
28
+ },
29
+ {
30
+ "cell_type": "markdown",
31
+ "id": "3bfbb706-4b0b-43de-a95a-884d46343668",
32
+ "metadata": {},
33
+ "source": [
34
+ "### Define a class that wraps tokenized data and labels for Hugging Face’s Trainer to use"
35
+ ]
36
+ },
37
+ {
38
+ "cell_type": "code",
39
+ "execution_count": 3,
40
+ "id": "c814c354-7962-4a2d-b7bd-5c498f1d004e",
41
+ "metadata": {},
42
+ "outputs": [],
43
+ "source": [
44
+ "class EmotionDataset(Dataset):\n",
45
+ " def __init__(self, encodings, labels):\n",
46
+ " self.encodings = encodings # BERT tokenized inputs (input_ids, attention_mask)\n",
47
+ " self.labels = labels # Encoded labels (integers)\n",
48
+ "\n",
49
+ " def __len__(self):\n",
50
+ " return len(self.labels) # Total number of samples\n",
51
+ "\n",
52
+ " def __getitem__(self, idx):\n",
53
+ " # Return dictionary of input tensors + label tensor for a single sample\n",
54
+ " return {\n",
55
+ " key: torch.tensor(val[idx]) for key, val in self.encodings.items()\n",
56
+ " } | {\"labels\": torch.tensor(self.labels[idx])}"
57
+ ]
58
+ },
59
+ {
60
+ "cell_type": "markdown",
61
+ "id": "f9b87257-f0c0-4532-9eee-939d8747ef79",
62
+ "metadata": {},
63
+ "source": [
64
+ "### Load the dataset from Hugging Face, clean and encode it, then tokenize it using the BERT tokenizer."
65
+ ]
66
+ },
67
+ {
68
+ "cell_type": "code",
69
+ "execution_count": 5,
70
+ "id": "18e312be-5863-4e24-900a-843e42e145cc",
71
+ "metadata": {},
72
+ "outputs": [],
73
+ "source": [
74
+ "# Load train/test splits and label encoder\n",
75
+ "train_texts, test_texts, train_labels, test_labels, label_encoder = load_and_prepare_data()\n",
76
+ "\n",
77
+ "# Load BERT tokenizer\n",
78
+ "tokenizer = get_tokenizer()\n",
79
+ "\n",
80
+ "# Tokenize training and testing texts with truncation and padding\n",
81
+ "train_encodings = tokenizer(train_texts, truncation=True, padding=True, max_length=128)\n",
82
+ "test_encodings = tokenizer(test_texts, truncation=True, padding=True, max_length=128)\n",
83
+ "\n",
84
+ "# Wrap the tokenized data into EmotionDataset objects\n",
85
+ "train_dataset = EmotionDataset(train_encodings, train_labels)\n",
86
+ "test_dataset = EmotionDataset(test_encodings, test_labels)"
87
+ ]
88
+ },
89
+ {
90
+ "cell_type": "markdown",
91
+ "id": "66b99b4e-5297-4bc0-8cfb-20dbe22526c0",
92
+ "metadata": {},
93
+ "source": [
94
+ "### Samples from the dataset"
95
+ ]
96
+ },
97
+ {
98
+ "cell_type": "code",
99
+ "execution_count": 7,
100
+ "id": "35db4426-db21-4438-ba0e-ebb51d52edfb",
101
+ "metadata": {},
102
+ "outputs": [
103
+ {
104
+ "name": "stdout",
105
+ "output_type": "stream",
106
+ "text": [
107
+ "Sample 1\n",
108
+ "Text: i'd just feel less out of place, i guess. my sa makes me feel like i'm so behind my peers in terms of a social life\n",
109
+ "Label (encoded): 9\n",
110
+ "\n",
111
+ "Sample 2\n",
112
+ "Text: i love the lady in the green jacket chasing after the second car looking back at the first car like \"look what you did\"\n",
113
+ "Label (encoded): 18\n",
114
+ "\n",
115
+ "Sample 3\n",
116
+ "Text: man. really bad last possession there. bummer.\n",
117
+ "Label (encoded): 10\n",
118
+ "\n",
119
+ "Sample 4\n",
120
+ "Text: never would’ve guessed that one.\n",
121
+ "Label (encoded): 20\n",
122
+ "\n",
123
+ "Sample 5\n",
124
+ "Text: i wasn’t even expecting the reply that’s why i’m literally bamboozled.\n",
125
+ "Label (encoded): 27\n",
126
+ "\n"
127
+ ]
128
+ }
129
+ ],
130
+ "source": [
131
+ "for i in range(5):\n",
132
+ " print(f\"Sample {i+1}\")\n",
133
+ " print(f\"Text: {train_texts[i]}\")\n",
134
+ " print(f\"Label (encoded): {train_labels[i]}\")\n",
135
+ " print()"
136
+ ]
137
+ },
138
+ {
139
+ "cell_type": "markdown",
140
+ "id": "0883760a-a449-42ca-ba69-fa01d874e50b",
141
+ "metadata": {},
142
+ "source": [
143
+ "### Set up the BERT model for sequence classification and define training parameters."
144
+ ]
145
+ },
146
+ {
147
+ "cell_type": "code",
148
+ "execution_count": 9,
149
+ "id": "3176ccf4-d20d-460c-b620-c73a1ab9cb6d",
150
+ "metadata": {},
151
+ "outputs": [
152
+ {
153
+ "name": "stderr",
154
+ "output_type": "stream",
155
+ "text": [
156
+ "Some weights of BertForSequenceClassification were not initialized from the model checkpoint at bert-base-uncased and are newly initialized: ['classifier.bias', 'classifier.weight']\n",
157
+ "You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n",
158
+ "/opt/anaconda3/lib/python3.12/site-packages/transformers/training_args.py:1545: FutureWarning: `evaluation_strategy` is deprecated and will be removed in version 4.46 of 🤗 Transformers. Use `eval_strategy` instead\n",
159
+ " warnings.warn(\n"
160
+ ]
161
+ }
162
+ ],
163
+ "source": [
164
+ "# Load pre-trained BERT model with classification head for number of emotion classes\n",
165
+ "model = get_model(num_labels=len(label_encoder.classes_))\n",
166
+ "\n",
167
+ "# Set training configuration: batch size, epochs, logging, saving, evaluation\n",
168
+ "training_args = get_training_args()"
169
+ ]
170
+ },
171
+ {
172
+ "cell_type": "markdown",
173
+ "id": "874a4e6a-80dd-470d-9283-e1c88e731b8e",
174
+ "metadata": {},
175
+ "source": [
176
+ "### Train the Model "
177
+ ]
178
+ },
179
+ {
180
+ "cell_type": "code",
181
+ "execution_count": 13,
182
+ "id": "4c312e56-52bf-417d-82c0-8a1f47b82670",
183
+ "metadata": {},
184
+ "outputs": [
185
+ {
186
+ "data": {
187
+ "text/html": [
188
+ "\n",
189
+ " <div>\n",
190
+ " \n",
191
+ " <progress value='5448' max='5448' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
192
+ " [5448/5448 1:46:28, Epoch 3/3]\n",
193
+ " </div>\n",
194
+ " <table border=\"1\" class=\"dataframe\">\n",
195
+ " <thead>\n",
196
+ " <tr style=\"text-align: left;\">\n",
197
+ " <th>Epoch</th>\n",
198
+ " <th>Training Loss</th>\n",
199
+ " <th>Validation Loss</th>\n",
200
+ " <th>Accuracy</th>\n",
201
+ " <th>F1</th>\n",
202
+ " </tr>\n",
203
+ " </thead>\n",
204
+ " <tbody>\n",
205
+ " <tr>\n",
206
+ " <td>1</td>\n",
207
+ " <td>1.358900</td>\n",
208
+ " <td>1.335635</td>\n",
209
+ " <td>0.613467</td>\n",
210
+ " <td>0.579882</td>\n",
211
+ " </tr>\n",
212
+ " <tr>\n",
213
+ " <td>2</td>\n",
214
+ " <td>0.947100</td>\n",
215
+ " <td>1.284574</td>\n",
216
+ " <td>0.615671</td>\n",
217
+ " <td>0.601428</td>\n",
218
+ " </tr>\n",
219
+ " <tr>\n",
220
+ " <td>3</td>\n",
221
+ " <td>0.970400</td>\n",
222
+ " <td>1.297894</td>\n",
223
+ " <td>0.617048</td>\n",
224
+ " <td>0.606042</td>\n",
225
+ " </tr>\n",
226
+ " </tbody>\n",
227
+ "</table><p>"
228
+ ],
229
+ "text/plain": [
230
+ "<IPython.core.display.HTML object>"
231
+ ]
232
+ },
233
+ "metadata": {},
234
+ "output_type": "display_data"
235
+ },
236
+ {
237
+ "data": {
238
+ "text/html": [
239
+ "\n",
240
+ " <div>\n",
241
+ " \n",
242
+ " <progress value='5448' max='5448' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
243
+ " [5448/5448 1:35:20, Epoch 3/3]\n",
244
+ " </div>\n",
245
+ " <table border=\"1\" class=\"dataframe\">\n",
246
+ " <thead>\n",
247
+ " <tr style=\"text-align: left;\">\n",
248
+ " <th>Epoch</th>\n",
249
+ " <th>Training Loss</th>\n",
250
+ " <th>Validation Loss</th>\n",
251
+ " <th>Accuracy</th>\n",
252
+ " <th>F1</th>\n",
253
+ " </tr>\n",
254
+ " </thead>\n",
255
+ " <tbody>\n",
256
+ " <tr>\n",
257
+ " <td>1</td>\n",
258
+ " <td>0.907200</td>\n",
259
+ " <td>1.365916</td>\n",
260
+ " <td>0.602313</td>\n",
261
+ " <td>0.595804</td>\n",
262
+ " </tr>\n",
263
+ " <tr>\n",
264
+ " <td>2</td>\n",
265
+ " <td>0.549100</td>\n",
266
+ " <td>1.488130</td>\n",
267
+ " <td>0.595566</td>\n",
268
+ " <td>0.591464</td>\n",
269
+ " </tr>\n",
270
+ " <tr>\n",
271
+ " <td>3</td>\n",
272
+ " <td>0.514400</td>\n",
273
+ " <td>1.593286</td>\n",
274
+ " <td>0.591297</td>\n",
275
+ " <td>0.589066</td>\n",
276
+ " </tr>\n",
277
+ " </tbody>\n",
278
+ "</table><p>"
279
+ ],
280
+ "text/plain": [
281
+ "<IPython.core.display.HTML object>"
282
+ ]
283
+ },
284
+ "metadata": {},
285
+ "output_type": "display_data"
286
+ },
287
+ {
288
+ "data": {
289
+ "text/plain": [
290
+ "TrainOutput(global_step=5448, training_loss=0.7054264770818002, metrics={'train_runtime': 5721.3012, 'train_samples_per_second': 15.23, 'train_steps_per_second': 0.952, 'total_flos': 5733080823638016.0, 'train_loss': 0.7054264770818002, 'epoch': 3.0})"
291
+ ]
292
+ },
293
+ "execution_count": 13,
294
+ "metadata": {},
295
+ "output_type": "execute_result"
296
+ }
297
+ ],
298
+ "source": [
299
+ "trainer = train_model(\n",
300
+ " model=model,\n",
301
+ " args=training_args,\n",
302
+ " train_dataset=train_dataset,\n",
303
+ " val_dataset=test_dataset,\n",
304
+ " compute_metrics=compute_metrics\n",
305
+ ")\n",
306
+ "\n",
307
+ "# Begin training\n",
308
+ "trainer.train()"
309
+ ]
310
+ },
311
+ {
312
+ "cell_type": "markdown",
313
+ "id": "020729b6-c545-42ba-bd2c-00ee5f9bbb80",
314
+ "metadata": {},
315
+ "source": [
316
+ "### Save both model weights and tokenizer files for future inference or deployment."
317
+ ]
318
+ },
319
+ {
320
+ "cell_type": "code",
321
+ "execution_count": 23,
322
+ "id": "5f12aedb-b3f8-4a1b-8e1f-6a68eb29933f",
323
+ "metadata": {},
324
+ "outputs": [
325
+ {
326
+ "data": {
327
+ "text/plain": [
328
+ "('../outputs/model/tokenizer_config.json',\n",
329
+ " '../outputs/model/special_tokens_map.json',\n",
330
+ " '../outputs/model/vocab.txt',\n",
331
+ " '../outputs/model/added_tokens.json')"
332
+ ]
333
+ },
334
+ "execution_count": 23,
335
+ "metadata": {},
336
+ "output_type": "execute_result"
337
+ }
338
+ ],
339
+ "source": [
340
+ "from pathlib import Path\n",
341
+ "model_path = Path(\"..\") / \"outputs\" / \"model\"\n",
342
+ "model.save_pretrained(model_path)\n",
343
+ "tokenizer.save_pretrained(model_path)"
344
+ ]
345
+ }
346
+ ],
347
+ "metadata": {
348
+ "kernelspec": {
349
+ "display_name": "Python 3 (ipykernel)",
350
+ "language": "python",
351
+ "name": "python3"
352
+ },
353
+ "language_info": {
354
+ "codemirror_mode": {
355
+ "name": "ipython",
356
+ "version": 3
357
+ },
358
+ "file_extension": ".py",
359
+ "mimetype": "text/x-python",
360
+ "name": "python",
361
+ "nbconvert_exporter": "python",
362
+ "pygments_lexer": "ipython3",
363
+ "version": "3.12.2"
364
+ }
365
+ },
366
+ "nbformat": 4,
367
+ "nbformat_minor": 5
368
+ }
notebooks/.ipynb_checkpoints/03_evaluation-checkpoint.ipynb ADDED
The diff for this file is too large to render. See raw diff
 
notebooks/.ipynb_checkpoints/04_model_comparison-checkpoint.ipynb ADDED
@@ -0,0 +1,290 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": 1,
6
+ "id": "4032a920-2db8-4977-8b4f-a5a771dd022f",
7
+ "metadata": {},
8
+ "outputs": [],
9
+ "source": [
10
+ "import sys\n",
11
+ "import os\n",
12
+ "\n",
13
+ "project_root = os.path.abspath(os.path.join(os.getcwd(), \"..\"))\n",
14
+ "sys.path.append(project_root)\n",
15
+ "\n",
16
+ "from transformers import pipeline\n",
17
+ "from src.model_hartmann import load_model as load_hartmann_model, load_tokenizer as load_hartmann_tokenizer\n",
18
+ "from src.model_custom import load_model as load_custom_model, load_tokenizer as load_custom_tokenizer"
19
+ ]
20
+ },
21
+ {
22
+ "cell_type": "code",
23
+ "execution_count": 2,
24
+ "id": "525cf57e-4ec3-40fd-aca2-0e9700a73298",
25
+ "metadata": {},
26
+ "outputs": [],
27
+ "source": [
28
+ "hartmann_model = load_hartmann_model()\n",
29
+ "hartmann_tokenizer = load_hartmann_tokenizer()\n",
30
+ "\n",
31
+ "custom_model = load_custom_model()\n",
32
+ "custom_tokenizer = load_custom_tokenizer()"
33
+ ]
34
+ },
35
+ {
36
+ "cell_type": "code",
37
+ "execution_count": 3,
38
+ "id": "04f9415c-3d4f-4ac0-8f51-74ec4bd64293",
39
+ "metadata": {},
40
+ "outputs": [
41
+ {
42
+ "name": "stderr",
43
+ "output_type": "stream",
44
+ "text": [
45
+ "Hardware accelerator e.g. GPU is available in the environment, but no `device` argument is passed to the `Pipeline` object. Model will be on CPU.\n",
46
+ "/opt/anaconda3/lib/python3.12/site-packages/transformers/pipelines/text_classification.py:104: UserWarning: `return_all_scores` is now deprecated, if want a similar functionality use `top_k=None` instead of `return_all_scores=True` or `top_k=1` instead of `return_all_scores=False`.\n",
47
+ " warnings.warn(\n",
48
+ "Hardware accelerator e.g. GPU is available in the environment, but no `device` argument is passed to the `Pipeline` object. Model will be on CPU.\n"
49
+ ]
50
+ }
51
+ ],
52
+ "source": [
53
+ "# Create pipelines for easy predictions\n",
54
+ "hartmann_pipeline = pipeline(\"text-classification\", model=hartmann_model, tokenizer=hartmann_tokenizer, return_all_scores=True)\n",
55
+ "custom_pipeline = pipeline(\"text-classification\", model=custom_model, tokenizer=custom_tokenizer, return_all_scores=True)"
56
+ ]
57
+ },
58
+ {
59
+ "cell_type": "code",
60
+ "execution_count": 4,
61
+ "id": "3fcdf650-3abc-42a6-b1fd-0129e49d1e68",
62
+ "metadata": {},
63
+ "outputs": [
64
+ {
65
+ "name": "stdout",
66
+ "output_type": "stream",
67
+ "text": [
68
+ "========= Sentence 1 ==========\n",
69
+ "Text: I love spending time with my family.\n",
70
+ "\n",
71
+ "--- Hartmann Model Top 3 Predictions ---\n",
72
+ "joy: 0.9883\n",
73
+ "sadness: 0.0067\n",
74
+ "disgust: 0.0013\n",
75
+ "\n",
76
+ "--- Pretrained Model Top 3 Predictions ---\n",
77
+ "love: 0.9536\n",
78
+ "joy: 0.0134\n",
79
+ "admiration: 0.0108\n",
80
+ "\n",
81
+ "\n",
82
+ "========= Sentence 2 ==========\n",
83
+ "Text: This is the worst day of my life.\n",
84
+ "\n",
85
+ "--- Hartmann Model Top 3 Predictions ---\n",
86
+ "disgust: 0.9805\n",
87
+ "anger: 0.0086\n",
88
+ "sadness: 0.0055\n",
89
+ "\n",
90
+ "--- Pretrained Model Top 3 Predictions ---\n",
91
+ "anger: 0.3353\n",
92
+ "surprise: 0.2010\n",
93
+ "disgust: 0.1235\n",
94
+ "\n",
95
+ "\n",
96
+ "========= Sentence 3 ==========\n",
97
+ "Text: I'm feeling very nervous about the exam.\n",
98
+ "\n",
99
+ "--- Hartmann Model Top 3 Predictions ---\n",
100
+ "fear: 0.9947\n",
101
+ "sadness: 0.0013\n",
102
+ "joy: 0.0011\n",
103
+ "\n",
104
+ "--- Pretrained Model Top 3 Predictions ---\n",
105
+ "nervousness: 0.6201\n",
106
+ "fear: 0.0828\n",
107
+ "embarrassment: 0.0393\n",
108
+ "\n",
109
+ "\n",
110
+ "========= Sentence 4 ==========\n",
111
+ "Text: What a beautiful sunset!\n",
112
+ "\n",
113
+ "--- Hartmann Model Top 3 Predictions ---\n",
114
+ "joy: 0.8377\n",
115
+ "surprise: 0.1189\n",
116
+ "neutral: 0.0221\n",
117
+ "\n",
118
+ "--- Pretrained Model Top 3 Predictions ---\n",
119
+ "admiration: 0.8548\n",
120
+ "excitement: 0.0729\n",
121
+ "joy: 0.0351\n",
122
+ "\n",
123
+ "\n",
124
+ "========= Sentence 5 ==========\n",
125
+ "Text: I feel so disappointed and frustrated with the situation.\n",
126
+ "\n",
127
+ "--- Hartmann Model Top 3 Predictions ---\n",
128
+ "sadness: 0.9310\n",
129
+ "anger: 0.0381\n",
130
+ "disgust: 0.0158\n",
131
+ "\n",
132
+ "--- Pretrained Model Top 3 Predictions ---\n",
133
+ "disappointment: 0.5645\n",
134
+ "annoyance: 0.1864\n",
135
+ "anger: 0.0736\n",
136
+ "\n",
137
+ "\n",
138
+ "========= Sentence 6 ==========\n",
139
+ "Text: I'm not sure how to feel about this.\n",
140
+ "\n",
141
+ "--- Hartmann Model Top 3 Predictions ---\n",
142
+ "neutral: 0.5698\n",
143
+ "disgust: 0.2213\n",
144
+ "sadness: 0.0720\n",
145
+ "\n",
146
+ "--- Pretrained Model Top 3 Predictions ---\n",
147
+ "confusion: 0.9011\n",
148
+ "optimism: 0.0230\n",
149
+ "disapproval: 0.0223\n",
150
+ "\n",
151
+ "\n",
152
+ "========= Sentence 7 ==========\n",
153
+ "Text: That was hilarious, I can't stop laughing!\n",
154
+ "\n",
155
+ "--- Hartmann Model Top 3 Predictions ---\n",
156
+ "joy: 0.9336\n",
157
+ "surprise: 0.0306\n",
158
+ "neutral: 0.0178\n",
159
+ "\n",
160
+ "--- Pretrained Model Top 3 Predictions ---\n",
161
+ "amusement: 0.9551\n",
162
+ "joy: 0.0286\n",
163
+ "optimism: 0.0032\n",
164
+ "\n",
165
+ "\n",
166
+ "========= Sentence 8 ==========\n",
167
+ "Text: I feel completely empty and lost.\n",
168
+ "\n",
169
+ "--- Hartmann Model Top 3 Predictions ---\n",
170
+ "sadness: 0.9808\n",
171
+ "neutral: 0.0086\n",
172
+ "disgust: 0.0051\n",
173
+ "\n",
174
+ "--- Pretrained Model Top 3 Predictions ---\n",
175
+ "surprise: 0.8055\n",
176
+ "disappointment: 0.1067\n",
177
+ "optimism: 0.0222\n",
178
+ "\n",
179
+ "\n",
180
+ "========= Sentence 9 ==========\n",
181
+ "Text: Your help means a lot to me, thank you!\n",
182
+ "\n",
183
+ "--- Hartmann Model Top 3 Predictions ---\n",
184
+ "joy: 0.9760\n",
185
+ "neutral: 0.0104\n",
186
+ "surprise: 0.0057\n",
187
+ "\n",
188
+ "--- Pretrained Model Top 3 Predictions ---\n",
189
+ "gratitude: 0.9890\n",
190
+ "caring: 0.0014\n",
191
+ "sadness: 0.0009\n",
192
+ "\n",
193
+ "\n",
194
+ "========= Sentence 10 ==========\n",
195
+ "Text: I'm so angry I could scream.\n",
196
+ "\n",
197
+ "--- Hartmann Model Top 3 Predictions ---\n",
198
+ "anger: 0.9785\n",
199
+ "fear: 0.0084\n",
200
+ "neutral: 0.0047\n",
201
+ "\n",
202
+ "--- Pretrained Model Top 3 Predictions ---\n",
203
+ "anger: 0.9155\n",
204
+ "annoyance: 0.0223\n",
205
+ "optimism: 0.0082\n",
206
+ "\n",
207
+ "\n"
208
+ ]
209
+ }
210
+ ],
211
+ "source": [
212
+ "from tabulate import tabulate\n",
213
+ "\n",
214
+ "goemotions_labels = [\n",
215
+ " \"admiration\", \"amusement\", \"anger\", \"annoyance\", \"approval\", \"caring\", \"confusion\", \"curiosity\",\n",
216
+ " \"desire\", \"disappointment\", \"disapproval\", \"disgust\", \"embarrassment\", \"excitement\", \"fear\",\n",
217
+ " \"gratitude\", \"grief\", \"joy\", \"love\", \"nervousness\", \"optimism\", \"pride\", \"realization\", \"relief\",\n",
218
+ " \"remorse\", \"sadness\", \"surprise\", \"neutral\"\n",
219
+ "]\n",
220
+ "\n",
221
+ "\n",
222
+ "# Your 10 test sentences\n",
223
+ "sentences = [\n",
224
+ " \"I love spending time with my family.\",\n",
225
+ " \"This is the worst day of my life.\",\n",
226
+ " \"I'm feeling very nervous about the exam.\",\n",
227
+ " \"What a beautiful sunset!\",\n",
228
+ " \"I feel so disappointed and frustrated with the situation.\",\n",
229
+ " \"I'm not sure how to feel about this.\",\n",
230
+ " \"That was hilarious, I can't stop laughing!\",\n",
231
+ " \"I feel completely empty and lost.\",\n",
232
+ " \"Your help means a lot to me, thank you!\",\n",
233
+ " \"I'm so angry I could scream.\"\n",
234
+ "]\n",
235
+ "\n",
236
+ "# Loop over sentences and collect results\n",
237
+ "for i, sentence in enumerate(sentences):\n",
238
+ " print(f\"========= Sentence {i+1} ==========\")\n",
239
+ " print(f\"Text: {sentence}\\n\")\n",
240
+ "\n",
241
+ " # Get predictions\n",
242
+ " hartmann_results = hartmann_pipeline(sentence, return_all_scores=True)\n",
243
+ " custom_results = custom_pipeline(sentence, return_all_scores=True)\n",
244
+ "\n",
245
+ " # Unwrap the list to get the actual results\n",
246
+ " hartmann_results = hartmann_results[0]\n",
247
+ " custom_results = custom_results[0]\n",
248
+ "\n",
249
+ " # Sort and get top 3 predictions for each\n",
250
+ " hartmann_top3 = sorted(hartmann_results, key=lambda x: x['score'], reverse=True)[:3]\n",
251
+ " custom_top3 = sorted(custom_results, key=lambda x: x['score'], reverse=True)[:3]\n",
252
+ "\n",
253
+ " # Display Hartmann predictions\n",
254
+ " print(\"--- Hartmann Model Top 3 Predictions ---\")\n",
255
+ " for res in hartmann_top3:\n",
256
+ " print(f\"{res['label']}: {res['score']:.4f}\")\n",
257
+ "\n",
258
+ " # Display Custom Model predictions\n",
259
+ " print(\"\\n--- Pretrained Model Top 3 Predictions ---\")\n",
260
+ " for res in custom_top3:\n",
261
+ " label_idx = int(res['label'].split(\"_\")[-1])\n",
262
+ " emotion = goemotions_labels[label_idx]\n",
263
+ " print(f\"{emotion}: {res['score']:.4f}\")\n",
264
+ "\n",
265
+ " print(\"\\n\")\n"
266
+ ]
267
+ }
268
+ ],
269
+ "metadata": {
270
+ "kernelspec": {
271
+ "display_name": "Python 3 (ipykernel)",
272
+ "language": "python",
273
+ "name": "python3"
274
+ },
275
+ "language_info": {
276
+ "codemirror_mode": {
277
+ "name": "ipython",
278
+ "version": 3
279
+ },
280
+ "file_extension": ".py",
281
+ "mimetype": "text/x-python",
282
+ "name": "python",
283
+ "nbconvert_exporter": "python",
284
+ "pygments_lexer": "ipython3",
285
+ "version": "3.12.2"
286
+ }
287
+ },
288
+ "nbformat": 4,
289
+ "nbformat_minor": 5
290
+ }
notebooks/01_exploration.ipynb ADDED
@@ -0,0 +1,358 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": 1,
6
+ "id": "ec88103e-4da3-4eb9-9ed5-8aab3f7745a5",
7
+ "metadata": {},
8
+ "outputs": [],
9
+ "source": [
10
+ "from datasets import load_dataset\n",
11
+ "\n",
12
+ "dataset = load_dataset(\"go_emotions\")"
13
+ ]
14
+ },
15
+ {
16
+ "cell_type": "code",
17
+ "execution_count": 2,
18
+ "id": "9e38e4c1-5c32-4e1b-8612-e723645e34bb",
19
+ "metadata": {},
20
+ "outputs": [],
21
+ "source": [
22
+ "import pandas as pd\n",
23
+ "import matplotlib.pyplot as plt\n",
24
+ "from collections import Counter"
25
+ ]
26
+ },
27
+ {
28
+ "cell_type": "markdown",
29
+ "id": "169cb7bc-8ac6-41d4-a109-c30ca1688899",
30
+ "metadata": {},
31
+ "source": [
32
+ "### Converting the dataset to a dataframe for ease"
33
+ ]
34
+ },
35
+ {
36
+ "cell_type": "code",
37
+ "execution_count": 4,
38
+ "id": "fadfe4cd-e0a3-4f09-a411-56db306fbd0b",
39
+ "metadata": {},
40
+ "outputs": [
41
+ {
42
+ "data": {
43
+ "text/html": [
44
+ "<div>\n",
45
+ "<style scoped>\n",
46
+ " .dataframe tbody tr th:only-of-type {\n",
47
+ " vertical-align: middle;\n",
48
+ " }\n",
49
+ "\n",
50
+ " .dataframe tbody tr th {\n",
51
+ " vertical-align: top;\n",
52
+ " }\n",
53
+ "\n",
54
+ " .dataframe thead th {\n",
55
+ " text-align: right;\n",
56
+ " }\n",
57
+ "</style>\n",
58
+ "<table border=\"1\" class=\"dataframe\">\n",
59
+ " <thead>\n",
60
+ " <tr style=\"text-align: right;\">\n",
61
+ " <th></th>\n",
62
+ " <th>text</th>\n",
63
+ " <th>labels</th>\n",
64
+ " <th>id</th>\n",
65
+ " </tr>\n",
66
+ " </thead>\n",
67
+ " <tbody>\n",
68
+ " <tr>\n",
69
+ " <th>0</th>\n",
70
+ " <td>My favourite food is anything I didn't have to...</td>\n",
71
+ " <td>[27]</td>\n",
72
+ " <td>eebbqej</td>\n",
73
+ " </tr>\n",
74
+ " <tr>\n",
75
+ " <th>1</th>\n",
76
+ " <td>Now if he does off himself, everyone will thin...</td>\n",
77
+ " <td>[27]</td>\n",
78
+ " <td>ed00q6i</td>\n",
79
+ " </tr>\n",
80
+ " <tr>\n",
81
+ " <th>2</th>\n",
82
+ " <td>WHY THE FUCK IS BAYLESS ISOING</td>\n",
83
+ " <td>[2]</td>\n",
84
+ " <td>eezlygj</td>\n",
85
+ " </tr>\n",
86
+ " <tr>\n",
87
+ " <th>3</th>\n",
88
+ " <td>To make her feel threatened</td>\n",
89
+ " <td>[14]</td>\n",
90
+ " <td>ed7ypvh</td>\n",
91
+ " </tr>\n",
92
+ " <tr>\n",
93
+ " <th>4</th>\n",
94
+ " <td>Dirty Southern Wankers</td>\n",
95
+ " <td>[3]</td>\n",
96
+ " <td>ed0bdzj</td>\n",
97
+ " </tr>\n",
98
+ " </tbody>\n",
99
+ "</table>\n",
100
+ "</div>"
101
+ ],
102
+ "text/plain": [
103
+ " text labels id\n",
104
+ "0 My favourite food is anything I didn't have to... [27] eebbqej\n",
105
+ "1 Now if he does off himself, everyone will thin... [27] ed00q6i\n",
106
+ "2 WHY THE FUCK IS BAYLESS ISOING [2] eezlygj\n",
107
+ "3 To make her feel threatened [14] ed7ypvh\n",
108
+ "4 Dirty Southern Wankers [3] ed0bdzj"
109
+ ]
110
+ },
111
+ "execution_count": 4,
112
+ "metadata": {},
113
+ "output_type": "execute_result"
114
+ }
115
+ ],
116
+ "source": [
117
+ "df = pd.DataFrame(dataset[\"train\"])\n",
118
+ "df.head()"
119
+ ]
120
+ },
121
+ {
122
+ "cell_type": "code",
123
+ "execution_count": 5,
124
+ "id": "20a1d0af-1cd6-45c9-8128-29be160713d4",
125
+ "metadata": {},
126
+ "outputs": [],
127
+ "source": [
128
+ "label_counts = Counter() # counts number of occurences\n",
129
+ "\n",
130
+ "# Looping through all label lists and counting each label's total occurrences\n",
131
+ "for labels in df[\"labels\"]:\n",
132
+ " label_counts.update(labels)"
133
+ ]
134
+ },
135
+ {
136
+ "cell_type": "code",
137
+ "execution_count": 6,
138
+ "id": "11c20083-c1a7-412d-9f98-e51defaded84",
139
+ "metadata": {},
140
+ "outputs": [],
141
+ "source": [
142
+ "# Mapping indices to label names\n",
143
+ "label_names = dataset[\"train\"].features[\"labels\"].feature.names\n",
144
+ "label_distribution = {label_names[i]: count for i, count in label_counts.items()}"
145
+ ]
146
+ },
147
+ {
148
+ "cell_type": "markdown",
149
+ "id": "967e6d78-3dec-4dc5-b035-8ff263e689c8",
150
+ "metadata": {},
151
+ "source": [
152
+ "### Plot for the number of occurences of each emotion in the training set"
153
+ ]
154
+ },
155
+ {
156
+ "cell_type": "code",
157
+ "execution_count": 8,
158
+ "id": "91e04be4-4132-4c78-8e4e-6d4c1b29fd6c",
159
+ "metadata": {},
160
+ "outputs": [
161
+ {
162
+ "data": {
163
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAABKUAAAJOCAYAAABm7rQwAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAAC+y0lEQVR4nOzdd3gUVf/+8XtJISEkS01CkN5DUYpCwK/0IiBig8dgAEEQUZCmwmOhqCCgFMUCitIULAiiYAARUQSkBqQLhqIQghASSkhCcn5/8Ms+LAkthpkF3q/r2uvKzpydvXezZfYzZ85xGGOMAAAAAAAAAAvlsTsAAAAAAAAAbj0UpQAAAAAAAGA5ilIAAAAAAACwHEUpAAAAAAAAWI6iFAAAAAAAACxHUQoAAAAAAACWoygFAAAAAAAAy1GUAgAAAAAAgOUoSgEAAAAAAMByFKUAALgFbNmyRd27d1e5cuXk7+8vf39/VahQQU8++aTWr1+fo21OmzZNDofjkpeffvopdx/EVVi0aJGGDRuW7brSpUura9eulua5WsOGDZPD4dA///zzr7e1b98+ORwOvfnmm7mQzH2b06ZNu6p2mRcfHx8VLlxYd955p/r3769t27Zluc1PP/2Uo9fLe++9d8U8V3NfXbt2Vf78+a9pO1eyatUqDRs2TCdOnMiyrlGjRmrUqFGu3h8AADcqb7sDAACA62vy5Ml65plnVKlSJT377LOqWrWqHA6HduzYodmzZ+vOO+/Unj17VK5cuRxt/5NPPlHlypWzLA8PD/+30a/ZokWL9O6772ZbmJo3b56CgoIsz3Qr6tOnjyIjI5WRkaETJ05o06ZN+vjjj/XOO+9o1KhReu6551xta9WqpdWrV1/z6+W9995TkSJFrqnQmNP7ularVq3S8OHD1bVrVxUoUMBt3XvvvXdd7xsAgBsJRSkAAG5iv/76q3r37q02bdroq6++kq+vr2tdkyZN9PTTT+vLL7+Uv79/ju+jWrVqqlOnTm7Eva5q1qxpd4RbRsmSJVWvXj3X9datW2vAgAF68MEH9fzzz6tatWq69957JUlBQUFuba+HtLQ0ORwOS+7rSuwo1gIA4Kk4fQ8AgJvYyJEj5eXlpcmTJ7sVpC70yCOPKCwszG3ZggULFBERoXz58ikwMFDNmzfX6tWrc5zD4XDomWee0SeffKJKlSrJ399fderU0Zo1a2SM0dixY1WmTBnlz59fTZo00Z49e7Js4+OPP9btt98uPz8/FSpUSA888IB27NjhWt+1a1e9++67rvvLvOzbt09S9qfvHThwQI899piCg4OVN29eValSRW+99ZYyMjJcbS48HW7cuHGunBEREVqzZo3b9v7880/95z//UVhYmPLmzauQkBA1bdpUMTExOX7uMh09elS9e/dWeHi48ufPr+DgYDVp0kS//PJLtu0zMjL0+uuvq2TJkvLz81OdOnW0bNmyLO3++OMPRUZGuj0Hmc9jbvL399fUqVPl4+OjsWPHupZnd0rdlZ7H0qVLa9u2bVqxYoXr/1y6dGm37c2cOVMDBw5U8eLFlTdvXu3Zs+eypwpu27ZNTZs2VUBAgIoWLapnnnlGZ86cca2/3CmMDofD1Ttv2LBhrp5gZcqUyXI6a3an7x0/fly9e/dW8eLF5evrq7Jly+rFF19USkpKlvt55plnNHPmTFWpUkX58uXT7bffru++++7K/wAAADwQPaUAALhJpaena/ny5apTp46KFSt21bf77LPP1KlTJ7Vo0UKzZ89WSkqKxowZo0aNGmnZsmW6++67s9zPuXPn3JY5HA55eXm5Lfvuu++0adMmvfHGG3I4HHrhhRfUpk0bdenSRX/++acmTZqkxMREDRgwQA899JBiYmLkcDgkSaNGjdJ///tfPfrooxo1apSOHTumYcOGKSIiQuvWrVOFChX08ssv6/Tp0/rqq6/cCmiXeuxHjx5V/fr1lZqaqldffVWlS5fWd999p0GDBmnv3r1ZTrN69913VblyZU2YMEGS9PLLL6t169aKjY2V0+mUdL5HUHp6usaMGaOSJUvqn3/+0apVq7IdW+haHT9+XJI0dOhQhYaG6tSpU5o3b57r/3JxoWPSpEkqVaqUJkyYoIyMDI0ZM0b33nuvVqxYoYiICEnS9u3bVb9+fZUsWVJvvfWWQkNDtXjxYvXt21f//POPhg4d+q9zXygsLEy1a9fWqlWrdO7cOXl7Z78reqXncd68eXr44YfldDpd/6e8efO6bWPIkCGKiIjQBx98oDx58ig4OFhxcXHZ3l9aWppat26tJ598UoMHD9aqVav02muvaf/+/fr222+v6TE+8cQTOn78uN555x19/fXXrtffpXpInT17Vo0bN9bevXs1fPhw1ahRQ7/88otGjRql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euqpp1SxYsVryrllyxY988wzeuSRR1ShQgX5+vrqxx9/1JYtWzR48OCr2sa3337rNl5Qpocfflht27bVq6++qqFDh6phw4batWuXRowYoTJlymT7/Ht5eal58+YaMGCAMjIyNHr0aCUlJWn48OGuNhMnTtTdd9+t//u//9NTTz2l0qVL6+TJk9qzZ4++/fbbLONqXa0DBw5ozZo1ysjIUGJiojZt2qSPP/5Y+/fv11tvvaUWLVpc8rZX+zxWr15dc+bM0eeff66yZcvKz8/P9f+/Vr6+vnrrrbd06tQp3Xnnna7Z9+69917XbJMOh0OPPfaYPv74Y5UrV06333671q5d6ypeXSgzx8SJE9WlSxf5+PioUqVK2f5vO3furHfffVddunTRvn37VL16da1cuVIjR45U69at1axZsxw9JgAAbgj2jrMOAACsEBMTYx5//HFTpkwZkzdvXuPn52fKly9vOnfubJYtW5al/fz5803dunWNn5+fCQgIME2bNjW//vqrW5vLzb4nyXz44YeutpLM008/7Xb7S83UljlD2pdffum2/KOPPjI1atQwvr6+xul0mvvvv99s27bNrU1KSop54oknTNGiRY3D4XCbAe3i2feMMWb//v0mMjLSFC5c2Pj4+JhKlSqZsWPHus08eLkZ5XTBrGtHjhwxXbt2NZUrVzYBAQEmf/78pkaNGmb8+PFus/ZlJ3P2vUtdMh/boEGDTPHixY2fn5+pVauWmT9/vunSpYspVapUlryjR482w4cPN7fddpvx9fU1NWvWNIsXL85y37GxsaZbt26mePHixsfHxxQtWtTUr1/fvPbaa1m2ebWz72VevLy8TMGCBU3t2rVNv379svy/jMk6I97VPo/79u0zLVq0MIGBgUaS6zm41Osnu/sy5vzsewEBAWbLli2mUaNGxt/f3xQqVMg89dRTbrNFGmNMYmKieeKJJ0xISIgJCAgw9913n9m3b1+W2feMMWbIkCEmLCzM5MmTx+0+L559zxhjjh07Znr16mWKFStmvL29TalSpcyQIUPM2bNn3dpl9z4yJvvXNgAANwKHMVeYAgUAAAAAAADIZYwpBQAAAAAAAMtRlAIAAAAAAIDlKEoBAAAAAADAchSlAAAAAAAAYDmKUgAAAAAAALAcRSkAAAAAAABYztvuADeTjIwMHTp0SIGBgXI4HHbHAQAA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fdq1a5fKli2rl19+Wfv377e9uLJixQrde++9atCggX7++Wft2LFDZcuW1ZgxY7R27Vp99dVXtmXz8vLS4cOHFRwc7Lb82LFjCg4OVnp6uk3JpIceekgLFy5UiRIl9Pjjj6tLly4qXry4bXmyc+7cOf3000/au3evIiMjFRgYqEOHDikoKEj58+e3LMeDDz541W2//vrr65jkytauXauffvop28+4cePG2ZTqvPz582vr1q0qXbq0rTkutnXrVn388cf69NNPlZKSoo4dO6p79+6666677I4myfO+uy7UokULPfjgg+rVq5dOnDihypUry8fHR//884/GjRunp556yrZsefLkUVxcXJbP3/j4eBUvXlxpaWk2JfNsW7ZsyXa5w+GQn5+fSpYsqbx581qc6n8yMjL0+uuv64MPPtCRI0e0e/du1z5J6dKl1b17d9uyXeo7/59//lFoaKjOnTtnUzLPfj948n5c8eLF9cMPP6hKlSq2ZbhRefI+cHJysowxypcvn6TzB1TmzZun8PBwtWjRwvI83t7eOnTokIKDgy/5vHma1NRUxcbGqly5cvL29rYlQ+HChbVo0SLVrVtXefLk0ZEjR1S0aFFbskiSPc8CXN5+++2rbtu3b9/rmOTynn32WU2bNk1t2rRRtWrVrrogdL20b9/e1vu/WgMGDFDXrl01ZswYBQYGupbfe++9ioyMtDHZeYMHD9Zrr72mAQMGuOVr3LixJk6caGMyyRiT7evsr7/+ktPptCHR/8ydO1fHjh3TrFmzNG3aNA0dOlTNmjVT9+7ddf/998vHx8fWfPv371erVq104MABpaSkqHnz5goMDNSYMWN09uxZffDBB5Zlsft/dbVGjhypl156SZUqVVJISIjba8/uzztJatasmX766Sd17drV7ihuqlWrpnHjxmnMmDH69ttvNW3aNN19992qUKGCunfvrqioKFt3cjztu+tCGzdu1Pjx4yVJX331lUJCQrRp0ybNnTtXr7zyii1FqQuLKtu3b1dcXJzrenp6uqKjoz2iAH/69Gm98cYblyw2/vnnn7bkuuOOOy77GvPx8VHHjh01efJk+fn5WZjsvNdee03Tp0/XmDFj1KNHD9fy6tWra/z48bYUpZKSkmSMkTFGJ0+edHte0tPTtWjRItt+YN4I7wdP3o/r06ePRo8erY8++si2H95Xsnfv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+uuv25pNOn9Ut2vXripevLiMMQoPD1d6eroiIyP10ksv2ZqtS5cuks4PBpjdmCF2nhderFgxZWRk6NFHH9XatWt1xx13ZGnTsmVLFShQwPJsktS8eXNNmDBBU6ZMkXS+J82pU6c0dOhQW09jevvtt/Xiiy+qS5cu+uabb/T4449r7969WrdunZ5++mnbcknSoEGD1KZNG5UrV07h4eEe9Rl3sbNnz9oyHk123n//fXXr1k2PP/64QkNDs21TsmRJTZ061eJk53nyd9fDDz+su+++W4cPH9btt9/uWt60aVM98MADtuXKtHv37ksO/G/3d+urr76qV155RdOnT3cNtusJKleurDfeeENTpkxx9VRNS0vTG2+8ocqVK0s631spJCTElnxDhw5VVFSU/v77b2VkZOjrr7/Wrl27NGPGDH333Xe2ZMpUqlQpnThxQmvXrs32Nde5c2ebkknTp09XkSJF1KZNG0nS888/rylTpig8PFyzZ89WqVKlbMvmyftxns6Te5k1bNhQGRkZ2r17d7bvh3vuucemZOc//yMjI9W/f381bdrU1XNryZIlqlmzpm25pPO/HU6cOKGZM2dq7969eu6551SoUCFt3LhRISEhtv9f77zzTi1cuFB9+vSR9L8xSz/88ENbe8AdP35cjzzyiJYvXy6Hw6E//vhDZcuW1RNPPKECBQrorbfeuu4ZGFPKgyxbtkzt2rVTmTJltGvXLlWrVk379u2TMUa1atWydZagxx9//LLrP/nkE4uSZFWuXDm9/fbbatOmjQIDAxUTE+NatmbNGn322We2Zcv0448/auPGjcrIyFCtWrXUrFkzuyO5+fPPP135atasadtYSBf6448/1K1bN61atcptufGA88JnzpypRx55xGMKAxc7dOiQGjduLC8vL/3xxx+qU6eO/vjjDxUpUkQ///yzbYPGVq5cWUOHDtWjjz7qNvbFK6+8ouPHj2vSpEm25JKkp59+WlOnTlXjxo2zDHQu2fsZJ50fS2LkyJEeOWuWJ/Pk766LJSUl6ccff1SlSpVsn63qww8/1FNPPaUiRYooNDQ0y8D/ds5qK50fe3Dv3r0yxqh06dJZio125Vu1apXatWunPHnyqEaNGnI4HNqyZYvS09P13XffqV69epo5c6bi4uL03HPP2ZJx8eLFGjlypDZs2ODaJ3nllVdsmTXrQt9++606deqk06dPKzAwMMtr7vjx47Zlq1Spkt5//301adJEq1evVtOmTTVhwgR999138vb2tq24bYzRgQMHVLRoUcXFxXncfpx0fhKHL774ItuD7XZ/jjz//PNavXq1vvzyS1WsWFEbN27UkSNH1LlzZ3Xu3FlDhw61LduaNWsUGRmp/fv3ZxnPzO59YEmKi4tzHVDJkyePpPMzGAcFBbkK8Hbw9FnPV61apVatWqlTp06aNm2annzySW3btk2rV6/WihUrVLt2bVtyde7cWfHx8froo49UpUoV1/75kiVL1L9/f23btu26Z6Ao5UHuuusutWrVyjXQ2ObNmxUcHKxOnTqpVatWtk4P7ckCAgK0Y8cOlSxZUsWKFdPChQtVq1Yt/fnnn6pZs6YSExPtjogcaNCggby9vTV48OBsB7K9sGeB1bp166aJEydmOff69OnT6tOnjz7++GObkv1PcnKyZs+e7VYM7dSpk/z9/W3LlC9fPu3YsUOlSpVScHCwli5dqttvv11//PGH6tWrp2PHjtmWLTAwUHPmzHEdCfc0I0aM0PTp0zVixAj16NFDW7duVdmyZfXFF19o/PjxWr16tW3ZTpw4oalTp2rHjh1yOByqUqWKunfvfsPMvGiXDh066J577tEzzzyj5ORk3X777a4DUXPmzLF1LJZSpUqpd+/eeuGFF2zLcDnDhw+/7Ho7f0yeOnVKs2bN0u7du2WMUeXKlRUZGWnvWB03gIoVK6p169YaOXKkR/V+k9wnJXjhhRd0+PBhzZgxQ9u2bVOjRo109OhRW3JlZGTIz89P27Zt85gi1IUu7B394YcfZukdbfcZA2lpaeratavmzJkjY4y8vb1dvcymTZtm63hhd9xxhypWrKjhw4dnuw/sSd+vnnRApWnTpqpdu7Zr1vPM4sqqVasUGRmpffv22ZpPkn7//Xe9+eabbgcGXnjhBVWvXt22TKGhoVq8eLFuv/12t+ctNjZW1atX16lTp65/CMtOFMQV5c+f3+zZs8cYY0yBAgXM1q1bjTHnzzMtVaqUjcn+Jz4+3vzyyy9m5cqVJj4+3u44xhhjKlasaNasWWOMMebuu+82o0aNMsYYM2fOHFO0aFHL80ycOPGqL3Z76KGHXM/XhcaMGWMefvhhGxL9T758+bIdm8MT5MmTxxw5ciTL8qNHj9o2ds6FTp8+bXeEbJUpU8Zs2LDBGGNMnTp1zAcffGCMMWbx4sW2j/9WsmRJj329GWNMuXLlzA8//GCMcR+HYMeOHbaNXWaMMevWrTOFChUyxYsXNw888IBp3769ue2220zhwoVd/2tP4InfXSEhISYmJsYYY8ynn35qypcvb06fPm3ee+89c8cdd9iaLTAw0PUaw83jwIED5uDBg67rv/32m3n22WfN5MmTbUx1Xr58+Tz2NVe0aFGzceNGY4wxd9xxh5k+fboxxpg9e/aYgIAAO6OZ8PBws3r1alszXEqlSpXMZ599Zoxx/956+eWXzdNPP21nNDd79+41X375pfn888/N7t277Y5jjDn/fvjjjz/sjpGtRx55xLzzzjvGGGPOnDljKlSoYHx8fIy3t7f56quvbM0WFBTk+i194Wtu3759to8T5sny58/veu1f+LytXbvWFCpUyJIMFKU8SEhIiGtw4vDwcPPNN98YY84Xpez+0jt16pR5/PHHjZeXl3E4HMbhcBhvb2/TrVs3238Av/DCC+b11183xpwfONbb29uUL1/e+Pr6mhdeeMHyPKVLl3a7BAQEGIfD4Rp43eFwmICAAFOmTBnLs12sSJEiZsuWLVmWb9myxfYBsevUqWN++eUXWzNcLDEx0Zw4ccI4HA6zZ88ek5iY6LocP37cTJ8+3RQrVszumCYgIMB06tTJREdHe9TAsd27d3cNvPr+++8bf39/06xZM1OgQAHTrVs3W7N9/PHHpkOHDrZ/nl2Kn5+f2bdvnzHGfYdh27Zttn4/3H333aZr164mLS3NtSwtLc106dLF/N///Z9tuTJ58neXn5+fOXDggDHGmKioKNf31f79+23/zu/WrZt5//33bc1wNdavX29mzpxpZs2a5Soa2G3Xrl1m8uTJ5tVXXzXDhw93u9jt7rvvNjNmzDDGGNfA2BEREaZw4cK253vggQfM559/bmuGS4mMjDS1atUy3bt3N/ny5TP//POPMcaYb775xlStWtXWbN999525++67ze+//25rjuz4+/u7vreKFi3qKsLv3r3bsh+61+LcuXNm06ZN5vjx43ZHMY0bNzbff/+93TGy5ckHVIKDg13fBRfuKy1evNjcdttttmS68LfClS52ad26tXnppZeMMcY1MVd6erp55JFHzEMPPWRJBopSHuT+++83U6ZMMcacn02jfPny5rXXXjO1atUyTZs2tTVbz549TdmyZc2iRYtcb5yFCxeacuXKmV69etma7WJr1qwxb731lquoZ6dPP/3UNGjQwOzcudO1bOfOneb//u//zKxZs2xMdp6fn59btkwXzhRkl2XLlpmIiAizfPly888//3jEB7fD4TB58uS55MXLy8u89tprtmS70Ny5c83DDz9s/P39TUhIiOnbt69Zu3at3bFMenq6W/Hi888/N3369DETJ040KSkpNiY7f/Q7MDDQ5M+f31SrVs2jZgY0xnNnzbrUbGPbtm2zbYaxC3nyd1eFChXM559/bk6dOmWKFi1qli1bZow5fyCqcOHCtmYbOXKkKVKkiOnSpYt58803Pa6X75EjR0zjxo1dB3wKFChgHA6HadKkia094aZMmWK8vLxMSEiIuf32280dd9zhunjC50iBAgVc3/kTJ0409evXN8ac/8Fm94Gyjz76yJQsWdIMHTrUfPXVV+abb75xu9gpISHBPP3006Zdu3ZuhYJXXnnF9u/8AgUKGF9fX5MnTx7j5+fnUTNQe3LvaGOMefbZZ81HH31kjDlfkGrQoIHrwPHy5cttzfb111+b8PBw88knn5j169ebzZs3u13s5MkHVDxx1vMr/Xa48GKXbdu2maJFi5pWrVoZX19f8/DDD5sqVaqYkJAQV8+z640xpTzIn3/+qVOnTqlGjRo6c+aMBg0apJUrV6p8+fIaP368rbN7FClSRF999ZUaNWrktnz58uXq0KGDbefTS9KZM2c8bvyBTOXKldNXX32VZTaKDRs26OGHH1ZsbKxNyc678847dd9992WZSWnYsGH69ttvtWHDBpuSyTVw4sXn0RsbBzpfsWKFjDFq0qSJ5s6dq0KFCrnW+fr6qlSpUgoLC7M816WcPHlSX331lWbPnq3ly5erTJkyeuyxx2yfOcsTefIYNdL5QYCjoqI0ZMgQjRgxQsOHD3ebNat58+a25AoJCdHMmTOzDJK8ePFide7cWUeOHLElVyZP/u5677339Oyzzyp//vwqWbKkNm3apDx58uidd97R119/reXLl9uW7eLZqC7kcDj0559/Wpgmq44dO2rv3r2aOXOmawyT7du3q0uXLipfvrxmz55tSy5PH4srf/782rp1q0qXLq127dqpQYMGeuGFF3TgwAFVqlRJycnJtmXL/M7PjicM7Oyppk+fftn1mTMZ2+GJJ55QiRIlNHToUH3wwQcaMGCAGjRooPXr1+vBBx+0bVbWTLfddpvmz5+vOnXqaP78+erdu7d++uknzZgxQ8uXL9evv/5qW7bs3g8Oh8MjJvupWLGiXnvtNbVp00ZlypTRnDlz1KRJE23evFlNmzbVP//8Y1u2pKQktW7dWtu2bdPJkycVFhbmmvV80aJFCggIsDzTihUrXH/v27dPgwcPVteuXV2z7a1evVrTp0/XqFGjbH2/xsXF6f3333cb6+rpp59WsWLFLLl/ilIeIj09XStXrlSNGjVUsGBBu+NkkS9fPm3YsCHLAHbbtm3TXXfdpdOnT9uU7PxOVvv27RUVFaXmzZtfdsfGavny5dNPP/2ku+66y2352rVr1ahRI505c8amZOctWLBADz30kCIjI9WkSRNJ52eBnD17tr788ku1b9/etmwXfohnp2HDhhYlyWr//v0qWbJkloKZJ9u+fbs6derkmgnKDplFsU6dOtk6O8uNyhNnzerbt6/mzZunN998U/Xr15fD4dDKlSv13HPP6aGHHtKECRNsyyZ59neXJK1fv14HDx5U8+bNlT9/fknSwoULVaBAATVo0MDWbJ7M6XTqhx9+0J133um2fO3atWrRooVOnDhhS66goCDFxMSobNmyttz/ldStW1eNGzdWmzZt1KJFC61Zs0a333671qxZo4cfflh//fWX3RE90s8//3zZ9ffcc49FSW4sGRkZysjIkLe3tyTpiy++cB1s79Wrl3x9fW3N5+fnpz179ui2225Tz549lS9fPk2YMEGxsbG6/fbblZSUZFu2/fv3X3a9nR0VPPmASiZPnfW8adOmeuKJJ/Too4+6Lf/ss880ZcoU/fTTT/YE8wAUpTyIn5+fduzYcdkjlHZp2rSpChcurBkzZsjPz0/S+dm9unTpouPHj+uHH36wLdvXX3+t2bNna+HChQoKClLHjh312GOPZdlZtcN9992nAwcOaOrUqapdu7YcDofWr1+vHj16qESJElqwYIHdEbVw4UKNHDlSMTEx8vf3V40aNTR06FBbiz6eaMuWLapWrZry5MmjLVu2XLZtjRo1LEp1eWfPntWCBQv02WefKTo6WsHBwXr00Uc1evRoW/KMGzdOs2fP1oYNG1SzZk1FRUWpY8eOlh2FuZyDBw/K4XDotttuk3T+x+1nn32m8PBw9ezZ0+Z0nis1NVXPPfecPvjgA507d07GGPn6+uqpp57SG2+8obx589qaz5O/uzKlpqYqNjZW5cqVc/148xSemi0wMFC//PKL7rjjDrflmzZtUsOGDW37Mdm9e3fdeeed6tWrly33fyU//fSTHnjgASUlJalLly6umWL/+9//aufOnfr6669tTnje2bNnXe9XT3CpXiuZrD7Qk5SUpKCgINffl5PZDlmVKlVKH374oZo2baoyZcrovffeU9u2bbVt2zbdfffdSkhIsDuix+KASs7ky5dPmzdvzjJb5u7du3XHHXdY2lnB437XWHKSIK5KnTp1XLMreZrff//dFC9e3BQuXNg0adLENG3a1BQuXNgUL17cNUug3ZKSkszHH39smjdvbry9vU2FChVsH7gzPj7e3HvvvcbhcBhfX1/Xef/33ntvtrO3wd3PP/9sOnXqZCIiIsxff/1ljDFmxowZtgyA7nA4XP+zzPPDMwdOvvBi5znhmRYvXmw6d+5sgoKCTMGCBU2PHj3MTz/9ZHcsl127dplXXnnFVKxY0Xh7e5vmzZu7ZjOyiycPAHwjOH36tNmyZYvZvHmz7QOIX8iTv7tOnz5tunXrZry8vIyXl5drnLA+ffpkOysq2f6nXbt25p577jF///23a9lff/1lGjZsaNq3b29bLk8fi8uY82PnXDyQc2xsrO37JOfOnTMjRowwYWFhbq+5l156yTXuj11OnDjhdjl69KhZsmSJqVu3ri377RfOAHyp8Wo8ZX8kcz+uXr16tu/HXWzo0KHG6XSaypUrm5IlS5qzZ88aY4yZOnWqqVevns3pzj9P9evXN8WKFXMNGD9+/Hgzf/58m5Odl5KSYnbu3Ok2VqgdJk6caJKTk11/e/Ks5xUrVjQDBgzIsnzAgAGmYsWKlmbxtN819JTyIEuWLNELL7ygV199VbVr185y3qvdRzuSk5M1a9Ys7dy5U8YYhYeHq1OnTvL397c1V3Y84VSlC+3evdv1vFWpUkUVK1a0O5Kb1NRUxcfHKyMjw215yZIlbUokzZ07V1FRUerUqZNmzpyp7du3q2zZsnrvvff03XffadGiRZbmufCUPU/uVi2dPxLTpk0bderUSW3atJGPj4+teS5nzZo1euqpp2x/rxYsWFBr1qxRpUqV9Pbbb+vzzz/Xr7/+qiVLlqhXr162j6FTsGDBbE8XdTgc8vPzU/ny5dW1a1c9/vjj1z3Lgw8+qGnTpikoKEgPPvjgZdvmz59fVatWVa9eveR0Oq97tux46nfXs88+q19//VUTJkxQq1attGXLFpUtW1YLFizQ0KFDtWnTJrJdwsGDB3X//fdr69atKlGihBwOhw4cOKDq1avrm2++cfV4tJqnj8XlyUaMGKHp06drxIgR6tGjh7Zu3aqyZcvqiy++0Pjx47V69Wq7I2bx888/q3///paPv7lixQo1aNBA3t7eHj3Ugaftx10q44EDB/TII4+4PjemT5+uAgUK6P7777ct1/vvv69XXnlF/fr10+uvv+56P0ybNk3Tp0+39RS5M2fOqE+fPq7xzHbv3q2yZcuqb9++CgsL0+DBgy3NU6ZMGa1fv16FCxf2+M/gRYsW6aGHHlK5cuVUr149Sef3g/fu3au5c+eqdevWlmXxtN81FKU8yIXdgy/88WE8YFC7G4Gnnap0I/jjjz/UrVs3rVq1ym25J7zmatasqf79+6tz584KDAzU5s2bVbZsWcXExKhVq1aKi4uzLZunu7Brv6fKPD3u888/V2Jiou677z59/vnntuXx5AGAJWn8+PF6/fXXde+99+quu+6SMUbr1q1TdHS0+vfvr9jYWM2cOVPvvPOOevTocV2zPP7443r77bcVGBh4xSJYSkqKVq9ererVq3vE6cqepFSpUvr8889Vr149t8+4PXv2qFatWraOZ+LJ2S60dOlSt2Kjp4wb4klq1aqlZcuWqWDBgqpZs+Zlx0LcuHGjhcnclS9fXpMnT1bTpk3dXnM7d+5URESER55KtWPHDt155506deqU3VE8kifvx6WlpalFixaaPHmyxx0olqTw8HCNHDlS7du3d3vutm7dqkaNGtk6mLinH7TwdAcPHtT777/v9t3Vq1cvlShRwpY8aWlp6tmzp15++WVbx0P0nAEC4BEDw11owYIFuvfee+Xj43PFHxPt2rWzKFVWS5Ys0aeffqr58+fLy8tLDz/8sBYvXuwRYyJ169btsuszx3OwS9euXeXt7a3vvvtOxYoV86iBu3ft2pXt4KFBQUG2DWKbafr06SpSpIjatGkjSXr++ec1ZcoUhYeHa/bs2bb3lAoKClJ6errmz5+vHTt2yOFwqEqVKrr//vvl5eVlW67du3fr008/1WeffaZ9+/apcePGeuONN/Tggw8qMDDQtlySVLVqVX3wwQdq06aNli5dqldffVWSdOjQIRUuXNjWbJK0cuVKvfbaa1nGqpk8ebKWLFmiuXPnqkaNGnr77beve1Hqk08+yfbvS9m+fbulY/zdKN9dR48eVXBwcJblp0+ftv2z2JOzXah58+a2zTx5o7j//vtdY7vZOXnJlfz9998qX758luUZGRlKS0uzIdH/XDzeijFGhw8f1htvvKHbb7/dplTnRUdHK3/+/Lr77rslSe+++64+/PBDhYeH691337V18iRP3o/z8fHR1q1bPerz7EKxsbFZZu6WpLx589o+Qcf8+fNdBy0ufP7Cw8O1d+9eG5PdGEqUKKGRI0faHcPFx8dH8+bN08svv2xrDopSHqRMmTKubugXMsbo4MGDludp37694uLiFBwcfNkdGbt71LRv315t2rTR9OnTPe5UpYuP7KWlpWnr1q06ceKEa7Y7O8XExGjDhg0eORNasWLFtGfPHpUuXdpt+cqVK22f2WjkyJF6//33JZ2fynXSpEmaMGGCvvvuO/Xv39/2wWL37Nmj1q1b6++//1alSpVkjNHu3btVokQJLVy4UOXKlbMlV+XKlVWnTh09/fTT+s9//qPQ0FBbcmRn9OjReuCBBzR27Fh16dLF9UNjwYIFWWbPtMPixYuz7fXZtGlTDRw4UJLUunVry7vNX41KlSpl6Y15Pd0o31133nmnFi5cqD59+rjySNKHH37omiraLp6Y7e2331bPnj3l5+ent99++7Jt+/bta1EqacCAAXr11VcVEBCgAQMGXLbtuHHjLEr1P0OHDpV0fjDuRo0aeewsz1WrVtUvv/yS5aDOl19+me2Pcyvdcccdcjgcuvjkknr16tl+cPG5555zfTf8/vvvGjBggAYOHKgff/xRAwYMuKoDB9eLJ+/HSVLnzp01depUvfHGG3ZHyaJMmTKKiYnJ8n74/vvvFR4eblOq8zztoMWVPncvZMdnsMcNKJ6NBx54QPPnz7+m5zK3UZTyIGXKlNHhw4ezvNGPHz+uMmXKWL7zfOH4QhePNeRJ4uLiPPZUpXnz5mVZlpGRod69e3vEF3J4eLitXYAv58knn9Szzz6rjz/+WA6HQ4cOHdLq1as1aNAgvfLKK7ZmO3jwoOuI7vz58/Xwww+rZ8+eatCggRo1amRrNun8D7Jy5cppzZo1KlSokCTp2LFjeuyxx9S3b18tXLjQllw7d+70yG7yklzd4ZOSktx+sGVOE223QoUK6dtvv1X//v3dln/77beu//Hp06dt73GWHS8vL0t7E9wo312jRo1Sq1attH37dp07d04TJ07Utm3btHr16iuOE3MrZhs/frw6deokPz8/jR8//pLtHA6HpUWpTZs2uXrybNy48ZI/yuzukeHl5aWWLVtqx44dHlmUGjp0qKKiovT3338rIyNDX3/9tXbt2qUZM2bou+++szVbbGys2/U8efKoaNGiHjFDYGxsrKtIMXfuXN13330aOXKkNm7caOn4NNnx5P046fx4qh999JGWLl2qOnXqZBnL144CRqbnnntOTz/9tM6ePStjjNauXavZs2dr1KhR+uijj2zLJXneQYurPV3Qrs/gO+64w3Wg7FIFbsneA2Xly5fXq6++qlWrVmU7rrUl36mWDKeOq+JwOEx8fHyW5fv27TP58uWzIdH/TJ8+3TUrxYVSUlJsnzXLmPOztnz11Vfm1VdfNa+99pqZO3euOXfunN2xLmnnzp0mNDTU7hhm2bJlJiIiwixfvtz8888/JjEx0e1it//+97/G39/fNQOEn5+feemll+yOZYoWLWo2btxojDHmjjvucL0H9uzZYwICAuyMZowxJl++fGbLli1ZlsfExHhEvvXr15uZM2eaWbNmmQ0bNtgd54YwZcoU4+XlZe677z7X51y7du2Mt7e3a2aqN99803To0MHmpJ4vISHB7gguW7ZsMZ07dzZVq1Y1VapUMZ06dcr2vWsHT86GnPHkWZ6NMSY6Otrcc889JiAgwPj7+5sGDRqYxYsX2x3LoxUsWNBs27bNGGNMgwYNzOTJk40x52dU9Pf3tzzP5s2bTXp6uuu6p+7HGWNMo0aNLnlp3Lix3fHMlClTTMmSJV3P3W233Wb7TJTGGPPrr7+awMBA06tXL+Pn52eeffZZ06xZMxMQEGDWr19vdzyPs2/fPpORkeH6+3IXu5QuXfqSlzJlyliSgYHOPUBmV7mJEyeqR48ebkfl09PT9dtvv8nLy0u//vqrXRHl5eWVbS+uY8eOKTg42NZTIDz1VKXLWbRokbp06aKjR4/amiNzcP3sThm1+9SWTGfOnNH27duVkZGh8PBw5c+f3+5I6tSpk3bu3KmaNWtq9uzZOnDggAoXLqwFCxbov//9r7Zu3WprvkKFCum7775T/fr13Zb/+uuv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",
164
+ "text/plain": [
165
+ "<Figure size 1200x600 with 1 Axes>"
166
+ ]
167
+ },
168
+ "metadata": {},
169
+ "output_type": "display_data"
170
+ }
171
+ ],
172
+ "source": [
173
+ "# Plot for the number of occurences of each emotion in the training set\n",
174
+ "plt.figure(figsize=(12, 6))\n",
175
+ "pd.Series(label_distribution).sort_values(ascending=False).plot(kind='bar')\n",
176
+ "plt.title(\"GoEmotions Label Distribution\")\n",
177
+ "plt.ylabel(\"Count\")\n",
178
+ "plt.xticks(rotation=90)\n",
179
+ "plt.tight_layout()\n",
180
+ "plt.show()"
181
+ ]
182
+ },
183
+ {
184
+ "cell_type": "code",
185
+ "execution_count": 9,
186
+ "id": "6d28b28c-d87f-41e5-afd2-cc3257dd974b",
187
+ "metadata": {},
188
+ "outputs": [
189
+ {
190
+ "data": {
191
+ "text/html": [
192
+ "<div>\n",
193
+ "<style scoped>\n",
194
+ " .dataframe tbody tr th:only-of-type {\n",
195
+ " vertical-align: middle;\n",
196
+ " }\n",
197
+ "\n",
198
+ " .dataframe tbody tr th {\n",
199
+ " vertical-align: top;\n",
200
+ " }\n",
201
+ "\n",
202
+ " .dataframe thead th {\n",
203
+ " text-align: right;\n",
204
+ " }\n",
205
+ "</style>\n",
206
+ "<table border=\"1\" class=\"dataframe\">\n",
207
+ " <thead>\n",
208
+ " <tr style=\"text-align: right;\">\n",
209
+ " <th></th>\n",
210
+ " <th>text</th>\n",
211
+ " <th>labels</th>\n",
212
+ " <th>id</th>\n",
213
+ " <th>clean_text</th>\n",
214
+ " </tr>\n",
215
+ " </thead>\n",
216
+ " <tbody>\n",
217
+ " <tr>\n",
218
+ " <th>0</th>\n",
219
+ " <td>My favourite food is anything I didn't have to...</td>\n",
220
+ " <td>[27]</td>\n",
221
+ " <td>eebbqej</td>\n",
222
+ " <td>my favourite food is anything i didnt have to ...</td>\n",
223
+ " </tr>\n",
224
+ " <tr>\n",
225
+ " <th>1</th>\n",
226
+ " <td>Now if he does off himself, everyone will thin...</td>\n",
227
+ " <td>[27]</td>\n",
228
+ " <td>ed00q6i</td>\n",
229
+ " <td>now if he does off himself everyone will think...</td>\n",
230
+ " </tr>\n",
231
+ " <tr>\n",
232
+ " <th>2</th>\n",
233
+ " <td>WHY THE FUCK IS BAYLESS ISOING</td>\n",
234
+ " <td>[2]</td>\n",
235
+ " <td>eezlygj</td>\n",
236
+ " <td>why the fuck is bayless isoing</td>\n",
237
+ " </tr>\n",
238
+ " <tr>\n",
239
+ " <th>3</th>\n",
240
+ " <td>To make her feel threatened</td>\n",
241
+ " <td>[14]</td>\n",
242
+ " <td>ed7ypvh</td>\n",
243
+ " <td>to make her feel threatened</td>\n",
244
+ " </tr>\n",
245
+ " <tr>\n",
246
+ " <th>4</th>\n",
247
+ " <td>Dirty Southern Wankers</td>\n",
248
+ " <td>[3]</td>\n",
249
+ " <td>ed0bdzj</td>\n",
250
+ " <td>dirty southern wankers</td>\n",
251
+ " </tr>\n",
252
+ " <tr>\n",
253
+ " <th>5</th>\n",
254
+ " <td>OmG pEyToN iSn'T gOoD eNoUgH tO hElP uS iN tHe...</td>\n",
255
+ " <td>[26]</td>\n",
256
+ " <td>edvnz26</td>\n",
257
+ " <td>omg peyton isnt good enough to help us in the ...</td>\n",
258
+ " </tr>\n",
259
+ " <tr>\n",
260
+ " <th>6</th>\n",
261
+ " <td>Yes I heard abt the f bombs! That has to be wh...</td>\n",
262
+ " <td>[15]</td>\n",
263
+ " <td>ee3b6wu</td>\n",
264
+ " <td>yes i heard abt the f bombs that has to be why...</td>\n",
265
+ " </tr>\n",
266
+ " <tr>\n",
267
+ " <th>7</th>\n",
268
+ " <td>We need more boards and to create a bit more s...</td>\n",
269
+ " <td>[8, 20]</td>\n",
270
+ " <td>ef4qmod</td>\n",
271
+ " <td>we need more boards and to create a bit more s...</td>\n",
272
+ " </tr>\n",
273
+ " <tr>\n",
274
+ " <th>8</th>\n",
275
+ " <td>Damn youtube and outrage drama is super lucrat...</td>\n",
276
+ " <td>[0]</td>\n",
277
+ " <td>ed8wbdn</td>\n",
278
+ " <td>damn youtube and outrage drama is super lucrat...</td>\n",
279
+ " </tr>\n",
280
+ " <tr>\n",
281
+ " <th>9</th>\n",
282
+ " <td>It might be linked to the trust factor of your...</td>\n",
283
+ " <td>[27]</td>\n",
284
+ " <td>eczgv1o</td>\n",
285
+ " <td>it might be linked to the trust factor of your...</td>\n",
286
+ " </tr>\n",
287
+ " </tbody>\n",
288
+ "</table>\n",
289
+ "</div>"
290
+ ],
291
+ "text/plain": [
292
+ " text labels id \\\n",
293
+ "0 My favourite food is anything I didn't have to... [27] eebbqej \n",
294
+ "1 Now if he does off himself, everyone will thin... [27] ed00q6i \n",
295
+ "2 WHY THE FUCK IS BAYLESS ISOING [2] eezlygj \n",
296
+ "3 To make her feel threatened [14] ed7ypvh \n",
297
+ "4 Dirty Southern Wankers [3] ed0bdzj \n",
298
+ "5 OmG pEyToN iSn'T gOoD eNoUgH tO hElP uS iN tHe... [26] edvnz26 \n",
299
+ "6 Yes I heard abt the f bombs! That has to be wh... [15] ee3b6wu \n",
300
+ "7 We need more boards and to create a bit more s... [8, 20] ef4qmod \n",
301
+ "8 Damn youtube and outrage drama is super lucrat... [0] ed8wbdn \n",
302
+ "9 It might be linked to the trust factor of your... [27] eczgv1o \n",
303
+ "\n",
304
+ " clean_text \n",
305
+ "0 my favourite food is anything i didnt have to ... \n",
306
+ "1 now if he does off himself everyone will think... \n",
307
+ "2 why the fuck is bayless isoing \n",
308
+ "3 to make her feel threatened \n",
309
+ "4 dirty southern wankers \n",
310
+ "5 omg peyton isnt good enough to help us in the ... \n",
311
+ "6 yes i heard abt the f bombs that has to be why... \n",
312
+ "7 we need more boards and to create a bit more s... \n",
313
+ "8 damn youtube and outrage drama is super lucrat... \n",
314
+ "9 it might be linked to the trust factor of your... "
315
+ ]
316
+ },
317
+ "execution_count": 9,
318
+ "metadata": {},
319
+ "output_type": "execute_result"
320
+ }
321
+ ],
322
+ "source": [
323
+ "import re\n",
324
+ "\n",
325
+ "def clean_text(text):\n",
326
+ " text = text.lower() # this makes every character in the text lower-cased\n",
327
+ " text = re.sub(r\"http\\S+|www\\S+|https\\S+\", '', text) # this removes links\n",
328
+ " text = re.sub(r'[^A-Za-z0-9\\s]+', '', text) # this removes special characters\n",
329
+ " text = re.sub(r'\\s+', ' ', text).strip() # this normalizes whitespace\n",
330
+ " return text\n",
331
+ "\n",
332
+ "df[\"clean_text\"] = df[\"text\"].apply(clean_text)\n",
333
+ "df.head(10)"
334
+ ]
335
+ }
336
+ ],
337
+ "metadata": {
338
+ "kernelspec": {
339
+ "display_name": "Python 3 (ipykernel)",
340
+ "language": "python",
341
+ "name": "python3"
342
+ },
343
+ "language_info": {
344
+ "codemirror_mode": {
345
+ "name": "ipython",
346
+ "version": 3
347
+ },
348
+ "file_extension": ".py",
349
+ "mimetype": "text/x-python",
350
+ "name": "python",
351
+ "nbconvert_exporter": "python",
352
+ "pygments_lexer": "ipython3",
353
+ "version": "3.12.2"
354
+ }
355
+ },
356
+ "nbformat": 4,
357
+ "nbformat_minor": 5
358
+ }
notebooks/02_training.ipynb ADDED
@@ -0,0 +1,368 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "id": "80f816c1-0839-41cb-847b-c79a62ca1465",
6
+ "metadata": {},
7
+ "source": [
8
+ "### Load all required modules for loading data, model setup, training, and metric evaluation"
9
+ ]
10
+ },
11
+ {
12
+ "cell_type": "code",
13
+ "execution_count": 1,
14
+ "id": "2554d05b-f08a-4c21-953f-4f507407e426",
15
+ "metadata": {},
16
+ "outputs": [],
17
+ "source": [
18
+ "import sys\n",
19
+ "import os\n",
20
+ "sys.path.append(os.path.abspath(os.path.join(os.getcwd(), \"..\", \"src\")))\n",
21
+ "from data_loader import load_and_prepare_data \n",
22
+ "from model import get_model, get_tokenizer \n",
23
+ "from train import get_training_args, train_model \n",
24
+ "from evaluate import compute_metrics \n",
25
+ "from torch.utils.data import Dataset \n",
26
+ "import torch"
27
+ ]
28
+ },
29
+ {
30
+ "cell_type": "markdown",
31
+ "id": "3bfbb706-4b0b-43de-a95a-884d46343668",
32
+ "metadata": {},
33
+ "source": [
34
+ "### Define a class that wraps tokenized data and labels for Hugging Face’s Trainer to use"
35
+ ]
36
+ },
37
+ {
38
+ "cell_type": "code",
39
+ "execution_count": 3,
40
+ "id": "c814c354-7962-4a2d-b7bd-5c498f1d004e",
41
+ "metadata": {},
42
+ "outputs": [],
43
+ "source": [
44
+ "class EmotionDataset(Dataset):\n",
45
+ " def __init__(self, encodings, labels):\n",
46
+ " self.encodings = encodings # BERT tokenized inputs (input_ids, attention_mask)\n",
47
+ " self.labels = labels # Encoded labels (integers)\n",
48
+ "\n",
49
+ " def __len__(self):\n",
50
+ " return len(self.labels) # Total number of samples\n",
51
+ "\n",
52
+ " def __getitem__(self, idx):\n",
53
+ " # Return dictionary of input tensors + label tensor for a single sample\n",
54
+ " return {\n",
55
+ " key: torch.tensor(val[idx]) for key, val in self.encodings.items()\n",
56
+ " } | {\"labels\": torch.tensor(self.labels[idx])}"
57
+ ]
58
+ },
59
+ {
60
+ "cell_type": "markdown",
61
+ "id": "f9b87257-f0c0-4532-9eee-939d8747ef79",
62
+ "metadata": {},
63
+ "source": [
64
+ "### Load the dataset from Hugging Face, clean and encode it, then tokenize it using the BERT tokenizer."
65
+ ]
66
+ },
67
+ {
68
+ "cell_type": "code",
69
+ "execution_count": 5,
70
+ "id": "18e312be-5863-4e24-900a-843e42e145cc",
71
+ "metadata": {},
72
+ "outputs": [],
73
+ "source": [
74
+ "# Load train/test splits and label encoder\n",
75
+ "train_texts, test_texts, train_labels, test_labels, label_encoder = load_and_prepare_data()\n",
76
+ "\n",
77
+ "# Load BERT tokenizer\n",
78
+ "tokenizer = get_tokenizer()\n",
79
+ "\n",
80
+ "# Tokenize training and testing texts with truncation and padding\n",
81
+ "train_encodings = tokenizer(train_texts, truncation=True, padding=True, max_length=128)\n",
82
+ "test_encodings = tokenizer(test_texts, truncation=True, padding=True, max_length=128)\n",
83
+ "\n",
84
+ "# Wrap the tokenized data into EmotionDataset objects\n",
85
+ "train_dataset = EmotionDataset(train_encodings, train_labels)\n",
86
+ "test_dataset = EmotionDataset(test_encodings, test_labels)"
87
+ ]
88
+ },
89
+ {
90
+ "cell_type": "markdown",
91
+ "id": "66b99b4e-5297-4bc0-8cfb-20dbe22526c0",
92
+ "metadata": {},
93
+ "source": [
94
+ "### Samples from the dataset"
95
+ ]
96
+ },
97
+ {
98
+ "cell_type": "code",
99
+ "execution_count": 7,
100
+ "id": "35db4426-db21-4438-ba0e-ebb51d52edfb",
101
+ "metadata": {},
102
+ "outputs": [
103
+ {
104
+ "name": "stdout",
105
+ "output_type": "stream",
106
+ "text": [
107
+ "Sample 1\n",
108
+ "Text: i'd just feel less out of place, i guess. my sa makes me feel like i'm so behind my peers in terms of a social life\n",
109
+ "Label (encoded): 9\n",
110
+ "\n",
111
+ "Sample 2\n",
112
+ "Text: i love the lady in the green jacket chasing after the second car looking back at the first car like \"look what you did\"\n",
113
+ "Label (encoded): 18\n",
114
+ "\n",
115
+ "Sample 3\n",
116
+ "Text: man. really bad last possession there. bummer.\n",
117
+ "Label (encoded): 10\n",
118
+ "\n",
119
+ "Sample 4\n",
120
+ "Text: never would’ve guessed that one.\n",
121
+ "Label (encoded): 20\n",
122
+ "\n",
123
+ "Sample 5\n",
124
+ "Text: i wasn’t even expecting the reply that’s why i’m literally bamboozled.\n",
125
+ "Label (encoded): 27\n",
126
+ "\n"
127
+ ]
128
+ }
129
+ ],
130
+ "source": [
131
+ "for i in range(5):\n",
132
+ " print(f\"Sample {i+1}\")\n",
133
+ " print(f\"Text: {train_texts[i]}\")\n",
134
+ " print(f\"Label (encoded): {train_labels[i]}\")\n",
135
+ " print()"
136
+ ]
137
+ },
138
+ {
139
+ "cell_type": "markdown",
140
+ "id": "0883760a-a449-42ca-ba69-fa01d874e50b",
141
+ "metadata": {},
142
+ "source": [
143
+ "### Set up the BERT model for sequence classification and define training parameters."
144
+ ]
145
+ },
146
+ {
147
+ "cell_type": "code",
148
+ "execution_count": 9,
149
+ "id": "3176ccf4-d20d-460c-b620-c73a1ab9cb6d",
150
+ "metadata": {},
151
+ "outputs": [
152
+ {
153
+ "name": "stderr",
154
+ "output_type": "stream",
155
+ "text": [
156
+ "Some weights of BertForSequenceClassification were not initialized from the model checkpoint at bert-base-uncased and are newly initialized: ['classifier.bias', 'classifier.weight']\n",
157
+ "You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n",
158
+ "/opt/anaconda3/lib/python3.12/site-packages/transformers/training_args.py:1545: FutureWarning: `evaluation_strategy` is deprecated and will be removed in version 4.46 of 🤗 Transformers. Use `eval_strategy` instead\n",
159
+ " warnings.warn(\n"
160
+ ]
161
+ }
162
+ ],
163
+ "source": [
164
+ "# Load pre-trained BERT model with classification head for number of emotion classes\n",
165
+ "model = get_model(num_labels=len(label_encoder.classes_))\n",
166
+ "\n",
167
+ "# Set training configuration: batch size, epochs, logging, saving, evaluation\n",
168
+ "training_args = get_training_args()"
169
+ ]
170
+ },
171
+ {
172
+ "cell_type": "markdown",
173
+ "id": "874a4e6a-80dd-470d-9283-e1c88e731b8e",
174
+ "metadata": {},
175
+ "source": [
176
+ "### Train the Model "
177
+ ]
178
+ },
179
+ {
180
+ "cell_type": "code",
181
+ "execution_count": 13,
182
+ "id": "4c312e56-52bf-417d-82c0-8a1f47b82670",
183
+ "metadata": {},
184
+ "outputs": [
185
+ {
186
+ "data": {
187
+ "text/html": [
188
+ "\n",
189
+ " <div>\n",
190
+ " \n",
191
+ " <progress value='5448' max='5448' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
192
+ " [5448/5448 1:46:28, Epoch 3/3]\n",
193
+ " </div>\n",
194
+ " <table border=\"1\" class=\"dataframe\">\n",
195
+ " <thead>\n",
196
+ " <tr style=\"text-align: left;\">\n",
197
+ " <th>Epoch</th>\n",
198
+ " <th>Training Loss</th>\n",
199
+ " <th>Validation Loss</th>\n",
200
+ " <th>Accuracy</th>\n",
201
+ " <th>F1</th>\n",
202
+ " </tr>\n",
203
+ " </thead>\n",
204
+ " <tbody>\n",
205
+ " <tr>\n",
206
+ " <td>1</td>\n",
207
+ " <td>1.358900</td>\n",
208
+ " <td>1.335635</td>\n",
209
+ " <td>0.613467</td>\n",
210
+ " <td>0.579882</td>\n",
211
+ " </tr>\n",
212
+ " <tr>\n",
213
+ " <td>2</td>\n",
214
+ " <td>0.947100</td>\n",
215
+ " <td>1.284574</td>\n",
216
+ " <td>0.615671</td>\n",
217
+ " <td>0.601428</td>\n",
218
+ " </tr>\n",
219
+ " <tr>\n",
220
+ " <td>3</td>\n",
221
+ " <td>0.970400</td>\n",
222
+ " <td>1.297894</td>\n",
223
+ " <td>0.617048</td>\n",
224
+ " <td>0.606042</td>\n",
225
+ " </tr>\n",
226
+ " </tbody>\n",
227
+ "</table><p>"
228
+ ],
229
+ "text/plain": [
230
+ "<IPython.core.display.HTML object>"
231
+ ]
232
+ },
233
+ "metadata": {},
234
+ "output_type": "display_data"
235
+ },
236
+ {
237
+ "data": {
238
+ "text/html": [
239
+ "\n",
240
+ " <div>\n",
241
+ " \n",
242
+ " <progress value='5448' max='5448' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
243
+ " [5448/5448 1:35:20, Epoch 3/3]\n",
244
+ " </div>\n",
245
+ " <table border=\"1\" class=\"dataframe\">\n",
246
+ " <thead>\n",
247
+ " <tr style=\"text-align: left;\">\n",
248
+ " <th>Epoch</th>\n",
249
+ " <th>Training Loss</th>\n",
250
+ " <th>Validation Loss</th>\n",
251
+ " <th>Accuracy</th>\n",
252
+ " <th>F1</th>\n",
253
+ " </tr>\n",
254
+ " </thead>\n",
255
+ " <tbody>\n",
256
+ " <tr>\n",
257
+ " <td>1</td>\n",
258
+ " <td>0.907200</td>\n",
259
+ " <td>1.365916</td>\n",
260
+ " <td>0.602313</td>\n",
261
+ " <td>0.595804</td>\n",
262
+ " </tr>\n",
263
+ " <tr>\n",
264
+ " <td>2</td>\n",
265
+ " <td>0.549100</td>\n",
266
+ " <td>1.488130</td>\n",
267
+ " <td>0.595566</td>\n",
268
+ " <td>0.591464</td>\n",
269
+ " </tr>\n",
270
+ " <tr>\n",
271
+ " <td>3</td>\n",
272
+ " <td>0.514400</td>\n",
273
+ " <td>1.593286</td>\n",
274
+ " <td>0.591297</td>\n",
275
+ " <td>0.589066</td>\n",
276
+ " </tr>\n",
277
+ " </tbody>\n",
278
+ "</table><p>"
279
+ ],
280
+ "text/plain": [
281
+ "<IPython.core.display.HTML object>"
282
+ ]
283
+ },
284
+ "metadata": {},
285
+ "output_type": "display_data"
286
+ },
287
+ {
288
+ "data": {
289
+ "text/plain": [
290
+ "TrainOutput(global_step=5448, training_loss=0.7054264770818002, metrics={'train_runtime': 5721.3012, 'train_samples_per_second': 15.23, 'train_steps_per_second': 0.952, 'total_flos': 5733080823638016.0, 'train_loss': 0.7054264770818002, 'epoch': 3.0})"
291
+ ]
292
+ },
293
+ "execution_count": 13,
294
+ "metadata": {},
295
+ "output_type": "execute_result"
296
+ }
297
+ ],
298
+ "source": [
299
+ "trainer = train_model(\n",
300
+ " model=model,\n",
301
+ " args=training_args,\n",
302
+ " train_dataset=train_dataset,\n",
303
+ " val_dataset=test_dataset,\n",
304
+ " compute_metrics=compute_metrics\n",
305
+ ")\n",
306
+ "\n",
307
+ "# Begin training\n",
308
+ "trainer.train()"
309
+ ]
310
+ },
311
+ {
312
+ "cell_type": "markdown",
313
+ "id": "020729b6-c545-42ba-bd2c-00ee5f9bbb80",
314
+ "metadata": {},
315
+ "source": [
316
+ "### Save both model weights and tokenizer files for future inference or deployment."
317
+ ]
318
+ },
319
+ {
320
+ "cell_type": "code",
321
+ "execution_count": 23,
322
+ "id": "5f12aedb-b3f8-4a1b-8e1f-6a68eb29933f",
323
+ "metadata": {},
324
+ "outputs": [
325
+ {
326
+ "data": {
327
+ "text/plain": [
328
+ "('../outputs/model/tokenizer_config.json',\n",
329
+ " '../outputs/model/special_tokens_map.json',\n",
330
+ " '../outputs/model/vocab.txt',\n",
331
+ " '../outputs/model/added_tokens.json')"
332
+ ]
333
+ },
334
+ "execution_count": 23,
335
+ "metadata": {},
336
+ "output_type": "execute_result"
337
+ }
338
+ ],
339
+ "source": [
340
+ "from pathlib import Path\n",
341
+ "model_path = Path(\"..\") / \"outputs\" / \"model\"\n",
342
+ "model.save_pretrained(model_path)\n",
343
+ "tokenizer.save_pretrained(model_path)"
344
+ ]
345
+ }
346
+ ],
347
+ "metadata": {
348
+ "kernelspec": {
349
+ "display_name": "Python 3 (ipykernel)",
350
+ "language": "python",
351
+ "name": "python3"
352
+ },
353
+ "language_info": {
354
+ "codemirror_mode": {
355
+ "name": "ipython",
356
+ "version": 3
357
+ },
358
+ "file_extension": ".py",
359
+ "mimetype": "text/x-python",
360
+ "name": "python",
361
+ "nbconvert_exporter": "python",
362
+ "pygments_lexer": "ipython3",
363
+ "version": "3.12.2"
364
+ }
365
+ },
366
+ "nbformat": 4,
367
+ "nbformat_minor": 5
368
+ }
notebooks/03_evaluation.ipynb ADDED
The diff for this file is too large to render. See raw diff
 
notebooks/04_model_comparison.ipynb ADDED
@@ -0,0 +1,290 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": 1,
6
+ "id": "4032a920-2db8-4977-8b4f-a5a771dd022f",
7
+ "metadata": {},
8
+ "outputs": [],
9
+ "source": [
10
+ "import sys\n",
11
+ "import os\n",
12
+ "\n",
13
+ "project_root = os.path.abspath(os.path.join(os.getcwd(), \"..\"))\n",
14
+ "sys.path.append(project_root)\n",
15
+ "\n",
16
+ "from transformers import pipeline\n",
17
+ "from src.model_hartmann import load_model as load_hartmann_model, load_tokenizer as load_hartmann_tokenizer\n",
18
+ "from src.model_custom import load_model as load_custom_model, load_tokenizer as load_custom_tokenizer"
19
+ ]
20
+ },
21
+ {
22
+ "cell_type": "code",
23
+ "execution_count": 2,
24
+ "id": "525cf57e-4ec3-40fd-aca2-0e9700a73298",
25
+ "metadata": {},
26
+ "outputs": [],
27
+ "source": [
28
+ "hartmann_model = load_hartmann_model()\n",
29
+ "hartmann_tokenizer = load_hartmann_tokenizer()\n",
30
+ "\n",
31
+ "custom_model = load_custom_model()\n",
32
+ "custom_tokenizer = load_custom_tokenizer()"
33
+ ]
34
+ },
35
+ {
36
+ "cell_type": "code",
37
+ "execution_count": 3,
38
+ "id": "04f9415c-3d4f-4ac0-8f51-74ec4bd64293",
39
+ "metadata": {},
40
+ "outputs": [
41
+ {
42
+ "name": "stderr",
43
+ "output_type": "stream",
44
+ "text": [
45
+ "Hardware accelerator e.g. GPU is available in the environment, but no `device` argument is passed to the `Pipeline` object. Model will be on CPU.\n",
46
+ "/opt/anaconda3/lib/python3.12/site-packages/transformers/pipelines/text_classification.py:104: UserWarning: `return_all_scores` is now deprecated, if want a similar functionality use `top_k=None` instead of `return_all_scores=True` or `top_k=1` instead of `return_all_scores=False`.\n",
47
+ " warnings.warn(\n",
48
+ "Hardware accelerator e.g. GPU is available in the environment, but no `device` argument is passed to the `Pipeline` object. Model will be on CPU.\n"
49
+ ]
50
+ }
51
+ ],
52
+ "source": [
53
+ "# Create pipelines for easy predictions\n",
54
+ "hartmann_pipeline = pipeline(\"text-classification\", model=hartmann_model, tokenizer=hartmann_tokenizer, return_all_scores=True)\n",
55
+ "custom_pipeline = pipeline(\"text-classification\", model=custom_model, tokenizer=custom_tokenizer, return_all_scores=True)"
56
+ ]
57
+ },
58
+ {
59
+ "cell_type": "code",
60
+ "execution_count": 4,
61
+ "id": "3fcdf650-3abc-42a6-b1fd-0129e49d1e68",
62
+ "metadata": {},
63
+ "outputs": [
64
+ {
65
+ "name": "stdout",
66
+ "output_type": "stream",
67
+ "text": [
68
+ "========= Sentence 1 ==========\n",
69
+ "Text: I love spending time with my family.\n",
70
+ "\n",
71
+ "--- Hartmann Model Top 3 Predictions ---\n",
72
+ "joy: 0.9883\n",
73
+ "sadness: 0.0067\n",
74
+ "disgust: 0.0013\n",
75
+ "\n",
76
+ "--- Pretrained Model Top 3 Predictions ---\n",
77
+ "love: 0.9536\n",
78
+ "joy: 0.0134\n",
79
+ "admiration: 0.0108\n",
80
+ "\n",
81
+ "\n",
82
+ "========= Sentence 2 ==========\n",
83
+ "Text: This is the worst day of my life.\n",
84
+ "\n",
85
+ "--- Hartmann Model Top 3 Predictions ---\n",
86
+ "disgust: 0.9805\n",
87
+ "anger: 0.0086\n",
88
+ "sadness: 0.0055\n",
89
+ "\n",
90
+ "--- Pretrained Model Top 3 Predictions ---\n",
91
+ "anger: 0.3353\n",
92
+ "surprise: 0.2010\n",
93
+ "disgust: 0.1235\n",
94
+ "\n",
95
+ "\n",
96
+ "========= Sentence 3 ==========\n",
97
+ "Text: I'm feeling very nervous about the exam.\n",
98
+ "\n",
99
+ "--- Hartmann Model Top 3 Predictions ---\n",
100
+ "fear: 0.9947\n",
101
+ "sadness: 0.0013\n",
102
+ "joy: 0.0011\n",
103
+ "\n",
104
+ "--- Pretrained Model Top 3 Predictions ---\n",
105
+ "nervousness: 0.6201\n",
106
+ "fear: 0.0828\n",
107
+ "embarrassment: 0.0393\n",
108
+ "\n",
109
+ "\n",
110
+ "========= Sentence 4 ==========\n",
111
+ "Text: What a beautiful sunset!\n",
112
+ "\n",
113
+ "--- Hartmann Model Top 3 Predictions ---\n",
114
+ "joy: 0.8377\n",
115
+ "surprise: 0.1189\n",
116
+ "neutral: 0.0221\n",
117
+ "\n",
118
+ "--- Pretrained Model Top 3 Predictions ---\n",
119
+ "admiration: 0.8548\n",
120
+ "excitement: 0.0729\n",
121
+ "joy: 0.0351\n",
122
+ "\n",
123
+ "\n",
124
+ "========= Sentence 5 ==========\n",
125
+ "Text: I feel so disappointed and frustrated with the situation.\n",
126
+ "\n",
127
+ "--- Hartmann Model Top 3 Predictions ---\n",
128
+ "sadness: 0.9310\n",
129
+ "anger: 0.0381\n",
130
+ "disgust: 0.0158\n",
131
+ "\n",
132
+ "--- Pretrained Model Top 3 Predictions ---\n",
133
+ "disappointment: 0.5645\n",
134
+ "annoyance: 0.1864\n",
135
+ "anger: 0.0736\n",
136
+ "\n",
137
+ "\n",
138
+ "========= Sentence 6 ==========\n",
139
+ "Text: I'm not sure how to feel about this.\n",
140
+ "\n",
141
+ "--- Hartmann Model Top 3 Predictions ---\n",
142
+ "neutral: 0.5698\n",
143
+ "disgust: 0.2213\n",
144
+ "sadness: 0.0720\n",
145
+ "\n",
146
+ "--- Pretrained Model Top 3 Predictions ---\n",
147
+ "confusion: 0.9011\n",
148
+ "optimism: 0.0230\n",
149
+ "disapproval: 0.0223\n",
150
+ "\n",
151
+ "\n",
152
+ "========= Sentence 7 ==========\n",
153
+ "Text: That was hilarious, I can't stop laughing!\n",
154
+ "\n",
155
+ "--- Hartmann Model Top 3 Predictions ---\n",
156
+ "joy: 0.9336\n",
157
+ "surprise: 0.0306\n",
158
+ "neutral: 0.0178\n",
159
+ "\n",
160
+ "--- Pretrained Model Top 3 Predictions ---\n",
161
+ "amusement: 0.9551\n",
162
+ "joy: 0.0286\n",
163
+ "optimism: 0.0032\n",
164
+ "\n",
165
+ "\n",
166
+ "========= Sentence 8 ==========\n",
167
+ "Text: I feel completely empty and lost.\n",
168
+ "\n",
169
+ "--- Hartmann Model Top 3 Predictions ---\n",
170
+ "sadness: 0.9808\n",
171
+ "neutral: 0.0086\n",
172
+ "disgust: 0.0051\n",
173
+ "\n",
174
+ "--- Pretrained Model Top 3 Predictions ---\n",
175
+ "surprise: 0.8055\n",
176
+ "disappointment: 0.1067\n",
177
+ "optimism: 0.0222\n",
178
+ "\n",
179
+ "\n",
180
+ "========= Sentence 9 ==========\n",
181
+ "Text: Your help means a lot to me, thank you!\n",
182
+ "\n",
183
+ "--- Hartmann Model Top 3 Predictions ---\n",
184
+ "joy: 0.9760\n",
185
+ "neutral: 0.0104\n",
186
+ "surprise: 0.0057\n",
187
+ "\n",
188
+ "--- Pretrained Model Top 3 Predictions ---\n",
189
+ "gratitude: 0.9890\n",
190
+ "caring: 0.0014\n",
191
+ "sadness: 0.0009\n",
192
+ "\n",
193
+ "\n",
194
+ "========= Sentence 10 ==========\n",
195
+ "Text: I'm so angry I could scream.\n",
196
+ "\n",
197
+ "--- Hartmann Model Top 3 Predictions ---\n",
198
+ "anger: 0.9785\n",
199
+ "fear: 0.0084\n",
200
+ "neutral: 0.0047\n",
201
+ "\n",
202
+ "--- Pretrained Model Top 3 Predictions ---\n",
203
+ "anger: 0.9155\n",
204
+ "annoyance: 0.0223\n",
205
+ "optimism: 0.0082\n",
206
+ "\n",
207
+ "\n"
208
+ ]
209
+ }
210
+ ],
211
+ "source": [
212
+ "from tabulate import tabulate\n",
213
+ "\n",
214
+ "goemotions_labels = [\n",
215
+ " \"admiration\", \"amusement\", \"anger\", \"annoyance\", \"approval\", \"caring\", \"confusion\", \"curiosity\",\n",
216
+ " \"desire\", \"disappointment\", \"disapproval\", \"disgust\", \"embarrassment\", \"excitement\", \"fear\",\n",
217
+ " \"gratitude\", \"grief\", \"joy\", \"love\", \"nervousness\", \"optimism\", \"pride\", \"realization\", \"relief\",\n",
218
+ " \"remorse\", \"sadness\", \"surprise\", \"neutral\"\n",
219
+ "]\n",
220
+ "\n",
221
+ "\n",
222
+ "# Your 10 test sentences\n",
223
+ "sentences = [\n",
224
+ " \"I love spending time with my family.\",\n",
225
+ " \"This is the worst day of my life.\",\n",
226
+ " \"I'm feeling very nervous about the exam.\",\n",
227
+ " \"What a beautiful sunset!\",\n",
228
+ " \"I feel so disappointed and frustrated with the situation.\",\n",
229
+ " \"I'm not sure how to feel about this.\",\n",
230
+ " \"That was hilarious, I can't stop laughing!\",\n",
231
+ " \"I feel completely empty and lost.\",\n",
232
+ " \"Your help means a lot to me, thank you!\",\n",
233
+ " \"I'm so angry I could scream.\"\n",
234
+ "]\n",
235
+ "\n",
236
+ "# Loop over sentences and collect results\n",
237
+ "for i, sentence in enumerate(sentences):\n",
238
+ " print(f\"========= Sentence {i+1} ==========\")\n",
239
+ " print(f\"Text: {sentence}\\n\")\n",
240
+ "\n",
241
+ " # Get predictions\n",
242
+ " hartmann_results = hartmann_pipeline(sentence, return_all_scores=True)\n",
243
+ " custom_results = custom_pipeline(sentence, return_all_scores=True)\n",
244
+ "\n",
245
+ " # Unwrap the list to get the actual results\n",
246
+ " hartmann_results = hartmann_results[0]\n",
247
+ " custom_results = custom_results[0]\n",
248
+ "\n",
249
+ " # Sort and get top 3 predictions for each\n",
250
+ " hartmann_top3 = sorted(hartmann_results, key=lambda x: x['score'], reverse=True)[:3]\n",
251
+ " custom_top3 = sorted(custom_results, key=lambda x: x['score'], reverse=True)[:3]\n",
252
+ "\n",
253
+ " # Display Hartmann predictions\n",
254
+ " print(\"--- Hartmann Model Top 3 Predictions ---\")\n",
255
+ " for res in hartmann_top3:\n",
256
+ " print(f\"{res['label']}: {res['score']:.4f}\")\n",
257
+ "\n",
258
+ " # Display Custom Model predictions\n",
259
+ " print(\"\\n--- Pretrained Model Top 3 Predictions ---\")\n",
260
+ " for res in custom_top3:\n",
261
+ " label_idx = int(res['label'].split(\"_\")[-1])\n",
262
+ " emotion = goemotions_labels[label_idx]\n",
263
+ " print(f\"{emotion}: {res['score']:.4f}\")\n",
264
+ "\n",
265
+ " print(\"\\n\")\n"
266
+ ]
267
+ }
268
+ ],
269
+ "metadata": {
270
+ "kernelspec": {
271
+ "display_name": "Python 3 (ipykernel)",
272
+ "language": "python",
273
+ "name": "python3"
274
+ },
275
+ "language_info": {
276
+ "codemirror_mode": {
277
+ "name": "ipython",
278
+ "version": 3
279
+ },
280
+ "file_extension": ".py",
281
+ "mimetype": "text/x-python",
282
+ "name": "python",
283
+ "nbconvert_exporter": "python",
284
+ "pygments_lexer": "ipython3",
285
+ "version": "3.12.2"
286
+ }
287
+ },
288
+ "nbformat": 4,
289
+ "nbformat_minor": 5
290
+ }
outputs/.DS_Store ADDED
Binary file (8.2 kB). View file
 
outputs/interpretations/.DS_Store ADDED
Binary file (6.15 kB). View file
 
outputs/interpretations/sample_1_disapproval_bar.png ADDED
outputs/interpretations/sample_1_disapproval_heatmap.png ADDED
outputs/interpretations/sample_2_neutral_bar.png ADDED
outputs/interpretations/sample_2_neutral_heatmap.png ADDED
outputs/interpretations/sample_3_neutral_bar.png ADDED
outputs/interpretations/sample_3_neutral_heatmap.png ADDED
outputs/interpretations/sample_4_sadness_bar.png ADDED
outputs/interpretations/sample_4_sadness_heatmap.png ADDED
outputs/interpretations/sample_5_neutral_bar.png ADDED
outputs/interpretations/sample_5_neutral_heatmap.png ADDED
outputs/metrics/.DS_Store ADDED
Binary file (6.15 kB). View file
 
outputs/metrics/.gitkeep ADDED
File without changes
outputs/metrics/.ipynb_checkpoints/confusion_matrix-checkpoint.png ADDED
outputs/metrics/.ipynb_checkpoints/report-checkpoint.json ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "admiration": {
3
+ "precision": 0.6699186991869919,
4
+ "recall": 0.7601476014760148,
5
+ "f1-score": 0.7121866897147796,
6
+ "support": 542.0
7
+ },
8
+ "amusement": {
9
+ "precision": 0.727979274611399,
10
+ "recall": 0.8515151515151516,
11
+ "f1-score": 0.7849162011173184,
12
+ "support": 330.0
13
+ },
14
+ "anger": {
15
+ "precision": 0.4329501915708812,
16
+ "recall": 0.551219512195122,
17
+ "f1-score": 0.48497854077253216,
18
+ "support": 205.0
19
+ },
20
+ "annoyance": {
21
+ "precision": 0.2983425414364641,
22
+ "recall": 0.18620689655172415,
23
+ "f1-score": 0.22929936305732485,
24
+ "support": 290.0
25
+ },
26
+ "approval": {
27
+ "precision": 0.38440111420612816,
28
+ "recall": 0.368,
29
+ "f1-score": 0.3760217983651226,
30
+ "support": 375.0
31
+ },
32
+ "caring": {
33
+ "precision": 0.375,
34
+ "recall": 0.4846153846153846,
35
+ "f1-score": 0.4228187919463087,
36
+ "support": 130.0
37
+ },
38
+ "confusion": {
39
+ "precision": 0.4965986394557823,
40
+ "recall": 0.42441860465116277,
41
+ "f1-score": 0.45768025078369906,
42
+ "support": 172.0
43
+ },
44
+ "curiosity": {
45
+ "precision": 0.4628099173553719,
46
+ "recall": 0.60431654676259,
47
+ "f1-score": 0.5241809672386896,
48
+ "support": 278.0
49
+ },
50
+ "desire": {
51
+ "precision": 0.640625,
52
+ "recall": 0.5256410256410257,
53
+ "f1-score": 0.5774647887323944,
54
+ "support": 78.0
55
+ },
56
+ "disappointment": {
57
+ "precision": 0.3258426966292135,
58
+ "recall": 0.20422535211267606,
59
+ "f1-score": 0.2510822510822511,
60
+ "support": 142.0
61
+ },
62
+ "disapproval": {
63
+ "precision": 0.3228915662650602,
64
+ "recall": 0.4785714285714286,
65
+ "f1-score": 0.3856115107913669,
66
+ "support": 280.0
67
+ },
68
+ "disgust": {
69
+ "precision": 0.5113636363636364,
70
+ "recall": 0.45,
71
+ "f1-score": 0.4787234042553192,
72
+ "support": 100.0
73
+ },
74
+ "embarrassment": {
75
+ "precision": 0.7931034482758621,
76
+ "recall": 0.5609756097560976,
77
+ "f1-score": 0.6571428571428571,
78
+ "support": 41.0
79
+ },
80
+ "excitement": {
81
+ "precision": 0.42105263157894735,
82
+ "recall": 0.3137254901960784,
83
+ "f1-score": 0.3595505617977528,
84
+ "support": 102.0
85
+ },
86
+ "fear": {
87
+ "precision": 0.8113207547169812,
88
+ "recall": 0.5,
89
+ "f1-score": 0.6187050359712231,
90
+ "support": 86.0
91
+ },
92
+ "gratitude": {
93
+ "precision": 0.9085872576177285,
94
+ "recall": 0.8840970350404312,
95
+ "f1-score": 0.8961748633879781,
96
+ "support": 371.0
97
+ },
98
+ "grief": {
99
+ "precision": 0.0,
100
+ "recall": 0.0,
101
+ "f1-score": 0.0,
102
+ "support": 8.0
103
+ },
104
+ "joy": {
105
+ "precision": 0.55,
106
+ "recall": 0.5789473684210527,
107
+ "f1-score": 0.5641025641025641,
108
+ "support": 171.0
109
+ },
110
+ "love": {
111
+ "precision": 0.7774193548387097,
112
+ "recall": 0.8456140350877193,
113
+ "f1-score": 0.8100840336134454,
114
+ "support": 285.0
115
+ },
116
+ "nervousness": {
117
+ "precision": 0.46153846153846156,
118
+ "recall": 0.35294117647058826,
119
+ "f1-score": 0.4,
120
+ "support": 17.0
121
+ },
122
+ "neutral": {
123
+ "precision": 0.6760843613211301,
124
+ "recall": 0.6623781676413255,
125
+ "f1-score": 0.6691610870421426,
126
+ "support": 2565.0
127
+ },
128
+ "optimism": {
129
+ "precision": 0.6713286713286714,
130
+ "recall": 0.5581395348837209,
131
+ "f1-score": 0.6095238095238096,
132
+ "support": 172.0
133
+ },
134
+ "pride": {
135
+ "precision": 0.3333333333333333,
136
+ "recall": 0.1,
137
+ "f1-score": 0.15384615384615385,
138
+ "support": 10.0
139
+ },
140
+ "realization": {
141
+ "precision": 0.5625,
142
+ "recall": 0.15384615384615385,
143
+ "f1-score": 0.24161073825503357,
144
+ "support": 117.0
145
+ },
146
+ "relief": {
147
+ "precision": 0.0,
148
+ "recall": 0.0,
149
+ "f1-score": 0.0,
150
+ "support": 17.0
151
+ },
152
+ "remorse": {
153
+ "precision": 0.6122448979591837,
154
+ "recall": 0.8450704225352113,
155
+ "f1-score": 0.7100591715976331,
156
+ "support": 71.0
157
+ },
158
+ "sadness": {
159
+ "precision": 0.5540540540540541,
160
+ "recall": 0.5030674846625767,
161
+ "f1-score": 0.5273311897106109,
162
+ "support": 163.0
163
+ },
164
+ "surprise": {
165
+ "precision": 0.5688622754491018,
166
+ "recall": 0.6597222222222222,
167
+ "f1-score": 0.6109324758842444,
168
+ "support": 144.0
169
+ },
170
+ "accuracy": 0.6023134122831176,
171
+ "macro avg": {
172
+ "precision": 0.5125054563961818,
173
+ "recall": 0.47883579303055207,
174
+ "f1-score": 0.48261389641901975,
175
+ "support": 7262.0
176
+ },
177
+ "weighted avg": {
178
+ "precision": 0.6008835076974202,
179
+ "recall": 0.6023134122831176,
180
+ "f1-score": 0.595804330387673,
181
+ "support": 7262.0
182
+ }
183
+ }
outputs/metrics/report.json ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "admiration": {
3
+ "precision": 0.6699186991869919,
4
+ "recall": 0.7601476014760148,
5
+ "f1-score": 0.7121866897147796,
6
+ "support": 542.0
7
+ },
8
+ "amusement": {
9
+ "precision": 0.727979274611399,
10
+ "recall": 0.8515151515151516,
11
+ "f1-score": 0.7849162011173184,
12
+ "support": 330.0
13
+ },
14
+ "anger": {
15
+ "precision": 0.4329501915708812,
16
+ "recall": 0.551219512195122,
17
+ "f1-score": 0.48497854077253216,
18
+ "support": 205.0
19
+ },
20
+ "annoyance": {
21
+ "precision": 0.2983425414364641,
22
+ "recall": 0.18620689655172415,
23
+ "f1-score": 0.22929936305732485,
24
+ "support": 290.0
25
+ },
26
+ "approval": {
27
+ "precision": 0.38440111420612816,
28
+ "recall": 0.368,
29
+ "f1-score": 0.3760217983651226,
30
+ "support": 375.0
31
+ },
32
+ "caring": {
33
+ "precision": 0.375,
34
+ "recall": 0.4846153846153846,
35
+ "f1-score": 0.4228187919463087,
36
+ "support": 130.0
37
+ },
38
+ "confusion": {
39
+ "precision": 0.4965986394557823,
40
+ "recall": 0.42441860465116277,
41
+ "f1-score": 0.45768025078369906,
42
+ "support": 172.0
43
+ },
44
+ "curiosity": {
45
+ "precision": 0.4628099173553719,
46
+ "recall": 0.60431654676259,
47
+ "f1-score": 0.5241809672386896,
48
+ "support": 278.0
49
+ },
50
+ "desire": {
51
+ "precision": 0.640625,
52
+ "recall": 0.5256410256410257,
53
+ "f1-score": 0.5774647887323944,
54
+ "support": 78.0
55
+ },
56
+ "disappointment": {
57
+ "precision": 0.3258426966292135,
58
+ "recall": 0.20422535211267606,
59
+ "f1-score": 0.2510822510822511,
60
+ "support": 142.0
61
+ },
62
+ "disapproval": {
63
+ "precision": 0.3228915662650602,
64
+ "recall": 0.4785714285714286,
65
+ "f1-score": 0.3856115107913669,
66
+ "support": 280.0
67
+ },
68
+ "disgust": {
69
+ "precision": 0.5113636363636364,
70
+ "recall": 0.45,
71
+ "f1-score": 0.4787234042553192,
72
+ "support": 100.0
73
+ },
74
+ "embarrassment": {
75
+ "precision": 0.7931034482758621,
76
+ "recall": 0.5609756097560976,
77
+ "f1-score": 0.6571428571428571,
78
+ "support": 41.0
79
+ },
80
+ "excitement": {
81
+ "precision": 0.42105263157894735,
82
+ "recall": 0.3137254901960784,
83
+ "f1-score": 0.3595505617977528,
84
+ "support": 102.0
85
+ },
86
+ "fear": {
87
+ "precision": 0.8113207547169812,
88
+ "recall": 0.5,
89
+ "f1-score": 0.6187050359712231,
90
+ "support": 86.0
91
+ },
92
+ "gratitude": {
93
+ "precision": 0.9085872576177285,
94
+ "recall": 0.8840970350404312,
95
+ "f1-score": 0.8961748633879781,
96
+ "support": 371.0
97
+ },
98
+ "grief": {
99
+ "precision": 0.0,
100
+ "recall": 0.0,
101
+ "f1-score": 0.0,
102
+ "support": 8.0
103
+ },
104
+ "joy": {
105
+ "precision": 0.55,
106
+ "recall": 0.5789473684210527,
107
+ "f1-score": 0.5641025641025641,
108
+ "support": 171.0
109
+ },
110
+ "love": {
111
+ "precision": 0.7774193548387097,
112
+ "recall": 0.8456140350877193,
113
+ "f1-score": 0.8100840336134454,
114
+ "support": 285.0
115
+ },
116
+ "nervousness": {
117
+ "precision": 0.46153846153846156,
118
+ "recall": 0.35294117647058826,
119
+ "f1-score": 0.4,
120
+ "support": 17.0
121
+ },
122
+ "neutral": {
123
+ "precision": 0.6760843613211301,
124
+ "recall": 0.6623781676413255,
125
+ "f1-score": 0.6691610870421426,
126
+ "support": 2565.0
127
+ },
128
+ "optimism": {
129
+ "precision": 0.6713286713286714,
130
+ "recall": 0.5581395348837209,
131
+ "f1-score": 0.6095238095238096,
132
+ "support": 172.0
133
+ },
134
+ "pride": {
135
+ "precision": 0.3333333333333333,
136
+ "recall": 0.1,
137
+ "f1-score": 0.15384615384615385,
138
+ "support": 10.0
139
+ },
140
+ "realization": {
141
+ "precision": 0.5625,
142
+ "recall": 0.15384615384615385,
143
+ "f1-score": 0.24161073825503357,
144
+ "support": 117.0
145
+ },
146
+ "relief": {
147
+ "precision": 0.0,
148
+ "recall": 0.0,
149
+ "f1-score": 0.0,
150
+ "support": 17.0
151
+ },
152
+ "remorse": {
153
+ "precision": 0.6122448979591837,
154
+ "recall": 0.8450704225352113,
155
+ "f1-score": 0.7100591715976331,
156
+ "support": 71.0
157
+ },
158
+ "sadness": {
159
+ "precision": 0.5540540540540541,
160
+ "recall": 0.5030674846625767,
161
+ "f1-score": 0.5273311897106109,
162
+ "support": 163.0
163
+ },
164
+ "surprise": {
165
+ "precision": 0.5688622754491018,
166
+ "recall": 0.6597222222222222,
167
+ "f1-score": 0.6109324758842444,
168
+ "support": 144.0
169
+ },
170
+ "accuracy": 0.6023134122831176,
171
+ "macro avg": {
172
+ "precision": 0.5125054563961818,
173
+ "recall": 0.47883579303055207,
174
+ "f1-score": 0.48261389641901975,
175
+ "support": 7262.0
176
+ },
177
+ "weighted avg": {
178
+ "precision": 0.6008835076974202,
179
+ "recall": 0.6023134122831176,
180
+ "f1-score": 0.595804330387673,
181
+ "support": 7262.0
182
+ }
183
+ }
outputs/model-old/.gitkeep ADDED
File without changes
outputs/model-old/.ipynb_checkpoints/special_tokens_map-checkpoint.json ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ {
2
+ "cls_token": "[CLS]",
3
+ "mask_token": "[MASK]",
4
+ "pad_token": "[PAD]",
5
+ "sep_token": "[SEP]",
6
+ "unk_token": "[UNK]"
7
+ }
outputs/model-old/config.json ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_name_or_path": "bert-base-uncased",
3
+ "architectures": [
4
+ "BertForSequenceClassification"
5
+ ],
6
+ "attention_probs_dropout_prob": 0.1,
7
+ "classifier_dropout": null,
8
+ "gradient_checkpointing": false,
9
+ "hidden_act": "gelu",
10
+ "hidden_dropout_prob": 0.1,
11
+ "hidden_size": 768,
12
+ "id2label": {
13
+ "0": "LABEL_0",
14
+ "1": "LABEL_1",
15
+ "2": "LABEL_2",
16
+ "3": "LABEL_3",
17
+ "4": "LABEL_4",
18
+ "5": "LABEL_5",
19
+ "6": "LABEL_6",
20
+ "7": "LABEL_7",
21
+ "8": "LABEL_8",
22
+ "9": "LABEL_9",
23
+ "10": "LABEL_10",
24
+ "11": "LABEL_11",
25
+ "12": "LABEL_12",
26
+ "13": "LABEL_13",
27
+ "14": "LABEL_14",
28
+ "15": "LABEL_15",
29
+ "16": "LABEL_16",
30
+ "17": "LABEL_17",
31
+ "18": "LABEL_18",
32
+ "19": "LABEL_19",
33
+ "20": "LABEL_20",
34
+ "21": "LABEL_21",
35
+ "22": "LABEL_22",
36
+ "23": "LABEL_23",
37
+ "24": "LABEL_24",
38
+ "25": "LABEL_25",
39
+ "26": "LABEL_26",
40
+ "27": "LABEL_27"
41
+ },
42
+ "initializer_range": 0.02,
43
+ "intermediate_size": 3072,
44
+ "label2id": {
45
+ "LABEL_0": 0,
46
+ "LABEL_1": 1,
47
+ "LABEL_10": 10,
48
+ "LABEL_11": 11,
49
+ "LABEL_12": 12,
50
+ "LABEL_13": 13,
51
+ "LABEL_14": 14,
52
+ "LABEL_15": 15,
53
+ "LABEL_16": 16,
54
+ "LABEL_17": 17,
55
+ "LABEL_18": 18,
56
+ "LABEL_19": 19,
57
+ "LABEL_2": 2,
58
+ "LABEL_20": 20,
59
+ "LABEL_21": 21,
60
+ "LABEL_22": 22,
61
+ "LABEL_23": 23,
62
+ "LABEL_24": 24,
63
+ "LABEL_25": 25,
64
+ "LABEL_26": 26,
65
+ "LABEL_27": 27,
66
+ "LABEL_3": 3,
67
+ "LABEL_4": 4,
68
+ "LABEL_5": 5,
69
+ "LABEL_6": 6,
70
+ "LABEL_7": 7,
71
+ "LABEL_8": 8,
72
+ "LABEL_9": 9
73
+ },
74
+ "layer_norm_eps": 1e-12,
75
+ "max_position_embeddings": 512,
76
+ "model_type": "bert",
77
+ "num_attention_heads": 12,
78
+ "num_hidden_layers": 12,
79
+ "pad_token_id": 0,
80
+ "position_embedding_type": "absolute",
81
+ "problem_type": "single_label_classification",
82
+ "torch_dtype": "float32",
83
+ "transformers_version": "4.45.2",
84
+ "type_vocab_size": 2,
85
+ "use_cache": true,
86
+ "vocab_size": 30522
87
+ }
outputs/model-old/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a22a9c126ae06332bdd125ee414560a9539321c42dcfd4882c50f56b7d5a8c35
3
+ size 438038624
outputs/model-old/special_tokens_map.json ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ {
2
+ "cls_token": "[CLS]",
3
+ "mask_token": "[MASK]",
4
+ "pad_token": "[PAD]",
5
+ "sep_token": "[SEP]",
6
+ "unk_token": "[UNK]"
7
+ }
outputs/model-old/tokenizer_config.json ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "added_tokens_decoder": {
3
+ "0": {
4
+ "content": "[PAD]",
5
+ "lstrip": false,
6
+ "normalized": false,
7
+ "rstrip": false,
8
+ "single_word": false,
9
+ "special": true
10
+ },
11
+ "100": {
12
+ "content": "[UNK]",
13
+ "lstrip": false,
14
+ "normalized": false,
15
+ "rstrip": false,
16
+ "single_word": false,
17
+ "special": true
18
+ },
19
+ "101": {
20
+ "content": "[CLS]",
21
+ "lstrip": false,
22
+ "normalized": false,
23
+ "rstrip": false,
24
+ "single_word": false,
25
+ "special": true
26
+ },
27
+ "102": {
28
+ "content": "[SEP]",
29
+ "lstrip": false,
30
+ "normalized": false,
31
+ "rstrip": false,
32
+ "single_word": false,
33
+ "special": true
34
+ },
35
+ "103": {
36
+ "content": "[MASK]",
37
+ "lstrip": false,
38
+ "normalized": false,
39
+ "rstrip": false,
40
+ "single_word": false,
41
+ "special": true
42
+ }
43
+ },
44
+ "clean_up_tokenization_spaces": true,
45
+ "cls_token": "[CLS]",
46
+ "do_basic_tokenize": true,
47
+ "do_lower_case": true,
48
+ "mask_token": "[MASK]",
49
+ "model_max_length": 512,
50
+ "never_split": null,
51
+ "pad_token": "[PAD]",
52
+ "sep_token": "[SEP]",
53
+ "strip_accents": null,
54
+ "tokenize_chinese_chars": true,
55
+ "tokenizer_class": "BertTokenizer",
56
+ "unk_token": "[UNK]"
57
+ }
outputs/model-old/vocab.txt ADDED
The diff for this file is too large to render. See raw diff
 
outputs/model/config.json ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_name_or_path": "outputs/model",
3
+ "architectures": [
4
+ "BertForSequenceClassification"
5
+ ],
6
+ "attention_probs_dropout_prob": 0.1,
7
+ "classifier_dropout": null,
8
+ "gradient_checkpointing": false,
9
+ "hidden_act": "gelu",
10
+ "hidden_dropout_prob": 0.1,
11
+ "hidden_size": 768,
12
+ "id2label": {
13
+ "0": "LABEL_0",
14
+ "1": "LABEL_1",
15
+ "2": "LABEL_2",
16
+ "3": "LABEL_3",
17
+ "4": "LABEL_4",
18
+ "5": "LABEL_5",
19
+ "6": "LABEL_6",
20
+ "7": "LABEL_7",
21
+ "8": "LABEL_8",
22
+ "9": "LABEL_9",
23
+ "10": "LABEL_10",
24
+ "11": "LABEL_11",
25
+ "12": "LABEL_12",
26
+ "13": "LABEL_13",
27
+ "14": "LABEL_14",
28
+ "15": "LABEL_15",
29
+ "16": "LABEL_16",
30
+ "17": "LABEL_17",
31
+ "18": "LABEL_18",
32
+ "19": "LABEL_19",
33
+ "20": "LABEL_20",
34
+ "21": "LABEL_21",
35
+ "22": "LABEL_22",
36
+ "23": "LABEL_23",
37
+ "24": "LABEL_24",
38
+ "25": "LABEL_25",
39
+ "26": "LABEL_26",
40
+ "27": "LABEL_27"
41
+ },
42
+ "initializer_range": 0.02,
43
+ "intermediate_size": 3072,
44
+ "label2id": {
45
+ "LABEL_0": 0,
46
+ "LABEL_1": 1,
47
+ "LABEL_10": 10,
48
+ "LABEL_11": 11,
49
+ "LABEL_12": 12,
50
+ "LABEL_13": 13,
51
+ "LABEL_14": 14,
52
+ "LABEL_15": 15,
53
+ "LABEL_16": 16,
54
+ "LABEL_17": 17,
55
+ "LABEL_18": 18,
56
+ "LABEL_19": 19,
57
+ "LABEL_2": 2,
58
+ "LABEL_20": 20,
59
+ "LABEL_21": 21,
60
+ "LABEL_22": 22,
61
+ "LABEL_23": 23,
62
+ "LABEL_24": 24,
63
+ "LABEL_25": 25,
64
+ "LABEL_26": 26,
65
+ "LABEL_27": 27,
66
+ "LABEL_3": 3,
67
+ "LABEL_4": 4,
68
+ "LABEL_5": 5,
69
+ "LABEL_6": 6,
70
+ "LABEL_7": 7,
71
+ "LABEL_8": 8,
72
+ "LABEL_9": 9
73
+ },
74
+ "layer_norm_eps": 1e-12,
75
+ "max_position_embeddings": 512,
76
+ "model_type": "bert",
77
+ "num_attention_heads": 12,
78
+ "num_hidden_layers": 12,
79
+ "pad_token_id": 0,
80
+ "position_embedding_type": "absolute",
81
+ "problem_type": "single_label_classification",
82
+ "torch_dtype": "float32",
83
+ "transformers_version": "4.45.2",
84
+ "type_vocab_size": 2,
85
+ "use_cache": true,
86
+ "vocab_size": 30522
87
+ }
outputs/model/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a22a9c126ae06332bdd125ee414560a9539321c42dcfd4882c50f56b7d5a8c35
3
+ size 438038624
outputs/model/special_tokens_map.json ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cls_token": {
3
+ "content": "[CLS]",
4
+ "lstrip": false,
5
+ "normalized": false,
6
+ "rstrip": false,
7
+ "single_word": false
8
+ },
9
+ "mask_token": {
10
+ "content": "[MASK]",
11
+ "lstrip": false,
12
+ "normalized": false,
13
+ "rstrip": false,
14
+ "single_word": false
15
+ },
16
+ "pad_token": {
17
+ "content": "[PAD]",
18
+ "lstrip": false,
19
+ "normalized": false,
20
+ "rstrip": false,
21
+ "single_word": false
22
+ },
23
+ "sep_token": {
24
+ "content": "[SEP]",
25
+ "lstrip": false,
26
+ "normalized": false,
27
+ "rstrip": false,
28
+ "single_word": false
29
+ },
30
+ "unk_token": {
31
+ "content": "[UNK]",
32
+ "lstrip": false,
33
+ "normalized": false,
34
+ "rstrip": false,
35
+ "single_word": false
36
+ }
37
+ }
outputs/model/tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
outputs/model/tokenizer_config.json ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "added_tokens_decoder": {
3
+ "0": {
4
+ "content": "[PAD]",
5
+ "lstrip": false,
6
+ "normalized": false,
7
+ "rstrip": false,
8
+ "single_word": false,
9
+ "special": true
10
+ },
11
+ "100": {
12
+ "content": "[UNK]",
13
+ "lstrip": false,
14
+ "normalized": false,
15
+ "rstrip": false,
16
+ "single_word": false,
17
+ "special": true
18
+ },
19
+ "101": {
20
+ "content": "[CLS]",
21
+ "lstrip": false,
22
+ "normalized": false,
23
+ "rstrip": false,
24
+ "single_word": false,
25
+ "special": true
26
+ },
27
+ "102": {
28
+ "content": "[SEP]",
29
+ "lstrip": false,
30
+ "normalized": false,
31
+ "rstrip": false,
32
+ "single_word": false,
33
+ "special": true
34
+ },
35
+ "103": {
36
+ "content": "[MASK]",
37
+ "lstrip": false,
38
+ "normalized": false,
39
+ "rstrip": false,
40
+ "single_word": false,
41
+ "special": true
42
+ }
43
+ },
44
+ "clean_up_tokenization_spaces": true,
45
+ "cls_token": "[CLS]",
46
+ "do_basic_tokenize": true,
47
+ "do_lower_case": true,
48
+ "mask_token": "[MASK]",
49
+ "model_max_length": 512,
50
+ "never_split": null,
51
+ "pad_token": "[PAD]",
52
+ "sep_token": "[SEP]",
53
+ "strip_accents": null,
54
+ "tokenize_chinese_chars": true,
55
+ "tokenizer_class": "BertTokenizer",
56
+ "unk_token": "[UNK]"
57
+ }
outputs/model/vocab.txt ADDED
The diff for this file is too large to render. See raw diff
 
requirements.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ numpy
2
+ pandas
3
+ scikit-learn
4
+ transformers
5
+ torch
6
+ streamlit
7
+ captum
8
+ Pillow
9
+
save_clean_model.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from transformers import AutoModelForSequenceClassification, AutoTokenizer
2
+
3
+ # Load the current model from the existing folder
4
+ model = AutoModelForSequenceClassification.from_pretrained("outputs/model")
5
+ tokenizer = AutoTokenizer.from_pretrained("outputs/model")
6
+
7
+ # Save to a new folder without any GPU/device info
8
+ model.save_pretrained("outputs/model-clean")
9
+ tokenizer.save_pretrained("outputs/model-clean")
10
+
11
+ print("Model saved to outputs/model-clean")
12
+
src/__pycache__/data_loader.cpython-312.pyc ADDED
Binary file (2.17 kB). View file
 
src/__pycache__/evaluate.cpython-312.pyc ADDED
Binary file (2.11 kB). View file
 
src/__pycache__/model.cpython-312.pyc ADDED
Binary file (652 Bytes). View file
 
src/__pycache__/model_custom.cpython-312.pyc ADDED
Binary file (706 Bytes). View file
 
src/__pycache__/model_hartmann.cpython-312.pyc ADDED
Binary file (715 Bytes). View file