Кое-что о наивном Байесе

машинное обучение искусственный интеллект глубокое обучение Python программист Язык программирования анализ данных сбор данных
Кое-что о наивном Байесе

В области машинного обучения Наивный Байес — это простой классификатор вероятностей, основанный на теореме Байеса (классификация также называется обучением с учителем, так называемое обучение с учителем заключается в том, чтобы сделать вывод о возможности того, что вывод, по-видимому, завершает классификацию, в противном случае кластеризация проблема называется неконтролируемым обучением), Наивный Байес может получить лучшие результаты классификации при работе с текстовыми данными, поэтому он широко используется в текстовой классификации/фильтрации спама/обработке естественного языка и других сценариях.

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

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

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

Автор этой статьиSylvanasSun(sylvanas.sun@gmail.com), впервые опубликовано вБлог SylvanasSun. Исходная ссылка: https://sylvanassun.github.io/2017/12/20/2017-12-20-naive_bayes/ (Для перепечатки просьба сохранить заявление в этом абзаце и сохранить гиперссылку.)

PS: В настоящее время Nuggets не поддерживает использование LaTeX для создания математических формул.Поскольку в этой статье используется много формул, созданных LaTeX, рекомендуется проверить исходный текст в моем блоге.

Условная возможность


Условная вероятность (условная вероятность) относится к вероятности того, что событие A произойдет, когда произойдет событие B, выраженная как $P(A|B)$, читаемая как вероятность A при условии B.

На приведенной выше диаграмме Венна изображены два события A и B, пересечение которыхA ∩ B, и подставляя в формулу условной вероятности, можно сделать вывод, что вероятность наступления события A равна $P(A|B) = \frac{P({A}\bigcap{B})}{P(B)} $.

Небольшое преобразование этой формулы позволяет сделать вывод, что ${P({A}\bigcap{B})} = {P(A|B)}{P(B)}$ и ${P({A}\bigcap { B})} = {P(B|A)}{P(A)}$ (P(B|A)— вероятность B при условии A).

Тогда согласно этому соотношению можно сделать вывод, что ${P(A|B)}{P(B)} = {P(B|A)}{P(A)}$.

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

существуетTable1Пример пространства с 36 результатами описан вD1Если из 2 и выше 6 результатов, вероятность равна $P(D1=2) = \frac{6}{36} = \frac{1}{6}$.

Table2ОписаноD1 + D2 <= 5Вероятность , всего 10 результатов, выражается формулой условной вероятности как ${P(D1+D2\leq5)} = \frac{10}{36}$.

Table3описывает удовлетворениеTable2условия тоже соблюденыD1 = 2, он выбралTable2Три результата в , выражаются как ${P(D1=2 | D1+D2\leq5)} = \frac{3}{10} = 0,3$ с использованием формулы условной вероятности.

формула полной вероятности


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

Формула полной вероятности преобразует задачу решения вероятности сложного события в задачу суммирования вероятностей простых событий, происходящих при различных обстоятельствах, формула $P(B) = {\sum_{i=1}^n }P(A_i)P(B|A_i)$.

Предположим, что выборочное пространство S представляет собой сумму двух событий A и C, и событие B пересекается с ними обоими, как показано на следующем рисунке:

Тогда вероятность события B может быть выражена как $P(B) = P({B}\bigcap{A}) + P({B}\bigcap{C})$

С помощью условной вероятности можно сделать вывод, что $P({B}\bigcap{A}) = P(B|A)P(A)$, поэтому $P(B) = P(B|A)P(A ) + Р(В|С)Р(С)$

Это формула полной вероятности, то есть вероятность события В равна вероятности события А и события С, умноженной на сумму условных вероятностей В для этих двух событий.

Также возьмите каштан, чтобы применить эту формулу, предполагая, что есть два завода, производящих и поставляющих лампочки, лампочки, произведенные фабрикой X, могут работать более 5000 часов в 99% случаев, а лампочки, произведенные фабрикой Y, могут работают в 95% случаев.Свыше 5000 часов. Завод X имеет долю рынка 60%, а завод Y — 40. Как определить вероятность того, что купленные лампочки проработают более 5000 часов?

