Bubbli commited on
Commit
0564338
·
verified ·
1 Parent(s): e463b01

Upload 7 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ XLM-R/assets/xlm_logo.ico filter=lfs diff=lfs merge=lfs -text
37
+ XLM-R/XLM-R.exe filter=lfs diff=lfs merge=lfs -text
XLM-R/INPUT_SAMPLE.csv ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ,Row No.,Student_Comment,Sarcasm_Label,MP_Label
2
+ 1,1,"""Class discussion ba to o labyrinth? Kasi hindi ko alam paano lalabas dito.""",0,0
3
+ 2,2,"""The pace of the lectures is too fast, making it hard to keep up and absorb the material.""",0,0
4
+ 3,3,"""The grading system feels harsh, and it’s not clear how we’re being evaluated.""",0,0
5
+ 4,4,"""Your monotone voice is just what we needed para ma-feel na nasa funeral service kami.""",1,1
6
+ 5,5,"""Thank you for inspiring us, prof! Inspired na kaming humanap ng ibang paraan para matuto.""",1,1
7
+ 6,6,"""Prof, ‘yung quizzes mo talagang pang-mastermind level! Hindi namin alam kung saan nanggaling ‘yung questions.""",1,1
8
+ 7,7,"""‘Yung class schedule natin, parang marathon. ‘Di ko na alam kung makakatapos pa ako.""",1,1
9
+ 8,8,"""Sir, impressive po yung paraan niyo mag-explain, parang mind-reader lang dapat yung estudyante.""",1,2
10
+ 9,9,"""Ma'am, I love how you expect us to know everything by ourselves.""",1,2
11
+ 10,10,"""Ang husay niyo po mag-explain, Ma'am! Parang algebra sa chemistry class.""",1,2
12
+ 11,11,"""Sa dami ng sinasabi mo, parang wala namang kwenta ‘yung mga yun.""",1,1
13
+ 12,12,"""Prof, ang clear ng slides mo! Clear na clear na parang walang laman.""",1,1
14
+ 13,13,"""your jokes during class really helped—especially sa pag-pass ng oras. sa subject? Meh.""",1,1
15
+ 14,14,"""Sir, ang creative mo. You turned this subject into an unsolvable puzzle.""",1,1
16
+ 15,15,"""I appreciate how you break down difficult topics into smaller, more manageable parts.""",1,1
XLM-R/XLM-R.exe ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:acc4de35cce2d55fa481cca059aab16cc9d51093d87db21f850a1e2005cac40e
3
+ size 1880754286
XLM-R/assets/xlm_logo.ico ADDED

Git LFS Details

  • SHA256: e78723acd0f521bda74d05b71ed29c63393b447d7f0202ac4d56c1d33169e927
  • Pointer size: 131 Bytes
  • Size of remote file: 195 kB
