Несколько месяцев назад я наткнулся на конкурс Kaggle Jigsaw Rate Severity of Toxic Comments. Я всегда хотел участвовать в соревнованиях Kaggle, и это отличный способ попрактиковаться в моих навыках Data Science, особенно в области обработки естественного языка (NLP). В этом сообщении блога я опишу подход, который я использовал для решения этой проблемы, а также результаты.

!!ВНИМАНИЕ!! Набор данных для этого конкурса содержит текст, который считается непристойным, вульгарным или оскорбительным.

Проблема: Учитывая комментарии в текстовом формате, оцените серьезность токсичности комментария. Последняя задача состоит в том, чтобы дать баллы парам комментариев таким образом, чтобы тот, который был помечен как более токсичный, получил более высокий балл, а тот, который был помечен как менее токсичный, получил более низкий балл.

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

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

Более подробную информацию о конкурсе можно найти здесь: https://www.kaggle.com/c/jigsaw-toxic-severity-rating/overview

Стратегия: я планировал использовать три других набора данных для обучения, где оценка токсичности либо уже рассчитана, либо может быть рассчитана с использованием некоторого подхода. После изучения и очистки данных я планирую использовать tfidf, чтобы преобразовать комментарии в числовое представление, чтобы затем использовать метод регрессии для расчета оценки токсичности. Рисунок ниже иллюстрирует общую идею моей стратегии

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

А теперь давайте приступим к работе EDA!

Набор данных головоломки: этот набор данных использовался в предыдущем соревновании головоломки и содержит набор комментариев, помеченных как токсичные, крайне токсичные, непристойные, угрозы, оскорбления, ненависть к личности. Один комментарий будет иметь 1 под метками, которые соответствуют этому комментарию, и 0 в противном случае. Если комментарий имеет 0 во всех шести метках, то это доброкачественный. Я решил умножить столбец с тяжелым отравлением на 2, чтобы придать ему больший вес, добавить 1 и 0 во все строки и нормализовать, чтобы по существу превратить это в оценку токсичности комментария.

Фрагмент преобразованного набора данных показан ниже. Предупреждение: содержит оскорбительный текст.

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

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

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

Набор данных Ruddit: это набор данных комментариев Reddit, который содержит оценку оскорбительности для каждого комментария, ранжированную от -1 для максимально поддерживающей до 1 для максимально оскорбительной. Я решил переоценить оценки, чтобы они варьировались вместо этого от 0 до 1, а затем я построил распределение оценок ниже, которое кажется сбалансированным распределением.

Альтернативный набор данных Jigsaw: последний набор данных, который я использовал, был основан на предыдущих соревнованиях Jigsaw, где пользователь kaggle предварительно обработал его и определил оценки токсичности. Баллы не основаны на шкале от 0 до 1, но, поскольку в конкурсе не указано, что необходима шкала от 0 до 1, может быть выгоднее оставить ее как есть.

Далее давайте выполним предварительную обработку и очистку данных!

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

Давайте углубимся в НЛПдалее и Моделирование:

В любом проекте НЛП нам необходимо преобразовать текстовые данные в некоторое числовое представление, чтобы иметь возможность применять различные подходы машинного обучения к преобразованному выводу. Я решил использовать для этого Trem Frequency-Inverse Data Frequency (Tfidf). Для оценки преобразованного текста я хотел использовать простую регрессионную модель для расчета окончательных оценок токсичности, и для этого я решил использовать модель регрессии Риджа.

Краткий обзор Tfidf:Первая часть — это часть TF или Частота терминов, которая в своей самой простой форме просто вычисляет частоту термина в документе. Если наш Корпус D состоит из набора документов {d₀, d₁,….dₙ}, где n — количество документов (в нашем случае количество комментариев), то частота термина для термина t в документе d в простейшей форме

Использование только TF недостаточно, подумайте о том, что происходит с общими словами во всех документах, вы хотите, чтобы эти слова имели меньшее значение, поскольку они используются в большинстве корпусов и не полностью отражают суть документа. д. Чтобы учесть это, мы вычисляем IDF, который определяется формулой

Комбинируя оба, Tfidf (t, d, D) = TF (t, d) * IDF (t, D)

Кроме того, реализация scikit learning нормализует векторы по умолчанию, используя норму l2.