Используя формулу полной вероятности, мы можем получить: ? \begin{уравнение}\begin{split} Pr(A) &=Pr(A | B_x) \cdot Pr(B_x) + Pr(A|B_y) \cdot Pr(B_y)\ &= \frac{99}{100} \cdot \frac{6}{10} + \frac{95}{100} \cdot \frac{4}{10}\ &= \фракция{594 + 380}{1000}\ &= \фракция{974}{1000} \end{split}\end{уравнение} ?

  • $Pr(B_x) = \frac{6}{10}$: вероятность купить лампочку, произведенную на заводе X.

  • $Pr(B_y) = \frac{4}{10}$: вероятность купить лампочку, произведенную на заводе y.

  • $Pr(A|B_x) = \frac{99}{100}$: вероятность того, что лампочка, изготовленная на заводе x, проработала более 5000 часов.

  • $Pr(A|B_y) = \frac{95}{100}$: вероятность того, что лампочка, изготовленная на заводе y, проработала более 5000 часов.

Следовательно, можно знать, что вероятность покупки лампочки с наработкой более 5000 часов составляет 97,4%.

теорема Байеса


Теорема Байеса была впервые предложена Томасом Байесом (1701-1761), английским математиком (также теологом и философом), и интересно, что он не опубликовал при жизни ни одной академической статьи по математике, даже самые известные его достижения Байеса ' Теорема также была найдена и опубликована его другом Ричардом Прайсом из его посмертных реликвий (заметок).

Томас Байес заинтересовался вероятностью в более поздние годы своей жизни, так называемая теорема Байеса — это всего лишь статья, которую он написал для решения обратной задачи вероятности (чтобы доказать, существует ли Бог, кажется, эта задача нравится философам). В то время люди смогли рассчитать задачу прямой вероятности, скажем, есть мешок с X белых шаров и Y черных шаров, какова вероятность того, что вы протянете руку и коснетесь черных шаров? Это задача с прямой вероятностью, а обратная задача с точностью до наоборот: мы не знаем пропорцию шаров в мешке заранее, но продолжаем тянуться, чтобы коснуться нескольких шаров, а затем делаем вывод о пропорции черных и белые шары в зависимости от их цвета.

Теорема Байеса — это теорема об условной вероятности случайных событий А и В. Обычно вероятность события А при условии события В (наступления) не совпадает с вероятностью события В при условии события А (наступления), но между ними существует определенная связь, теорема Байе утверждает следующее. отношение.

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

Сказав столько теоретических знаний (многие математические теории говорят, кажется, о скороговорках), давайте взглянем на формулу.На самом деле, нам нужно только продолжить рассуждать формулу условной вероятности, которую мы вывели выше, и мы можем получить Формула Байе.

?P(A|B) = \frac{P(B|A)P(A)}{P(B)}?

  • $P(A|B)$: вероятность события A при условии B. В теореме Байеса условная вероятность также называется апостериорной вероятностью, то есть после наступления события B мы пересчитываем вероятность события А. оценить.

  • $P(B|A)$: Вероятность события B при условии A, таком же, как и предыдущее.

  • $P(A)$ и $P(B)$ называются априорными вероятностями (также известными как предельные вероятности), т. е. вывод о вероятности события A до того, как произойдет событие B (без учета каких-либо аспектов события B). ), и то же самое применяется позже.

  • $\frac{P(B|A)}{P(B)}$ называется стандартным сходством, которое является поправочным коэффициентом, главным образом для обеспечения того, чтобы прогнозируемая вероятность была ближе к истинной вероятности.

  • С точки зрения этих терминов теорема Байеса утверждает: апостериорная вероятность = стандартное сходство * априорная вероятность.

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

