File size: 7,451 Bytes
b0bfaf1
0847a47
b0bfaf1
 
 
 
 
 
 
 
 
 
0847a47
 
b0bfaf1
0847a47
 
 
b0bfaf1
 
0847a47
b0bfaf1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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

---
language: ru
license: mit
tags:
- toxicity
- multilabel-classification
- russian
- rubert-tiny2
- multitask-learning
pretty_name: RuBERT Tiny2 Toxicity Multitask
model_name: rubert-tiny2-toxicity-multitask
---

# Model Card for rubert-tiny2-toxicity-multitask

## Model Details

**Model Description:**  
Эта модель представляет собой многозадачный классификатор токсичности для русского языка. Она построена на основе лёгкого энкодера `cointegrated/rubert-tiny2` и содержит три независимые классификационные «головы» для одновременного предсказания трёх классов:

- **profanity** – нецензурная лексика и оскорбления
- **threat** – угрозы
- **illegal** – запросы, связанные с незаконными действиями

Модель обучена в мультитаск-режиме (Multi-Task Learning) с использованием взвешенной функции потерь для учёта дисбаланса классов.

**Разработчик:** Arrtemwolf  
**Модель доступна на Hugging Face:** [https://huggingface.co/Arrtemwolf/rubert-tiny2-toxicity-multitask](https://huggingface.co/Arrtemwolf/rubert-tiny2-toxicity-multitask)

## Intended Use

**Назначение:**  
Модель предназначена для автоматической модерации текстовых сообщений в социальных сетях, чатах, комментариях. Она может использоваться для:
- фильтрации нецензурной брани;
- выделения угроз для приоритетной проверки модераторами;
- обнаружения сообщений, содержащих запросы на совершение незаконных действий.

**Ограничения:**  
- Модель обучена на ограниченном наборе данных (около 5500 примеров) и может не охватывать все разнообразие русскоязычной токсичности.
- Рекомендуется использовать в связке с дополнительными фильтрами и человеческой модерацией для критичных применений.

## Training Data

Модель обучена на датасете, собранном из двух открытых источников:
- [petaevd/russian-toxicity-multilabel](https://huggingface.co/datasets/petaevd/russian-toxicity-multilabel) – для класса `illegal`
- [AlexSham/Toxic_Russian_Comments](https://huggingface.co/datasets/AlexSham/Toxic_Russian_Comments) – для классов `profanity` и `threat`

Датасет был очищен, сбалансирован и опубликован отдельно:  
[Arrtemwolf/ru-toxic-multi-label-clean](https://huggingface.co/datasets/Arrtemwolf/ru-toxic-multi-label-clean)

## Evaluation Results

Модель оценивалась на валидационной выборке (20% от общего датасета). Для каждого класса был подобран оптимальный порог вероятности, максимизирующий **F1-меру**.

| Класс      | Порог | Precision | Recall | F1-score |
|------------|-------|-----------|--------|----------|
| profanity  | 0.50  | 0.821     | 0.908  | **0.862**|
| threat     | 0.15  | 0.261     | 0.571  | **0.358**|
| illegal    | 0.40  | 1.000     | 1.000  | **1.000**|

> Примечание: высокий F1 для класса `illegal` обусловлен небольшим количеством положительных примеров в валидации; на более крупных выборках результаты могут отличаться.

## How to Use

### Загрузка модели и токенизатора

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

MODEL_NAME = "Arrtemwolf/rubert-tiny2-toxicity-multitask"
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
encoder = AutoModel.from_pretrained(MODEL_NAME)

# Загрузка обученных голов (классификаторов)
# Внимание: головы сохранены отдельно, их нужно загрузить и прикрепить к модели
# Ниже приведён пример класса-обёртки, который можно использовать после загрузки весов голов.
Для удобства рекомендуется использовать класс MultiTaskToxicityEncoder, который объединяет энкодер и три головы. Веса голов сохранены в файле multitask_heads.pt в репозитории. Пример загрузки:

python
class MultiTaskToxicityEncoder(torch.nn.Module):
    def __init__(self, encoder):
        super().__init__()
        self.encoder = encoder
        hidden_size = encoder.config.hidden_size
        self.head_profanity = torch.nn.Linear(hidden_size, 1)
        self.head_threat = torch.nn.Linear(hidden_size, 1)
        self.head_illegal = torch.nn.Linear(hidden_size, 1)
        self.dropout = torch.nn.Dropout(0.3)

    def forward(self, input_ids, attention_mask):
        outputs = self.encoder(input_ids=input_ids, attention_mask=attention_mask)
        cls_embedding = outputs.last_hidden_state[:, 0, :]
        cls_embedding = self.dropout(cls_embedding)
        return (self.head_profanity(cls_embedding),
                self.head_threat(cls_embedding),
                self.head_illegal(cls_embedding))

# Загружаем энкодер
encoder = AutoModel.from_pretrained(MODEL_NAME)
model = MultiTaskToxicityEncoder(encoder)

# Загружаем веса голов
state_dict = torch.load("multitask_heads.pt", map_location="cpu")
model.load_state_dict(state_dict, strict=False)  # strict=False, т.к. веса только для голов

model.eval()
Предсказание для одного текста
python
def predict(text, model, tokenizer, device="cpu"):
    encoded = tokenizer(text, padding=True, truncation=True, max_length=256, return_tensors="pt")
    input_ids = encoded["input_ids"].to(device)
    attention_mask = encoded["attention_mask"].to(device)

    with torch.no_grad():
        logit_p, logit_t, logit_i = model(input_ids, attention_mask)
        prob_p = torch.sigmoid(logit_p).item()
        prob_t = torch.sigmoid(logit_t).item()
        prob_i = torch.sigmoid(logit_i).item()

    # Пороги (оптимальные, полученные на валидации)
    thresholds = {"profanity": 0.50, "threat": 0.15, "illegal": 0.40}
    return {
        "profanity": {"prob": prob_p, "label": prob_p >= thresholds["profanity"]},
        "threat":    {"prob": prob_t, "label": prob_t >= thresholds["threat"]},
        "illegal":   {"prob": prob_i, "label": prob_i >= thresholds["illegal"]},
    }

# Пример
text = "Ты мне угрожаешь? Я вызову полицию!"
result = predict(text, model, tokenizer)
print(result)