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

Часть 1. Интуиция и как мы работаем с документами?

Часть 2. Обработка текста (модель N-грамм и модель TF-IDF)

Часть 3. Алгоритм обнаружения (машины опорных векторов и градиентный спуск)

Часть 4. Варианты этого подхода (обнаружение вредоносных программ с помощью классификации документов)

В части 1 мы рассмотрели представление документов в виде числовых векторов. Но у этого упрощенного подхода есть много проблем. Разрешите изложить то, что у нас получилось в прошлой статье:

Sentence 1 (S1): “vectorize this text to have numbers!”
Sentence 2 (S2): "what does it mean to vectorize?"
Sentence 3 (S3): "document classification is cool"

Затем мы создали набор слов:

V = ['classification', 'cool', 'document', 'does', 'have', 'is', 'it', 'mean', 'numbers', 'text', 'this', 'to', 'vectorize', 'what']

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

S1 = [0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0]
S2 = [0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1]
S3 = [1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]

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

Здесь нет понятия порядка или последовательности! Другой порядок вещей может существенно повлиять на смысл предложений, но при таком подходе это не учитывается. Например:

S1 = "Car was cleaned by Jack."
S2 = "Jack was cleaned by Car."

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

V = ["by", "car", "cleaned", "Jack", "was"]

S1 = [1,1,1,1,1]
S2 = [1,1,1,1,1]

… Это одни и те же предложения!

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

Модель N-граммов

В рамках модели n-грамм набор слов может выглядеть следующим образом:

V = ["by", "car", "cleaned", "Jack", "was"]

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

S1 = "Car was cleaned by Jack."
S2 = "Jack was cleaned by Car."

двухграммный подход создаст такой словарный набор:

V = ["car was", "was cleaned", "cleaned by", "by jack", ... ,"by car"]

Биграмма - это последовательность двух слов. При таком подходе с n-граммами наша предыдущая загадка не проблема:

V = ['by car', 'by jack', 'car was', 'cleaned by', 'jack was', 'was cleaned']

А векторное представление предложений скорее будет:

S1 = [0 1 1 1 0 1]
S2 = [1 0 0 1 1 1]

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

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

# 4 grams:
V = ['car was cleaned by', 'jack was cleaned by', 'was cleaned by car', 'was cleaned by jack']
# 5 grams: 
V = ['car was cleaned by jack', 'jack was cleaned by car']
# Combination of 4 and 5 grams:
V = ['car was cleaned by', 'car was cleaned by jack', 'jack was cleaned by', 'jack was cleaned by car', 'was cleaned by car', 'was cleaned by jack'

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

Взвешивание TF-IDF

Хорошо, теперь мы учитываем последовательности слов. Но давайте рассмотрим этот пример классификации предложений как положительный или отрицательный отзыв:

S1 = "This movie is bad"
S2 = "This movie is good"

Эти два предложения объективно очень похожи. У них есть большинство общих слов, кроме одного слова. Одно это слово («хороший», «плохой») кардинально меняет свою категорию. Но в нашей текущей модели наши классификаторы воспринимают каждое слово так же серьезно, как и любое другое слово, то есть каждое слово считается одинаковым, когда оно должно на самом деле слова «хороший» и «плохой» следует рассматривать больше.

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

Именно здесь на помощь приходит взвешивание TF-IDF, которое является очень популярным и стандартным инструментом классификации документов. Это расшифровывается как термин "частота-обратная документальная частота". Формула следующая:

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

Давайте сначала исследуем, что такое tf (w, d). По сути, это то, с чем мы работали раньше в наших предыдущих примерах, прежде чем мы представили взвешивание TF-IDF: количество раз, когда определенные слова (w) появляются в документе (d). Помните, что наше числовое представление текста основывалось только на том, сколько раз определенные слова появлялись в документе, индексах, соответствующих набору словаря. Таково значение tf (w, d), в этом нет ничего нового.

Но idf (w, D) - это то место, куда TF-IDF приходит, чтобы спасти нас. «D» представляет собой весь текстовый корпус. Знак абсолютного значения на «D» представляет размер корпуса и общее количество документов. Внизу df (d, w) обозначает, сколько документов содержит слово. Затем мы получаем логарифмически масштабированное значение количества документов в корпусе, деленное на количество раз, когда слово w появляется в корпусе для значения idf (w, D).

Позвольте мне объяснить это по-английски. Интуиция такова: если определенное слово встречается повсюду во всех документах, маловероятно, что оно будет значимым. Подумайте об этом, слово «the» будет появляться почти во всех документах, не давая никому никакого представления о том, относится ли оно к положительной или отрицательной рецензии. И поскольку это правда, мы можем в некоторой степени предположить, что это менее важно, чем другие слова, и поэтому ему следует уделять меньше внимания. Итак, для этого знаменатель в значении IDF - это количество документов, в которых встречается определенное слово, и по мере того, как это число становится больше, значение IDF уменьшается, потому что значение в знаменателе становится больше (1/2 больше 1 / 6)! Таким образом, слово, которое преобладает во всем корпусе, будет иметь меньшее значение TFIDF, потому что значение IDF, которое оно умножает на значение TF, будет меньше, чем у других.

Но как это работает с векторами?

Видите ли, это значение вычисляется довольно интуитивно, но как оно применяется к векторам? Как мы применим это к нашему текущему представлению предложений?

Мы просто помещаем значения TF-IDF, а не просто подсчитываем, сколько раз определенные слова (или n-граммы) встречаются в предложении. Затем мы нормализуем эти значения с помощью евклидовой нормы:

В нашем примере:

V = ['by car', 'by jack', 'car was', 'cleaned by', 'jack was', 'was cleaned']
# TF values
S1 = [0 1 1 1 0 1] 
S2 = [1 0 0 1 1 1]
# TF-IDF weighted:
S1 = [0, 1.40546511, 1.40546511, 1, 0, 1]
S2 = [1.40546511, 0, 0, 1, 1.40546511, 1]

Взяв в качестве примера одно из значений и применив нормализацию:

S1 = [ 0, 0.57615236, 0.57615236, 0.40993715, 0, 0.40993715]
S2 = [ 0.57615236, 0, 0, 0.40993715, 0.57615236, 0.40993715]

Значение нормализации выражается просто в следующем:

«Оставление неравенства дисперсий равносильно приданию большего веса переменным с меньшей дисперсией» - Франк

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

Реализация Python

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