Расширенный анализ текста для повышения точности вашей модели

В этой статье я покажу вам, как провести текстовый анализ, чтобы повысить точность вашей модели и обнаружить несколько фактов в ваших данных. Для этого я буду использовать набор данных, доступный на Kaggle.
Этот набор данных состоит из комментариев из «изменений страницы обсуждения Википедии», он снабжен идентификаторами пользователей, опубликовавших комментарий, но у нас нет информации о прокомментированной странице или личных данных пользователей. Тем не менее, у нас есть 6 разных ярлыков (Toxic, Severe_Toxic, Identity hate, непристойное, угроза, оскорбление), написанных от руки.

Для проведения анализа разделим наш корпус по меткам. Мы кратко рассмотрим распределение различных меток в базе данных, а затем сами эти подкорпуса, которые соответствуют тегам, перечисленным выше.

Видно, что корпус токсичных комментариев самый большой, и около 10% комментариев в учебном корпусе имеют этот ярлык, в то время как корпус угрожающих комментариев меньше. Однако это не означает, что 25% всех комментариев являются злонамеренными, поскольку один комментарий может иметь несколько ярлыков. Мы видим, что чуть менее 5% комментариев имеют только один тег, а около 7% вредоносных комментариев имеют как минимум два тега.

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

статистический анализ

Прежде чем приступить к анализу этих текстовых статистических данных, я предположил, что их создание было бы интересно сравнить данные с моими предубеждениями. То есть, я предполагаю (исходя из опыта), что комментарий, который является злонамеренным, будет содержать более высокую долю слов с заглавной буквы, менее развитый словарный запас и большее количество восклицательных знаков. Помня об этих идеях, я вычислил медианное значение некоторых из моих переменных и поместил их в одну шкалу, я не взял все переменные для удобства чтения графика, поэтому я оставил переменные, которые меня интересовали больше всего. Я создал первую радарную диаграмму с интересующими переменными, чтобы получить соответствующие обозначения между моими корпусами. Форма здесь более важна, чем значения, которые были стандартизированы (т. Е. Переменные были преобразованы так, чтобы их средние значения были сосредоточены на 0, а их дисперсии - на 1), чтобы получить согласованный график между переменными.

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

Более того, реальные цифры показывают, что в среднем количество восклицательных знаков в злонамеренных комментариях в десять раз больше, чем в соответствующих комментариях. Есть и менее развитая пунктуация. Длина предложений на 20% короче в несовместимых корпусах, а количество слов заглавными буквами примерно в 2,5 раза выше для 43 заглавных букв в среднем по сравнению с 14 для совместимого комментария, что связано со средней длиной предложения, в среднем 11 % слов в неканоническом комментарии написаны заглавными буквами, в то время как в среднем только 4% слов в соответствующем комментарии. Таким образом, лексическая бедность, основанная на количестве «уникальных» слов, то есть отличных от других, в этом типе корпуса в 1,5 раза ниже в среднем для 33 уникальных слов против примерно 50 в совместимом корпусе. Мы можем задать себе более глубокие вопросы об этой лексической бедности, давайте посмотрим на комментарии с более низким уникальным процентом слов - 30%.

В основном это токсичные комментарии. Если мы посмотрим на детали, то увидим, что эти
комментарии очень часто являются «спамом». Эта информация интересна для нашей модели - определим индикатор спама.

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

Вербальный и грамматический анализ

Во-первых, давайте разделим наши корпуса и рассмотрим алгоритмическую часть нашего алгоритма POS-тегов.

toxic = train[train["toxic"] ==1]
svr_tox = train[train["severe_toxic"] ==1]
identity_hate = train[train["identity_hate"] ==1]
obscene = train[train["obscene"] ==1]
threat = train[train["threat"] ==1]
insult = train[train["insult"] ==1]
clean_com = train.loc[(train['toxic'] == (0)) 
                      & (train['severe_toxic'] == (0))
                      & (train['obscene'] == (0)) 
                      & (train['threat'] == (0))
                      & (train['insult'] == (0))]text_severe_tox = " ".join(svr_tox.comment_text)
text_tox = " ".join(toxic.comment_text)
txxt_identity_hate = " ".join(identity_hate.comment_text)
txxt_obscene = " ".join(obscene.comment_text)
txxt_threat = " ".join(threat.comment_text)
txxt_insult = " ".join(insult.comment_text)
clean_text = " ".join(clean_com.comment_text)

Благодаря nltk library нам не нужно писать все с нуля, мы токенизируем наш корпус.

splitter = Splitter()
#example
print(txxt_threat[:30])
'Hi! I am back again!\nLast warn'
print(splitter.split(txxt_threat[:30]))
[['Hi', '!'], ['I', 'am', 'back', 'again', '!'], ['Last', 'warn']]

Затем мы применим наш алгоритм POS-тегов.

