Использование текстовых и извлеченных числовых признаков в задаче классификации комментариев



    Как выглядят данные?


    Во-первых, посмотрим на имеющиеся тестовые и тренировочные данные (данные соревнования «Toxic comment classification challenge» на платформе kaggle.com). В тренировочных данных, в отличии от тестовых, имеются метки для классификации:


    Рисунок 1 — Train data head

    Из таблицы видно, что мы имеем в тренировочных данных 6 столбцов-меток («toxic», «severe_toxic», «obscene», «threat», «insult», «identity_hate»), где значение «1» свидетельствует о принадлежности комментария к классу, также присутствует столбец «comment_text», содержащий комментарий и столбец «id» – идентификатор комментария.

    Тестовые данные не содержат меток классов, так как используются для отправки решения:


    Рисунок 2 — Test data head

    Извлечение признаков


    Следующий этап – извлечение признаков из комментариев и проведение исследовательского анализа данных (EDA). Во-первых, посмотрим распределение типов комментариев в тренировочном наборе данных. Для этого был создан новый столбец «toxic_type», содержащий все классы, к которым относился комментарий:


    Рисунок 3 — Топ-10 типов токсичных комментариев

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

    Также посмотрим, как распределено количество типов для каждого комментария:


    Рисунок 4 — Количество встречающихся типов

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

    Теперь перейдём к этапу извлечения признаков из текста, который часто называют features extraction. Я извлекла следующие признаки:

    Длина комментария. Я предполагаю, что гневные комментарии скорее всего будут короткими;
    Верхний регистр. В агрессивно-эмоциональных комментариях возможно в словах будет чаще встречаться верхний регистр;
    Смайлики. При написании токсичного комментария вряд ли будут использоваться позитивно окрашенные смайлики ( :), и т.д.), так же рассмотрим наличие грустных смайликов ( :(, и т.д.);
    Пунктуация. Вероятно, авторы негативных комментариев не придерживаются правил пунктуации, в большей степени они используют «!»;
    Количество сторонних символов. Некоторые люди при написании оскорбительных слов часто используют символы @, $ и т.д.
    Добавление признаков осуществляется следующим образом:

    train_data[‘total_length’] = train_data[‘comment_text’].apply(len)
    train_data[‘uppercase’] = train_data[‘comment_text’].apply(lambda comment: sum(1 for c in comment if c.isupper()))
    train_data[‘exclamation_punction’] = train_data[‘comment_text’].apply(lambda comment: comment.count(‘!’))
    train_data[‘num_punctuation’] = train_data[‘comment_text’].apply(lambda comment: comment.count(w) for w in ‘.,;:?’))
    train_data[‘num_symbols’] = train_data[‘comment_text’].apply(lambda comment: sum(comment.count(w) for w in ‘*&$%’))
    train_data[‘num_words’] = train_data[‘comment_text’].apply(lambda comment: len(comment.split()))
    train_data[‘num_happy_smilies’] = train_data[‘comment_text’].apply(lambda comment: sum(comment.count(w) for w in (‘:-)’, ‘:)’, ‘;)’, ‘;-)’)))
    train_data[‘num_sad_smilies’] = train_data[‘comment_text’].apply(lambda comment: sum(comment.count(w) for w in (‘:-(’, ‘:(’, ‘;(’, ‘;-(’)))

    Исследовательский анализ данных


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


    Рисунок 5 — Корреляция

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

    Например, можно увидеть, что количество слов и длина текста сильно коррелированы между собой (значение 0.99), значит, какой-то признак из них можно убрать, я убрала количество слов. Также мы можем сделать еще несколько выводов: корреляция практически отсутствует между выделенными признаками и метками классов, самый мало коррелируемый признак – количество символов, а длина текста коррелирует с количеством символов пунктуации и количеством символов, приведённых к верхнему регистру.

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


    Рисунок 6 — Распределение длин комментариев (график интерактивный, но тут скриншот)

    Как и предполагалось, для комментариев, которые были не отнесены к какому-либо классу (т.е. являются нормальными), длина намного больше, чем для помеченных комментариях. Из негативных комментариев самыми короткими являются угрозы (threat), а самыми длинными – токсичные (toxic).

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


    Рисунок 7 — Средние значения пунктуации (график интерактивный, но тут скриншот)

    Из рисунка видно, что мы получили три кластера.

    Первый – нормальные комментарии, для них характерно соблюдение пунктуационных правил (расстановка знаков препинания, «:», например) и небольшое количество восклицательных знаков.

    Второй состоит из угроз (threat) и очень токсичных комментариев (severe toxic), для такой группы характерно обильное использование восклицательных знаков и на среднем уровне используются иные знаки пунктуации.

    Третий кластер – токсичные (toxic), непристойные (obscene), оскорбления (insult) и ненавистные по отношению к некоторой личности (identity hate) имеют небольшое количество как пунктуационных знаков, так и восклицательных.

    Добавим третью ось для большей наглядности – верхний регистр:


    Рисунок 8 -Трёхмерное изображение (интерактивное, но тут скриншот)

    Здесь видим аналогичную ситуацию – выделяется три кластера. Также отметим, что расстояние между элементами второго кластера больше, чем расстояние между элементами третьего кластера. Это можно увидеть и на двумерном графике:


    Рисунок 9 — Верхний регистр и пунктуация (интерактивное, здесь скриншот)

    Теперь рассмотрим на типы комментариев в разрезе верхнего регистра/количества сторонних символов:


    Рисунок 10 — Верхний регистр и количество сторонних символов (интерактивное, здесь скриншот)

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

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

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

    Теперь рассмотрим, как можно использовать вместе текстовые и числовые признаки в Logistic regression.

    Во-первых, нужно выбрать модель для репрезентации текста в подходящей для алгоритмов машинного обучения форме. Я использовала tf-idf модель, так как она способна выделить специфичные слова и сделать менее значимыми частые слова (например, предлоги):

    tvec = TfidfVectorizer(
    sublinear_tf=True,
    strip_accents=’unicode’,
    analyzer=’word’,
    token_pattern=r’\w{1,}’,
    stop_words=’english’,
    ngram_range=(1, 1),
    max_features=10000
    )

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

    mapper = DataFrameMapper([
    			([‘uppercase’], StandardScaler()),
    			([‘exclamation_punctuation’], StandardScaler()),
    			([‘num_punctuation’], StandardScaler()),
    			([‘num_symbols’], StandardScaler()),
    			([‘num_happy_smilies’], StandardScaler()),
    			([‘num_sad_smilies’], StandardScaler()),
    			([‘total_length’], StandardScaler())
    		], df_out=True)

    Сначала нужно создать DataFrameMapper как показано выше, он должен содержать названия столбцов, имеющих numeric features. Далее создаём матрицу признаков, которую далее будем передавать в Logistic regression для обучения:

    x_train = np.round(mapper.fit_transform(numeric_features_train.copy()), 2).values
    x_train_features = sparse.hstack((csr_matrix(x_train), train_texts))

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

    Вычислительный эксперимент


    Для проведения multi-label classification построим цикл, который будет проходиться по всем категориям и оценивать качество классификации кросс-валидацией с параметрами cv=3 и scoring=’roc_auc’:

    scores = []
    class_names = [‘toxic’, ‘severe_toxic’, ‘obscene’, ‘threat’, ‘identity_hate’]
    for class_name in class_names:
    	train_target = train_data[class_name]
    	classifier = LogisticRegression(C=0.1, solver= ‘sag’)
    	cv_score = np.mean(cross_val_score(classifier, x_train_features, train_target, cv=3, scoring= ‘auc_roc’))
    	scores.append(cv_score)
    	print(‘CV score for class {} is {}’.format(class_name, cv_score))
    	classifier.fit(train_features, train_target)
    
    print(‘Total CV score is {}’.format(np.mean(scores)))</source
    <b>Результат работы:</b>
    
    <img src="https://habrastorage.org/webt/kt/a4/v6/kta4v6sqnr-tar_auhd6bxzo4dw.png" />
    <i>Рисунок 11 — Результат работы</i>
    
    Лучше всего классификатор справился с непристойными комментариями, также неплохие результаты были получены для токсичных, оскорбительных комментариев, которые, как мы видели при проведении исследовательского анализа, часто встречались вместе. Скорее всего, это можно обосновать тем, что в непристойных комментариях есть специфичные слова, которые хорошо их отделяют от остальных. Хорошее значение на кросс-валидации комментариев, отнесенных к “toxic”, возможно, обусловлено тем, что эта категория является самой популярной (согласно рисунку 3). Также классификатор хорошо справился с определением очень токсичных комментариев, вероятно, потому что этот тип явно выражен по отношению к остальным, о чём говорилось при проведении исследовательского анализа данных.

    Similar posts

    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 0

    Only users with full accounts can post comments. Log in, please.