Hate speech detection for Persian social media using cross-lingual attention on the PHate benchmark (Delbari et al., AAAI 2024).
The main model is JCLA — Joint Cross-Lingual Attention, formerly referred to as CLA-Live, with a live trainable P1 encoder.
Active label: HateSpeech (binary, primary); Violence / Hate / Vulgar / target (auxiliary in JCLA)
Dataset: 7,056 Persian tweets — 3,528 train / 706 val / 2,822 test
Primary metric: Macro-F1
| System | Test Macro-F1 | Test Macro-AUC | Notes |
|---|---|---|---|
| P1 LoRA (twitter-RoBERTa-hate) | 0.8404 ± 0.0009 | 0.9186 ± 0.0004 | English translations via GPT |
| P2 only (XLM-R-large + LoRA) | 0.8216 ± 0.0084 | 0.9045 ± 0.0059 | MLM-adapted on Persian tweets |
| JCLA (joint cross-lingual attention) | 0.8502 ± 0.0032 | 0.9282 ± 0.0024 | formerly CLA-Live |
All results averaged over 5 random seeds (42, 1, 2, 3, 4). Full per-seed metrics in experiments/*/summary.json.
JCLA is the presentation name for the model previously called CLA-Live. The table below reports the positive-class HateSpeech metrics over 5 seeds as mean ± standard deviation.
| Metric | Mean ± Std |
|---|---|
| Binary F1 | 0.8292 ± 0.0023 |
| Precision | 0.8423 ± 0.0232 |
| Recall | 0.8173 ± 0.0176 |
Persian tweet
│
├─── Branch U [English, trainable]
│ twitter-roberta-base-hate-latest + LoRA
│ ↓ Mean Pool → h_U (768-d, live forward pass)
│ proj_u: Linear(768 → 512) + LayerNorm → u (512-d)
│
├─── Branch P [Persian, trainable]
│ XLM-R-large + LoRA (r=32, α=64, targets: query/key/value)
│ ↓ token hidden states (N × T × 1024)
│ Self-Attention Pooling → h_P (1024-d)
│ proj_p: Linear(1024 → 512) + LayerNorm → p (512-d)
│
└─── Cross-Lingual Attention
Q = p (Persian queries the English representation)
K = V = u
MHA (8 heads, dim=512) → h_cross (512-d)
h_fused = LayerNorm(p + h_cross) ← residual
FFN: Linear(512 → 256) + GELU + Dropout(0.1) → h (256-d)
│
├── head_top: σ(Linear(256 → 1)) ← HateSpeech
├── head_sub: σ(Linear(256 → 3)) ← Violence / Hate / Vulgar
└── head_target: σ(Linear(256 → 2)) ← Individual / Group
Loss: L_total = L_task + 0.1 × SupConLoss(h, y_top)
L_task = BCE(top) + BCE(sub)[hate only] + BCE(target)[hate only]
In code and experiment paths this model still appears as cla_live / CLALiveModel; in figures, tables, and reporting it is referred to as JCLA.
conda create -n jcla python=3.10 -y
conda activate jcla
pip install -r requirements.txt
Get the raw Persian PHate data:
cd ~/Hate-Speach-Detection-for-Persian-Social-Media
git clone https://github.com/Zahra-D/Phate.git data/raw/Phate
For interactive inference testing, open and run:
notebooks/jcla_demo.ipynb
The notebook loads the JCLA checkpoint, runs predictions on Persian text with its English translation, and displays the model outputs and test-set summaries.
Step 1 — P1 LoRA (LoRA fine-tuning on English translations):
bash scripts/submit_p1_lora.sh
Results: experiments/p1_lora/summary.json
Step 2 — P2 MLM domain adaptation:
bash scripts/submit_p2_mlm.sh
Outputs: experiments/p2_mlm/best_checkpoint/ (LoRA adapter).
Step 3 — P2 supervised fine-tuning:
bash scripts/submit_p2_supervised.sh
Results: experiments/p2_supervised/with_mlm/summary.json
Needs: Step 2 complete (MLM checkpoint must exist).
Step 4 — JCLA live cross-lingual attention (5 seeds):
bash scripts/submit_cla_live.sh
Results: experiments/cla_live/with_p2/summary.json
runai logs <job-name> -f # stream logs
runai describe job <job-name> -p course-ee-559-<GASPAR_USERNAME> # status
runai delete job <job-name> -p course-ee-559-<GASPAR_USERNAME> # cancel/delete
Python
69.0%
Jupyter Notebook
23.1%
Shell
7.9%
Hate speech detection for Persian social media using cross-lingual attention on the PHate benchmark (Delbari et al., AAAI 2024).
The main model is JCLA — Joint Cross-Lingual Attention, formerly referred to as CLA-Live, with a live trainable P1 encoder.
Active label: HateSpeech (binary, primary); Violence / Hate / Vulgar / target (auxiliary in JCLA)
Dataset: 7,056 Persian tweets — 3,528 train / 706 val / 2,822 test
Primary metric: Macro-F1
| System | Test Macro-F1 | Test Macro-AUC | Notes |
|---|---|---|---|
| P1 LoRA (twitter-RoBERTa-hate) | 0.8404 ± 0.0009 | 0.9186 ± 0.0004 | English translations via GPT |
| P2 only (XLM-R-large + LoRA) | 0.8216 ± 0.0084 | 0.9045 ± 0.0059 | MLM-adapted on Persian tweets |
| JCLA (joint cross-lingual attention) | 0.8502 ± 0.0032 | 0.9282 ± 0.0024 | formerly CLA-Live |
All results averaged over 5 random seeds (42, 1, 2, 3, 4). Full per-seed metrics in experiments/*/summary.json.
JCLA is the presentation name for the model previously called CLA-Live. The table below reports the positive-class HateSpeech metrics over 5 seeds as mean ± standard deviation.
| Metric | Mean ± Std |
|---|---|
| Binary F1 | 0.8292 ± 0.0023 |
| Precision | 0.8423 ± 0.0232 |
| Recall | 0.8173 ± 0.0176 |
Persian tweet
│
├─── Branch U [English, trainable]
│ twitter-roberta-base-hate-latest + LoRA
│ ↓ Mean Pool → h_U (768-d, live forward pass)
│ proj_u: Linear(768 → 512) + LayerNorm → u (512-d)
│
├─── Branch P [Persian, trainable]
│ XLM-R-large + LoRA (r=32, α=64, targets: query/key/value)
│ ↓ token hidden states (N × T × 1024)
│ Self-Attention Pooling → h_P (1024-d)
│ proj_p: Linear(1024 → 512) + LayerNorm → p (512-d)
│
└─── Cross-Lingual Attention
Q = p (Persian queries the English representation)
K = V = u
MHA (8 heads, dim=512) → h_cross (512-d)
h_fused = LayerNorm(p + h_cross) ← residual
FFN: Linear(512 → 256) + GELU + Dropout(0.1) → h (256-d)
│
├── head_top: σ(Linear(256 → 1)) ← HateSpeech
├── head_sub: σ(Linear(256 → 3)) ← Violence / Hate / Vulgar
└── head_target: σ(Linear(256 → 2)) ← Individual / Group
Loss: L_total = L_task + 0.1 × SupConLoss(h, y_top)
L_task = BCE(top) + BCE(sub)[hate only] + BCE(target)[hate only]
In code and experiment paths this model still appears as cla_live / CLALiveModel; in figures, tables, and reporting it is referred to as JCLA.
conda create -n jcla python=3.10 -y
conda activate jcla
pip install -r requirements.txt
Get the raw Persian PHate data:
cd ~/Hate-Speach-Detection-for-Persian-Social-Media
git clone https://github.com/Zahra-D/Phate.git data/raw/Phate
For interactive inference testing, open and run:
notebooks/jcla_demo.ipynb
The notebook loads the JCLA checkpoint, runs predictions on Persian text with its English translation, and displays the model outputs and test-set summaries.
Step 1 — P1 LoRA (LoRA fine-tuning on English translations):
bash scripts/submit_p1_lora.sh
Results: experiments/p1_lora/summary.json
Step 2 — P2 MLM domain adaptation:
bash scripts/submit_p2_mlm.sh
Outputs: experiments/p2_mlm/best_checkpoint/ (LoRA adapter).
Step 3 — P2 supervised fine-tuning:
bash scripts/submit_p2_supervised.sh
Results: experiments/p2_supervised/with_mlm/summary.json
Needs: Step 2 complete (MLM checkpoint must exist).
Step 4 — JCLA live cross-lingual attention (5 seeds):
bash scripts/submit_cla_live.sh
Results: experiments/cla_live/with_p2/summary.json
runai logs <job-name> -f # stream logs
runai describe job <job-name> -p course-ee-559-<GASPAR_USERNAME> # status
runai delete job <job-name> -p course-ee-559-<GASPAR_USERNAME> # cancel/delete
Python
69.0%
Jupyter Notebook
23.1%
Shell
7.9%