Наивный байесовский классификатор — полное объяснение с формулами и кодом

МЕНЮ


Главная страница
Поиск
Регистрация на сайте
Помощь проекту
Архив новостей

ТЕМЫ


Новости ИИРазработка ИИВнедрение ИИРабота разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика

Авторизация



В 1763 году Томас Байес вывел теорему, которую сам не успел опубликовать. Она увидела свет только через несколько лет после его смерти — её издал его друг математик Ричард Прайс. Два с половиной века спустя байесовские алгоритмы всё ещё работают — например, фильтруют спам в каждом крупном почтовом сервисе, не требуя ни мощных процессоров, ни гигабайтов обучающих данных.

Как стать ML-инженером в 2026 году: от Python до первого оффера

Наивный байесовский классификатор не используется в продакшене, где бьются за десятые доли процента точности. Но если нужно быстро отсеять мусор, определить тональность отзыва или накидать baseline, от которого оттолкнутся более сложные модели, — он до сих пор в коротком списке. Алгоритм сознательно упрощает реальность: считает все признаки в тексте независимыми. Это грубое допущение, но именно оно позволяет обучаться на небольших выборках и работать со словарями в десятки тысяч слов. Там, где другие модели требуют данных и времени, наивный байес обходится арифметикой восемнадцатого века — и выигрывает за счёт скорости.

Нейросети и анализ данных с нуля

Что такое байесовская теорема

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

Возьмём классический пример. Вы просыпаетесь утром и видите, что асфальт мокрый. Можно предположить: ночью шёл дождь. Почему? Потому что дождь обычно оставляет мокрый асфальт, а вероятность того, что асфальт намок сам по себе, крайне мала. Мозг автоматически перемножил несколько вероятностей и выдал самую правдоподобную гипотезу.

Формула Байеса записывается так:

P(A?B)=P(B?A)?P(A)/P(B)

Каждое значение имеет конкретный смысл:

  • P(A|B) — апостериорная вероятность. Это ответ на вопрос: «Какова вероятность события A, если мы уже знаем, что произошло событие B?». В примере с мокрым асфальтом: вероятность того, что ночью был дождь, при условии, что асфальт мокрый.
  • P(B|A) — правдоподобие. Вероятность увидеть мокрый асфальт, если дождь действительно был. Высокое, около 0.9 или даже 1.0 — дождь почти всегда делает асфальт мокрым.
  • P(A) — априорная вероятность. Частота, с которой дождь идёт вообще, без привязки к наблюдениям. Допустим, в вашем городе дождь бывает раз в три дня — значит, P(A) ? 0.33.
  • P(B) — полная вероятность наблюдения. Вероятность того, что асфальт мокрый в любой день: и когда прошёл дождь, и когда его не было, но, скажем, проехала поливальная машина.

На практике знаменатель P(B) часто не считают явно. Он одинаковый для любого возможного исхода, поэтому на итоговое решение не влияет — сравнивают только числители.

В реальных задачах у нас не одно событие B, а множество признаков: слова в письме, симптомы у пациента, пиксели на изображении. И здесь начинается основная проблема, ради которой и придумали наивное допущение.

Библиотека Pandas в Python и что с ней можно делать

Наивное допущение: почему «наивный»

Допустим, нужно классифицировать текст письма. Признаков много — каждое слово. Чтобы честно посчитать вероятность P(слова | класс), пришлось бы учитывать все возможные комбинации слов: вероятность того, что «купите» и «прямо» и «сейчас» встретятся вместе в спаме, и так для каждой тройки, четвёрки и так далее. Количество комбинаций растёт экспоненциально с ростом словаря. Обучающей выборки никогда не хватит, чтобы оценить все эти сочетания. Это называется «проклятием размерности».

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

Но даже с таким грубым упрощением классификатор часто работает на удивление хорошо. Особенно в задачах, где признаков много, а связи между ними не критичны для принятия решения. 

Теоретическое объяснение этому дали Педро Домингос и Майкл Паццани, исследователи из Калифорнийского университета в Ирвайне, в 1997 году — они показали, что наивный байес может выдавать правильный класс даже тогда, когда его вероятностные оценки далеки от реальных. Достаточно, чтобы максимум вероятности приходился на верный класс, а абсолютные значения не так важны. Оригинальная работа на эту тему доступна в архиве университета Вашингтона. 

Полезный блок со скидкой

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

Если хотите системно изучить такие алгоритмы и научиться применять их на практике, — держите промокод Практикума на любой платный курс: KOD (можно просто нажать). Он даст скидку при покупке и позволит сэкономить на обучении.

Бесплатные курсы в Практикуме тоже есть — по всем специальностям и направлениям, начать можно в любой момент, карту привязывать не нужно, если что.

Что даёт допущение о независимости

