company_banner

Выявление и классификация токсичных комментариев. Лекция в Яндексе

    Во всех современных системах модерации используется либо краудсорсинг, либо уже ставшее классикой машинное обучение. На очередной тренировке по ML в Яндексе Константин Котик, Игорь Галицкий и Алексей Носков рассказали о своём участии в конкурсе по массовому выявлению оскорбительных комментариев. Конкурс проходил на платформе Kaggle.


    — Всем привет! Меня зовут Константин Котик, я data scientist в компании «Кнопка жизни», студент физфака и Высшей школы бизнеса МГУ.

    Сегодня мы с коллегами — Игорем Галицким и Алексеем Носковым — расскажем вам о соревновании Toxic Comment Classification Challenge, в котором наша команда DecisionGuys заняла 10 место среди 4551 команды.

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

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

    Одна исследовательская группа из Google и еще какой-то компании работает над инструментами, которые помогают улучшить онлайн-обсуждение.

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


    Ссылка

    К настоящему моменту эта группа разработала публичное API, которое может определять степень токсичности комментария, но текущие их модели по-прежнему совершают ошибки. И в этом соревновании нам, кегглерам, был брошен вызов построить модель, которая способна выявлять комментарии, содержащие угрозы, ненависть, оскорбления и тому подобное. Причем в идеале требовалось, чтобы эта модель была лучше, чем текущая модель для их API.

    Имеем задачу обработки текста: выявить, а затем классифицировать комментарии. В качестве обучающей и тестовой выборок были предоставлены комментарии со страниц обсуждения статей Википедии. В трейне было порядка 160 тысяч комментариев, в тесте 154 тысячи.



    Обучающая выборка была размечена следующим образом. Каждому комментарию соответствует шесть меток. Метки принимают значение 1, если в комментарии есть данный тип токсичности, 0 — иначе. И может быть так, что все метки нулевые, случай адекватного комментария. А может быть так, что один комментарий содержит несколько типов токсичности, сразу угрозу и непристойность.

    В силу того, что мы находимся в эфире, я не могу продемонстрировать конкретные примеры этих классов. Касательно тестовой выборки — для каждого комментария надо было предсказать вероятность наличия каждого типа токсичности.

    Метрика качества — это усредненный по типам токсичности ROC AUC, то есть среднее арифметическое ROC AUC для каждого класса в отдельности.



    Здесь приведено распределение объектов по классам в обучающей выборке. Видно, что данные сильно не сбалансированы. Сразу скажу, что наша команда забила на пробу методов по работе с несбалансированными данными, например, оверсемплингом или андерсемплингом.



    При построении модели я использовал двухэтапную предобработку данных. Первый этап — базовая предобработка данных, это преобразований вида на слайде, это приведение текста к нижнему регистру, удаление ссылок, IP-адресов, цифр и пунктуации.



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

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

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

    Конечно, есть и более сложные порождающие процессы, но суть не меняется — этот подход никак не учитывает общий порядок слов. Можно перейти к инграммам, но там будет учитываться только оконный порядок слов, а не общий. Поэтому я понимал и мои партнеры по команде, что нужно использовать что-то более умное.


    Ссылка

    Первое умное, что пришло мне в голову, это использовать векторное представление с помощью Doc2vec. Это Word2vec плюс вектор, учитывающий уникальность конкретного документа. В исходной статье этот вектор называется как параграф id.

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

    Логистическая регрессия очень долго обучалась. Мне вообще в оперативку не помещалась. На мощностях Игоря, чтобы получить результат, как на слайде, где-то день потратили. По этой причине мы сразу отказались от использования Doc2vec в силу большого ожидания, хотя и можно было его улучшить на 1000, если комментарий с дополнительной предобработкой данных сделать.



    Более умное, что использовали мы и другие участники соревнования, это рекуррентные нейронные сети. Они на вход последовательно получают слова, обновляя свое скрытое состояние после каждого слова. Я с Игорем использовал рекуррентную сеть GRU по word embedding fastText, который особенен тем, что там решается множество независимых бинарных задач классификации. Предсказать независимо наличие или отсутствие контекстного слова.

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

    Вы спросите, в чем состоял секрет успеха?



    Он состоял в блендинге, его было невроятно много, с стекинге, и в подходе нетворкинг. Подход нетворкинг нужно изобразить в виде ориентированного графа.



    В начале соревнования команда DecisionGuys состояла из двух человек. Затем Павел Плесков в Slack канале ODS выразил желание, что он хочет объединиться с кем-нибудь из топ-200. Мы тогда как раз находились где-то на 157 месте, и Павел Плесков на 154, где-то по соседству. Игорь заметил его желание присоединиться, а я пригласил его в команду. Затем к нам присоединился Андрей Литвинов, потом Павел пригласил грандмастера Алексея Носкова к нам в команду. Игорь — Евгению. И последним партнером нашей команды стал болгар Атанас Атанасов, и вот такой получился человеческий международный ансамбль.

    Сейчас Игорь Галицкий расскажет, как он обучал gru, более подробно расскажет об идеях и подходах Павла Плескова, Андрея Литвинова и Атанаса Атанасова.

    Игорь Галицкий:
    — Я data scientist в компании Epoch8, и я расскажу о большинстве архитектур, которые мы использовали.



    Все началось со стандартной didirectional gru с двумя слоями, все практически из команд ей пользовались, и в качестве embedding был fastText, функция активации EL.

    Тут особенно сказать нечего, простая архитектура, без изысков. Почему она нам дала такие неплохие результаты, с которыми мы довольно долго держались в топ-150? У нас была хорошая предобработка текста. Нужно было двигаться дальше.



    У Павла был свой подход. После блендинга с нашим это дало существенный прирост. До этого у нас был блендинг gru и модели на Doc2vec, она давала 61 LB.



    Расскажу о подходах Атанаса Атанасова, он прямо энтузиаст всяких новых статей. Здесь изображено gru с attention, все параметры на слайде. У него было очень много реально крутых подходов, но он до последнего момента использовал свою предобработку, и весь профит нивелировался. Скор на слайде.



    Дальше был иерархический attention, он показал даже хуже результат, поскольку изначально это сеть для классификации документов, состоящих из предложений. Он это прикрутил, но подход не очень.


    Ссылка

    Был интересный подход, мы изначально можем доставать из предложения фичи из начала и с конца. С помощью конволюции, сверточных слоев, у нас отдельно достаются фичи слева и справа по дереву. Это с начала и конца предложения, потом они мерджатся и опять пускаются через gru.



    Также Bi-GRU с attention блоком. Это одна из лучших на private была, достаточно глубокая сеть, показала хорошие результаты.



    Следующий подход — как можно еще больше выделить фич? После слоя рекуррентной сети делаем еще три параллельных слоя конволюции. И тут мы брали не такую большую длину предложений, обрезали на 250, но за счет трех конволюций это дало неплохой результат.


    Ссылка

    Это была самая глубокая сеть. Как сказал Атанас, он просто хотел что-то большое и интересное обучить. Обычная сверточная сетка, которая училась на текстовых фичах, результаты ничего особенного.


    Ссылка

    Это достаточно интересный новый подход, в 2017 году была статья на эту тему, она использовалась для ImageNet, и там позволила улучшить на 25% предыдущий результат. Ее основная фишка в том, что параллельно сверточному блоку пускается маленький слой, который учит веса для каждой свертки в этом блоке. Она дала очень крутой подход, несмотря на обрезание предложений.

    Проблема в том, что максимальная длина предложений в этих задачах доходило до 1500 слов, очень большие комментарии были. У других команд тоже возникали мысли, как поймать в этом большом предложении, как найти, потому что все засовывать не очень. И многие сказали, что в конце предложения была очень важная инфа. К сожалению, во всех этих подходах это не учитывалось, потому что бралось начало. Возможно, это дало бы дальнейший прирост.


    Ссылка

    Здесь архитектура AC-BLSTM. Суть в том, что если нижнее разделение на две части, помимо attention, это умный пуллинг, а параллельно идет еще обычный, и это все конкретизируется. Тоже неплохие результаты.



    И Атанас весь свой зоопарк моделей, потом это классно смешивал. Помимо самих моделей, добавлял какие-то фичи текстовые, обычно длина, количество больших букв, количество плохих слов, количество символов, это все добавлял. Кросс-валидация из пяти фолдов, и получались отличные результаты, на private LB 0.9867.


    Ссылка

    И второй подход, он с другим эмбеддингом учил, но результаты получились похуже. В основном все использовали fastText.

    Хотелось сказать про подход другого нашего коллеги, Андрея c ником Лаоль в ODS. Он обучал очень много public kernel, стакал их как не в себе, и это реально дало очень классные результаты. Можно было это все не делать, а просто взять кучу public kernel различных, даже на tf-idf есть, gru всякие конволюционные.


    Ссылка

    У него один из лучших подходов был, с которым мы долго держались в топ-15, пока к нам не присоединился Алексей и Атанас, он сблендил блендинг и стакинг этого всего. А также очень крутой момент, который, как я понял, ни одна из команд не использовала, мы потом еще делали фичи из результатов API организаторов. Про это дальше расскажет Алексей.

    Алексей Носков:
    — Привет. Расскажу про подход, который я использовал, и чем мы это завершили.



    У меня все было достаточно просто: 10 фолдов кросс-валидации, модели, предуобученные на различных векторах с различным препроцессингом, чтобы у них был побольше diversity в ансамбле, немного аугментация и два цикла разработки. Первый, который в основном вначале работал — обучил какое-то количество моделей, посмотрел ошибки на кросс-валидации, на каких примерах оно делает очевидные ошибки, и исправил исходя из этого препроцессинг, потому что там как раз понятнее, как их пофиксить.

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



    Тут видно, что она имеет местами блочную структуру, некоторые модели при том, что имели хорошее качество, были слабо скоррелированы с остальными, и весьма хорошие результаты давало то, что я брал эти модели в качестве основы, обучал несколько различных их вариаций, отличающихся различными гиперпараметрами или препроцессингом, и добавлял потом в ансамбль.


    Ссылка

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

    И второй подход, который не так сильно помогал, но тоже помог, это то что можно попытаться взять два произвольных комментария, как правило не очень длинных, склеить их и взять в качестве лейбла на таргет объединение лейблов или немного задебустить там, где только один из них содержал лейбл.

    Оба эти подхода хорошо работали, если их применить не заранее ко всему трейн-сету, а менять набор примеров, к которым применять аугментацию каждую эпоху. Каждую эпоху в процессе формирования батча мы выбираем, допустим, 30% примеров, которые прогоняет через переводы. Вернее заранее где-то лежит параллельно уже в памяти, просто выбираем на основе версию для перевода, и добавляем в батч при ее обучении.


    Первая ссылка, вторая ссылка

    Интересным отличием были модели, обученные на BPE. Есть SentencePiece — токенайзер Google, который позволяет разбить на токены, в которых не будет UNK вообще. Ограниченный словарь, в котором любая строка разобьется на какие-то токены. Если в реальном тексте количество слов больше, чем целевой размер словаря, они начинают разбиваться на более мелкие кусочки, и получается промежуточный подход между character level и word level моделями.

    Там используется два основных алгоритма построения: BPE и Unigram. Для алгоритма BPE в сети было достаточно легко найти запредтрейненные эмбеддинги, и с некоторым фиксированным словарем — у меня как раз хорошо заработал словарь 50к — можно было еще обучить модели, которые давали неплохой (неразборчиво — прим. ред.), чуть-чуть похуже, чем обычные на fastText, зато они были очень слабо скоррелированы со всеми остальными и давали хороший буст.



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



    У меня было большое количество моделей. Просто скидывать их все в какой-то стекер? Работало не очень хорошо, он переобучался, но поскольку модели представляли из себя группы, которые были достаточно сильно скоррелированы, я их просто объединял в эти группы, внутри каждой группы усреднял и получал 5–7 групп очень похожих моделей, от которых в качестве фич для следующего уровня использовал усредненные значения. Обучал на этом LightGBM, багал 20 запусков с различными семплами, докидывал немного мета-фич аналогично тому, что делал Атанас, и в конце это стало наконец работать, давать некоторый буст поверх простого усреднения.


    Ссылка

    Больше всего в итоге добавило API, которое нашел Андрей и которое содержит сходный набор лейблов. Модели для них организаторы построили изначально. Поскольку он изначально отличался, то участники его не использовали, нельзя было его просто сопоставить с теми, которые нам необходимо было предсказать. Зато если это закидывалось в качестве мета-фич в хорошо работающий стекинг, то давало замечательный буст, особенно на классе TOXIC, который, судя по всему, был наиболее сложным на лидерборде, и позволило нам на несколько мест подпрыгнуть в конце, буквально в последний день.



    Поскольку мы обнаружили, что у нас так хорошо работает стекинг и API, то перед финальным сабмишном немного сомневались в том, насколько хорошо это перенесется на private. Работало уж очень подозрительно хорошо, поэтому мы выбрали два сабмишна по следующему принципу: один — бленд моделей без API, который был получен до этого, плюс стекинг с метафичами из API. Тут получилось 0,9880 на паблике и 0,9874 на private. Здесь у меня перепутаны отметки.



    И второй — бленд моделей без API, без использования стекинга и без использования LightGBM, поскольку были опасения, что это какое-то небольшое переобучение под паблик, и мы можем с этим сильно слететь. Обошлось, не слетели, и в итоге с результатом 0,9876 на private мы получили десятую позицию. Всё.

    Яндекс

    470,00

    Как мы делаем Яндекс

    Поделиться публикацией
    Комментарии 23
      +3

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


      Под большинством видео на YouTube комментарии такие, что глаза начинают слезиться после прочтения… А там, где нет, значит автор видео поработал над модерацией, и мне их становится жалко — сколько же гадостей им приходится читать перед отправкой в бан.

        +1
        Тут еще главное — не перестараться, а то использование слов «дубляж» или «Шебалин» на известных ресурсах приводит к блокировке отправки сообщения.
        +5
        Предобработка: удаление изображений

        Афтар убейся ап стену
          +4
          Я к тому, что фигня все эти технические средства. Нужно самому развивать устойчивость к токсичности, а не плодить изнеженных людей, которые выпадают в осадок от простого посыла куда подальше.
            +2

            Невозможно развить устойчивость к токсичности. Все равно весь этот негативный фон влияет на подсознание. Это те вещи, на которые нельзя повлиять волевым усилием.


            Поэтому я просто избегаю общения с токсичными людьми. Комментарии стараюсь не читать вообще. Хотя здесь на Хабре комментарии — неотъемлемая часть экспириенса, но к счастью здесь и токсичных людей не очень много.

              +1
              Все равно весь этот негативный фон влияет на подсознание.

              Можно доказательство этого?
                0

                Большая часть поступающих через органы чувств данных проходит в память мимо сознания. Ну и потом, вы можете сознательно игнорировать тот же шум, но он всё равно будет негативно влиять на ваше внимание, мышление, работоспособность.


                Я уж не говорю о том, что токсичная атмосфера двигает мышление к тому, что токсичность это норма

                  +2
                  Я просил доказательства, а не рассуждения на тему.
          +11

          Прекрасная технология, не отклоняйся она в политически популярную сторону.


          Несколько прекрасных примеров, в качестве фраз взяты заголовки статей интернет-изданий (можете попробовать сами):


          Различие на двадцать пунктов. Первый комментарий — "ой, программа не уверена токсичен ли комментарий". Второй — "явно токсично!".




          Уже лучше, токсичность определены в обоих, но опять наблюдается различие более чем на пять-десять пунктов.




          Пре-кра-сно. Повторяется ситуация с первым набором комментариев — токсичность по отношению к белым = "ну хз", токсичность по отношению к чёрным = токсичность.


          Очень интересное такое совпадение, что включение в токсичный комментарий слов "white", "male" и пр. резко понижает его токсичность.

            –1
            Политика (общественное мнение) всегда ежесекундно, если у вас черные люди были только, что в рабстве, то упоминание черный-рабство — токсично, потому что связано с многочисленными психологическими травмами, белый-рабство не будет вызывать никаких эмоций.
            Это не объективная реальность, а субъективное ощущение токсичности, связанное с пережитым опытом, которое надо постоянно измерять и мониторить в обществе. Причем, что токсично для одного круга лиц, может быть абсолютно приемлемо для другого.
              +3
              Я всё никак не могу понять, откуда взялись все эти черные люди, которые получили психологическую травму от невыносимого рабства…
                0

                Культура и остаточные стигмы общества. Рабство как установка упразднено, а стереотипы остались. Не то что бы стереотипы это обязательно плохо, но в случае с пренебрежительным отношением к определённой расе (привет, 282 УК РФ!) это таки-плохо и может травмировать.


                Собственно, зайдите в зарубежный Интернет — увидите массу травмированных людей — озлобленных, недовольных, etc — как раз благодаря стереотипно-пренебрежительному (или ещё веселее — как к писаной торбе) отношению к ним.

                +4

                То есть по-вашему, то что нельзя говорить гадости в сторону уже травмированного человека, позволяет говорить гадости в сторону человека не травмированного? Получается, если человек оскорбит в комментариях инвалида — это плохо, а вот если здорового — так пожалуйста?


                В любом случае своё предназначение система выполняет не полностью — не всегда определяет токсичность при замене всего одного слова (белый → чёрный, например), и явно имеет уклон в сторону. Токсичность — не ок, и не важно по отношению к кому она проявляется.


                Причем, что токсично для одного круга лиц, может быть абсолютно приемлемо для другого.

                Отличная идея, вот только присмотритесь к комментариям с картинок — токсичность на них вполне себе универсальна. Особенно на первой.

              +3
              Я не разбираюсь в машинном обучении- чем такая система от цензуры отличается?
              Когда политиканы решают за врослых людей- что те должны смотреть, как и где- это вроде как плохо и деструктивно.
              А когда комерсы решают за взрослых людей- какую эмоциональную окраску должно иметь их общение, это типа круто и прогрессивно.
              Нечего подобного дорогие товарищи, господа или кто вы там.
              Запрет ругать политиков с чинарями и запрет ругать друг друга это одного куска фекалий разные стороны.
              Давайте, разрабатывайте алгоритм выявления «неправильных» коментов. Вас же потом вашим же алгоритмом и выявят. Когда будете в очередно раз возмущаться, что надо цак носить и три раза КУ делать обладателям разноцветных штанов.
                0

                Создайте свой форум, где можно свободно ругать кого угодно. При цензуре создать такой форум вам не позволило бы государство.

                0

                Отличие от цензуры — в реакции на токсичность. Можно тереть каменты, а можно ведь и выявлять детракторов, чтобы понять проблемы.

                  +1
                  Если это единственное отличие- можно сказать, что отличий нет.
                  Просто у «операторов» цензуры один взгляд на то, что люди имеют право писать, а у операторов подобных штук немного другие.
                  И те и другие пользуясь своей властью принимают за других решения- что тем надлежит думать и говорить.
                  Просто переводим одно слово в Вашей цитате с маркетингового жаргона на нормальный язык и фраза подходит для обоих «операторов»:
                  «Можно тереть каменты, а можно ведь и выявлять критиков, чтобы понять проблемы.»
                  0

                  Токсичных?) И какая у них ПДК?

                    –1

                    Тот случай, когда хайп победил здравый смысл. Смотрите, подход, применяемый здесь на хабре, гораздо эффективнее и проще:


                    (1) шрифт неприятного комментария, получающего минусы, будет всё более прозрачным, пока совсем не скроется из виду, а его автор в какой-то момент просто лишится возможности комментировать,


                    (2) комментирование подразумевает идентификацию (причём, в общем случае, безотносительно набивших оскомину персональных данных).

                      +2
                      По моему мнению борьба с так называемой «токсичностью» (мне не нравится что этот человек говорит не так, как я хочу и не то, что я хочу) — крайне опасное явление само по себе. Это ни что иное, как высокотехнологичная негосударственная цензура, навязываемая it-гигантами.
                        0
                        А можно её где-нибудь покрутить самостоятельно? Хотя бы в виде API?

                        Хочу натравить на один ролевой форум, замерять общий уровень токсичности и токсикомании участников.

                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                        Самое читаемое