Подставляя в теорему Байеса, предположим, что событие А выражается как вероятность заболеть (P(A) = 0.001), это наша априорная вероятность, которая является ожидаемой заболеваемостью пациента до фактической инъекции реагента (отсутствие экспериментальных результатов), и если предположить, что событие B является вероятностью положительного результата реагента, нам нужно рассчитать условная возможностьP(A|B), то есть вероятность А при условии события В, которая является апостериорной вероятностью, то есть коэффициентом заболеваемости, полученным пациентом после введения реагента (получения результата эксперимента).

Поскольку все еще существует вероятность не заболеть, необходимо также предположить, что событие С является априорной вероятностью не заболеть (P(C) = 1 - 0.001 = 0.999),ТакP(B|C)Апостериорная вероятность представляет собой вероятность того, что результат реагента при условии отсутствия заболевания будет положительным, и тогда окончательный результат может быть получен путем подстановки его в формулу полной вероятности.

? \begin{equation}\begin{split} P(A|B)&=\frac{P(B|A)P(A)}{P(B)}\ &= \frac{P(B|A)P(A)}{P(B|A)P(A) + P(B|C)P(C)}\ &= \frac{0.99 \times 0.001}{0.99 \times 0.001 + 0.05 \times 0.999}\approx 0.019 \end{split}\end{equation} ?

Окончательный результат составляет около 2%, и даже если у пациента положительный результат теста, его шанс заболеть составляет всего 2%.

Наивные байесовские вероятностные модели


Мы устанавливаем элемент для классификации $X = {f_1,f_2,\cdots,f_n}$, где каждыйfзаXАтрибут объекта , а затем задайте набор категорий $C_1,C_2,\cdots,C_m$.

Затем нам нужно вычислить $P(C_1|X), P(C_2|X), \cdots, P(C_m|X)$, мы можем получить набор обучающих выборок (набор известных элементов классификации, которые необходимо классифицировать) , а затем получите статистику Условная вероятность каждого атрибута объекта в каждой категории:

$P(f_1|C_1),P(f_2|C_1),\cdots,P(f_n|C_1),\cdots,P(f_1|C_2),P(f_2|C_2),\cdots,P(f_n|C_2),\cdots,P(f_1|C_m),P(f_2|C_m),\cdots,P(f_n|C_m)$

Если $P(C_k|X) = MAX(P(C_1|X),P(C_2|X),\cdots,P(C_m|X))$, то ${X}\in{C_k}$ (будет Классификация Yess на самом деле является наиболее вероятной).

Наивный Байес предполагает, что каждый признак независим, что можно вывести из теоремы Байеса: $P(C_i|X) = \frac{P(X|C_i)P(C_i)}{P(X) }$, поскольку знаменатель постоянен для всех категорий, необходимо только максимизировать числитель, а так как каждый признак не зависит друг от друга, то окончательно получается:

В соответствии с приведенным выше выводом формулы процесс наивного Байеса можно показать на следующем рисунке:

Далее, давайте пройдемся по процессу, показанному на рисунке выше, через случай.

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

  • Сначала необходимо определить атрибуты и категории признаков, а затем получить обучающие выборки. Предположим, учетная запись имеет три характеристики: количество журналов/количество дней регистрации (F1), количество друзей/количество дней регистрации (F2), используется ли настоящий аватар (True — 1, False — 0).

  • На сайте используется 10 000 аккаунтов, отобранных вручную как обучающая выборка, тогда вероятность расчета каждой категории $P(C_0) = 8900 \div 10000 = 0,89, P(C_1) = 1100 \div 10000 = 0,11$,C0Вероятность категории быть реальной учетной записью составляет 89%.C1Вероятность категории фейкового аккаунта составляет 11%.

  • После этого необходимо рассчитать условную вероятность каждого признака в каждой категории и подставить ее в наивный байесовский классификатор, чтобы получить $P(F_1|C)P(F_2|C)P(F_3|C)P(C )$, но один вопрос,F1иF2является непрерывной переменной и не подходит для расчета вероятностей при конкретном значении. Решение состоит в том, чтобы преобразовать непрерывные значения в дискретные значения, а затем вычислить вероятность интервала, напримерF1Разложен на[0,0.05]、[0.05,0.2]、[0.2,+∞]Три интервала, а затем вычислить вероятность каждого интервала.

  • Данные известной учетной записи следующие: $F_1 = 0,1, F_2 = 0,2, F_3 = 0$, предполагается, является ли учетная запись реальной учетной записью или поддельной учетной записью. В этом примереF1равно 0,1, что попадает во второй интервал, поэтому при расчете используется вероятность появления второго интервала. Результаты, полученные на обучающих выборках:

