File size: 5,308 Bytes
0fbf965 | 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 | ---
language:
- ru
license: mit
tags:
- text-classification
- toxicity
- multi-label-classification
- multi-task-learning
- russian
- bert
base_model: cointegrated/rubert-tiny2
---
# RU Multi-Task Toxicity Encoder
Лёгкая multi-task модель для классификации токсичности русскоязычных текстов
по трём независимым категориям одновременно.
## Описание
Модель построена на базе [cointegrated/rubert-tiny2](https://huggingface.co/cointegrated/rubert-tiny2)
с тремя независимыми классификационными головами поверх эмбеддинга `[CLS]` токена.
Каждая голова предсказывает один бинарный класс:
- **profanity** — ненормативная лексика
- **threat** — угрозы в адрес пользователя
- **illegal** — запросы, связанные с нарушением закона
## Архитектура
```
Encoder (rubert-tiny2)
└── [CLS] embedding (312-dim)
├── Dropout (p=0.2)
├── Linear(312 → 1) → profanity_logit
├── Linear(312 → 1) → threat_logit
└── Linear(312 → 1) → illegal_logit
```
## Метрики (валидационная выборка)
| Класс | Порог | Precision | Recall | F1 |
|------------|----------|-------------|---------|---------|
| profanity | 0.60 | 0.9454 | 0.9256 | 0.9354 |
| threat | 0.75 | 1.0000 | 0.9286 | 0.9630 |
| illegal | 0.16 | 1.0000 | 1.0000 | 1.0000 |
> Пороги подобраны индивидуально для каждого класса по максимуму F1-score
> на валидационной выборке. Классы сильно несбалансированы — это учтено
> через `pos_weight` в `BCEWithLogitsLoss` при обучении.
## Пример использования
```python
import json
import torch
import torch.nn as nn
from transformers import AutoModel, AutoTokenizer
# 1. Загрузка токенизатора и конфига
tokenizer = AutoTokenizer.from_pretrained("AtesiT/ru-multitask-toxicity-encoder")
with open("toxicity_config.json") as f:
config = json.load(f)
# 2. Определение архитектуры
class MultiTaskToxicityEncoder(nn.Module):
def __init__(self, model_name, hidden_size, dropout=0.2):
super().__init__()
self.encoder = AutoModel.from_pretrained(model_name)
self.dropout = nn.Dropout(dropout)
self.profanity_head = nn.Linear(hidden_size, 1)
self.threat_head = nn.Linear(hidden_size, 1)
self.illegal_head = nn.Linear(hidden_size, 1)
def forward(self, input_ids, attention_mask):
out = self.encoder(input_ids=input_ids, attention_mask=attention_mask)
cls = self.dropout(out.last_hidden_state[:, 0, :])
return (
self.profanity_head(cls),
self.threat_head(cls),
self.illegal_head(cls),
)
# 3. Загрузка весов
model = MultiTaskToxicityEncoder(
model_name=config["base_model"],
hidden_size=config["hidden_size"],
)
state_dict = torch.load("model_weights.pt", map_location="cpu")
model.load_state_dict(state_dict)
model.eval()
# 4. Инференс
thresholds = config["thresholds"]
def predict(text):
enc = tokenizer(
text, return_tensors="pt",
padding="max_length", truncation=True,
max_length=config["max_length"],
)
with torch.no_grad():
p_logit, t_logit, i_logit = model(
enc["input_ids"], enc["attention_mask"]
)
probs = {
"profanity": torch.sigmoid(p_logit).item(),
"threat": torch.sigmoid(t_logit).item(),
"illegal": torch.sigmoid(i_logit).item(),
}
labels = {k: int(v >= thresholds[k]) for k, v in probs.items()}
return {"probs": probs, "labels": labels}
print(predict("Ты полный идиот, заткнись!"))
```
## Обучение
- **Датасет**: [AtesiT/ru-multitask-toxicity](https://huggingface.co/datasets/AtesiT/ru-multitask-toxicity)
- **Функция потерь**: `BCEWithLogitsLoss` с `pos_weight` для каждого класса
- **Оптимизатор**: AdamW (lr=2e-5, weight_decay=0.01)
- **Early Stopping**: patience=3 по валидационному лоссу
- **Макс. длина последовательности**: 64 токена
## Ограничения
- Модель обучена на синтетически аугментированных данных для редких классов
(`threat`, `illegal`) — качество на реальных данных может отличаться.
- Короткие тексты (< 5 слов) могут обрабатываться менее точно.
- Модель не учитывает контекст диалога — только отдельное сообщение.
## Лицензия
MIT. Создано в учебных целях для курса по трансформерным энкодерам.
|