XLM-R/assets/xlm_logo.png ADDED
XLM-R/best_models/best_model_mtl_7.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6f858cb01045ef04b8f1fa02c527970c05dd0707c14188715b8b974dc6638036
3
+ size 1113052569
XLM-R/best_models/best_model_stl_7.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:50feef4e588b306f7c9ddc47da3d47d61d95b13f761b1292ac5a2c78d68510f2
3
+ size 1112655749
[SOURCE CODE] XLM-R Sarcasm and Mock Politeness Detector.py ADDED
@@ -0,0 +1,1292 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Integrated screens (home page, file upload for sarcasm, & file upload for mp)
2
+
3
+ """
4
+ Program Title: XLM-R: Sarcasm and Mock Politeness Detector
5
+
6
+ Overview:
7
+ 1. Main Window (Home Page):
8
+ a. Displays a title, logo, and two model selection buttons ("Sarcasm Detection" and "Sarcasm and Mock Politeness Detection").
9
+ b. Each button leads to a respective frame for file selection and classification.
10
+
11
+ UI Design and Navigation:
12
+ 1. Sarcasm Detection Frame:
13
+ a. Contains a file selection button for uploading a CSV file.
14
+ b. Includes an entry field to display the selected file path.
15
+ c. A "Classify" button initiates classification.
16
+ d. A "Back" button navigates to the home page.
17
+ 2. Sarcasm and Mock Politeness Detection Frame:
18
+ a. Similar to the Sarcasm Detection frame but for the "Sarcasm and Mock Politeness Detection" model.
19
+ b. Includes file selection, entry field, classify, and back buttons.
20
+ 3. UI Elements:
21
+ a. Rounded rectangle buttons and labels organize the interface with hover effects for a polished experience.
22
+
23
+ Utility Functions and Preprocessing:
24
+ 1. File Selection: Users can select CSV files using the filedialog.askopenfilename function.
25
+ 2. Emoticon and Emoji Processing:
26
+ a. replace_emoticons and convert_emoji_and_emoticon functions convert emoticons and emojis to textual descriptions.
27
+
28
+ Data Management:
29
+ 1. Lists & Dictionaries - Store labels, detected emoticons, and classification reports.
30
+ 2. Pandas DataFrame - Manages CSV file data, including student comments and classification labels.
31
+
32
+ Machine Learning Model:
33
+ 1. Model Architecture:
34
+ a. Multi-Task Learning Model - Uses shared encoder layers with separate classification heads for sarcasm and mock politeness.
35
+ 2. Tokenization & Embedding:
36
+ a. Uses XLMRobertaTokenizer for text processing and feature extraction.
37
+ 3. PyTorch Tensors & Neural Network:
38
+ a. Handles tokenized input and model predictions using XLM-RoBERTa.
39
+
40
+ Control Flow and Logic:
41
+ 1. Event-Driven Programming:
42
+ a. Tkinter handles UI interaction and event flow.
43
+ 2. Looping & Conditional Logic:
44
+ a. Loops for text processing and if-else conditions for classification decisions.
45
+ 3. Multithreading:
46
+ a. Ensures UI remains responsive while processing large datasets.
47
+
48
+ Performance Evaluation:
49
+ 1. Confusion Matrix Calculation:
50
+ a. Confusion matrix is computed and displayed after classification.
51
+ 2. Visualization:
52
+ a. Confusion matrix results are displayed in a visual format using Seaborn and Matplotlib.
53
+
54
+ """
55
+
56
+ import tkinter as tk
57
+ from tkinter import Canvas, filedialog
58
+ from tkinter import ttk
59
+ import threading
60
+ import emoji
61
+ import emot
62
+ import pandas as pd
63
+ import torch
64
+ from transformers import XLMRobertaTokenizer, XLMRobertaModel
65
+ import torch.nn as nn
66
+ from tkinter import messagebox
67
+ import seaborn as sns
68
+ import matplotlib.pyplot as plt
69
+ from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
70
+ from sklearn.metrics import classification_report, confusion_matrix
71
+ import numpy as np
72
+ import sys
73
+
74
+
75
+ def create_rounded_rectangle(canvas, x1, y1, x2, y2, radius=25, **kwargs):
76
+ points = [x1+radius, y1, x1+radius, y1, x2-radius, y1, x2-radius, y1,
77
+ x2, y1, x2, y1+radius, x2, y1+radius, x2, y2-radius, x2, y2-radius,
78
+ x2, y2, x2-radius, y2, x2-radius, y2, x1+radius, y2, x1+radius, y2,
79
+ x1, y2, x1, y2-radius, x1, y2-radius, x1, y1+radius, x1, y1+radius, x1, y1]
80
+ return canvas.create_polygon(points, **kwargs, smooth=True)
81
+
82
+ def choose_file(entry):
83
+ filename = filedialog.askopenfilename(filetypes=[("CSV Files", "*.csv")])
84
+ if filename:
85
+ entry.delete(0, tk.END)
86
+ entry.insert(0, filename)
87
+
88
+ def on_hover(canvas, button_bg, button_text):
89
+ canvas.itemconfig(button_bg, fill="#6c7ce0")
90
+ canvas.itemconfig(button_text, fill="white")
91
+
92
+ def on_leave(canvas, button_bg, button_text):
93
+ canvas.itemconfig(button_bg, fill="#3d52d5")
94
+ canvas.itemconfig(button_text, fill="white")
95
+
96
+ def bind_button_states(canvas, button_bg, button_text):
97
+ canvas.tag_bind(button_bg, "<Enter>", lambda e: on_hover(canvas, button_bg, button_text))
98
+ canvas.tag_bind(button_bg, "<Leave>", lambda e: on_leave(canvas, button_bg, button_text))
99
+ canvas.tag_bind(button_text, "<Enter>", lambda e: on_hover(canvas, button_bg, button_text))
100
+ canvas.tag_bind(button_text, "<Leave>", lambda e: on_leave(canvas, button_bg, button_text))
101
+
102
+ def show_page(page_frame):
103
+ home_frame.place_forget()
104
+ sarcasm_frame.place_forget()
105
+ mock_politeness_frame.place_forget()
106
+ Sarcasm_and_MP_Frame.place_forget()
107
+ Sarcasm_Frame.place_forget()
108
+ page_frame.place(x=0, y=0, width=1440, height=1000)
109
+ page_frame.update_idletasks()
110
+ page_frame.place(x=0, y=0, width=1440, height=1000)
111
+ page_frame.lift() # Bring the frame to the front
112
+
113
+
114
+
115
+ # Initialize the emoticon detector
116
+ emoticon_detector = emot.core.emot()
117
+
118
+ def replace_emoticons(text):
119
+ # Detect emoticons in the text
120
+ detected_emoticons = emoticon_detector.emoticons(text)
121
+ # Get the lists of emoticons and their meanings
122
+ emoticons = detected_emoticons['value']
123
+ meanings = detected_emoticons['mean']
124
+
125
+ # Loop over each emoticon and its meaning
126
+ for i in range(len(emoticons)):
127
+ emoticon = emoticons[i]
128
+ description = meanings[i]
129
+ # Replace emoticon with its description
130
+ text = text.replace(emoticon, description)
131
+ return text
132
+
133
+ # Integrating into the overall function
134
+ def convert_emoji_and_emoticon(text):
135
+ text = emoji.demojize(text, delimiters=("", "")) # Convert emojis to text
136
+ text = replace_emoticons(text) # Replace emoticons with descriptions
137
+ return text
138
+
139
+
140
+ # Home page / Main window
141
+ root = tk.Tk()
142
+ root.title("XLM-RoBERTa Model Selection")
143
+ root.geometry("1440x1000")
144
+ root.resizable(False, False)
145
+ root.configure(bg='white')
146
+
147
+
148
+ #####################################################################################################################################################
149
+
150
+ # Home Page Frame
151
+ home_frame = tk.Frame(root, bg="white")
152
+ home_frame.place(x=0, y=0, width=1440, height=1000)
153
+
154
+ # Indigo rectangle (left)
155
+ indigo_frame = tk.Frame(home_frame, bg="#090c9b")
156
+ indigo_frame.place(x=0, y=0, width=475, height=1024)
157
+
158
+ # Logo
159
+ logo_image = tk.PhotoImage(file="assets/xlm_logo.png")
160
+ logo_label = tk.Label(home_frame, image=logo_image, bg="#090c9b")
161
+ logo_label.place(x=10, y=367, width=450, height=350)
162
+
163
+ # Title for the home page
164
+ title_label = tk.Label(home_frame, text="Choose a Model", font=("Inter", 60, "bold", "underline"), bg="white", fg="#3c3744")
165
+ title_label.place(x=660, y=136)
166
+
167
+ # White rectangle (right)
168
+ canvas_home = Canvas(home_frame, bg="white", highlightthickness=0)
169
+ canvas_home.place(x=490, y=280, width=900, height=550)
170
+
171
+ # Frames for labels
172
+ create_rounded_rectangle(canvas_home, 50, 50, 375, 375, radius=30, fill="white", outline="#3d52d5", width=4) # Frame 1
173
+ create_rounded_rectangle(canvas_home, 475, 50, 875, 375, radius=30, fill="white", outline="#3d52d5", width=4) # Frame 2
174
+
175
+ # Labels
176
+ canvas_home.create_text(210, 200, text="Sarcasm\nDetection", font=("Inter", 30, "bold"), fill="#3c3744", justify='center')
177
+ canvas_home.create_text(675, 210, text="Sarcasm and\nMock Politeness\nDetection", font=("Inter", 30, "bold"), fill="#3c3744", justify='center')
178
+
179
+ # Button 1 (for Sarcasm Detection)
180
+ button1_bg = create_rounded_rectangle(canvas_home, 45, 470, 385, 530, radius=20, fill="#3d52d5", outline="#3d52d5")
181
+ button1_text = canvas_home.create_text(212, 500, text="Select", font=("Inter", 25, "bold"), fill="white")
182
+ bind_button_states(canvas_home, button1_bg, button1_text)
183
+
184
+ # Bind Select button (for Sarcasm Detection)
185
+ canvas_home.tag_bind(button1_bg, "<Button-1>", lambda e: show_page(sarcasm_frame))
186
+ canvas_home.tag_bind(button1_text, "<Button-1>", lambda e: show_page(sarcasm_frame))
187
+
188
+ # Button 2 (for Sarcasm and Mock Politeness Detection)
189
+ button2_bg = create_rounded_rectangle(canvas_home, 475, 470, 875, 530, radius=20, fill="#3d52d5", outline="#3d52d5")
190
+ button2_text = canvas_home.create_text(670, 500, text="Select", font=("Inter", 25, "bold"), fill="white")
191
+ bind_button_states(canvas_home, button2_bg, button2_text)
192
+
193
+ # Bind Select button (for Sarcasm and Mock Politeness Detection)
194
+ canvas_home.tag_bind(button2_bg, "<Button-1>", lambda e: show_page(mock_politeness_frame))
195
+ canvas_home.tag_bind(button2_text, "<Button-1>", lambda e: show_page(mock_politeness_frame))
196
+
197
+
198
+
199
+ ####################################################################################################################################################3
200
+
201
+
202
+ # Sarcasm Detection Frame
203
+ sarcasm_frame = tk.Frame(root, bg="white")
204
+
205
+ # Indigo rectangle (left)
206
+ indigo_frame_sarcasm = tk.Frame(sarcasm_frame, bg="#090c9b")
207
+ indigo_frame_sarcasm.place(x=0, y=0, width=475, height=1024)
208
+
209
+ # Logo
210
+ logo_label_sarcasm = tk.Label(sarcasm_frame, image=logo_image, bg="#090c9b")
211
+ logo_label_sarcasm.place(x=10, y=367, width=450, height=350)
212
+
213
+ canvas_sarcasm = Canvas(sarcasm_frame, bg="white", highlightthickness=0)
214
+ canvas_sarcasm.place(x=490, y=150, width=900, height=800)
215
+
216
+ # Title Label
217
+ canvas_sarcasm.create_text(480, 250, text="Sarcasm Detection", font=("Inter", 40, "bold", "underline"), fill="#3d52d5", justify='center')
218
+
219
+ # File selection button for Sarcasm Detection
220
+ choose_file_bg_sarcasm = create_rounded_rectangle(canvas_sarcasm, 200, 320, 400, 370, radius=20, fill="#3d52d5", outline="#3d52d5")
221
+ choose_file_text_sarcasm = canvas_sarcasm.create_text(300, 345, text="Choose CSV File", font=("Inter", 14, "bold"), fill="white")
222
+ bind_button_states(canvas_sarcasm, choose_file_bg_sarcasm, choose_file_text_sarcasm)
223
+
224
+ # Entry field
225
+ entry_bg_sarcasm = create_rounded_rectangle(canvas_sarcasm, 420, 320, 820, 370, radius=20, fill="white", outline="#3d52d5")
226
+ file_entry_sarcasm = tk.Entry(canvas_sarcasm, font=("Inter", 14), width=35, bd=0, relief="flat")
227
+ file_path_sarcasm = file_entry_sarcasm.get()
228
+ canvas_sarcasm.create_window(620, 345, window=file_entry_sarcasm)
229
+
230
+ # Choose file bind button (Sarcasm Detection)
231
+ canvas_sarcasm.tag_bind(choose_file_bg_sarcasm, "<Button-1>", lambda e: choose_file(file_entry_sarcasm))
232
+ canvas_sarcasm.tag_bind(choose_file_text_sarcasm, "<Button-1>", lambda e: choose_file(file_entry_sarcasm))
233
+
234
+ # Classify button
235
+ classify_bg_sarcasm = create_rounded_rectangle(canvas_sarcasm, 350, 450, 600, 500, radius=20, fill="#3d52d5", outline="#3d52d5")
236
+ classify_text_sarcasm = canvas_sarcasm.create_text(475, 475, text="Classify", font=("Inter", 16, "bold"), fill="white")
237
+ bind_button_states(canvas_sarcasm, classify_bg_sarcasm, classify_text_sarcasm)
238
+
239
+ # Back button
240
+ back_bg_sarcasm = create_rounded_rectangle(canvas_sarcasm, 700, 700, 800, 750, radius=20, fill="#3d52d5", outline="#3d52d5")
241
+ back_text_sarcasm = canvas_sarcasm.create_text(750, 725, text="Back", font=("Inter", 14, "bold"), fill="white")
242
+ bind_button_states(canvas_sarcasm, back_bg_sarcasm, back_text_sarcasm)
243
+
244
+
245
+ canvas_sarcasm.tag_bind(back_bg_sarcasm, "<Button-1>", lambda e: show_page(home_frame))
246
+ canvas_sarcasm.tag_bind(back_text_sarcasm, "<Button-1>", lambda e: show_page(home_frame))
247
+
248
+
249
+
250
+ ##############################################################################################################################################################
251
+
252
+
253
+ # Sarcasm and Mock Politeness Detection Frame
254
+ mock_politeness_frame = tk.Frame(root, bg="white")
255
+
256
+ # Indigo rectangle (left)
257
+ indigo_frame_mock = tk.Frame(mock_politeness_frame, bg="#090c9b")
258
+ indigo_frame_mock.place(x=0, y=0, width=475, height=1024)
259
+
260
+ # Logo
261
+ logo_label_mock = tk.Label(mock_politeness_frame, image=logo_image, bg="#090c9b")
262
+ logo_label_mock.place(x=10, y=367, width=450, height=350)
263
+
264
+ canvas_mock = Canvas(mock_politeness_frame, bg="white", highlightthickness=0)
265
+ canvas_mock.place(x=490, y=150, width=900, height=800)
266
+
267
+ # Title Label
268
+ canvas_mock.create_text(480, 220, text="Sarcasm and\nMock Politeness Detection", font=("Inter", 40, "bold", "underline"), fill="#3d52d5", justify='center')
269
+
270
+ # File selection button for Sarcasm and Mock Politeness Detection
271
+ choose_file_bg_mock = create_rounded_rectangle(canvas_mock, 200, 320, 400, 370, radius=20, fill="#3d52d5", outline="#3d52d5")
272
+ choose_file_text_mock = canvas_mock.create_text(300, 345, text="Choose CSV File", font=("Inter", 14, "bold"), fill="white")
273
+ bind_button_states(canvas_mock, choose_file_bg_mock, choose_file_text_mock)
274
+
275
+ # Entry field
276
+ entry_bg_mock = create_rounded_rectangle(canvas_mock, 420, 320, 820, 370, radius=20, fill="white", outline="#3d52d5")
277
+ file_entry_mock = tk.Entry(canvas_mock, font=("Inter", 14), width=35, bd=0, relief="flat")
278
+ file_path_mock = file_entry_mock.get()
279
+
280
+ canvas_mock.create_window(620, 345, window=file_entry_mock)
281
+
282
+ # Choose file bind button (Sarcasm and Mock Politeness Detection)
283
+ canvas_mock.tag_bind(choose_file_bg_mock, "<Button-1>", lambda e: choose_file(file_entry_mock))
284
+ canvas_mock.tag_bind(choose_file_text_mock, "<Button-1>", lambda e: choose_file(file_entry_mock))
285
+
286
+ # Classify button
287
+ classify_bg_mock = create_rounded_rectangle(canvas_mock, 350, 450, 600, 500, radius=20, fill="#3d52d5", outline="#3d52d5")
288
+ classify_text_mock = canvas_mock.create_text(475, 475, text="Classify", font=("Inter", 16, "bold"), fill="white")
289
+ bind_button_states(canvas_mock, classify_bg_mock, classify_text_mock)
290
+
291
+ # Back button
292
+ back_bg_mock = create_rounded_rectangle(canvas_mock, 700, 700, 800, 750, radius=20, fill="#3d52d5", outline="#3d52d5")
293
+ back_text_mock = canvas_mock.create_text(750, 725, text="Back", font=("Inter", 14, "bold"), fill="white")
294
+ bind_button_states(canvas_mock, back_bg_mock, back_text_mock)
295
+
296
+ # Bind back button event to go back to the home page
297
+ canvas_mock.tag_bind(back_bg_mock, "<Button-1>", lambda e: show_page(home_frame))
298
+ canvas_mock.tag_bind(back_text_mock, "<Button-1>", lambda e: show_page(home_frame))
299
+
300
+ ####################################################################################################################################
301
+ # Loading screen
302
+ def show_page_loading_screen(frame):
303
+ # Hide all frames by using place_forget, then show the specified frame
304
+ for widget in root.winfo_children():
305
+ if isinstance(widget, tk.Frame):
306
+ widget.place_forget() # Hide all frames
307
+
308
+ frame.place(x=0, y=0, width=1440, height=1000) # Show the desired frame
309
+
310
+
311
+ def LoadingFrame():
312
+ global loading_frame1 # Make these global
313
+
314
+ # Frame 1
315
+ loading_frame1 = tk.Frame(root, bg="white")
316
+ loading_frame1.place(x=0, y=0, width=1440, height=1000)
317
+
318
+ # Indigo rectangle (left) for Frame 1
319
+ indigo_frame1 = tk.Frame(loading_frame1, bg="#090c9b")
320
+ indigo_frame1.place(x=0, y=0, width=475, height=1024)
321
+
322
+ # Logo in Frame 1
323
+ logo_image = tk.PhotoImage(file="assets/xlm_logo.png") # Make sure this path is correct
324
+ logo_label = tk.Label(loading_frame1, image=logo_image, bg="#090c9b")
325
+ logo_label.image = logo_image
326
+ logo_label.place(x=10, y=367, width=450, height=350)
327
+
328
+ canvas_loading1 = Canvas(loading_frame1, bg="white", highlightthickness=0)
329
+ canvas_loading1.place(x=490, y=150, width=900, height=800)
330
+
331
+ # Title for Frame 1
332
+ title_label1 = tk.Label(loading_frame1, text="Predicting Labels...", font=("Inter", 50, "bold"), bg="white", fg="#3d52d5")
333
+ title_label1.place(x=660, y=400)
334
+
335
+
336
+ # Bind back button event to go back to the previous page
337
+
338
+ progress_bar = ttk.Progressbar(loading_frame1, orient="horizontal", length=300, mode="indeterminate")
339
+ progress_bar.place(x=660, y=530, width=640, height=20)
340
+
341
+ style_loading = ttk.Style()
342
+ style_loading.theme_use('clam') # Use a theme that supports color changes
343
+ style_loading.configure("custom.Horizontal.TProgressbar",
344
+ troughcolor="blue", # Background color of the progress bar
345
+ background="white") # Color of the progress
346
+ progress_bar['style'] = "custom.Horizontal.TProgressbar"
347
+
348
+ progress_bar.start() # Start the progress bar animation
349
+
350
+
351
+
352
+ return loading_frame1
353
+
354
+
355
+ ####################################################################################################################################
356
+ # Result Page for Sarcasm and NonSarcasm
357
+
358
+ Sarcasm_Frame = tk.Frame(root, bg="white")
359
+
360
+ # Indigo rectangle (left) with proper padding for margins
361
+ indigo_frame_Result_Sarcasm = tk.Frame(Sarcasm_Frame, bg="#090c9b")
362
+ indigo_frame_Result_Sarcasm.place(x=20, y=20, width=860, height=960) # Adding margin to each side
363
+
364
+ # White rectangle (right)
365
+ canvas_Sarcasm_Result = Canvas(Sarcasm_Frame, bg="white", highlightthickness=0)
366
+ canvas_Sarcasm_Result.place(x=900, y=150, width=510, height=800)
367
+
368
+ # Confusion matrix button
369
+ cm_bg_sarcasm = create_rounded_rectangle(canvas_Sarcasm_Result, 90, 400, 410, 500, radius=20, fill="#3d52d5", outline="#3d52d5")
370
+ cm_text_sarcasm = canvas_Sarcasm_Result.create_text(250, 448, text="Confusion Matrix", font=("Inter", 25 , "bold"), fill="white")
371
+ bind_button_states(canvas_Sarcasm_Result, cm_bg_sarcasm, cm_text_sarcasm)
372
+
373
+ # Bind the button click to save the file path and show the page
374
+ canvas_Sarcasm_Result.tag_bind(cm_bg_sarcasm, "<Button-1>", lambda e: stl_cm())
375
+ canvas_Sarcasm_Result.tag_bind(cm_text_sarcasm, "<Button-1>", lambda e: stl_cm())
376
+
377
+ # Title Label
378
+ canvas_Sarcasm_Result.create_text(250, 160, text="Results", font=("Inter", 30, "bold"), fill="#000000", justify='center')
379
+
380
+ # Placeholder text that will be updated dynamically
381
+ total_comments_text_sarcasm = canvas_Sarcasm_Result.create_text(250, 220, text="Total Comments = 0", font=("Inter", 20), fill="#000000", justify='center')
382
+ sarcasm_count_text_sarcasm = canvas_Sarcasm_Result.create_text(250, 260, text="Sarcasm Detection = 0", font=("Inter", 20), fill="#000000", justify='center')
383
+ non_sarcasm_count_text_sarcasm = canvas_Sarcasm_Result.create_text(250, 300, text="Non Sarcasm Detection = 0", font=("Inter", 20), fill="#000000", justify='center')
384
+
385
+ # Create the Back to Home button
386
+ back_home_bg = create_rounded_rectangle(canvas_Sarcasm_Result, 90, 520, 410, 620, radius=20,
387
+ fill="#3d52d5", outline="#3d52d5")
388
+ back_home_text = canvas_Sarcasm_Result.create_text(250, 570, text="Back to Home", font=("Inter", 25, "bold"), fill="white")
389
+
390
+ # Bind button states for hover effects and interactions
391
+ bind_button_states(canvas_Sarcasm_Result, back_home_bg, back_home_text)
392
+
393
+ # Bind the Back to Home button to show the home page
394
+ canvas_Sarcasm_Result.tag_bind(back_home_bg, "<Button-1>", lambda e: show_page(home_frame))
395
+ canvas_Sarcasm_Result.tag_bind(back_home_text, "<Button-1>", lambda e: show_page(home_frame))
396
+
397
+ # Display the result frame
398
+ Sarcasm_Frame.pack(fill=tk.BOTH, expand=True)
399
+
400
+ def sarcasm_model(file):
401
+
402
+
403
+ # Load your dataset
404
+ dataset = pd.read_csv(file)
405
+ global df, pred_sarcasm_labels
406
+ df = dataset
407
+
408
+ # Apply the conversion function to the 'Value' column in your dataset
409
+ df['Student_Comment'] = df['Student_Comment'].apply(convert_emoji_and_emoticon)
410
+
411
+ # Define the device
412
+ device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
413
+
414
+ # Load the tokenizer and model for XLM-Roberta
415
+ tokenizer = XLMRobertaTokenizer.from_pretrained('xlm-roberta-base')
416
+
417
+
418
+ # Define your custom model class for sarcasm detection
419
+ class CustomXLMRobertaModel(nn.Module):
420
+ def __init__(self, dropout_prob=0.3):
421
+ super(CustomXLMRobertaModel, self).__init__()
422
+ self.xlm_roberta = XLMRobertaModel.from_pretrained("xlm-roberta-base")
423
+
424
+ # Dropout layer
425
+ self.dropout = nn.Dropout(dropout_prob)
426
+
427
+ # Hidden layer size (adjust as needed)
428
+ hidden_layer_size = 128 # Adjust the size of the hidden layer as you see fit
429
+
430
+ # Sarcasm classification head with an extra hidden layer
431
+ self.classifier_sarcasm = nn.Sequential(
432
+ nn.Linear(self.xlm_roberta.config.hidden_size, hidden_layer_size), # First hidden layer
433
+ nn.ReLU(), # Activation function
434
+ nn.Linear(hidden_layer_size, 1) # Output layer for binary classification
435
+ )
436
+
437
+ # Loss functions
438
+ self.criterion_sarcasm = nn.BCEWithLogitsLoss() # Use BCEWithLogitsLoss for binary classification
439
+
440
+ def forward(self, input_ids, attention_mask, labels_sarcasm=None):
441
+ outputs = self.xlm_roberta(input_ids=input_ids, attention_mask=attention_mask)
442
+
443
+ # Get the CLS token output (first token's hidden state)
444
+ cls_token_output = outputs[0][:, 0, :] # Shape: [batch_size, hidden_size]
445
+
446
+ # Apply dropout to CLS token output
447
+ cls_token_output = self.dropout(cls_token_output)
448
+
449
+ # Sarcasm classification head
450
+ logits_sarcasm = self.classifier_sarcasm(cls_token_output).squeeze(-1) # Shape: [batch_size]
451
+
452
+ loss = None
453
+ if labels_sarcasm is not None :
454
+ # Compute the loss for both tasks
455
+ loss_sarcasm = self.criterion_sarcasm(logits_sarcasm, labels_sarcasm.float()) # Binary cross-entropy loss
456
+
457
+ # Combine losses (you can adjust the weights of the losses if needed)
458
+ loss = loss_sarcasm
459
+
460
+ return loss, logits_sarcasm
461
+
462
+ # Initialize the model
463
+ model = CustomXLMRobertaModel(dropout_prob=0.3)
464
+
465
+ # Load the tokenizer
466
+ tokenizer = XLMRobertaTokenizer.from_pretrained('xlm-roberta-base')
467
+
468
+ # Load your trained model state
469
+ try:
470
+ model.load_state_dict(torch.load(r"best_models\best_model_stl_7.pt", map_location=device))
471
+ except RuntimeError as e:
472
+ print(f"Error loading model state: {e}")
473
+
474
+ # Move model to the defined device
475
+ model.to(device)
476
+ model.eval() # Set the model to evaluation mode
477
+
478
+ global true_sarcasm_labels, pred_sarcasm_labels, pred_sarcasm_label
479
+ # Initialize lists to hold predicted sarcasm labels
480
+ pred_sarcasm_labels = []
481
+ true_sarcasm_labels= df['Sarcasm_Label'].tolist() # True labels for mock politeness
482
+
483
+ # Iterate over the DataFrame and get predictions
484
+ with torch.no_grad(): # Disable gradient calculation
485
+ for index, row in df.iterrows():
486
+ # Get the input text
487
+ input_text = row['Student_Comment']
488
+
489
+ # Tokenize the input
490
+ inputs = tokenizer(input_text, return_tensors='pt', padding=True, truncation=True)
491
+
492
+ # Move inputs to the device
493
+ inputs = {key: value.to(device) for key, value in inputs.items()}
494
+
495
+ # Forward pass to get model output (loss and logits_sarcasm)
496
+ _, logits_sarcasm = model(**inputs)
497
+
498
+ # Get predictions (1 for sarcasm, 0 for non-sarcasm)
499
+ predictions = (torch.sigmoid(logits_sarcasm) > 0.5).int().cpu().numpy()
500
+ pred_sarcasm_labels.extend(predictions)
501
+
502
+ # Loop through each row in your DataFrame to print the labels
503
+ for index, row in df.iterrows():
504
+ if index < len(pred_sarcasm_labels):
505
+
506
+ pred_sarcasm_label = 'Sarcasm' if pred_sarcasm_labels[index] == 1 else 'Non-Sarcasm'
507
+
508
+ # Print the sentence with the predicted label
509
+ print(f"Row No: {row['Row No.']}")
510
+ print(f"Sentence: {row['Student_Comment']}")
511
+ print(f"Predicted Sarcasm Label: {pred_sarcasm_label}")
512
+ print('-' * 80) # separator line for readability
513
+ else:
514
+ print(f"Prediction not available for index {index}.")
515
+
516
+ # Save the updated DataFrame to a CSV file
517
+ #output_file = "classified_output_STL.csv"
518
+ #df.to_csv(output_file, index=False)
519
+ #print(f"Classified output saved to {output_file}")
520
+
521
+
522
+ # Result Page for Sarcasm and Mock Politeness
523
+
524
+ class TreeviewTooltip:
525
+ def __init__(self, tree):
526
+ self.tree = tree
527
+ self.tooltip = None
528
+ self.tree.bind("<Motion>", self.on_hover)
529
+ self.hover_id = None # ID for the delayed tooltip
530
+
531
+ def on_hover(self, event):
532
+ # Get the item under the mouse
533
+ item = self.tree.identify_row(event.y)
534
+ column = self.tree.identify_column(event.x)
535
+
536
+ if item and column:
537
+ item_values = self.tree.item(item, "values")
538
+ col_index = int(column[1:]) - 1 # Convert from "#1", "#2" to index 0, 1
539
+ if 0 <= col_index < len(item_values):
540
+ text = item_values[col_index]
541
+
542
+ # Schedule the tooltip with a 1-second delay
543
+ if self.hover_id:
544
+ self.tree.after_cancel(self.hover_id) # Reset delay if moving
545
+ self.hover_id = self.tree.after(300, lambda: self.show_tooltip(event, text))
546
+ else:
547
+ self.hide_tooltip() # Hide if not hovering over a valid cell
548
+
549
+ def show_tooltip(self, event, text):
550
+ if self.tooltip:
551
+ self.tooltip.destroy() # Remove previous tooltip
552
+ self.tooltip = tk.Toplevel(self.tree)
553
+ self.tooltip.wm_overrideredirect(True) # Remove window decorations
554
+ self.tooltip.wm_geometry(f"+{event.x_root + 10}+{event.y_root + 10}") # Position near cursor
555
+
556
+ # Define maximum width before wrapping (adjust as needed)
557
+ max_width = 300
558
+
559
+ # Styling
560
+ label = tk.Label(
561
+ self.tooltip,
562
+ text=text,
563
+ background="white",
564
+ foreground="black",
565
+ relief="solid",
566
+ borderwidth=1,
567
+ padx=8,
568
+ pady=4,
569
+ font=("Inter", 14, "bold"),
570
+ wraplength=max_width, # Enables text wrapping
571
+ justify="left", # Align text for readability
572
+ )
573
+ label.pack(ipadx=6, ipady=3)
574
+ self.tooltip.configure(bg="gray") # Simulated drop shadow
575
+ self.tree.bind("<Leave>", self.hide_tooltip) # Hide on mouse leave
576
+
577
+ def hide_tooltip(self, event=None):
578
+ if self.tooltip:
579
+ self.tooltip.destroy()
580
+ self.tooltip = None
581
+ if self.hover_id:
582
+ self.tree.after_cancel(self.hover_id)
583
+ self.hover_id = None
584
+
585
+ # Function to load and display the CSV content in the Treeview
586
+ def load_csv_Sarcasm():
587
+ global tree # Make tree global for access in tooltip
588
+ # Create the Treeview widget
589
+ tree = ttk.Treeview(indigo_frame_Result_Sarcasm, columns=("Value", "Label"), show='headings', height=10)
590
+
591
+ # Define the columns
592
+ tree.heading("Value", text="Value")
593
+ tree.heading("Label", text="Label")
594
+
595
+ # Set the column widths
596
+ tree.column("Value", width=400, anchor='center') # Set width for the Value column
597
+ tree.column("Label", width=100, anchor='center') # Set width for the Label column
598
+
599
+ # Custom styling
600
+ style = ttk.Style()
601
+ style.configure("Treeview",
602
+ background="#b4c5e4", # Background color for the cells
603
+ foreground="black", # Text color for the cells
604
+ rowheight=50, # Row height (increased for visibility)
605
+ fieldbackground="#b4c5e4", # Field background color
606
+ borderwidth=2,
607
+ font=('Inter', 14)) # Width of the cell border
608
+
609
+ style.configure("Treeview.Heading",
610
+ padding=[11, 11, 11, 11],
611
+ background="white", # Header background color
612
+ foreground="black", # Header text color
613
+ font=('Inter', 18, 'bold', 'underline')) # Header font style
614
+
615
+ ''' #style.map("Treeview",
616
+ background=[('selected', '#d1e8ff')], # Color when row is selected
617
+ foreground=[('selected', 'black')]) # Text color when row is selected'''
618
+
619
+ # Counters for sarcasm and non-sarcasm
620
+ total_comments = 0
621
+ sarcasm_count = 0
622
+ non_sarcasm_count = 0
623
+
624
+ # Create a Scrollbar
625
+ scrollbar = ttk.Scrollbar(indigo_frame_Result_Sarcasm, orient="vertical", command=tree.yview)
626
+ tree.configure(yscrollcommand=scrollbar.set)
627
+
628
+ # Apply padding (margins) to the Treeview frame
629
+ indigo_frame_Result_Sarcasm.grid_columnconfigure(0, weight=1, pad=20)
630
+ indigo_frame_Result_Sarcasm.grid_rowconfigure(0, weight=1, pad=20)
631
+
632
+ # Place the Treeview and Scrollbar using grid for centering and alignment
633
+ tree.grid(row=0, column=0, sticky="nsew", padx=20, pady=20)
634
+ scrollbar.grid(row=0, column=1, sticky="ns")
635
+
636
+ for index, row in df.iterrows():
637
+ if index < len(pred_sarcasm_labels):
638
+ pred_sarcasm_label = (
639
+ 'Sarcasm' if pred_sarcasm_labels[index] == 1
640
+ else 'Non-Sarcasm'
641
+ )
642
+
643
+ # Insert the data row by row
644
+ tree.insert("", "end", values=(row['Student_Comment'], pred_sarcasm_label))
645
+ total_comments += 1
646
+ if pred_sarcasm_label == 'Sarcasm':
647
+ sarcasm_count += 1
648
+ else:
649
+ non_sarcasm_count += 1
650
+
651
+ canvas_Sarcasm_Result.itemconfig(total_comments_text_sarcasm, text="Total Comments = " + str(total_comments))
652
+ canvas_Sarcasm_Result.itemconfig(sarcasm_count_text_sarcasm, text="Sarcasm Detection = " + str(sarcasm_count))
653
+ canvas_Sarcasm_Result.itemconfig(non_sarcasm_count_text_sarcasm, text="Non-Sarcasm Detection = " + str(non_sarcasm_count))
654
+
655
+ TreeviewTooltip(tree) # Attach tooltip functionality
656
+
657
+ def followfunction_sarcasm():
658
+ # Show the loading frame first
659
+ loadingframe_sarcasm = LoadingFrame() # Create the loading frame and keep a reference to it
660
+
661
+ # Use threading to run the next steps without blocking the UI
662
+ threading.Thread(target=Sarcasm_save_file_path_and_show_page, args=(loadingframe_sarcasm,)).start()
663
+
664
+ def Sarcasm_save_file_path_and_show_page(loadingframe_sarcasm):
665
+ try:
666
+ file_path_sarcasm = file_entry_sarcasm.get().strip() # Get the file path and remove extra spaces
667
+
668
+ if not file_path_sarcasm: # Check if the file path is empty
669
+ raise ValueError("File path cannot be empty.")
670
+
671
+ # Now that the path is saved, call the sarcasm model
672
+ sarcasm_model(file_path_sarcasm)
673
+
674
+ # Load the CSV for Sarcasm and Non-Sarcasm
675
+ load_csv_Sarcasm()
676
+
677
+ # Destroy the loading frame once the process is complete
678
+ loadingframe_sarcasm.destroy()
679
+
680
+ # Call the function to show the Sarcasm_Frame page
681
+ show_page(Sarcasm_Frame)
682
+
683
+ except ValueError as e:
684
+ loadingframe_sarcasm.destroy() # Ensure the loading frame is removed if there's an error
685
+ messagebox.showerror("Error", str(e)) # Show an error message to the user
686
+
687
+
688
+ # Bind the button click to save the file path and show the page
689
+ canvas_sarcasm.tag_bind(classify_bg_sarcasm, "<Button-1>", lambda e: followfunction_sarcasm())
690
+ canvas_sarcasm.tag_bind(classify_text_sarcasm, "<Button-1>", lambda e: followfunction_sarcasm())
691
+ # Bind the button click to save the file path and show the page
692
+ canvas_Sarcasm_Result.tag_bind(cm_bg_sarcasm, "<Button-1>", lambda e: stl_cm())
693
+ canvas_Sarcasm_Result.tag_bind(cm_text_sarcasm, "<Button-1>", lambda e: stl_cm())
694
+
695
+ ####################################################################################################################################
696
+
697
+ # Result Page for Sarcasm and Mock Politeness
698
+
699
+ Sarcasm_and_MP_Frame = tk.Frame(root, bg="white")
700
+
701
+ # Indigo rectangle (left) with proper padding for margins
702
+ indigo_frame_Result_MP = tk.Frame(Sarcasm_and_MP_Frame, bg="#090c9b")
703
+ indigo_frame_Result_MP.place(x=20, y=20, width=860, height=960) # Adding margin to each side
704
+
705
+ # White rectangle (right)
706
+ canvas_MP_Result= Canvas(Sarcasm_and_MP_Frame, bg="white", highlightthickness=0)
707
+ canvas_MP_Result.place(x=900, y=150, width=510, height=800)
708
+
709
+ # Confusion matrix button
710
+ cm_bg_mock = create_rounded_rectangle(canvas_MP_Result,90, 400, 410, 500, radius=20, fill="#3d52d5", outline="#3d52d5")
711
+ cm_text_mock = canvas_MP_Result.create_text(250, 448, text="Confusion Matrix", font=("Inter", 25, "bold"), fill="white")
712
+ bind_button_states(canvas_MP_Result, cm_bg_mock, cm_text_mock)
713
+
714
+ # Bind the button click to save the file path and show the page
715
+ canvas_MP_Result.tag_bind(cm_bg_mock, "<Button-1>", lambda e: mtl_cm())
716
+ canvas_MP_Result.tag_bind(cm_text_mock, "<Button-1>", lambda e: mtl_cm())
717
+
718
+ # Title Label
719
+ canvas_MP_Result.create_text(250, 160, text="Results", font=("Inter", 30, "bold"), fill="#000000", justify='center')
720
+
721
+ # Placeholder text that will be updated dynamically
722
+ total_comments_text_mp = canvas_MP_Result.create_text(250, 220, text="Total Comments = 0", font=("Inter", 20), fill="#000000", justify='center')
723
+ sarcasm_count_text_mp = canvas_MP_Result.create_text(250, 260, text="Sarcasm Detection = 0", font=("Inter", 20), fill="#000000", justify='center')
724
+ mock_politeness_count_text_mp = canvas_MP_Result.create_text(250, 300, text="Mock Politeness Detection = 0", font=("Inter", 20), fill="#000000", justify='center')
725
+ non_sarcasm_count_text_mp = canvas_MP_Result.create_text(250, 340, text="Non-Sarcasm Detection = 0", font=("Inter", 20), fill="#000000", justify='center')
726
+
727
+ # Create the Back to Home button
728
+ back_home_bg = create_rounded_rectangle(canvas_MP_Result, 90, 520, 410, 620, radius=20,
729
+ fill="#3d52d5", outline="#3d52d5")
730
+ back_home_text = canvas_MP_Result.create_text(250, 570, text="Back to Home", font=("Inter", 25, "bold"), fill="white")
731
+
732
+ # Bind button states for hover effects and interactions
733
+ bind_button_states(canvas_MP_Result, back_home_bg, back_home_text)
734
+
735
+ # Bind the Back to Home button to show the home page
736
+ canvas_MP_Result.tag_bind(back_home_bg, "<Button-1>", lambda e: show_page(home_frame))
737
+ canvas_MP_Result.tag_bind(back_home_text, "<Button-1>", lambda e: show_page(home_frame))
738
+
739
+ # Display the result frame
740
+ Sarcasm_Frame.pack(fill=tk.BOTH, expand=True)
741
+
742
+ def MockPoliteness_Model(file):
743
+ # Load your dataset
744
+
745
+ dataset = pd.read_csv(file)
746
+ global df, pred_mock_politeness_labels, pred_mock_politeness_label
747
+ df = dataset
748
+ # Apply the conversion function to the 'Value' column in your dataset
749
+ df['Student_Comment'] = df['Student_Comment'].apply(convert_emoji_and_emoticon)
750
+
751
+ # Define the device
752
+ device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
753
+
754
+ # Load the tokenizer and model from the pre-trained model
755
+ tokenizer = XLMRobertaTokenizer.from_pretrained('xlm-roberta-base')
756
+
757
+
758
+ # Define your custom model class
759
+ class CustomXLMRobertaModel(nn.Module):
760
+ def __init__(self, dropout_prob=0.3):
761
+ super(CustomXLMRobertaModel, self).__init__()
762
+ self.xlm_roberta = XLMRobertaModel.from_pretrained("xlm-roberta-base")
763
+
764
+ # Dropout layer
765
+ self.dropout = nn.Dropout(dropout_prob)
766
+
767
+ # Hidden layer size (adjust as needed)
768
+ hidden_layer_size = 128 # Adjust the size of the hidden layer as you see fit
769
+
770
+ # Sarcasm classification head with an extra hidden layer
771
+ self.classifier_sarcasm = nn.Sequential(
772
+ nn.Linear(self.xlm_roberta.config.hidden_size, hidden_layer_size), # First hidden layer
773
+ nn.ReLU(), # Activation function
774
+ nn.Linear(hidden_layer_size, 1) # Output layer for binary classification
775
+ )
776
+
777
+ # Mock Politeness classification head with an extra hidden layer
778
+ self.classifier_mockpoliteness = nn.Sequential(
779
+ nn.Linear(self.xlm_roberta.config.hidden_size, hidden_layer_size), # First hidden layer
780
+ nn.ReLU(), # Activation function
781
+ nn.Linear(hidden_layer_size, 3) # Output layer for 3-class classification
782
+ )
783
+
784
+ # Loss functions
785
+ self.criterion_sarcasm = nn.BCEWithLogitsLoss() # For binary classification
786
+ self.criterion_mockpoliteness = nn.CrossEntropyLoss() # For multiclass classification
787
+
788
+ def forward(self, input_ids, attention_mask, labels_sarcasm=None, labels_mockpoliteness=None):
789
+ # XLM-RoBERTa forward pass
790
+ outputs = self.xlm_roberta(input_ids=input_ids, attention_mask=attention_mask)
791
+
792
+ # Get the CLS token output (first token's hidden state)
793
+ cls_token_output = outputs[0][:, 0, :] # Shape: [batch_size, hidden_size]
794
+
795
+ # Apply dropout to CLS token output
796
+ cls_token_output = self.dropout(cls_token_output)
797
+
798
+ # Sarcasm classification head
799
+ logits_sarcasm = self.classifier_sarcasm(cls_token_output).squeeze(-1) # Shape: [batch_size]
800
+
801
+ # Mock Politeness classification head
802
+ logits_mockpoliteness = self.classifier_mockpoliteness(cls_token_output) # Shape: [batch_size, 3]
803
+
804
+ loss = None
805
+ if labels_sarcasm is not None and labels_mockpoliteness is not None:
806
+ # Compute the loss for both tasks
807
+ loss_sarcasm = self.criterion_sarcasm(logits_sarcasm, labels_sarcasm.float()) # Binary cross-entropy loss
808
+ loss_mockpoliteness = self.criterion_mockpoliteness(logits_mockpoliteness, labels_mockpoliteness) # Cross-entropy loss
809
+
810
+ # Weighted combination of losses
811
+ loss = (loss_sarcasm + loss_mockpoliteness) / 2
812
+
813
+ return loss, logits_sarcasm, logits_mockpoliteness
814
+
815
+ # Initialize the model
816
+ model = CustomXLMRobertaModel(dropout_prob=0.3)
817
+
818
+
819
+ # Load your trained model state
820
+ try:
821
+ model.load_state_dict(torch.load(r"best_models\best_model_mtl_7.pt", map_location=device))
822
+ except RuntimeError as e:
823
+ print(f"Error loading model state: {e}")
824
+ # Handle the error or exit
825
+
826
+ # Move model to the defined device
827
+ model.to(device)
828
+ model.eval()
829
+ global pred_mock_politeness_labels, true_mock_politeness_labels
830
+ # Initialize lists to hold true and predicted mock politeness labels
831
+ pred_mock_politeness_labels = []
832
+ true_mock_politeness_labels = df['MP_Label'].tolist() # True labels for mock politeness
833
+
834
+ with torch.no_grad(): # Disable gradient calculation
835
+ for index, row in df.iterrows():
836
+ # Get the input text
837
+ input_text = row['Student_Comment']
838
+
839
+ # Tokenize the input
840
+ inputs = tokenizer(input_text, return_tensors='pt', padding=True, truncation=True)
841
+
842
+ # Move inputs to the device
843
+ inputs = {key: value.to(device) for key, value in inputs.items()}
844
+
845
+ # Forward pass to get model output (loss, logits_sarcasm, logits_mockpoliteness)
846
+ _, logits_sarcasm, logits_mockpoliteness = model(**inputs)
847
+
848
+ # Get predictions by taking the argmax of the mock politeness logits
849
+ predictions = torch.argmax(logits_mockpoliteness, dim=1).cpu().numpy()
850
+ pred_mock_politeness_labels.extend(predictions)
851
+ # Loop through each row in your DataFrame to print the labels
852
+ for index, row in df.iterrows():
853
+ # Check if the index exists in predictions
854
+ if index < len(pred_mock_politeness_labels):
855
+ # Predicted Mock Politeness Label
856
+ pred_mock_politeness_label = (
857
+ 'Mock Politeness' if pred_mock_politeness_labels[index] == 2
858
+ else 'Sarcasm' if pred_mock_politeness_labels[index] == 1
859
+ else 'Non-Sarcasm'
860
+ )
861
+
862
+ # Print the sentence with the true and predicted labels
863
+ print(f"Row No: {row['Row No.']}")
864
+ print(f"Sentence: {row['Student_Comment']}")
865
+ print("Predicted Mock Politeness Label: " + pred_mock_politeness_label)
866
+ print('-' * 80) # separator line for readability
867
+ else:
868
+ print(f"Prediction not available for index {index}.")
869
+
870
+ # Add predicted labels to the DataFrame
871
+ df['True_Label'] = [
872
+ 'Mock Politeness' if label == 2 else 'Sarcasm' if label == 1 else 'Non-Sarcasm'
873
+ for label in true_mock_politeness_labels
874
+ ]
875
+ df['Predicted_Label'] = [
876
+ 'Mock Politeness' if label == 2 else 'Sarcasm' if label == 1 else 'Non-Sarcasm'
877
+ for label in pred_mock_politeness_labels
878
+ ]
879
+ # Save the updated DataFrame to a CSV file
880
+ #output_file = "classified_output_MTL.csv"
881
+ #df.to_csv(output_file, index=False)
882
+ #print(f"Classified output saved to {output_file}")
883
+
884
+
885
+ # Result Page for Sarcasm and Mock Politeness
886
+
887
+ # Function to load and display the CSV content in the Treeview
888
+ def load_csv_Sarcasm_and_MP():
889
+ # Create the Treeview widget
890
+ tree = ttk.Treeview(indigo_frame_Result_MP, columns=("Value", "Label"), show='headings', height=10)
891
+
892
+ # Define the columns
893
+ tree.heading("Value", text="Value")
894
+ tree.heading("Label", text="Label")
895
+
896
+ # Set the column widths
897
+ tree.column("Value", width=460, anchor='center') # Set width for the Value column
898
+ tree.column("Label", width=40, anchor='center') # Set width for the Label column
899
+
900
+ # Custom styling
901
+ style = ttk.Style()
902
+ style.configure("Treeview",
903
+ background="#b4c5e4", # Background color for the cells
904
+ foreground="black", # Text color for the cells
905
+ rowheight=50, # Row height (increased for visibility)
906
+ fieldbackground="#b4c5e4", # Field background color
907
+ borderwidth=2,
908
+ font=('Inter', 14)) # Width of the cell border
909
+
910
+ style.configure("Treeview.Heading",
911
+ padding=[11, 11, 11, 11],
912
+ background="white", # Header background color
913
+ foreground="black", # Header text color
914
+ font=('Inter', 18, 'bold', 'underline')) # Header font style
915
+
916
+ ''' #style.map("Treeview",
917
+ background=[('selected', '#d1e8ff')], # Color when row is selected
918
+ foreground=[('selected', 'black')]) # Text color when row is selected'''
919
+
920
+ # Counters for sarcasm and non-sarcasm
921
+ total_comments = 0
922
+ sarcasm_count = 0
923
+ mock_politeness_count = 0
924
+ non_sarcasm = 0
925
+
926
+
927
+ # Read the CSV and insert the rows into the Treeview
928
+
929
+
930
+ # Create a Scrollbar
931
+ scrollbar = ttk.Scrollbar(indigo_frame_Result_MP, orient="vertical", command=tree.yview)
932
+ tree.configure(yscrollcommand=scrollbar.set)
933
+
934
+ # Apply padding (margins) to the Treeview frame
935
+ indigo_frame_Result_MP.grid_columnconfigure(0, weight=1, pad=20)
936
+ indigo_frame_Result_MP.grid_rowconfigure(0, weight=1, pad=20)
937
+
938
+ # Place the Treeview and Scrollbar using grid for centering and alignment
939
+ tree.grid(row=0, column=0, sticky="nsew", padx=20, pady=20)
940
+ scrollbar.grid(row=0, column=1, sticky="ns")
941
+ for index, row in df.iterrows():
942
+ if index < len(pred_mock_politeness_labels):
943
+
944
+ pred_mock_politeness_label = (
945
+ 'Mock Politeness' if pred_mock_politeness_labels[index] == 2
946
+ else 'Sarcasm' if pred_mock_politeness_labels[index] == 1
947
+ else 'Non-Sarcasm'
948
+ )
949
+
950
+ # Insert the data row by row
951
+ tree.insert("", "end", values=(row['Student_Comment'], pred_mock_politeness_label))
952
+ total_comments += 1
953
+ if pred_mock_politeness_labels[index] == 2:
954
+ mock_politeness_count += 1
955
+ elif pred_mock_politeness_labels[index] == 1:
956
+ sarcasm_count += 1
957
+ else:
958
+ non_sarcasm += 1
959
+
960
+
961
+ # Update the canvas_MP_Result text with the counts
962
+ canvas_MP_Result.itemconfig(total_comments_text_mp, text="Total Comments = " + str(total_comments))
963
+ canvas_MP_Result.itemconfig(sarcasm_count_text_mp, text="Sarcasm Detection = " + str(sarcasm_count))
964
+ canvas_MP_Result.itemconfig(mock_politeness_count_text_mp, text="Mock Politeness Detection = " + str(mock_politeness_count))
965
+ canvas_MP_Result.itemconfig(non_sarcasm_count_text_mp, text="Non-Sarcasm Detection = " + str(non_sarcasm))
966
+
967
+ TreeviewTooltip(tree) # Attach tooltip functionality
968
+
969
+
970
+ def followfunction_mock():
971
+ # Show the loading frame first
972
+ loadingframe_mock = LoadingFrame() # Create the loading frame and keep a reference to it
973
+
974
+ # Use threading to run the next steps without blocking the UI
975
+ threading.Thread(target=MP_save_file_path_and_show_page, args=(loadingframe_mock,)).start()
976
+
977
+
978
+
979
+ def MP_save_file_path_and_show_page(loadingframe_mock):
980
+ try:
981
+ file_path_mock = file_entry_mock.get() # Get the file path entered by the user
982
+
983
+ # Show the loading window
984
+ if not file_path_mock:
985
+ raise ValueError("File path cannot be empty.")
986
+
987
+ # Process the file with the selected path
988
+ MockPoliteness_Model(file_path_mock)
989
+
990
+ # Load CSV with Sarcasm and Mock Politeness data
991
+ load_csv_Sarcasm_and_MP()
992
+
993
+ loading_frame1.destroy()
994
+
995
+
996
+ # Show the new page or frame
997
+ show_page(Sarcasm_and_MP_Frame)
998
+ except ValueError as e:
999
+ loadingframe_mock.destroy() # Ensure the loading frame is removed if there's an error
1000
+ messagebox.showerror("Error", str(e)) # Show an error message to the user
1001
+
1002
+
1003
+
1004
+ # Bind the button click to save the file path and show the page
1005
+ canvas_mock.tag_bind(classify_bg_mock, "<Button-1>", lambda e: followfunction_mock())
1006
+ canvas_mock.tag_bind(classify_text_mock, "<Button-1>", lambda e: followfunction_mock())
1007
+
1008
+ #######################################################################################################################################################
1009
+
1010
+
1011
+ # Confusion matrix and metrics for sarcasm classification
1012
+ def stl_cm():
1013
+
1014
+
1015
+ # Check if true labels are provided and are not NaN
1016
+ if not true_sarcasm_labels or np.any(pd.isna(true_sarcasm_labels)):
1017
+ messagebox.showerror("Error", "A confusion matrix can't be generated due to lack of true labels.")
1018
+ return # Stop further execution if labels are missing or invalid
1019
+
1020
+ # STL Frame (Sarcasm Detection)
1021
+ global stl_frame
1022
+ stl_frame = tk.Frame(root, bg="white", width=1440, height=1000)
1023
+
1024
+ # Indigo rectangle (left) for STL Frame
1025
+ stl_left_frame = tk.Frame(stl_frame, bg="#090c9b", width=720, height=1000)
1026
+ stl_left_frame.pack(side=tk.LEFT, fill=tk.Y)
1027
+ stl_canvas_2 = Canvas(stl_left_frame, bg="#090c9b", highlightthickness=0)
1028
+ stl_canvas_2.place(x=0, y=0, width=720, height=1000)
1029
+ stl_left_label = tk.Label(stl_left_frame, text="Sarcasm Detection\nConfusion Matrix",
1030
+ font=("Inter", 28, "bold"), fg="white", bg="#090c9b", justify="center")
1031
+ stl_left_label.place(x=180, y=90)
1032
+
1033
+
1034
+ # White rectangle (right) for STL Frame
1035
+ stl_right_frame = tk.Frame(stl_frame, bg="white", width=720, height=1000)
1036
+ stl_right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)
1037
+ stl_canvas_1 = Canvas(stl_right_frame, bg="white", highlightthickness=0)
1038
+ stl_canvas_1.place(x=0, y=0, width=720, height=1000)
1039
+ stl_right_label = tk.Label(stl_right_frame, text="Performance Metrics", font=("Inter", 28, "bold"), fg="black", bg="white")
1040
+ stl_right_label.place(x=170, y=125)
1041
+
1042
+
1043
+
1044
+ # Create confusion matrix and classification report
1045
+ cm = confusion_matrix(true_sarcasm_labels, pred_sarcasm_labels)
1046
+ report = classification_report(true_sarcasm_labels, pred_sarcasm_labels, output_dict=True)
1047
+
1048
+ # Plot heatmap for confusion matrix on the left side
1049
+ fig, ax = plt.subplots(figsize=(6, 6)) # Create a figure and axis for the heatmap
1050
+ sns.heatmap(cm, annot=True, fmt="d", cmap="Blues", cbar=False,
1051
+ annot_kws={"size": 16}, # Increase annotation font size
1052
+ xticklabels=['Non-Sarcasm', 'Sarcasm'],
1053
+ yticklabels=['Non-Sarcasm', 'Sarcasm'], ax=ax)
1054
+
1055
+ ax.set_xlabel('Predicted Label', fontsize=18)
1056
+ ax.set_ylabel('True Label', fontsize=18)
1057
+
1058
+ # Set larger font for tick labels
1059
+ ax.tick_params(axis='both', which='major', labelsize=14)
1060
+
1061
+ # Embed Matplotlib figure in Tkinter's canvas
1062
+ canvas = FigureCanvasTkAgg(fig, master=stl_left_frame)
1063
+ canvas.draw()
1064
+ canvas.get_tk_widget().place(x=60, y=200)
1065
+
1066
+ # Create a Treeview for the classification report
1067
+ tree_frame = tk.Frame(stl_right_frame)
1068
+ tree_frame.place(x=50, y=200, width=620, height=600)
1069
+
1070
+ # Create Treeview without style
1071
+ tree2 = ttk.Treeview(tree_frame, columns=("Label", "Precision", "Recall", "F1 Score", "Support"), show='headings')
1072
+
1073
+ # Define column headings
1074
+ tree2.heading("Label", text="Label")
1075
+ tree2.heading("Precision", text="Precision")
1076
+ tree2.heading("Recall", text="Recall")
1077
+ tree2.heading("F1 Score", text="F1 Score")
1078
+ tree2.heading("Support", text="Support")
1079
+
1080
+ # Set column widths for better visibility
1081
+ tree2.column("Label", width=100, anchor='center') # Label column width
1082
+ tree2.column("Precision", width=130, anchor='center') # Precision column width
1083
+ tree2.column("Recall", width=130, anchor='center') # Recall column width
1084
+ tree2.column("F1 Score", width=130, anchor='center') # F1 Score column width
1085
+ tree2.column("Support", width=100, anchor='center') # Support column width
1086
+
1087
+ label_map = {
1088
+ '0': 'Non-Sarcasm',
1089
+ '1': 'Sarcasm',
1090
+
1091
+ }
1092
+
1093
+ # Insert data into the Treeview, converting scores to percentages
1094
+ for label, metrics in report.items():
1095
+ if label in label_map: # Only include the individual classes
1096
+ precision = "{:.2f}%".format(metrics['precision'] * 100)
1097
+ recall = "{:.2f}%".format(metrics['recall'] * 100)
1098
+ f1_score = "{:.2f}%".format(metrics['f1-score'] * 100)
1099
+ support = metrics['support']
1100
+ tree2.insert("", "end", values=(label_map[label], precision, recall, f1_score, support))
1101
+
1102
+ # Add macro and weighted averages
1103
+ macro_precision = "{:.2f}%".format(report['macro avg']['precision'] * 100)
1104
+ macro_recall = "{:.2f}%".format(report['macro avg']['recall'] * 100)
1105
+ macro_f1 = "{:.2f}%".format(report['macro avg']['f1-score'] * 100)
1106
+ macro_support = report['macro avg']['support']
1107
+
1108
+ weighted_precision = "{:.2f}%".format(report['weighted avg']['precision'] * 100)
1109
+ weighted_recall = "{:.2f}%".format(report['weighted avg']['recall'] * 100)
1110
+ weighted_f1 = "{:.2f}%".format(report['weighted avg']['f1-score'] * 100)
1111
+ weighted_support = report['weighted avg']['support']
1112
+
1113
+ tree2.insert("", "end", values=("Macro avg", macro_precision, macro_recall, macro_f1, macro_support))
1114
+ tree2.insert("", "end", values=("Weighted avg", weighted_precision, weighted_recall, weighted_f1, weighted_support))
1115
+
1116
+ # Add Scrollbars
1117
+ scrollbar_y = ttk.Scrollbar(tree_frame, orient="vertical", command=tree2.yview)
1118
+ scrollbar_y.pack(side='right', fill='y')
1119
+ tree2.configure(yscrollcommand=scrollbar_y.set)
1120
+
1121
+ scrollbar_x = ttk.Scrollbar(tree_frame, orient="horizontal", command=tree2.xview)
1122
+ scrollbar_x.pack(side='bottom', fill='x')
1123
+ tree2.configure(xscrollcommand=scrollbar_x.set)
1124
+
1125
+ tree2.pack(fill=tk.BOTH, expand=True)
1126
+
1127
+
1128
+ mtlbutton_bg = create_rounded_rectangle(stl_canvas_1, 230, 840, 490, 920, radius=20, fill="#3d52d5", outline="#3d52d5")
1129
+ mtlbutton_text = stl_canvas_1.create_text(360, 880, text="Back to Results", font=("Inter", 20, "bold"), fill="white")
1130
+ # Bind the hover effects for the button (for MTL transition)
1131
+ bind_button_states(stl_canvas_1, mtlbutton_bg, mtlbutton_text)
1132
+
1133
+
1134
+ # Bind the mtlbutton to switch from STL to MTL frame
1135
+ stl_canvas_1.tag_bind(mtlbutton_bg, "<Button-1>", lambda e: show_page(Sarcasm_Frame))
1136
+ stl_canvas_1.tag_bind(mtlbutton_text, "<Button-1>", lambda e: show_page(Sarcasm_Frame))
1137
+
1138
+ bbmtlbutton_bg = create_rounded_rectangle(stl_canvas_2, 230, 840, 490, 920, radius=20, fill="#3d52d5", outline="#3d52d5")
1139
+ bbmtlbutton_text = stl_canvas_2.create_text(360, 880, text="Back to Home", font=("Inter", 20, "bold"), fill="white")
1140
+ # Bind the hover effects for the button (for MTL transition)
1141
+ bind_button_states(stl_canvas_2, bbmtlbutton_bg, bbmtlbutton_text)
1142
+
1143
+
1144
+ # Bind the mtlbutton to switch from STL to MTL frame
1145
+ stl_canvas_2.tag_bind(bbmtlbutton_bg, "<Button-1>", lambda e: show_page(home_frame))
1146
+ stl_canvas_2.tag_bind(bbmtlbutton_text, "<Button-1>", lambda e: show_page(home_frame))
1147
+
1148
+ show_page(stl_frame)
1149
+
1150
+
1151
+ def mtl_cm():
1152
+
1153
+ # Check if true labels are provided and are not NaN
1154
+ if not true_mock_politeness_labels or np.any(pd.isna(true_mock_politeness_labels)):
1155
+ messagebox.showerror("Error", "A Confusion Matrix can't be generated due to lack of True Labels.")
1156
+ return # Stop further execution if labels are missing or invalid
1157
+
1158
+ global mtl_frame
1159
+
1160
+ # MTL Frame (Mock Politeness Detection)
1161
+ mtl_frame = Canvas(root, bg="white", width=1440, height=1000)
1162
+
1163
+
1164
+ # Indigo rectangle (left) for MTL Frame
1165
+ mtl_left_frame = tk.Frame(mtl_frame, bg="#090c9b", width=720, height=1000)
1166
+ mtl_left_frame.pack(side=tk.LEFT, fill=tk.Y)
1167
+ # White rectangle (right) for MTL Frame
1168
+ mtl_right_frame = Canvas(mtl_frame, bg="white", width=720, height=1000)
1169
+ mtl_right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)
1170
+ # Button to go back to STL
1171
+ mtl_canvas_1 = Canvas(mtl_right_frame, bg="white", highlightthickness=0)
1172
+ mtl_canvas_1.place(x=0, y=0, width=720, height=1000)
1173
+ mtl_canvas_2 = Canvas(mtl_left_frame, bg="#090c9b", highlightthickness=0)
1174
+ mtl_canvas_2.place(x=0, y=0, width=720, height=1000)
1175
+ mtl_left_label = tk.Label(mtl_left_frame, text="Sarcasm and Mock\nPoliteness Detection\nConfusion Matrix",
1176
+ font=("Inter", 28, "bold"), fg="white", bg="#090c9b", justify="center")
1177
+ mtl_left_label.place(x=180, y=40)
1178
+ mtl_right_label = tk.Label(mtl_right_frame, text="Performance Metrics", font=("Inter", 28, "bold"), fg="black", bg="white")
1179
+ mtl_right_label.place(x=170, y=125)
1180
+
1181
+ # Create confusion matrix and classification report
1182
+ cm = confusion_matrix(true_mock_politeness_labels, pred_mock_politeness_labels)
1183
+ report = classification_report(true_mock_politeness_labels, pred_mock_politeness_labels, output_dict=True)
1184
+
1185
+ # Plot heatmap for confusion matrix on the left side
1186
+ fig, ax = plt.subplots(figsize=(6, 6)) # Create a figure and axis for the heatmap
1187
+ sns.heatmap(cm, annot=True, fmt="d", cmap="Blues", cbar=False,
1188
+ annot_kws={"size": 16}, # Increase annotation font size
1189
+ xticklabels=['Non-Sarcasm', 'Sarcasm', 'Mock Politeness'],
1190
+ yticklabels=['Non-Sarcasm', 'Sarcasm', 'Mock Politeness'], ax=ax)
1191
+
1192
+ ax.set_xlabel('Predicted Label', fontsize=18)
1193
+ ax.set_ylabel('True Label', fontsize=18)
1194
+
1195
+ # Set larger font for tick labels
1196
+ ax.tick_params(axis='both', which='major', labelsize=14)
1197
+
1198
+ # Embed Matplotlib figure in Tkinter's canvas
1199
+ canvas = FigureCanvasTkAgg(fig, master=mtl_left_frame)
1200
+ canvas.draw()
1201
+ canvas.get_tk_widget().place(x=60, y=200)
1202
+
1203
+ # Create a Treeview for the classification report
1204
+ tree_frame = tk.Frame(mtl_right_frame)
1205
+ tree_frame.place(x=50, y=200, width=620, height=600)
1206
+
1207
+ # Create Treeview without style
1208
+ tree2 = ttk.Treeview(tree_frame, columns=("Label", "Precision", "Recall", "F1 Score", "Support"), show='headings')
1209
+
1210
+ # Define column headings
1211
+ tree2.heading("Label", text="Label")
1212
+ tree2.heading("Precision", text="Precision")
1213
+ tree2.heading("Recall", text="Recall")
1214
+ tree2.heading("F1 Score", text="F1 Score")
1215
+ tree2.heading("Support", text="Support")
1216
+
1217
+ # Set column widths for better visibility
1218
+ tree2.column("Label", width=100, anchor='center') # Label column width
1219
+ tree2.column("Precision", width=130, anchor='center') # Precision column width
1220
+ tree2.column("Recall", width=130, anchor='center') # Recall column width
1221
+ tree2.column("F1 Score", width=130, anchor='center') # F1 Score column width
1222
+ tree2.column("Support", width=100, anchor='center') # Support column width
1223
+
1224
+ label_map = {
1225
+ '0': 'Non-Sarcasm',
1226
+ '1': 'Sarcasm',
1227
+ '2': 'Mock Politeness'
1228
+ }
1229
+
1230
+ # Insert data into the Treeview, converting scores to percentages
1231
+ for label, metrics in report.items():
1232
+ if label in label_map: # Only include the individual classes
1233
+ precision = "{:.2f}%".format(metrics['precision'] * 100)
1234
+ recall = "{:.2f}%".format(metrics['recall'] * 100)
1235
+ f1_score = "{:.2f}%".format(metrics['f1-score'] * 100)
1236
+ support = metrics['support']
1237
+ tree2.insert("", "end", values=(label_map[label], precision, recall, f1_score, support))
1238
+
1239
+ # Add macro and weighted averages
1240
+ macro_precision = "{:.2f}%".format(report['macro avg']['precision'] * 100)
1241
+ macro_recall = "{:.2f}%".format(report['macro avg']['recall'] * 100)
1242
+ macro_f1 = "{:.2f}%".format(report['macro avg']['f1-score'] * 100)
1243
+ macro_support = report['macro avg']['support']
1244
+
1245
+ weighted_precision = "{:.2f}%".format(report['weighted avg']['precision'] * 100)
1246
+ weighted_recall = "{:.2f}%".format(report['weighted avg']['recall'] * 100)
1247
+ weighted_f1 = "{:.2f}%".format(report['weighted avg']['f1-score'] * 100)
1248
+ weighted_support = report['weighted avg']['support']
1249
+
1250
+ tree2.insert("", "end", values=("Macro avg", macro_precision, macro_recall, macro_f1, macro_support))
1251
+ tree2.insert("", "end", values=("Weighted avg", weighted_precision, weighted_recall, weighted_f1, weighted_support))
1252
+
1253
+ # Add Scrollbars
1254
+ scrollbar_y = ttk.Scrollbar(tree_frame, orient="vertical", command=tree2.yview)
1255
+ scrollbar_y.pack(side='right', fill='y')
1256
+ tree2.configure(yscrollcommand=scrollbar_y.set)
1257
+
1258
+ scrollbar_x = ttk.Scrollbar(tree_frame, orient="horizontal", command=tree2.xview)
1259
+ scrollbar_x.pack(side='bottom', fill='x')
1260
+ tree2.configure(xscrollcommand=scrollbar_x.set)
1261
+
1262
+
1263
+ tree2.pack(fill=tk.BOTH, expand=True)
1264
+ # Create rounded rectangles and text on the Canvas
1265
+
1266
+ stlbutton_bg_mtl = create_rounded_rectangle(mtl_canvas_1, 230, 840, 490, 920, radius=20, fill="#3d52d5", outline="#3d52d5")
1267
+ stlbutton_text_mtl = mtl_canvas_1.create_text(360, 880, text="Back To Results", font=("Inter", 20, "bold"), fill="white")
1268
+ # Bind the hover effects for the button (to return to STL)
1269
+ bind_button_states(mtl_canvas_1, stlbutton_bg_mtl, stlbutton_text_mtl)
1270
+ # Bind the stlbutton in MTL frame to switch back to STL frame
1271
+ mtl_canvas_1.tag_bind(stlbutton_bg_mtl, "<Button-1>", lambda e: show_page(Sarcasm_and_MP_Frame))
1272
+ mtl_canvas_1.tag_bind(stlbutton_text_mtl, "<Button-1>", lambda e: show_page(Sarcasm_and_MP_Frame))
1273
+
1274
+ bbutton_bg_mtl = create_rounded_rectangle(mtl_canvas_2, 230, 840, 490, 920, radius=20, fill="#3d52d5", outline="#3d52d5")
1275
+ bbutton_text_mtl = mtl_canvas_2.create_text(360, 880, text="Back To Home", font=("Inter", 20, "bold"), fill="white")
1276
+ # Bind the hover effects for the button (to return to STL)
1277
+ bind_button_states(mtl_canvas_2, bbutton_bg_mtl, bbutton_text_mtl)
1278
+ # Bind the stlbutton in MTL frame to switch back to STL frame
1279
+ mtl_canvas_2.tag_bind(bbutton_bg_mtl, "<Button-1>", lambda e: show_page(home_frame))
1280
+ mtl_canvas_2.tag_bind(bbutton_text_mtl, "<Button-1>", lambda e: show_page(home_frame))
1281
+
1282
+
1283
+ show_page(mtl_frame)
1284
+
1285
+
1286
+
1287
+
1288
+
1289
+
1290
+ show_page(home_frame)
1291
+ root.protocol("WM_DELETE_WINDOW", sys.exit)
1292
+ root.mainloop()