? \begin{equation}\begin{split} P(F_1|C_0) = 0.5, P(F_1|C_1) = 0.1\ P(F_2|C_0) = 0.7, P(F_2|C_1) = 0.2\ P(F_3|C_0) = 0.2, P(F_3|C_1) = 0.9 \end{split}\end{equation} ?

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

? \begin{equation}\begin{split} P(F_1|C_0)P(F_2|C_0)P(F_3|C_0)P(C_0) &= 0.5 \times 0.7 \times 0.2 \times 0.89\ &= 0.0623 \end{split}\end{equation} ? ? \begin{equation}\begin{split} P(F_1|C_1)P(F_2|C_1)P(F_3|C_1)P(C_1) &= 0.1 \times 0.2 \times 0.9 \times 0.11\ &= 0.00198 \end{split}\end{equation} ?

Конечным результатом является то, что учетная запись является реальной учетной записью.

Алгоритмическая модель наивного Байеса


В наивном байесовском алгоритме есть три модели алгоритмов:

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

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

    Tобщее количество проб,m— общее количество категорий, $T_{cm}$ — количество образцов категории $C_m$,aявляется гладким значением. Формула условной вероятности:
    ,nэто количество признаков,T_cmfnдля категорииC_mбыл характеризованF_nколичество образцов. Когда сглаженное значениеa = 1и0 < a < 1, называемый какLaplaceгладкий, когдаa = 0без сглаживания. На самом деле его идея состоит в том, чтобы добавить 1 к подсчетам всех подразделений в каждой категории, так что, если количество обучающих выборок достаточно велико, это не повлияет на результаты, и решить явление, состоящее в том, что частота $P(F|C )$ равно 0 (определенный раздел объекта в определенной категории не отображается, что может серьезно повлиять на качество классификатора).

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

Реализация наивного Байеса


Зная достаточно теории, мы будем использовать python для реализации гауссовского наивного байесовского алгоритма, цель которого состоит в том, чтобы решить проблему диабета пима (индейское племя),Образец данных (пожалуйста, получите его по этой гиперссылке)представляет собой файл csv, где каждое значение представляет собой число, описывающее мгновенные измерения возраста пациента, количества беременностей и результатов анализа крови. Каждая запись имеет категориальное значение (логическое значение, представленное 0 или 1), которое показывает, был ли у пациента диабет в течение пяти лет. Это набор данных, который широко изучался в литературе по машинному обучению, и хорошая точность прогноза должна составлять 70–76 %. Значение каждого столбца выборочных данных следующее:

列1:怀孕次数
列2:在口服葡萄糖耐量试验中,血浆葡萄糖的浓度(2小时)
列3:心脏的舒张压((mm Hg))
列4:肱三头肌皮肤褶皱厚度(mm)
列5:二小时内的血清胰岛素(mu U/ml)
列6:体质指数 ((weight in kg/(height in m)^2))
列7:糖尿病家族作用
列8:年龄
列9:类别布尔值,0为5年没得过糖尿病,1为5年内得过糖尿病
------------------------------------
6,148,72,35,0,33.6,0.627,50,1
1,85,66,29,0,26.6,0.351,31,0
8,183,64,0,0,23.3,0.672,32,1
1,89,66,23,94,28.1,0.167,21,0
0,137,40,35,168,43.1,2.288,33,1
.........

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

import csv

def load_csv_file(filename):
    with open(filename) as f:
        lines = csv.reader(f)
        data_set = list(lines)
    for i in range(len(data_set)):
        data_set[i] = [float(x) for x in data_set[i]]
    return data_set

