Machine Learning, NLP

Детекция токсичных комментариев на минималках, или как жить и делать NLP, когда отобрали GPU.

Время прочтения: 3 мин.

Недавно закончилось соревнование OK ML CUP по детектированию токсичных комментариев. Стоит отметить, что данная задача стала уже своего рода “притчей во языцех” как машинного обучения, так и ML в частности. Плавно перетекая из разряда насущных в раздел обыденных, она сводится к использованию моделей с transformer-архитектурой, вроде BERT’а.

Но проблема таких архитектур заключается в их тяжести, поэтому иногда в качестве R&D хакатонов, ставятся задачи упрощения подобных моделей или использование более простых аналогов, с минимальными потерями в качестве. 

Достаточно просто осознать, что в соответствии с требованиями Docker контейнера, приведенными ниже, не удастся запихать в него не то чтобы BERT, а даже какие-нибудь простые векторные представления слов вроде Word2Vec. И да, там нет GPU.

MAX_PUSH_GB: 5 // Размер контейнера

MAX_REPO_GB: 8 // Размер хранилища

MAX_PUSH_CNT_PER_DAY: 20 // Количество пушей в день

MAX_BUFFER_SIZE_BYTES: 2712e6 // Размер буфера

TIMEOUT: 600 // Время на выполнение контейнера в секундах

За 10 минут можно провести только инференс. И то, без особых излишеств.

Итак, имеем, тренировочную выборку данных, состоящую из 90000 тысяч комментариев, содержащую в себе оскорбления, пошлость, угрозы из Одноклассников и нормальные комментарии. Хотя, стоит сказать, что после нескольких часов ADA EDA (подсчёта статистик, построения WordCloud, чтения комментариев) понятие нормальности, уже стало довольно расплывчатым. Это как, если бы персонажи картин Босха могли бы разговаривать. Но они не могут. И это наверно к лучшему.

Данная выборка выглядит следующим образом.

В качестве базовой модели использовался lightgbm + TF-IDF по словам и n-граммам.

Из предпроцессинга стоит отметить автокорректировку слов. Это нужно было с целью выявить слова, в которых намеренно сделана ошибка, чтобы не сработал фильтр. 

Для этого, каждый токен (последовательность символов) искался с помощью эмбеддингов (локально их можно было использовать) и, если оно отсутствовало в пространстве слов данного текстового представления, генерировались все слова, расстояние по Левенштейну в которых было равно единице. Далее среди этих слов осуществлялся поиск того слова, которое существует в эмбеддинге. Допускалось, что пользователь совершает не более одной ошибки в слове. В качестве наивной реализации бралось первое такое слово из данного множества. Пример работы данной реализации можно увидеть на рисунке ниже.

Данный подход на удивление неплохо справлялся с поставленной задачей. Его пришлось придумать ввиду строгости требований к модели и как следствие, её простоты и лёгкости.  Ну и удаление пунктуации, куда же без него.

Далее модели сохранялись для написанного инференса и отправлялись в контейнер. Контейнер собирался и отправлялся на сервер.

А финальный результат отображается в личном кабинете.

Исходя из вышеописанного и результатов можно сделать вывод о том, что данный подход эффективен. Средняя точность модели при таком наивном подходе составляет около 93.5 и это позволяет попасть в топ 20 участников. При этом нельзя сказать, что модель сильно переобучилась.  Данная техника позволяет детектировать различные слова, которые пользователь пытался намеренно исказить, чтобы скрыть смысл написанного для алгоритмов автоматической модерации. Также это улучшает качество классификации. Это может быть использовано для построения моделей, или алгоритмов, для которых важно наличие определенных слов.  Автокорректировка доступна в репозитории на Github для ознакомления по следующей   ссылке

Stay tuned…

Советуем почитать