ringorsolya commited on
Commit
8975537
·
verified ·
1 Parent(s): 7e3a40a

Update README.md

Browse files
Files changed (1) hide show
  1. README.md +173 -3
README.md CHANGED
@@ -1,3 +1,173 @@
1
- ---
2
- license: cc-by-4.0
3
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: cc-by-4.0
3
+ ---
4
+ ---
5
+ language:
6
+ - en
7
+ license: mit
8
+ tags:
9
+ - text-classification
10
+ - emotion-recognition
11
+ - guilt-detection
12
+ - political-communication
13
+ - xlm-roberta
14
+ - poltextlab
15
+ datasets:
16
+ - custom
17
+ metrics:
18
+ - accuracy
19
+ - precision
20
+ - recall
21
+ - f1
22
+ - roc-auc
23
+ - pr-auc
24
+ pipeline_tag: text-classification
25
+ ---
26
+
27
+ # GuiltRoBERTa-en: A Two-Stage Classifier for Guilt-Assignment Rhetoric in English Political Texts
28
+
29
+ **GuiltRoBERTa-en** is a two-stage AI pipeline for detecting guilt-assignment rhetoric in English political discourse. It combines:
30
+
31
+ 1. **Stage 1 – Emotion Pre-Filtering:** emotion labels from the [Babel Emotions6 Tool](https://emotionsbabel.poltextlab.com/)
32
+ 2. **Stage 2 – Guilt Classification:** a fine-tuned binary XLM-RoBERTa model trained on manually annotated English texts (`guilt` vs `no_guilt`)
33
+
34
+ The approach is grounded in political communication theory, which suggests that **guilt attribution often emerges in anger-laden contexts**. Thus, only texts labeled as **"Anger"** in Stage 1 are passed to the guilt classifier.
35
+
36
+ ---
37
+
38
+ ## 🧩 Model Architecture
39
+
40
+ ### Stage 1: Emotion Pre-Filtering (Babel Emotions Tool)
41
+
42
+ * **Tool:** [Emotions 6 Babel Machine](https://emotionsbabel.poltextlab.com/)
43
+ * **Task:** 6-class emotion classification (`Anger`, `Fear`, `Disgust`, `Sadness`, `Joy`, `None of them`)
44
+ * **Input:** CSV file with one text per row
45
+ * **Output:** CSV file with predicted labels and probabilities
46
+ * **Usage:** retain only rows with `predicted_emotion == "Anger"` for Stage 2
47
+
48
+ ⚙️ **The Babel Emotions Tool is not an API but a web-based interface.** Upload a CSV file, download the labeled results, and use them as input to the guilt classifier.
49
+
50
+ ### Stage 2: Guilt Classification
51
+
52
+ * **Base model:** `xlm-roberta-base`
53
+ * **Task:** Binary classification (`guilt`, `no_guilt`)
54
+ * **Training data:** Sentence-level annotated English corpus
55
+ * **Optimization:** Class-weighted loss function to handle label imbalance
56
+ * **Recommended threshold:** τ = **0.15**
57
+
58
+ ---
59
+
60
+ ## Motivation
61
+
62
+ **Guilt assignment** — attributing moral responsibility or blame — is a key rhetorical strategy in political communication. Since guilt often appears alongside anger, direct one-stage classification risks conflating emotional tones.
63
+
64
+ This two-stage pipeline improves precision by:
65
+ * Filtering anger-related contexts first
66
+ * Then applying a dedicated guilt detector only where relevant
67
+
68
+ ---
69
+
70
+ ## Evaluation
71
+
72
+ The model was evaluated on a held-out validation set (20% stratified split) with the following approach:
73
+
74
+ | Stage 1 Filter | Threshold (τ) | Precision | Recall | F1 | Accuracy |
75
+ |----------------|---------------|-----------|--------|-----|----------|
76
+ | Anger-only | 0.15 | optimized | optimized | optimized | optimized |
77
+
78
+ * **Best configuration:** Anger-only, τ = 0.15
79
+ * **Metrics:** Accuracy, Precision, Recall, F1-score, ROC-AUC, PR-AUC
80
+ * The two-stage model shows improved performance compared to single-stage baselines
81
+
82
+ ---
83
+
84
+ ## Usage Example
85
+
86
+ ### Step 1: Get Emotion Predictions from Babel
87
+
88
+ 1. Visit [https://emotionsbabel.poltextlab.com/](https://emotionsbabel.poltextlab.com/)
89
+ 2. Upload your CSV file (one text per row)
90
+ 3. Download the predictions (includes `emotion_predicted` column)
91
+
92
+ ### Step 2: Apply Guilt Classifier
93
+ ```python
94
+ import pandas as pd
95
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification, TextClassificationPipeline
96
+
97
+ # Load Babel emotion predictions
98
+ df = pd.read_excel("your_data_with_emotion_predictions.xlsx")
99
+
100
+ # Filter for 'Anger' only
101
+ anger_df = df[df["emotion_predicted"] == "Anger"].copy()
102
+
103
+ # Load the guilt classifier
104
+ repo_id = "your-org/guiltroberta-en" # Update with actual path
105
+ tokenizer = AutoTokenizer.from_pretrained(repo_id)
106
+ model = AutoModelForSequenceClassification.from_pretrained(repo_id)
107
+ pipe = TextClassificationPipeline(model=model, tokenizer=tokenizer, return_all_scores=True)
108
+
109
+ # Apply guilt predictions with threshold
110
+ THRESHOLD = 0.15
111
+
112
+ anger_df["guilt_score"] = anger_df["text"].apply(
113
+ lambda t: pipe(t)[0][1]["score"] # score for 'guilt' label
114
+ )
115
+
116
+ anger_df["guilt_predicted"] = anger_df["guilt_score"] > THRESHOLD
117
+
118
+ # Save results
119
+ anger_df.to_excel("anger_with_guilt_predictions.xlsx", index=False)
120
+
121
+ # Statistics
122
+ print(f"Total anger sentences: {len(anger_df)}")
123
+ print(f"Predicted guilt: {anger_df['guilt_predicted'].sum()}")
124
+ print(f"Guilt ratio: {anger_df['guilt_predicted'].mean():.2%}")
125
+ ```
126
+
127
+ ### Alternative: Direct Inference
128
+ ```python
129
+ import torch
130
+ from transformers import XLMRobertaTokenizer, XLMRobertaForSequenceClassification
131
+
132
+ # Load model
133
+ model_path = "your-org/guiltroberta-en"
134
+ tokenizer = XLMRobertaTokenizer.from_pretrained(model_path)
135
+ model = XLMRobertaForSequenceClassification.from_pretrained(model_path)
136
+
137
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
138
+ model.to(device)
139
+ model.eval()
140
+
141
+ # Example: anger-labeled sentence
142
+ text = "I'm furious at myself for letting this happen again."
143
+
144
+ # Tokenize and predict
145
+ inputs = tokenizer(text, return_tensors="pt", truncation=True, max_length=512, padding=True)
146
+ inputs = {k: v.to(device) for k, v in inputs.items()}
147
+
148
+ with torch.no_grad():
149
+ outputs = model(**inputs)
150
+ logits = outputs.logits
151
+ prob_guilt = torch.softmax(logits, dim=-1)[0][1].item()
152
+
153
+ # Apply threshold
154
+ THRESHOLD = 0.15
155
+ prediction = "guilt" if prob_guilt > THRESHOLD else "no_guilt"
156
+
157
+ print(f"Guilt probability: {prob_guilt:.4f}")
158
+ print(f"Prediction: {prediction}")
159
+ ```
160
+
161
+ ---
162
+
163
+ ## Training Configuration
164
+ ```python
165
+ Epochs: 4
166
+ Learning Rate: 2e-5
167
+ Batch Size: 8
168
+ Max Sequence Length: 512 tokens
169
+ Optimizer: AdamW
170
+ Scheduler: Linear warmup
171
+ Train/Validation Split: 80/20 (stratified)
172
+ Class Weighting: Applied to handle label imbalance
173
+ ```