AtesiT commited on
Commit
0fbf965
·
verified ·
1 Parent(s): b0d6d13

Upload README.md with huggingface_hub

Browse files
Files changed (1) hide show
  1. README.md +136 -0
README.md ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ language:
3
+ - ru
4
+ license: mit
5
+ tags:
6
+ - text-classification
7
+ - toxicity
8
+ - multi-label-classification
9
+ - multi-task-learning
10
+ - russian
11
+ - bert
12
+ base_model: cointegrated/rubert-tiny2
13
+ ---
14
+
15
+ # RU Multi-Task Toxicity Encoder
16
+
17
+ Лёгкая multi-task модель для классификации токсичности русскоязычных текстов
18
+ по трём независимым категориям одновременно.
19
+
20
+ ## Описание
21
+
22
+ Модель построена на базе [cointegrated/rubert-tiny2](https://huggingface.co/cointegrated/rubert-tiny2)
23
+ с тремя независимыми классификационными головами поверх эмбеддинга `[CLS]` токена.
24
+
25
+ Каждая голова предсказывает один бинарный класс:
26
+ - **profanity** — ненормативная лексика
27
+ - **threat** — угрозы в адрес пользователя
28
+ - **illegal** — запросы, связанные с нарушением закона
29
+
30
+ ## Архитектура
31
+
32
+ ```
33
+ Encoder (rubert-tiny2)
34
+ └── [CLS] embedding (312-dim)
35
+ ├── Dropout (p=0.2)
36
+ ├── Linear(312 → 1) → profanity_logit
37
+ ├── Linear(312 → 1) → threat_logit
38
+ └── Linear(312 → 1) → illegal_logit
39
+ ```
40
+
41
+ ## Метрики (валидационная выборка)
42
+
43
+ | Класс | Порог | Precision | Recall | F1 |
44
+ |------------|----------|-------------|---------|---------|
45
+ | profanity | 0.60 | 0.9454 | 0.9256 | 0.9354 |
46
+ | threat | 0.75 | 1.0000 | 0.9286 | 0.9630 |
47
+ | illegal | 0.16 | 1.0000 | 1.0000 | 1.0000 |
48
+
49
+ > Пороги подобраны индивидуально для каждого класса по максимуму F1-score
50
+ > на валидационной выборке. Классы сильно несбалансированы — это учтено
51
+ > через `pos_weight` в `BCEWithLogitsLoss` при обучении.
52
+
53
+ ## Пример использования
54
+
55
+ ```python
56
+ import json
57
+ import torch
58
+ import torch.nn as nn
59
+ from transformers import AutoModel, AutoTokenizer
60
+
61
+ # 1. Загрузка токенизатора и конфига
62
+ tokenizer = AutoTokenizer.from_pretrained("AtesiT/ru-multitask-toxicity-encoder")
63
+
64
+ with open("toxicity_config.json") as f:
65
+ config = json.load(f)
66
+
67
+ # 2. Определение архитектуры
68
+ class MultiTaskToxicityEncoder(nn.Module):
69
+ def __init__(self, model_name, hidden_size, dropout=0.2):
70
+ super().__init__()
71
+ self.encoder = AutoModel.from_pretrained(model_name)
72
+ self.dropout = nn.Dropout(dropout)
73
+ self.profanity_head = nn.Linear(hidden_size, 1)
74
+ self.threat_head = nn.Linear(hidden_size, 1)
75
+ self.illegal_head = nn.Linear(hidden_size, 1)
76
+
77
+ def forward(self, input_ids, attention_mask):
78
+ out = self.encoder(input_ids=input_ids, attention_mask=attention_mask)
79
+ cls = self.dropout(out.last_hidden_state[:, 0, :])
80
+ return (
81
+ self.profanity_head(cls),
82
+ self.threat_head(cls),
83
+ self.illegal_head(cls),
84
+ )
85
+
86
+ # 3. Загрузка весов
87
+ model = MultiTaskToxicityEncoder(
88
+ model_name=config["base_model"],
89
+ hidden_size=config["hidden_size"],
90
+ )
91
+ state_dict = torch.load("model_weights.pt", map_location="cpu")
92
+ model.load_state_dict(state_dict)
93
+ model.eval()
94
+
95
+ # 4. Инференс
96
+ thresholds = config["thresholds"]
97
+
98
+ def predict(text):
99
+ enc = tokenizer(
100
+ text, return_tensors="pt",
101
+ padding="max_length", truncation=True,
102
+ max_length=config["max_length"],
103
+ )
104
+ with torch.no_grad():
105
+ p_logit, t_logit, i_logit = model(
106
+ enc["input_ids"], enc["attention_mask"]
107
+ )
108
+ probs = {
109
+ "profanity": torch.sigmoid(p_logit).item(),
110
+ "threat": torch.sigmoid(t_logit).item(),
111
+ "illegal": torch.sigmoid(i_logit).item(),
112
+ }
113
+ labels = {k: int(v >= thresholds[k]) for k, v in probs.items()}
114
+ return {"probs": probs, "labels": labels}
115
+
116
+ print(predict("Ты полный идиот, заткнись!"))
117
+ ```
118
+
119
+ ## Обучение
120
+
121
+ - **Датасет**: [AtesiT/ru-multitask-toxicity](https://huggingface.co/datasets/AtesiT/ru-multitask-toxicity)
122
+ - **Функция потерь**: `BCEWithLogitsLoss` с `pos_weight` для каждого класса
123
+ - **Оптимизатор**: AdamW (lr=2e-5, weight_decay=0.01)
124
+ - **Early Stopping**: patience=3 по валидационному лоссу
125
+ - **Макс. длина последовательности**: 64 токена
126
+
127
+ ## Ограничения
128
+
129
+ - Модель обучена на синтетически аугментированных данных для редких классов
130
+ (`threat`, `illegal`) — качество на реальных данных может отличаться.
131
+ - Короткие тексты (< 5 слов) могут обрабатываться менее точно.
132
+ - Модель не учитывает контекст диалога — только отдельное сообщение.
133
+
134
+ ## Лицензия
135
+
136
+ MIT. Создано в учебных целях для курса по трансформерным энкодерам.