Математическое следствие выглядит так. Совместная вероятность признаков при условии класса раскладывается в произведение:

P(x1,x2,…,xn?Ck)=P(x1?Ck)?P(x2?Ck)???P(xn?Ck)?

Без этого допущения пришлось бы вычислять P(x_1, x_2, …, x_n | C_k) как одну большую многомерную вероятность, что практически невозможно при большом n. А с допущением задача распадается на n простых — посчитать частоту каждого признака по отдельности. Для 10 000 слов нужно оценить 10 000 вероятностей, а не миллиарды их комбинаций. Именно это делает наивный байес пригодным для текстов, словарь которых может достигать десятков тысяч слов.

Как работает наивный байесовский классификатор

Обучение наивного байеса — это подсчёт частот по размеченным данным. Берут выборку, где для каждого примера известен класс. Сначала для каждого класса вычисляют априорную вероятность: делят количество его примеров на общее число объектов. Затем для каждого признака внутри каждого класса считают, как часто он встречается. Так получают условные вероятности P(признак|класс).

Когда появляется новый объект, алгоритм предсказывает класс в три шага:

  1. Для каждого класса перемножают его априорную вероятность и условные вероятности всех признаков, входящих в объект. Если какого-то признака в обучающей выборке для этого класса не было, используют сглаженное значение, а не ноль.
  2. Знаменатель P(B) из формулы Байеса не считают. Он одинаков для всех классов, поэтому на выбор максимума не влияет.
  3. Сравнивают полученные числа. Класс с наибольшим значением объявляется предсказанием. Такой подход называют MAP-правилом — от maximum a posteriori, то есть выбор гипотезы с максимальной апостериорной вероятностью.

Пример: фильтрация спама шаг за шагом

Разберём на конкретных числах. Пусть обучающая выборка состоит из четырёх писем. Два из них — спам, два — нормальные (часто их называют «хам», от английского ham).

Подсчитываем частоты слов в каждом классе. В спаме слово «купите» встретилось 15 раз, «дорогой» — 1 раз, «встреча» — 2 раза. В нормальных письмах «купите» — 2 раза, «дорогой» — 10 раз, «встреча» — 8 раз. Общее количество слов в спаме — 40, в нормальных письмах — 50.

Приходит новое письмо: «дорогой купите встреча». Нужно определить, спам это или нет. Сначала вычисляем априорные вероятности классов — оба равны 0.5, поскольку писем поровну.

Теперь считаем вероятности слов при условии каждого класса. Для спама:

  • P(«дорогой» | спам) = 1/40 = 0.025
  • P(«купите» | спам) = 15/40 = 0.375
  • P(«встреча» | спам) = 2/40 = 0.05

Для нормального письма:

  • P(«дорогой» | хам) = 10/50 = 0.2
  • P(«купите» | хам) = 2/50 = 0.04
  • P(«встреча» | хам) = 8/50 = 0.16

Перемножаем (без учёта знаменателя — он всё равно общий):

Спам: 0.5 ? 0.025 ? 0.375 ? 0.05 = 0.000234375
Хам: 0.5 ? 0.2 ? 0.04 ? 0.16 = 0.00064

0.00064 > 0.000234375, значит, классификатор отнесёт письмо к нормальным. Логично: слово «дорогой» гораздо чаще встречается в легитимной переписке, и это перевешивает подозрительное «купите».

Наивный байес — простой способ сделать фильтр для писем или текстов. А если хочется посмотреть, как похожая задача решается уже через нейросеть, у нас есть отдельный гайд о том, как создать ИИ-фильтр с нуля.

Проблема нулевых вероятностей и сглаживание Лапласа

В примере выше всё считается гладко, потому что каждое слово из тестового письма встречалось в обучающей выборке хотя бы раз. Но в реальности это не так. Предположим, в новом письме появляется слово «конференция», которого вообще не было в обучающей выборке для класса «спам». Тогда P(«конференция» | спам) = 0/40 = 0, и всё произведение обнуляется. Модель говорит: «Этого мы никогда не видели, значит, такого не может быть». Очевидно, вывод поспешный.

Решение — сглаживание Лапласа. Идея простая: прежде чем считать вероятности, ко всем счётчикам прибавляют небольшую константу ? (обычно 1). Формула вместо P(x_i | C) = count(x_i, C) / count(C) принимает вид:

P(xi?C)=count(xi,C)+?count(C)+??V?

где V — размер словаря (общее количество уникальных слов). Теперь даже слово, которое ни разу не встречалось в классе, получает ненулевую вероятность: P = ? / (count(C) + ?·V). Маленькую, но не ноль. Это не даёт одному незнакомому слову обнулить всё решение.