lemmatizer = WordNetLemmatizer()
splitter = Splitter()
lemmatization_using_pos_tagger = LemmatizationWithPOSTagger()
tokens = splitter.split(txxt_threat)
treat = lemmatization_using_pos_tagger.pos_tag(tokens)
print(treat[:30])
[[('Hi', 'Hi', 'NN'), ('!', '!', '.')],
 [('I', 'I', 'PRP'),
  ('am', 'be', 'VBP'),
  ('back', 'back', 'RB'),
  ('again', 'again', 'RB'),
  ('!', '!', '.')],
 [('Last', 'Last', 'JJ'), ('warning', 'warning', 'NN'), ('!', '!', '.')],

Мы можем видеть, что наш алгоритм делает три вещи, которые он токенизирует, он лемматизирует (учитывая преобразованный глагол, он возвращает вербальный корень), и он дал нам вербальную / грамматическую ссылку на токены. Затем, учитывая этот корпус с тегами pos, мы можем выделить вербальное / грамматическое распределение корпуса. Мы посчитаем каждую метку и присвоим им вес.

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

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

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

Затем мы определим функцию, которая найдет 25 самых распространенных слов в этой глагольной форме и построит график.

микро анализ иностранных слов дает нам представление о большем количестве интересных моментов, мы видим несколько вещей, слов, связанных с корпусами, которые было бы интересно интегрировать в качестве переменных, таких как «puta, Nazi, mother, фуккин ». Есть также символы, которые появляются как повторяющиеся слова, указывая на то, что текстовая статистика количества созданных выше символов, несомненно, повлияет на будущий алгоритм.

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

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

Uni | Bi | Трехкратный анализ

Для этого мы построим матрицу слов, используя метод TFIDF, ограничивая количество ngram и приводя к aLogistic Regression , чтобы посмотреть на важность переменных.

Чем выше оценка, тем важнее функция (я отсортировал значение по токсичным, что означает, что первое слово является более высоким, принадлежащим отсортированному ярлыку)

Например, присутствие слова «ебать» в комментарии увеличит вероятность принадлежности к токсичному ярлыку на 52%, а слово «Ты» оказывает сильное влияние на весь корпус, поскольку оно является основным триггером в качестве униграмма угрожающего ярлыка.

var_imp = get_feature_importances(model, analyzer='word', ngram=2, ngram2 =2, lowercase=True)
var_imp.head(10)

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

var_imp = get_feature_importances(model, analyzer='word', ngram=3, ngram2 =3, lowercase=True)
var_imp.head(10)

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

Весь наш анализ позволит нам создать новые обучающие переменные, которые, я думаю, окажут значительное влияние на нашу модель. Итак, сначала мы будем моделировать наши данные, используя только текст в качестве переменной, мы создадим на жаргоне текстового анализа Bag of Word и будем использовать его в качестве основы обучения для нашего классификатора. Эта матрица построена таким образом, что слова становятся столбцами, id комментариев - строками, а каждая строка состоит из 0 или 1, которые являются индикаторами присутствия слова, поэтому мы имеем дело с разреженной матрицей. Затем мы будем использовать наши знания текста, чтобы улучшить понимание нашего классификатора и посмотреть, действительно ли это влияет на нашу модель.

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

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

for dframe in tqdm([train, test]) : 
    regex_features(dframe)

Затем мы создадим матрицу без функциональной инженерии, а другую - с

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

terms = vectorizer.get_feature_names()
var_imp = pd.DataFrame(index=terms)
for label in lab:
    print('... Processing {}'.format(label))
    y = sample_train[label].values
    classifier = LogisticRegression()
    classifier.fit(train_text_matrix, y)
    y_pred_X = classifier.predict(test_test_matrix)
    print('Valid Accuracy is {}'.format(accuracy_score(y, y_pred_X)))
    var_imp[label] =  np.sqrt(scaler.var_) * classifier.coef_[0]
    
var_imp = var_imp.sort_values('toxic', ascending=False)

Без проектирования функций результаты будут следующими:

Toxic | Obscene | Identity Hate | Severe Toxic | Insult 
79.7  | 88.9    | 98.7          |  98.5        | 91.9

С разработкой функций:

Toxic | Obscene | Identity Hate | Severe Toxic | Insult 
89.3  | 83.9    | 99.6          |  98.7        | 94.3

Видно, что модель с исследуемыми переменными работает намного лучше. Мы можем видеть, что алгоритм достигает более 9 баллов при предсказании токсичной метки, что не является незначительным. Это означает, что из 9,5% комментариев, помеченных как токсичные во всем корпусе, то есть около 15 000 комментариев, прогнозирование 89,3% меток без ошибок означает, что около 13 500 комментариев будут хорошо предсказаны по сравнению с чуть менее 12 000 комментариев в применяемом алгоритме. без текстового анализа, т.е. 1500 дополнительных токсичных комментариев, которых следует избегать. Этот новый алгоритм работает со всеми метками и улучшает обнаружение определенных меток, которые уже были очень хороши, например, корпус ненависти, который по-прежнему получает балл и приближается к идеальному предсказанию.

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

Затем при проектировании функций важности функций становятся:

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