mmendoza commited on
Commit
5690502
·
verified ·
1 Parent(s): cf9922e

Add multi-label RoBERTuito+CL2 (hate + target-group detection) + model card

Browse files
README.md ADDED
@@ -0,0 +1,151 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ language: es
3
+ license: apache-2.0
4
+ library_name: transformers
5
+ pipeline_tag: text-classification
6
+ base_model: pysentimiento/robertuito-base-uncased
7
+ tags:
8
+ - hate-speech-detection
9
+ - multi-label
10
+ - target-group-detection
11
+ - chilean-spanish
12
+ - spanish
13
+ - social-media
14
+ - roberta
15
+ datasets:
16
+ - CL2
17
+ metrics:
18
+ - f1
19
+ - roc_auc
20
+ widget:
21
+ - text: "estos inmigrantes de mierda que se vayan de mi pais"
22
+ - text: "las minas no saben manejar, mejor que se queden en la casa"
23
+ ---
24
+
25
+ # RoBERTuito + CL2 — multi-label hate speech and target-group detection (Chilean Spanish)
26
+
27
+ A **multi-label** classifier for Chilean Spanish social-media text. For each
28
+ message it predicts, independently, **five** binary targets:
29
+
30
+ | Target | Meaning |
31
+ |---|---|
32
+ | `hate` | the message is hate speech |
33
+ | `women` | it references women |
34
+ | `lgbtq` | it references the LGBTQ+ community |
35
+ | `immigrants` | it references immigrant communities |
36
+ | `indigenous` | it references Indigenous (Native American) peoples |
37
+
38
+ So it detects both **whether** a message is hateful **and which protected
39
+ group(s) it targets or mentions**. It is [RoBERTuito](https://huggingface.co/pysentimiento/robertuito-base-uncased)
40
+ fine-tuned on the **CL2** corpus, using both its hate/non-hate label and its
41
+ target-group annotations.
42
+
43
+ This is a companion to
44
+ [`mmendoza/robertuito-cl2-hate-speech`](https://huggingface.co/mmendoza/robertuito-cl2-hate-speech)
45
+ (binary hate/non-hate). Use the binary model if you only need hate detection;
46
+ use this one if you also need the targeted group. The group layer is a secondary
47
+ annotation in CL2 and is not part of the main results in the paper.
48
+
49
+ ## Usage
50
+
51
+ The model **requires the same normalisation used at training** (mentions →
52
+ `@usuario`, links → `url`, lowercase). Outputs are **independent sigmoids**
53
+ (multi-label), not a softmax.
54
+
55
+ ```python
56
+ import re, torch
57
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
58
+
59
+ _user = re.compile(r"@\w+"); _url = re.compile(r"https?://\S+|www\.\S+")
60
+ def preprocess(t):
61
+ return _url.sub("url", _user.sub("@usuario", str(t))).lower().strip()
62
+
63
+ name = "mmendoza/robertuito-cl2-multigroup"
64
+ tok = AutoTokenizer.from_pretrained(name)
65
+ model = AutoModelForSequenceClassification.from_pretrained(name).eval()
66
+ labels = [model.config.id2label[i] for i in range(model.config.num_labels)]
67
+
68
+ text = "estos inmigrantes de mierda que se vayan de mi pais"
69
+ enc = tok(preprocess(text), return_tensors="pt", truncation=True, max_length=128)
70
+ with torch.no_grad():
71
+ probs = torch.sigmoid(model(**enc).logits)[0]
72
+ for lab, p in zip(labels, probs):
73
+ flag = " <-- active" if p >= 0.5 else ""
74
+ print(f"{lab:11s} {p:.3f}{flag}")
75
+ ```
76
+
77
+ Label order: `hate, women, lgbtq, immigrants, indigenous`. Each is an independent
78
+ probability; threshold at 0.5 (tune per target if needed).
79
+
80
+ ## Training data
81
+
82
+ **CL2** — 4,547 Chilean Spanish tweets, 45.6 % hate, annotated by three
83
+ independent annotators (majority vote) for a hate/non-hate label and for four
84
+ target groups. Group prevalence (majority vote): women 17.2 %, immigrants
85
+ 14.5 %, Indigenous 12.8 %, LGBTQ+ 10.8 %. A tweet can reference more than one
86
+ group. Corpus: https://zenodo.org/records/14619078
87
+
88
+ ## Training procedure
89
+
90
+ Fine-tuned with a multi-label head (`problem_type="multi_label_classification"`,
91
+ `BCEWithLogitsLoss`) on the full CL2 corpus:
92
+
93
+ | Hyperparameter | Value |
94
+ |---|---|
95
+ | Base model | `pysentimiento/robertuito-base-uncased` |
96
+ | Epochs | 5 |
97
+ | Batch size | 32 |
98
+ | Learning rate | 5e-5 |
99
+ | Max sequence length | 128 |
100
+ | Weight decay | 0.01 |
101
+ | Warmup ratio | 0.1 |
102
+ | Precision | fp16 |
103
+ | Seed | 42 |
104
+
105
+ ## Evaluation
106
+
107
+ Held-out 20 % of CL2 (stratified on the hate label, n = 910), threshold 0.5:
108
+
109
+ | Target | Precision | Recall | F1 | AUC |
110
+ |---|---|---|---|---|
111
+ | hate | 0.846 | 0.884 | 0.865 | 0.935 |
112
+ | women | 0.741 | 0.818 | 0.778 | 0.960 |
113
+ | lgbtq | 0.739 | 0.791 | 0.764 | 0.970 |
114
+ | immigrants | 0.878 | 0.915 | 0.896 | 0.994 |
115
+ | indigenous | 0.946 | 0.911 | 0.928 | 0.991 |
116
+ | **macro-F1** | | | **0.846** | |
117
+ | **micro-F1** | | | **0.853** | |
118
+
119
+ Group detection is even stronger than hate detection (group references are more
120
+ lexical/topical), and adding the group targets does not degrade the hate output
121
+ (F1 0.865 vs 0.854 for the binary-only model).
122
+
123
+ *(The released weights are trained on the full CL2 corpus for deployment; the
124
+ figures above come from a held-out split.)*
125
+
126
+ ## Limitations and biases
127
+
128
+ - **Scope is Chilean Spanish** and the **four groups annotated in CL2** (women,
129
+ immigrants, Indigenous peoples, LGBTQ+). Other targets and varieties are out
130
+ of scope.
131
+ - The group layer is a **secondary annotation**; per-group performance depends
132
+ on each group's prevalence and is lower for rarer groups.
133
+ - Trained on keyword/hashtag/account-sampled data, which over-represents explicit
134
+ hate; the model can err on colloquial profanity and on non-hateful mentions of
135
+ a group. Use human review for consequential decisions.
136
+ - The model detects the group **referenced** in a message, which is not always
137
+ the group being **attacked**; read the `hate` and group outputs together.
138
+
139
+ ## Citation
140
+
141
+ ```bibtex
142
+ @article{benoit_hate_chilean_spanish,
143
+ title = {Hate speech detection in Chilean Spanish and its cross-lingual transferability},
144
+ author = {Benoit, Domingo and {\~N}anculef, Ricardo and Mendoza, Marcelo},
145
+ journal = {International Journal of Data Science and Analytics (under review)},
146
+ year = {2026}
147
+ }
148
+ ```
149
+
150
+ Please also cite the base model (Pérez et al., RoBERTuito, LREC 2022) and the CL2
151
+ corpus (Zenodo 14619078).
config.json ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_name_or_path": "pysentimiento/robertuito-base-uncased",
3
+ "architectures": [
4
+ "RobertaForSequenceClassification"
5
+ ],
6
+ "attention_probs_dropout_prob": 0.1,
7
+ "bos_token_id": 0,
8
+ "classifier_dropout": null,
9
+ "eos_token_id": 2,
10
+ "gradient_checkpointing": false,
11
+ "hidden_act": "gelu",
12
+ "hidden_dropout_prob": 0.1,
13
+ "hidden_size": 768,
14
+ "id2label": {
15
+ "0": "hate",
16
+ "1": "women",
17
+ "2": "lgbtq",
18
+ "3": "immigrants",
19
+ "4": "indigenous"
20
+ },
21
+ "initializer_range": 0.02,
22
+ "intermediate_size": 3072,
23
+ "label2id": {
24
+ "hate": 0,
25
+ "immigrants": 3,
26
+ "indigenous": 4,
27
+ "lgbtq": 2,
28
+ "women": 1
29
+ },
30
+ "layer_norm_eps": 1e-12,
31
+ "max_position_embeddings": 130,
32
+ "model_type": "roberta",
33
+ "num_attention_heads": 12,
34
+ "num_hidden_layers": 12,
35
+ "pad_token_id": 1,
36
+ "position_embedding_type": "absolute",
37
+ "problem_type": "multi_label_classification",
38
+ "torch_dtype": "float32",
39
+ "transformers_version": "4.41.2",
40
+ "type_vocab_size": 1,
41
+ "use_cache": true,
42
+ "vocab_size": 30000
43
+ }
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1ffd69d0903425f7ff68f482c96d359bf85ae2835a07096f9b47f8832bdffd3f
3
+ size 435188308
special_tokens_map.json ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "bos_token": {
3
+ "content": "<s>",
4
+ "lstrip": false,
5
+ "normalized": false,
6
+ "rstrip": false,
7
+ "single_word": false
8
+ },
9
+ "cls_token": {
10
+ "content": "<s>",
11
+ "lstrip": false,
12
+ "normalized": false,
13
+ "rstrip": false,
14
+ "single_word": false
15
+ },
16
+ "eos_token": {
17
+ "content": "</s>",
18
+ "lstrip": false,
19
+ "normalized": false,
20
+ "rstrip": false,
21
+ "single_word": false
22
+ },
23
+ "mask_token": {
24
+ "content": "<mask>",
25
+ "lstrip": false,
26
+ "normalized": false,
27
+ "rstrip": false,
28
+ "single_word": false
29
+ },
30
+ "pad_token": {
31
+ "content": "<pad>",
32
+ "lstrip": false,
33
+ "normalized": false,
34
+ "rstrip": false,
35
+ "single_word": false
36
+ },
37
+ "sep_token": {
38
+ "content": "</s>",
39
+ "lstrip": false,
40
+ "normalized": false,
41
+ "rstrip": false,
42
+ "single_word": false
43
+ },
44
+ "unk_token": {
45
+ "content": "<unk>",
46
+ "lstrip": false,
47
+ "normalized": false,
48
+ "rstrip": false,
49
+ "single_word": false
50
+ }
51
+ }
tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
tokenizer_config.json ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "added_tokens_decoder": {
3
+ "0": {
4
+ "content": "<s>",
5
+ "lstrip": false,
6
+ "normalized": false,
7
+ "rstrip": false,
8
+ "single_word": false,
9
+ "special": true
10
+ },
11
+ "1": {
12
+ "content": "<pad>",
13
+ "lstrip": false,
14
+ "normalized": false,
15
+ "rstrip": false,
16
+ "single_word": false,
17
+ "special": true
18
+ },
19
+ "2": {
20
+ "content": "</s>",
21
+ "lstrip": false,
22
+ "normalized": false,
23
+ "rstrip": false,
24
+ "single_word": false,
25
+ "special": true
26
+ },
27
+ "3": {
28
+ "content": "<unk>",
29
+ "lstrip": false,
30
+ "normalized": false,
31
+ "rstrip": false,
32
+ "single_word": false,
33
+ "special": true
34
+ },
35
+ "4": {
36
+ "content": "<mask>",
37
+ "lstrip": false,
38
+ "normalized": false,
39
+ "rstrip": false,
40
+ "single_word": false,
41
+ "special": true
42
+ }
43
+ },
44
+ "bos_token": "<s>",
45
+ "clean_up_tokenization_spaces": true,
46
+ "cls_token": "<s>",
47
+ "eos_token": "</s>",
48
+ "mask_token": "<mask>",
49
+ "max_length": 128,
50
+ "model_max_length": 1000000000000000019884624838656,
51
+ "pad_to_multiple_of": null,
52
+ "pad_token": "<pad>",
53
+ "pad_token_type_id": 0,
54
+ "padding_side": "right",
55
+ "sep_token": "</s>",
56
+ "stride": 0,
57
+ "tokenizer_class": "PreTrainedTokenizerFast",
58
+ "truncation_side": "right",
59
+ "truncation_strategy": "longest_first",
60
+ "unk_token": "<unk>"
61
+ }