В библиотеке scikit-learn параметр alpha для MultinomialNB по умолчанию равен 1.0 — классическое сглаживание Лапласа. Для маленьких выборок значение alpha часто подбирают вручную, потому что стандартная единица может слишком сильно исказить оценки. Иногда значения alpha = 0.5 или 0.1 работают лучше — особенно в медицинских задачах с сильным дисбалансом классов.

Логарифмический трюк: зачем складывать, а не перемножать

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

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

log?P(Ck?x)?log?P(Ck)+?i=1nlog?P(xi?Ck)

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

Именно так и работают реализации в scikit-learn — внутри класса MultinomialNB вероятности хранятся в атрибуте feature_log_prob_, то есть уже прологарифмированными.

Виды наивных байесовских классификаторов

Под одним названием скрывается целое семейство алгоритмов. Различаются они тем, как моделируют распределение признаков. Выбор конкретного варианта зависит от типа данных.

ТипТип данныхТипичная задача
Гауссовский (GaussianNB)Непрерывные числаКлассификация по числовым признакам: рост, вес, температура
Мультиномиальный (MultinomialNB)Счётчики, частоты словКлассификация текстов, NLP
Бернуллиевский (BernoulliNB)Бинарные признаки (0/1)Флаги наличия или отсутствия слова в тексте

Гауссовский наивный байес предполагает, что числовые признаки внутри каждого класса распределены по нормальному закону. Он оценивает среднее значение и дисперсию для каждого признака в каждом классе, а затем вычисляет вероятность нового значения по формуле гауссовой плотности. Хорошо работает для задач вроде классификации ирисов Фишера — классического датасета, где признаки (длина лепестка, ширина чашелистика) примерно нормальны.

Мультиномиальный вариант — основной для текстов. Он оперирует частотами слов, и именно его используют спам-фильтры и анализаторы тональности. В scikit-learn он называется MultinomialNB и принимает на вход матрицу «документ-термин», где каждая ячейка содержит количество вхождений слова в документ.

Бернуллиевский похож на мультиномиальный, но учитывает только факт присутствия или отсутствия слова, а не частоту. Применяют его реже — в основном для коротких текстов вроде твитов, где повторения слов мало что дают.

Где применяется наивный байес

Наиболее распространенные сферы применения: 

  • Спам-фильтры. Классическая задача. Алгоритм быстро обучается на письмах, которые пользователь пометил как спам, и предсказывает класс для новых сообщений. SpamAssassin до сих пор использует байесовскую фильтрацию в качестве одного из модулей.
  • Анализ тональности. Компании классифицируют отзывы клиентов как положительные или отрицательные. Байес здесь хорош тем, что не требует гигантского корпуса размеченных данных — хватает нескольких сотен примеров на каждый класс.
  • Медицинская диагностика. По набору симптомов модель оценивает вероятность заболевания. Сглаживание Лапласа здесь критически важно, потому что обучающие выборки часто маленькие, а комбинации симптомов могут быть редкими.
  • Рекомендательные системы. Алгоритм предсказывает, купит ли пользователь товар, на основе истории его покупок и покупок похожих пользователей. Быстро переобучается при поступлении новых данных, что для рекомендаций существенно.
  • Классификация новостей. Рубрикация статей по темам — спорт, политика, технологии. Мультиномиальный наивный байес справляется с этим лучше многих более сложных методов, если тексты короткие и словарь ограничен.

Как устроены рекомендательные системы

Реализация на Python: минимальный рабочий пример

Ниже — код, который обучает MultinomialNB на произвольном наборе текстов и предсказывает класс для нового документа. Пример использует scikit-learn версии 1.4 или выше.

Лучшие Python-библиотеки для машинного обучения

from sklearn.feature_extraction.text import CountVectorizer from sklearn.naive_bayes import MultinomialNB  # Обучающие тексты: спам и нормальные письма texts = [     "купите прямо сейчас",     "только сегодня скидка",     "бесплатная доставка",     "привет как дела",     "встреча завтра в три",     "скинь документы на почту" ] # Метки: 1 — спам, 0 — не спам labels = [1, 1, 1, 0, 0, 0]  # Векторизатор превращает текст в матрицу частот слов vectorizer = CountVectorizer() X = vectorizer.fit_transform(texts)  # Обучаем классификатор model = MultinomialNB(alpha=1.0) model.fit(X, labels)  # Тестовое письмо test_text = ["скидка на встречу"] test_vec = vectorizer.transform(test_text)  prediction = model.predict(test_vec)[0] prob = model.predict_proba(test_vec)[0]  print(f"Класс: {'спам' if prediction == 1 else 'не спам'}") print(f"Вероятность спама: {prob[1]:.4f}") print(f"Вероятность не спама: {prob[0]:.4f}") # Вывод: Класс: не спам # Вероятность спама: 0.3345 # Вероятность не спама: 0.6655