После получения выборочных данных, чтобы оценить точность модели, их необходимо разделить на набор обучающих данных (который необходимо использовать наивному байесовскому методу для прогнозирования) и набор тестовых данных. Данные выбираются случайным образом в процессе сегментации, но мы выберем соотношение для управления размером набора обучающих данных и набора тестовых данных, обычно 67%: 33%, что является относительно распространенным соотношением.

import random

def split_data_set(data_set, split_ratio):
    train_size = int(len(data_set) * split_ratio)
    train_set = []
    data_set_copy = list(data_set)
    while len(train_set) < train_size:
        index = random.randrange(len(data_set_copy))
        train_set.append(data_set_copy.pop(index))
    return [train_set, data_set_copy]

После разделения выборочных данных набор обучающих данных необходимо обработать более подробно.Поскольку гауссовский наивный байесовский метод предполагает, что каждая функция следует нормальному распределению, необходимо извлечь сводку из набора обучающих данных, которая содержит среднее значение и стандарт , Плохо, количество сводок определяется количеством комбинаций категорий и атрибутов объектов.Например, если есть 3 категории и 7 атрибутов объектов, то необходимо рассчитать среднее значение и стандартное отклонение для каждого атрибута объекта и категории, который составляет 21 резюме.

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

def separate_by_class(data_set, class_index):
    result = {}
    for i in range(len(data_set)):
        vector = data_set[i]
        class_val = vector[class_index]
        if (class_val not in result):
            result[class_val] = []
        result[class_val].append(vector)
    return result

Поскольку вы уже знаете, что существует только одна категория, и она является последней в каждой строке данных, вам нужно передать только -1 в параметр class_index. Затем необходимо рассчитать сводку набора обучающих данных (среднее значение и стандартное отклонение каждого признака атрибута в каждой категории), среднее значение будет использоваться как среднее значение нормального распределения, а стандартное отклонение описывает степень дисперсии данных. , он принимается как ожидаемое распределение каждого атрибута объекта в нормальном распределении.

Стандартное отклонение представляет собой квадратный корень из дисперсии, а стандартное отклонение можно получить, сначала найдя дисперсию (среднее значение суммы квадратов разностей между каждым собственным значением и средним значением).

import math

def mean(numbers):
    return sum(numbers) / float(len(numbers))

def stdev(numbers):
    avg = mean(numbers)
    variance = sum([pow(x - avg, 2) for x in numbers]) / float(len(numbers))
    return math.sqrt(variance)    

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

def summarize(data_set):
    # 使用zip函数将每个元素中的第n个属性封装为一个元组
	# 简单地说,就是把每列(特征)都打包到一个元组中
    summaries = [(mean(feature), stdev(feature)) for feature in zip(*data_set)]
    del summaries[-1] # 最后一行是类别与类别的摘要 所以删除
    return summaries

def summarize_by_class(data_set):
    class_map = separate_by_class(data_set, -1)
    summaries = {}
    for class_val, data in class_map.items():
        summaries[class_val] = summarize(data)
    return summaries

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

def calculate_probability(x, mean, stdev):
    exponent = math.exp(-(math.pow(x - mean, 2) / (2 * math.pow(stdev, 2))))
    return (1 / (math.sqrt(2 * math.pi) * stdev)) * exponent

def calculate_conditional_probabilities(summaries, input_vector):
    probabilities = {}
    for class_val, class_summaries in summaries.items():
        probabilities[class_val] = 1
        for i in range(len(class_summaries)):
            mean, stdev = class_summaries[i]
			# input_vector是test_set的一行数据,x为该行中的某一特征属性
            x = input_vector[i]
			# 将概率相乘
            probabilities[class_val] *= calculate_probability(x, mean, stdev)
    return probabilities

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

def predict(summaries, input_vector):
    probabilities = calculate_conditional_probabilities(summaries, input_vector)
    best_label, best_prob = None, -1
    for class_val, probability in probabilities.items():
        if best_label is None or probability > best_prob:
            best_label = class_val
            best_prob = probability
    return best_label

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

