NLP классификация текста через Bag of Words

NLP - Natural language processing (обработка естественного языка). Направление исскуственного интелекта, которое решает задачи:

  • Классификация текста (автор, жанр, категория)
  • Машинный перевод
  • Анализ семантики и настроения текста
  • Ответы на вопросы
  • Генерация описания по картинке
  • Генерация текста
  • Синтез речи

One-hot вектор

Самое простое представление текста. Пусть дан словарь из N слов.

1) День
2) Дуб
3) Зеленый
4) Златая
5) Кот
6) Кругом
7) Лукоморье
8) Ночь
9) Ученый
10) Ходить
11) Цепь

One-hot вектор - это вектор для кодирования одного слова. Этот вектор длинной со словарь, в котором все нулю, кроме индекса слова. Там стоит 1.

Пример, слово кот будет кодирован следующим образом:

Index =          [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
One_hot_vector = [0, 0, 0, 0, 1, 0, 0, 0, 0,  0,  0]

Bag of Words

Это принцип кодирование предложения, как сумма one-hot векторов слов в этом предложении.

Тогда предложение будут иметь следующий вид:

У лукоморья дуб зелёный, Златая цепь на дубе том
     7       2     3        4    11      2

Index =       [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
Bag_Of_Word = [0, 2, 1, 1, 0, 0, 1, 0, 0,  0,  1]

Второе предложение:

И днём и ночью кот учёный всё ходит по цепи кругом
    1      8    5    9         10       11    6

Index =       [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
Bag_Of_Word = [1, 0, 0, 0, 1, 1, 0, 1, 1,  1,  1]

TF-IDF

Пусть дана коллекция документов D.

  • t - это индекс слова;
  • d - это индекс отдельного документа из коллекции D;
  • count(t, d) - Это сколько раз встречается слова t в документе d;
  • words(d) - Количество слов в документе d;
  • len(D) - количество документов в коллекции D;

TF (Term Frequency) - это частота встречаемости слова t в документе d. Определяется как количество слов в документе, деленное на общее количество слов.

\(tf(t,d) = \frac{ count(t,d) } { words(d) }\)

IDF (Inverse Document Frequency) - это обратная частота документа, которая определяется как количество всех документов, деленное на количество документов, в которых встречается слов t

\(idf(t) = \log \frac{ len(D) } { \displaystyle\sum_{i=0}^{len(D)} count(t,d) > 0 }\)

TF-IDF вычисляется по формуле

\(tfidf(t,d) = tf(t,d) \times idf(t,D)\)

Высокое значение TF-IDF означает, что слово t в документе d встречается больше, чем в остальных документах, а значит более значимый. Если TF-IDF равен нулю, то он встречается во всех документах и малозначительное.

Идея классификации текста

1) Перед анализом нужно очистить весь текст от лишних символов и стоп слов.

2) Затем проанализировать весь текст, составить словарь всех слов и посчитать их частотность. Оставить только те слова, которые употребляются, например, более 3х раз. И обязательно отсортировать по убыванию частотности.

Также можно фильтровать и сортировать по метрике TF-IDF.

3) Затем весь текст нужно разбить на строки длиной L, со сдвигом P и поставить этой строке соответствие с категорией. Каждое слово можно обработать через pyrmorphy или nltk и привести в инфинитив.

Например текст Пушкина:

У лукоморья дуб зелёный;
Златая цепь на дубе том:
И днём и ночью кот учёный
Всё ходит по цепи кругом;
Идёт направо - песнь заводит,
Налево - сказку говорит.

С длиной L=5 и P=2 текст превратится в набор строк:

лукоморье дуб зелёный златой цепь
зелёный златой цепь дуб тот
цепь дуб тот день ночью
тот день ночью кот учёный
ночью кот учёный всё ходить
учёный всё ходить цепь кругом
ходить цепь кругом идти направо
кругом идти направо песня заводить
направо песня заводить налево сказка
заводить налево сказка говорить

На практике обычно берут L=1000 и P=2.

Всем этим строкам нужно поставить соответствие Пушкин. Эти обработанные строки можно сохранить в dataset.json.

4) Каждую строку нужно сконвертировать в BagOfWord и подать в классификатор Dense и обучить нейронную сеть.

Пример простой сети:

model = ai.CustomModel(
	model_name = "Model_bow_2",
	input_shape = input_shape,
	module = nn.Sequential(
		
		nn.Linear(input_shape[0], 512),
		nn.ReLU(inplace=True),
		
		nn.BatchNorm1d(512),
		
		nn.Linear(512, 256),
		nn.ReLU(inplace=True),
		
		nn.Linear(256, output_shape[0]),
		nn.Softmax(dim=-1),
	),
)

input_shape - это входной вектор, размер BagOfWord

output_shape - это выходной вектор, количество категорий.

Минусы Bag of Word

  1. Отсутсвует сохранение порядка слов в предложении
  2. Большие вектора по длине, больше времени считать
  3. При добавлении нового слова в словарь нужно заново обновлять вектора

А также, но это не точно:

  1. Плохо распознает редкие слова. Редкие слова будут иметь одинаковую маленькую частотность.
  2. Часто встречаемые слова, предлоги будут иметь большие значения в векторе. Высокая частотность слова не всегда означает важность этого слова.

Материалы по теме

  1. Википедия: Мешок слов
  2. Википедия: TF-IDF
  3. Лекция. Введение в NLP. Эмбеддинги слов (06.03.2020)
  4. Лекция. Word embeddings
  5. Семинар. Word embeddings
  6. Лекция по языковым моделям (20.03.2020)
  7. Лекция. Языковые модели. Введение. Частотный подход
  8. Лекция. Языковые модели. Нейронные сети
  9. Лекция. Seq2Seq, машинный перевод.
  10. Лекция: Архитектуры NLP, Transformer, Bert. (10.04.2020)
  11. Аугментация для текстов (Text Augmentation)