Bag of Words и TF–IDF
Формулы, интерпретация весов.
В предыдущих главах мы говорили о тексте как о данных и о том, что компьютер не умеет читать слова "как человек". Для него текст – это набор символов, чисел и статистик. В этой главе мы разберём два базовых, но до сих пор крайне полезных подхода к представлению текста в виде чисел: Bag of Words и TF–IDF.
Они просты, почти наивны, но именно поэтому идеально подходят для понимания того, как из слов появляется математика. Более того, многие современные идеи в NLP логически вырастают именно из них.
Идея Bag of Words
BOW - Bag of Words (мешок слов) – это способ представить текст без учёта порядка слов. Нас интересует только то, какие слова встретились и сколько раз.
Представим два предложения:
"Кот ест рыбу"
"Рыбу ест кот"
Для человека они почти одинаковы. Для Bag of Words – абсолютно одинаковы.
Мы как бы высыпаем слова из текста в мешок, перемешиваем их и считаем количество каждого слова.
Формирование словаря
Первый шаг – построить словарь. Это просто список всех уникальных слов во всех документах.
Пусть у нас есть три документа:
D1: "кот ест рыбу"
D2: "кот любит рыбу"
D3: "собака ест мясо"
Словарь будет таким:
Каждому слову мы сопоставляем индекс.
Вектор Bag of Words
Теперь каждый документ превращается в вектор длины ∣V∣, где ∣V∣ – размер словаря.
D1: "кот ест рыбу":
D2: "кот любит рыбу"
D3: "собака ест мясо"
Каждое число – это количество вхождений слова.

Немного математики
Формально Bag of Words можно записать так.
Пусть:
V=w1,w2,…,wn – словарь
d – документ
Тогда вектор документа:
где ci – количество вхождений слова wi в документ d.
Это обычный вектор в Rn (для чистого Bag of Words – в Nn).
И уже на этом этапе мы можем:
сравнивать документы
обучать классификаторы
искать похожие тексты
Но есть одна проблема.
Проблема частот
Рассмотрим слово "кот" и слово "и".
Слово "и" будет встречаться почти в каждом документе. Его частота большая, но смысловая ценность почти нулевая.
Bag of Words не различает:
важные слова
служебные слова
редкие, но информативные термины
Все слова равны. А это плохо.
И тут появляется TF–IDF.
TF–IDF: интуиция
TF–IDF расшифровывается как: Term Frequency – Inverse Document Frequency
Идея очень простая:
слово важно, если оно часто встречается в документе
но оно теряет ценность, если встречается почти во всех документах
TF – "насколько часто слово встречается в данном документе"
IDF – "насколько слово редкое в корпусе"
Итоговый вес – их произведение.
Term Frequency (TF)
Самый простой вариант TF:
Но часто используют нормализацию:
где ∣d∣ – общее количество слов в документе.
Интерпретация:
0 → слова нет
чем больше значение, тем важнее слово для конкретного документа
Inverse Document Frequency (IDF)
IDF показывает, насколько слово редкое.
Формула:
где:
где log — натуральный логарифм (его же и используем далее)
N – общее число документов
df(w) – количество документов, где встречается слово w
Иногда добавляют сглаживание:
Интерпретация:
редкое слово → высокий IDF
частое слово → IDF мал (без сглаживания – близок к 0, со сглаживанием – близок к 1)
Итоговая формула TF–IDF
Вес слова w в документе d:
Таким образом:
слово часто в документе → вес растёт
слово часто во всех документах → вес падает

Пример расчёта
Пусть у нас 3 документа, и слово "кот" встречается в двух из них.
Итого
А слово "собака" встречается только в одном документе:
Поэтому
Даже если в документе они встречаются по одному разу, "собака" будет весить значительно больше.
Вектор TF–IDF
Как и Bag of Words, TF–IDF – это вектор.
Отличие только в том, что вместо целых чисел мы получаем вещественные веса.
Этот вектор:
обычно хранится в разреженном виде
высокоразмерный
хорошо отражает смысл документа на базовом уровне
Сравнение документов
TF–IDF часто используют вместе с cosine similarity.
Почему? Потому что:
длины документов разные
важна не сумма весов, а направление вектора
Cosine similarity измеряет угол между векторами, а не расстояние между точками.

Ограничения Bag of Words и TF–IDF
Важно понимать границы этих моделей.
Они:
не учитывают порядок слов
не понимают контекст
не различают омонимы
не знают семантики
"river bank" и "bank of money" для них – почти одно и то же.
Но при этом они:
быстрые
интерпретируемые
отлично работают на малых данных
являются хорошей базовой линией
Почему это всё ещё важно
Bag of Words и TF–IDF — это фундамент.
Если вы понимаете:
откуда берётся вектор
почему вес слова именно такой
как редкость влияет на значение
то эмбеддинги, attention и трансформеры перестают быть такими непонятными. Они просто делают то же самое, но сложнее и умнее.
Именно поэтому мы начали с мешка слов.
Простой пример TF–IDF на PHP (без библиотек)
Ниже — максимально простой пример, который показывает саму механику, без оптимизаций и абстракций. Такой код легко читать и удобно разбирать построчно.
Пусть у нас есть три документа:
Шаг 1. Токенизация
Шаг 2. Словарь
Шаг 3. Term Frequency (TF)
Шаг 4. Document Frequency и IDF
Шаг 5. TF–IDF вектор документа
Теперь $tfidfVectors содержит TF–IDF веса слов для каждого документа.
Пример использования и результат
Добавим простой вывод результатов, чтобы увидеть реальные числа:
Вывод будет примерно таким:
Как это интерпретировать
Слова "кот", "ест" и "рыбу" встречаются в нескольких документах, поэтому их IDF маленький и итоговый вес низкий
Слова "любит", "собака" и "мясо" встречаются только в одном документе, поэтому их вес заметно выше
Даже при одинаковой частоте внутри документа редкость в корпусе сильно влияет на результат
Важно не то, что код "боевой", а то, что здесь буквально реализованы формулы из предыдущих разделов. Никакой магии — только частоты и логарифмы.
В следующей главе мы сделаем следующий шаг — поговорим о эмбеддингах как непрерывных пространствах смысла.
Last updated