Кейс 2. Спам-фильтр на словах (Bernoulli Naive Bayes)
Связать с реальным ML
Этот кейс – классика машинного обучения. Именно на задаче фильтрации спама наивный Байес десятилетиями показывал удивительно хорошую практическую эффективность. И что особенно важно – здесь максимально ясно видно, почему он работает, несмотря на наивное предположение о независимости признаков.
Цель кейса
Показать, как:
текст превращается в признаки
каждое слово становится независимым доказательством
логарифмы превращают произведение вероятностей в линейную сумму
простейшая модель решает реальную задачу
Здесь мы используем вариант Bernoulli Naive Bayes – модель, где важен не счет слов, а сам факт их присутствия.
Сценарий
Мы строим примитивный спам-фильтр.
Есть два класса:
spam
ham (обычное письмо)
Модель учитывает только одно:
слово либо есть в письме, либо его нет.
Частота появления слова внутри письма не имеет значения. Это и есть ключевая особенность Bernoulli-подхода.
Обучающая выборка
Каждое письмо – это набор слов.
Никакой грамматики, порядка слов или контекста мы не учитываем.
Шаг 1. Подсчет априорных вероятностей
Мы получаем P(spam) и P(ham).
Если спама больше – модель будет к нему априори склоняться.
Шаг 2. Подсчет условных вероятностей слов
Здесь мы оцениваем: P(word∣class)
Например:
P("free"∣spam)
P("meeting"∣ham)
Каждое слово рассматривается отдельно – это и есть предположение условной независимости.
Шаг 3. Классификация нового письма
Допустим, пришло письмо:
В нем одновременно есть слово, типичное для спама, и слово, характерное для обычной переписки.
Теперь считаем логарифмы вероятностей:
Сравниваем:
spam = -3.3479
ham = -3.7534
-3.34 > -3.75 → модель выбирает spam
Модель:
Берет априорную вероятность класса.
Добавляет вклад каждого слова.
Выбирает класс с максимальным значением.
Что здесь важно понять
1. Каждое слово – условно независимое доказательство при фиксированном классе
Слово "free" голосует за spam.
Слово "meeting" голосует за ham.
Итог – сумма этих голосов в лог-пространстве. Это буквально раздел "Голосование признаков" из теоретической главы.
2. Произведение превращается в линейную модель
Формально:
После логарифмирования:
Это уже линейная сумма. Именно поэтому наивный Байес часто ведет себя как линейный классификатор (в лог-пространстве модель эквивалентна линейному классификатору по признакам).
3. Почему модель работает несмотря на наивность
В реальности слова зависимы:
"free" и "win" часто встречаются вместе
"meeting" и "project" коррелируют
Но для классификации нам важна не идеальная оценка вероятностей, а правильное сравнение классов. Ошибки из-за зависимостей часто распределяются симметрично и не меняют итоговый выбор.
Ограничения текущей реализации
В этом примере:
нет сглаживания (Laplace smoothing)
не учитывается отсутствие слов
в ручной реализации словарь явно не фиксируется (в отличие от примера с RubixML)
данные крайне малы
Это демонстрационная версия, цель которой – показать механику.
Та же задача с использованием RubixML
Теперь посмотрим, как выглядит тот же самый процесс через библиотеку.
Как видите, результат такой же как и в примере с чистым PHP.
Здесь:
каждое слово стало бинарным признаком
1 – означает присутствие
0 – отсутствие
RubixML автоматически считает частоты и применяет формулу Байеса
С точки зрения логики – ничего не изменилось. Изменился только уровень абстракции.
Выводы
Этот кейс показывает три фундаментальные вещи.
Во-первых, наивный Байес идеально подходит для текстовых задач, где признаки естественно бинарны.
Во-вторых, модель работает как механизм суммирования доказательств. Каждый признак добавляет небольшой вклад, и итоговое решение – это их совокупность.
В-третьих, простота модели – не недостаток, а преимущество. Именно благодаря этой простоте наивный Байес десятилетиями оставался одним из базовых инструментов в задачах фильтрации спама.
Если после этого кейса становится ясно, что спам-фильтр – это не "искусственный интеллект", а аккуратная работа с вероятностями, значит, глава достигла своей цели.
Чтобы самостоятельно протестировать этот код, воспользуйтесь онлайн-демонстрацией для его запуска.
Last updated