Пост

Обработка естественного языка. Применение готовых моделей для анализа текста

Используем модели с Hugging Face для определения токсичности, эмоциональной окраски и принадлежности к спаму комментариев

В качестве первого шага цикла разработки системы оценки и фильтрации комментариев в Telegram-каналах опробую несколько готовых моделей для анализа текста с Hugging Face.

🔎 Платформа Hugging Face объединяет исследователей в области машинного обучения и предоставляет единую экосистему для работы, состоящую из богатого набора инструментов, моделей, датасетов и сопутствующих библиотек. Одним из крупнейших разделов платформы является обработка естественного языка (NLP), к которому и обратимся для выбора и тестирования моделей.

🔨 Подготовка

🔹 Для упрощения взаимодействия с моделями была разработана библиотека Transformers с поддержкой Torch. Устанавливаем

1
pip install transformers torch pandas

📝 Поскольку мы будем использовать класс pipeline из Transformers, то все модели и сопутствующая информация загрузятся автоматически, ничего отдельно скачивать не нужно.

🔹 В качестве тестовых данных можно воспользоваться подготовленными датасетами комментариев на русском языке, например, здесь или здесь или же самостоятельно выгрузить комментарии из Telegram-каналов способом, который я озвучивал в одной из предыдущих заметок.

💻 Демонстрационные версии скриптов и файл с тестовыми комментариями выложил в репозиторий на gitverse.

🚀 Применение

Заявленные критерии оценки относятся к задаче классификации текста. Из этого подраздела на Hugging Face и будем выбирать соответствующие модели.

📌 Эмоциональная окраска текста

Используем модель rubert-base-cased-russian-sentiment от частного исследователя Вячеслава Литвинова. Модель обучена различать 3 класса тональности: нейтральный, позитивный, негативный.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import pandas as pd
from transformers import pipeline

# объявляем pipeline (высокоуровневая обертка для работы с моделями)
# с указанием задачи text-classification
pipe = pipeline("text-classification", model="seara/rubert-base-cased-russian-sentiment")

# читаем файл с комментариями
with open("comments.txt", mode="r", encoding="utf-8") as f:
    comments = [line.rstrip() for line in f.readlines()]

labels = []
scores = []
for comment in comments:
    # определяем тональность текста
    result = pipe(comment)
    labels.append(result[0]["label"])
    scores.append(result[0]["score"])
    #print(f"\nComment: {comment}\nResult: {result}")

# собираем результаты в dataframe и выводим
print(pd.DataFrame({"Comment": comments, "Label": labels, "Score": scores}))

Результаты:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
                                              Comment     Label     Score
0               В этом ролике прекрасно абсолютно всё  positive  0.816063
1                           завтра самый ужасный день  negative  0.837498
2                                  я буду жить вечно)  positive  0.904710
3                             Го на великах кататься?   neutral  0.946308
4                    15 минут позора и все закончится  negative  0.753213
5                                         пьяная рожа   neutral  0.630692
6   У настоящих друзей всегда появляются какие-то ...   neutral  0.929818
7                      Топ-10 самых странных фильмов.   neutral  0.968063
8                         уродина, его так подвесить.   neutral  0.507614
9                            спасибо что приняли меня  positive  0.695750
10           твари, живут же такие подленькие людишки  negative  0.507779
11                               ты как футболный мяч   neutral  0.844260
12                                ублюдошное существо  negative  0.701768
13                             всё правильно написали   neutral  0.764136
14                        быдло оно и в африке быдло!  negative  0.668712
15  Уважаемый победитель, вы получили приз в нашей...   neutral  0.940999
16  Вы стали участником розыгрыша призов: проверьт...   neutral  0.944460
17                           Привет, как дела? Яблоко   neutral  0.985681
18  Уважаемый пользователь, ваш аккаунт будет удал...   neutral  0.925131
19  Уважаемый подписчик, получите эксклюзивные нов...   neutral  0.815449

Стоит отметить наличие сомнений (низкой вероятности) в некоторых результатах из-за неоднозначности интерпретации текста.

📌 Определение токсичности

Применим модель russian_toxicity_classifier от группы s-nlp.

Принцип тот же самый, что и в предыдущем подходе, только указываем другую модель при создании pipeline

1
pipe = pipeline("text-classification", model="s-nlp/russian_toxicity_classifier")

Результаты:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
                                              Comment    Label     Score
