Views
No views yet
Joint sentiment classification & sarcasm detection for imbalanced Bangla social media text
| 📊 Task | 🌐 Language | 🏗️ Architecture | ⚡ Training Paradigm |
|---|---|---|---|
| Sentiment Analysis (4-class) + Sarcasm Detection (2-class) | Bengali (bn) | Dual-head BanglaBERT (csebuetnlp/banglabert_small) | Multi-task Learning, Dynamic Focal Loss, Class-Aware Threshold Calibration |
| File | Description |
|---|---|
model.pth | Trained dual-head BanglaBERT weights |
sent_thresholds.npy | Calibrated decision thresholds for sentiment (4 classes) |
sarc_thresholds.npy | Calibrated decision thresholds for sarcasm (2 classes) |
tokenizer/ | Standard BanglaBERT tokenizer files (vocab.txt, tokenizer_config.json, etc.) |
42) for all experimentsα scaling + linear γ decay (2.5 → 0.8) for epoch-aware hard-example miningpip install transformers torch numpy huggingface_hub1import torch
2import numpy as np
3from huggingface_hub import hf_hub_download
4from transformers import AutoTokenizer
5from model_architecture import DualHeadModel
6
7REPO_ID = "ahs95/sentiment-sarcasm-detection-BanglaBERT"
8
9# Load tokenizer & model
10tokenizer = AutoTokenizer.from_pretrained(REPO_ID)
11model = DualHeadModel(num_sentiment_classes=4, num_sarcasm_classes=2)
12
13model_path = hf_hub_download(repo_id=REPO_ID, filename="model.pth")
14model.load_state_dict(torch.load(model_path, map_location="cpu", weights_only=True))
15model.eval()
16
17# Load calibrated thresholds
18sent_thresholds = np.load(hf_hub_download(repo_id=REPO_ID, filename="sent_thresholds.npy"))
19sarc_thresholds = np.load(hf_hub_download(repo_id=REPO_ID, filename="sarc_thresholds.npy"))
20
21sentiment_labels = ["Positive", "Neutral", "Negative", "Mixed"]
22sarcasm_labels = ["Sarcastic", "Non-Sarcastic"] # Index 0 = Sarcastic
23
24def predict(text, max_len=512):
25 inputs = tokenizer(text, return_tensors="pt", truncation=True, max_length=max_len, padding="max_length")
26
27 with torch.no_grad():
28 # DualHeadModel returns tuple: (sent_logits, sarc_logits)
29 sent_logits, sarc_logits = model(inputs["input_ids"], inputs["attention_mask"])
30
31 sent_probs = torch.softmax(sent_logits.squeeze(0), dim=-1)
32 sarc_prob = torch.sigmoid(sarc_logits.squeeze(0))[0] # P(Sarcastic)
33
34 # Apply calibrated thresholds
35 sent_pred = "Neutral" # fallback
36 for i, prob in enumerate(sent_probs):
37 if prob >= sent_thresholds[i]:
38 sent_pred = sentiment_labels[i]
39 break
40
41 sarc_pred = sarcasm_labels[0] if sarc_prob >= sarc_thresholds[0] else sarcasm_labels[1]
42
43 return {
44 "sentiment": sent_pred,
45 "sarcasm": sarc_pred,
46 "confidence": {
47 "sentiment": sent_probs.tolist(),
48 "sarcasm": [sarc_prob.item(), 1 - sarc_prob.item()]
49 }
50 }
51
52# Test
53result = predict("বাংলাদেশ জিতবে ২০৫০ বিশ্বকাপ, তখন আমি আর বেঁচে থাকব না।")
54print(result)
55# Expected: {'sentiment': 'Negative', 'sarcasm': 'Sarcastic', 'confidence': {...}}📦 Note: TheDualHeadModelclass definition is available in the training repository. Copymodel_architecture.pyto your local environment before running the inference example.
| Class | Precision | Recall | F1-Score | Support |
|---|---|---|---|---|
| Positive | 0.64 | 0.68 | 0.66 | 1,407 |
| Neutral | 0.57 | 0.62 | 0.59 | 355 |
| Negative | 0.91 | 0.86 | 0.88 | 4,206 |
| Mixed | 0.53 | 0.65 | 0.58 | 539 |
| Macro F1 | 0.68 | |||
| Weighted F1 | 0.79 (95% CI: 0.784–0.804) |
| Class | Precision | Recall | F1-Score | Support |
|---|---|---|---|---|
| Sarcastic | 0.60 | 0.64 | 0.62 | 2,261 |
| Non-Sarcastic | 0.80 | 0.78 | 0.79 | 4,246 |
| Macro F1 | 0.70 | |||
| Weighted F1 | 0.73 (95% CI: 0.718–0.740) |
W-F1=0.69 (Sent) & 0.61 (Sarc) with complete minority-class collapse (Neutral/Mixed F1: 0.00).| Parameter | Value |
|---|---|
| Base Encoder | csebuetnlp/banglabert_small |
| Optimizer | 8-bit AdamW (bitsandbytes) |
| Learning Rate | 2e-5 (Cosine Annealing) |
| Batch Size | 16 (Gradient Accumulation ×2 → eff. 32) |
| Max Epochs | 5 (Early Stopping patience=2 on composite F1) |
| Loss Function | Dynamic Focal Loss: α ∈ [0.15, 0.45], γ: 2.5 → 0.8 |
| Augmentation | BanglaT5 paraphrasing (offline, minority-focused) |
| Hardware | T4 GPU (VRAM-optimized via 8-bit quantization) |
| Reproducibility | Fixed seed 42, 5-fold stratified splits |
মীরজাফর), and negation-driven intensification (লজ্জা নেই).[CLS] pooling, which compresses dual-polarity utterances and obscures long-range pragmatic dependencies.🔍 Error Analysis: 50.1% of misclassifications are sarcasm-related, primarily due to hyperbolic non-sarcastic comments sharing pragmatic features with irony.
1@article{banglasentimentsarcasm,
2 title={Sentiment and Sarcasm Detection in Bangla: A Calibrated Multitask Framework for Imbalanced Cricket Discourse},
3 author={Arshadul Hoque and Nasrin Sultana and Risul Islam Rasel},
4 year={2026},
5 publisher={Zenodo},
6 doi={10.5281/zenodo.20307593}
7}ahsbd95@gmail.com