Upload 7 files
Browse files- .gitattributes +2 -0
- XLM-R/INPUT_SAMPLE.csv +16 -0
- XLM-R/XLM-R.exe +3 -0
- XLM-R/assets/xlm_logo.ico +3 -0
- XLM-R/assets/xlm_logo.png +0 -0
- XLM-R/best_models/best_model_mtl_7.pt +3 -0
- XLM-R/best_models/best_model_stl_7.pt +3 -0
- [SOURCE CODE] XLM-R Sarcasm and Mock Politeness Detector.py +1292 -0
.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
|
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()
|