CountVectorizer строит словарь из всех слов в обучающей выборке и заменяет каждый текст вектором, где каждая позиция — количество вхождений слова. MultinomialNB(alpha=1.0) — классификатор с лапласовским сглаживанием. 

12 библиотек Python, которые стоит попробовать в 2026 году

Метод fit обучает модель: считает частоты слов в каждом классе и сохраняет их в атрибутах feature_count_ и feature_log_prob_. Затем predict выдаёт класс для тестового текста, а predict_proba — вероятности.

Преимущества и ограничения

Преимущества:

  • Обучается очень быстро. Один проход по данным — и модель готова. Для сравнения, логистической регрессии или деревьям решений нужны итеративные процедуры.
  • Работает с малыми выборками. Если других алгоритмов на сотне примеров не обучить толком, наивный байес уже выдаёт осмысленный результат.
  • Неплохо справляется с высокой размерностью. Десятки тысяч признаков — для текстов это норма.
  • Легко интерпретировать. Можно посмотреть, какие слова вносят наибольший вклад в решение о спаме.

Matplotlib: полное руководство по визуализации данных

Ограничения:

  • Сильное допущение о независимости. Если признаки жёстко связаны, точность падает. Классический пример — в медицинских данных симптомы часто коррелируют: температура и головная боль при гриппе идут в комплексе, и наивный байес дважды учитывает одну и ту же информацию.
  • Плохая калибровка вероятностей. Модель часто выдаёт экстремальные значения — 0.99 или 0.01 — которые не соответствуют реальной уверенности. Для задач, где важна именно вероятность, а не просто класс, это проблема.
  • Не умеет работать с пропущенными данными «из коробки». Требуется предварительная обработка данных — либо удалять пропуски, либо заполнять их.

Наивный байес vs. другие классификаторы

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

КритерийНаивный байесЛогистическая регрессияДерево решений
Скорость обученияОчень высокаяСредняяСредняя
Объём данныхМалые выборкиСредние и вышеСредние и выше
Зависимость признаковПроблемаУчитываетУчитывает
ИнтерпретируемостьВысокаяСредняяВысокая

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

Бустинг — ещё один способ машинного обучения

Практическое правило: если признаков очень много (тексты), данных мало, и нужна скорость — пробуйте наивный байес. Если данных много и признаки коррелированы — лучше взять логистическую регрессию.

Итог: когда использовать наивный байес

Наивный байес не стоит тащить в проект только потому, что он простой. Но есть сценарии, где он реально выигрывает:

  • текстовые данные с высокой размерностью: письма, новости, отзывы;
  • когда обучающей выборки мало, а обучить модель нужно быстро;
  • когда нужен baseline, от которого вы будете отталкиваться. 

Если наивный байес даёт 85% точности, а сложная нейросеть — 87%, стоит задуматься, окупает ли прирост в 2% затраты на обучение, подбор гиперпараметров и поддержку.

Байесовская теорема, открытая Томасом Байесом в 1763 году, до сих пор работает. Редкий случай, когда математика XVIII века напрямую применяется в современных продуктах — и неплохо справляется.

Советуем дополнительно почитать по теме: 

  • Как стать ML-инженером в 2026 году: от Python до первого оффера — полный гайд, чтобы вкатиться в data science на роль ML-инженера: путь из семи этапов с нуля до первого оффера — от математики и Python до деплоя модели в продакшн.
  • Что такое искусственный интеллект — не то же самое, что нейросеть: что это такое, какие есть типы и области изучения, что особенно популярно в мире сегодня и как на всём этом заработать.
  • 12 библиотек Python, которые стоит попробовать в 2026 году — для работы с данными, агентами и языковыми моделями: список библиотек, которые закрывают задачи с документами, данными и выходами языковых моделей.
  • Как поисковики понимают ваш запрос: векторы, эмбеддинги и косинусное расстояние — от «Спартака» до RAG: что происходит внутри поисковика, как запрос превращается в числовой вектор и сравнивается с другими векторами.
  • Анализируем тексты Льва Толстого: как привести все слова к одному виду — нормально делаем — нормально получается: как привести слова к нормальной форме, убрать стоп-слова и сделать анализ текста точнее.

Бонус для читателей

Пока наивный байес отделяет спам от полезных писем, самое время отбросить сомнения и войти в ИТ. Держите промокод Практикума на любой платный курс: KOD (можно просто нажать). Он даст скидку при покупке и поможет сэкономить на обучении.

Бесплатные курсы в Практикуме тоже есть — по всем специальностям и направлениям, начать можно в любой момент, карту привязывать не нужно.

Автор: Денис Кудерин


Телеграм: t.me/ainewsline

Источник: thecode.media

Комментарии: