File size: 4,808 Bytes
a5fa5e3
 
 
 
 
 
 
 
 
 
 
879c038
 
 
 
 
a5fa5e3
 
879c038
a5fa5e3
 
 
 
879c038
a5fa5e3
 
 
879c038
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a5fa5e3
879c038
 
 
 
 
a5fa5e3
879c038
a5fa5e3
 
 
 
 
 
 
879c038
a5fa5e3
879c038
 
 
a5fa5e3
879c038
 
a5fa5e3
879c038
 
 
 
 
 
 
a5fa5e3
 
 
 
 
 
879c038
 
a5fa5e3
 
879c038
a5fa5e3
879c038
a5fa5e3
879c038
 
 
a5fa5e3
 
879c038
a5fa5e3
879c038
 
 
 
a5fa5e3
 
879c038
 
 
 
 
 
 
 
 
 
 
a5fa5e3
879c038
 
 
 
a5fa5e3
879c038
 
 
 
a5fa5e3
 
879c038
a5fa5e3
 
 
879c038
 
 
a5fa5e3
879c038
a5fa5e3
 
 
 
879c038
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
---
language:
- ur
library_name: transformers
pipeline_tag: text-classification
tags:
- roberta
- urdu
- hate-speech
- sequence-classification
- pytorch
- smote
- tf-idf
license: other  # inherit/align with base model's license
datasets:
- Adnan855570/urdu-hate-speech
---

## Urdu RoBERTa Hate Speech Classifier (Balanced)

- **Base model**: `urduhack/roberta-urdu-small`
- **Task**: Binary text classification (hate vs. not_hate)
- **Language**: Urdu (ur)
- **Labels**
  - 0 → `not_hate`
  - 1 → `hate`

This model fine-tunes a small RoBERTa for Urdu hate-speech detection. Class imbalance was addressed by oversampling with SMOTE at the feature level (TF–IDF) prior to tokenization-based training.

### Training data and preprocessing
- Source dataset: `Adnan855570/urdu-hate-speech` (Excel files: `preprocessed_combined_file (1).xlsx`, `Urdu_Hate_Speech.xlsx`)
- Columns used in notebook: `Tweet` (text), `Tag` (label in {0,1})
- Steps:
  - TF–IDF featurization (max_features=10000)
  - SMOTE oversampling (random_state=42) to balance classes
  - Train/test split: 80/20 (random_state=42)
  - Tokenization: `AutoTokenizer.from_pretrained("urduhack/roberta-urdu-small")` with `truncation=True`, `padding=True`

### Training setup
- Model: `AutoModelForSequenceClassification` with `num_labels=2`
- Device: GPU if available
- Hyperparameters:
  - epochs: 3
  - per_device_train_batch_size: 8
  - per_device_eval_batch_size: 8
  - warmup_steps: 500
  - weight_decay: 0.01
  - evaluation_strategy: epoch
  - save_strategy: epoch
  - load_best_model_at_end: true
- Metrics:
  - Accuracy, Precision, Recall, F1 (binary)

### Evaluation results (test split)
- accuracy: 0.7891
- f1: 0.7854
- precision: 0.8208
- recall: 0.7529

Note: Results derive from the balanced (SMOTE) dataset and the 80/20 split used in the notebook.

### How to use (Transformers)

```python
from transformers import AutoTokenizer, AutoModelForSequenceClassification
import torch

MODEL_ID = "Adnan855570/urdu-roberta-hate"  # replace if different
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
model = AutoModelForSequenceClassification.from_pretrained(MODEL_ID).eval()

id2label = model.config.id2label or {"0":"not_hate","1":"hate"}

def predict(text: str):
    enc = tokenizer(text, return_tensors="pt", truncation=True, padding=True)
    with torch.no_grad():
        logits = model(**enc).logits
        probs = logits.softmax(dim=-1).squeeze().tolist()
        pred = int(logits.argmax(dim=-1).item())
    return {"label_id": pred, "label": id2label.get(str(pred), str(pred)),
            "scores": {"not_hate": probs[0], "hate": probs[1]}}

print(predict("یہ نفرت انگیز ہے یا نہیں؟"))
```

Or with a pipeline:

```python
from transformers import pipeline
clf = pipeline("text-classification", model="Adnan855570/urdu-roberta-hate", top_k=None)
print(clf("یہ نفرت انگیز ہے یا نہیں؟"))
```

### Inference API

- cURL
```bash
curl -X POST -H "Authorization: Bearer $HF_TOKEN" -H "Content-Type: application/json" \
  -d '{"inputs":"یہ نفرت انگیز ہے یا نہیں؟"}' \
  https://api-inference.huggingface.co/models/Adnan855570/urdu-roberta-hate
```

- Python
```python
import os, requests
API_URL = "https://api-inference.huggingface.co/models/Adnan855570/urdu-roberta-hate"
HEADERS = {"Authorization": f"Bearer {os.environ.get('HF_TOKEN','')}"}
print(requests.post(API_URL, headers=HEADERS, json={"inputs":"..."}, timeout=30).json())
```

### Intended uses and limitations
- Intended:
  - Flagging potentially hateful Urdu content
  - Assisting human moderation and research
- Limitations:
  - May misclassify satire, reclaimed slurs, or code-mixed content
  - Domain shift sensitivity (platform/community/topic)
- Risks:
  - False positives/negatives; do not use as the sole basis for punitive actions
- Recommendation:
  - Use with human-in-the-loop; periodically audit outcomes and bias

### Label mapping
Ensure the config includes:
- `id2label = {"0":"not_hate","1":"hate"}`
- `label2id = {"not_hate":0,"hate":1}`

### Reproducibility notes
- SMOTE and split seeds: `random_state=42`
- Tokenization: truncation and padding enabled (no explicit max_length set in notebook)
- Hardware: single GPU (e.g., Colab)

### License
- The model derivation should comply with the base model’s license (`urduhack/roberta-urdu-small`). Set a compatible license here once confirmed.

### Citation
```bibtex
@misc{urdu_roberta_hate_balanced_2025,
  title  = {Urdu RoBERTa Hate Speech Classifier (Balanced)},
  author = {Adnan},
  year   = {2025},
  howpublished = {\url{https://huggingface.co/Adnan855570/urdu-roberta-hate}}
}
```

### Acknowledgements
- Base: `urduhack/roberta-urdu-small`
- Libraries: 🤗 Transformers, Datasets, PyTorch
- Oversampling: SMOTE (imblearn)