Рассмотрим корпус, состоящий из двух предложений ниже:

Ниже приведены расчеты того, как рассчитывается Tfidf для предложения (1):

Чтобы, наконец, прийти к векторному представлению [0,318, 0,893, 0,318,0] для предложения (1).

Возвращаясь к нашей исходной проблеме

Tfidf + гребневая регрессия:

Для каждого из трех очищенных и предварительно обработанных наборов данных я использовал случайную выборку для создания разных версий обучающих данных, выбирая 80% данных для создания другой версии, как показано на рисунке ниже:

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

pipeline = Pipeline([
('tfidf', TfidfVectorizer(min_df = 10, analyzer=analyzer, ngram_range=ngram_range)),
('clf', Ridge(random_state=42, alpha=alpha))
])

Настройка гиперпараметров

Параметры TfidfVectorizer

Для TfidfVectorizer я установил min_df на 10, так что слова, которые имеют частоту документа менее 10, будут игнорироваться при вычислении вектора tfidf, это игнорирует редкие слова и имеет решающее значение для ускорения вычислений и вектор меньше.

Для анализатора я протестировал как «word», так и «char_wb», и варьировал «ngram_range» для каждого варианта. Анализатор «слов» использует слова в качестве базовой единицы для функций, и при выборе ngram_range = (1,1) — что является выбором по умолчанию — каждое слово в предложении считается характеристикой, где, как когда ngram_range = (3,5) , который я также тестировал, группы из 3, 4 или 5 слов считаются функциями. Для анализатора char_wb символы в слове считаются признаками, использование ngram_range (1,1) в этом случае не очень полезно, так как каждый отдельный символ будет считаться свойством, поэтому я решил протестируйте его с помощью ngram_range = (3,5) и (5,10).

Параметры гребневой регрессии

Для гребневой регрессии я изменил параметр альфа, который управляет регуляризацией, чтобы он имел значения: 0,01, 0,1, 1, 10 и 100.

Результаты

В процессе обучения я сохранил параметры, обеспечивающие наивысшую среднюю точность проверки (по 3 версиям набора данных) для каждого набора данных. Для всех трех наборов данных лучшим анализатором был char_wb с диапазоном энграмм от 3 до 5, а параметр регуляризации для гребневого регрессора — это то, что варьировалось от одного набора данных к другому. jigsaw — 1, для Ruddit — 0,1, а для альтернативного набора данных jigsaw — 10. Средняя точность проверки для этих 3 наборов данных соответственно составила 0,6811, 0,6229 и 0,6732. >.

Возможные улучшения. Можем ли мы улучшить результат, объединив результаты?

На следующем этапе я использовал лучшие параметры для каждого набора данных, чтобы обучить все образцы набора данных с использованием этих параметров, и использовал структуру, подобную ансамблю, которая взвешивает модели, соответствующие каждому набору данных, по-разному, чтобы получить набор весов, который получает мои три моделей для обеспечения максимальной точности проверки, которая составила 0,6862 (не такое уж большое улучшение по сравнению с исходной точностью проверки одной только головоломки). Затем я использовал эту окончательную модель, чтобы сделать свои окончательные прогнозы для поставленной задачи, и отправил эти прогнозы в Kaggle.

Результаты на Kaggle

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

Отражение

Мой окончательный рейтинг в этом конкурсе был 739-м из 2301 заявок, что сделало меня одним из 33% лучших. Это не очень впечатляет, однако это хорошее начало, учитывая, что это было мое первое публичное соревнование по kaggle. В целом, я думаю, что это был хороший опыт, который позволил мне столкнуться с неприятностями проблем NLL. В частности, неструктурированные данные, субъективность метрик, которые мы используем, и длительное время обучения.

Я надеюсь принять участие в будущих соревнованиях и изучить другие методы и подходы NLL. Окончательные результаты конкурса теперь доступны по адресу: https://www.kaggle.com/c/jigsaw-toxic-severity-rating/leaderboard, и я заметил, что в лучших работах использовалась языковая модель BERT (или вариант), поэтому было бы интересно посмотреть, как использование более сложной модели, такой как BERT, может улучшить результаты по сравнению с использованием классического Tfidf. Это увеличение сложности, вероятно, будет означать увеличение времени обучения и других вычислительных ресурсов.