0               В этом ролике прекрасно абсолютно всё  neutral  0.997773
1                           завтра самый ужасный день  neutral  0.999666
2                                  я буду жить вечно)  neutral  0.999704
3                             Го на великах кататься?  neutral  0.952712
4                    15 минут позора и все закончится  neutral  0.997644
5                                         пьяная рожа  neutral  0.956454
6   У настоящих друзей всегда появляются какие-то ...  neutral  0.988191
7                      Топ-10 самых странных фильмов.  neutral  0.989022
8                         уродина, его так подвесить.    toxic  0.996642
9                            спасибо что приняли меня  neutral  0.999728
10           твари, живут же такие подленькие людишки    toxic  0.986700
11                               ты как футболный мяч  neutral  0.993894
12                                ублюдошное существо    toxic  0.994068
13                             всё правильно написали  neutral  0.999644
14                        быдло оно и в африке быдло!    toxic  0.947654
15  Уважаемый победитель, вы получили приз в нашей...  neutral  0.994132
16  Вы стали участником розыгрыша призов: проверьт...  neutral  0.998991
17                           Привет, как дела? Яблоко  neutral  0.916787
18  Уважаемый пользователь, ваш аккаунт будет удал...  neutral  0.985312
19  Уважаемый подписчик, получите эксклюзивные нов...  neutral  0.984544

Здесь уже уверенности побольше, т.к. классификация бинарная, что несколько упрощает задачу.

📌 Определение спама

Для данного раздела возьмем модель spam_deberta_v4 от группы исследователей RUSpam.

Можно пойти уже проверенным путем и использовать pipeline или загрузить модель напрямую, настроить токенизатор (предобработка текста перед отправкой на модель) и обработчик результата. Разработчики предлагают второй вариант в описании, воспользуемся.

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
import pandas as pd
from transformers import AutoTokenizer, AutoModelForSequenceClassification
import torch

model_path = "RUSpam/spam_deberta_v4"
tokenizer = AutoTokenizer.from_pretrained(model_path)
model = AutoModelForSequenceClassification.from_pretrained(model_path)

def predict(text):
    inputs = tokenizer(text, return_tensors="pt", truncation=True, max_length=256)
    with torch.no_grad():
        outputs = model(**inputs)
        logits = outputs.logits
        predicted_class = torch.argmax(logits, dim=1).item()
    return "Спам" if predicted_class == 1 else "Не спам"

# читаем файл с комментариями
with open("comments.txt", mode="r", encoding="utf-8") as f:
    comments = [line.rstrip() for line in f.readlines()]

labels = []
for comment in comments:
    # бинарная классификация спам / не спам
    result = predict(comment)
    labels.append(result)
    #print(f"\nComment: {comment}\nResult: {result}")

# собираем результаты в dataframe и выводим
print(pd.DataFrame({"Comment": comments, "Label": labels}))

Результаты:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
                                              Comment    Label
0               В этом ролике прекрасно абсолютно всё  Не спам
1                           завтра самый ужасный день  Не спам
2                                  я буду жить вечно)  Не спам
3                             Го на великах кататься?  Не спам
4                    15 минут позора и все закончится  Не спам
5                                         пьяная рожа  Не спам
6   У настоящих друзей всегда появляются какие-то ...  Не спам
7                      Топ-10 самых странных фильмов.  Не спам
8                         уродина, его так подвесить.  Не спам
9                            спасибо что приняли меня  Не спам
10           твари, живут же такие подленькие людишки  Не спам
11                               ты как футболный мяч  Не спам
12                                ублюдошное существо  Не спам
13                             всё правильно написали  Не спам
14                        быдло оно и в африке быдло!  Не спам
15  Уважаемый победитель, вы получили приз в нашей...     Спам
16  Вы стали участником розыгрыша призов: проверьт...     Спам
17                           Привет, как дела? Яблоко  Не спам
18  Уважаемый пользователь, ваш аккаунт будет удал...     Спам
19  Уважаемый подписчик, получите эксклюзивные нов...     Спам

✅ Представителей такой узкой области как анализ спама не так много в русскоязычном сегменте по сравнению с английским, да еще и показывающих вполне адекватные результаты, однако выбор есть - датасеты формируются и обновляются, модели разной направленности периодически публикуются.

✅ Результаты применения одиночных моделей оказались на удивление информативными с учетом того, что предварительно никаких исследований не выполнялось. Не лишним будет провести эксперименты анализа текста по совокупности признаков, формируемых несколькими оценочными моделями, более точно сформулировав задачу и расширив тестовую выборку. Опробованные классификаторы найдут дальнейшее применение в системе фильтрации комментариев в Telegram.

Больше полезной информации в Telegram-канале