def get_predictions(summaries, test_set):
    predictions = []
    for i in range(len(test_set)):
        result = predict(summaries, test_set[i])
        predictions.append(result)
    return predictions

def get_accuracy(predictions, test_set):
    correct = 0
    for x in range(len(test_set)):
		# 分类结果与测试数据集一致,调整值自增
        if test_set[x][-1] == predictions[x]:
            correct += 1
    return (correct / float(len(test_set))) * 100.0

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

import csv, random, math

"""
A simple classifier base on the gaussian naive bayes and
problem of the pima indians diabetes.
(https://archive.ics.uci.edu/ml/datasets/Pima+Indians+Diabetes)
"""

def load_csv_file(filename):
    with open(filename) as f:
        lines = csv.reader(f)
        data_set = list(lines)
    for i in range(len(data_set)):
        data_set[i] = [float(x) for x in data_set[i]]
    return data_set

def split_data_set(data_set, split_ratio):
    train_size = int(len(data_set) * split_ratio)
    train_set = []
    data_set_copy = list(data_set)
    while len(train_set) < train_size:
        index = random.randrange(len(data_set_copy))
        train_set.append(data_set_copy.pop(index))
    return [train_set, data_set_copy]

def separate_by_class(data_set, class_index):
    result = {}
    for i in range(len(data_set)):
        vector = data_set[i]
        class_val = vector[class_index]
        if (class_val not in result):
            result[class_val] = []
        result[class_val].append(vector)
    return result

def mean(numbers):
    return sum(numbers) / float(len(numbers))

def stdev(numbers):
    avg = mean(numbers)
    variance = sum([pow(x - avg, 2) for x in numbers]) / float(len(numbers))
    return math.sqrt(variance)

def summarize(data_set):
    summaries = [(mean(feature), stdev(feature)) for feature in zip(*data_set)]
    del summaries[-1]
    return summaries

def summarize_by_class(data_set):
    class_map = separate_by_class(data_set, -1)
    summaries = {}
    for class_val, data in class_map.items():
        summaries[class_val] = summarize(data)
    return summaries

def calculate_probability(x, mean, stdev):
    exponent = math.exp(-(math.pow(x - mean, 2) / (2 * math.pow(stdev, 2))))
    return (1 / (math.sqrt(2 * math.pi) * stdev)) * exponent

def calculate_conditional_probabilities(summaries, input_vector):
    probabilities = {}
    for class_val, class_summaries in summaries.items():
        probabilities[class_val] = 1
        for i in range(len(class_summaries)):
            mean, stdev = class_summaries[i]
            x = input_vector[i]
            probabilities[class_val] *= calculate_probability(x, mean, stdev)
    return probabilities

def predict(summaries, input_vector):
    probabilities = calculate_conditional_probabilities(summaries, input_vector)
    best_label, best_prob = None, -1
    for class_val, probability in probabilities.items():
        if best_label is None or probability > best_prob:
            best_label = class_val
            best_prob = probability
    return best_label

def get_predictions(summaries, test_set):
    predictions = []
    for i in range(len(test_set)):
        result = predict(summaries, test_set[i])
        predictions.append(result)
    return predictions

def get_accuracy(predictions, test_set):
    correct = 0
    for x in range(len(test_set)):
        if test_set[x][-1] == predictions[x]:
            correct += 1
    return (correct / float(len(test_set))) * 100.0

def main():
    filename = 'pima-indians-diabetes.data.csv'
    split_ratio = 0.67
    data_set = load_csv_file(filename)
    train_set, test_set = split_data_set(data_set, split_ratio)
    print('Split %s rows into train set = %s and test set = %s rows'
                %(len(data_set), len(train_set), len(test_set)))
    # prepare model
    summaries = summarize_by_class(train_set)
    # predict and test
    predictions = get_predictions(summaries, test_set)
    accuracy = get_accuracy(predictions, test_set)
    print('Accuracy: %s' % accuracy)

main()

использованная литература