Наивный байесовский алгоритм — это простой алгоритм классификации, который хорошо известен своим классическим вариантом использования: классификация текста (например, фильтрация спама). Многие учебники начинаются с этих случаев, и эта статья не будет их повторять, а сосредоточится на теоретическом выводе (на самом деле это очень просто, не пугайтесь «теории»), трех распространенных моделях и их кодовой реализации (Python) .
Если вас не интересует теоретический процесс вывода, вы можете перейти непосредственно к трем часто используемым моделям и частям реализации кодирования, но я предлагаю вам все же взглянуть на теоретическую часть основы.
Кроме того, весь код в этой статье можноПолучите это с моего github
1. Теоретическая основа Наивного Байеса
Алгоритм наивного Байеса — это метод классификации, основанный на теореме Байеса и предположении о независимости признаков от условий.
упоминается здесьтеорема Байеса,Допущение условной независимости характеристикЭто две важные теоретические основы Наивного Байеса.
1.1 Теорема Байеса
Что первоеУсловная возможность.
P(A|B) представляет собой вероятность того, что событие A произойдет при условии, что произошло событие B, которая называется условной вероятностью события A при наступлении события B. Его основная формула решения: Р(А|В)=Р(АВ) Р(В)
Теорема Байеса основана на условной вероятности, и P(B|A) вычисляется как P(A|B):
P (B| A)=P (A| B) P(B) P (A)
Кстати, знаменатель P(A) в приведенной выше формуле можно разложить на:
P (A)=∑ n i =1 P (B i )P (A| B i )
1.2 Допущение независимости характерных условий
В этой части начинается теоретический вывод Наивного Байеса, из которого вы получите глубокое понимание того, что является предположением о независимости признаков от условий.
Учитывая набор обучающих данных (X, Y), где каждая выборка x включает n-мерные признаки, т.е. x =(x 1 ,x 2 ,x 3 ,...,x n ) набор меток класса содержит k категорий, а именно у = (у 1 , у 2 ,..., у к ) .
Если сейчас есть новый образец x, как мы оцениваем его категорию? С вероятностной точки зрения вопрос состоит в том, при данном x какой класс имеет наибольшую вероятность оказаться в нем. Тогда проблема превращается в решение Наибольшее из P (y 1 | x), P (y 2 | x),..., P (y k | x), то есть выход с наибольшей апостериорной вероятностью: a rg max y k P (y k | x)
Тот Как решить P(yk|x)? Ответ — теорема Байеса:
P (y k | x)=P (x| y k )P (y k )P (x)
В соответствии с формулой полной вероятности знаменатель в приведенной выше формуле может быть дополнительно разложен:
P (y k | x) = P (x | y k )P (y k )∑ k P (x | y k )P (y k )【Формула 1】
Отдохни здесь две минуты
Независимо от знаменателя, числитель P(yk) — это априорная вероятность, которую можно легко вычислить по обучающей выборке.
а условная вероятность P (x| y k )=P(x 1 ,x 2 ,...,x n | y k ) , его шкала параметров является экспоненциальной, предполагая i-е характеристики измерения Количество возможных значений для x i равно S i , количество значений категории равно k, тогда количество параметров равно: k ∏ n я =1 S я
Это явно невыполнимо.В ответ на эту проблему алгоритм наивного Байеса делает предположение о независимости условного распределения вероятностей., с точки зрения непрофессионала, это означает принятие характеристик каждого измерения x 1 , x 2 ,..., x n не зависят друг от друга.Исходя из этого предположения, условная вероятность может быть преобразована в:
P (x| y k )=P(x 1 ,x 2 ,...,x n | y k )=∏ n i =1 P (x i | y k )[Формула 2]
Таким образом, размер параметра уменьшается до ∑ п я =1 S я к
Вышеприведенное является характерным допущением условной независимости, сделанным для условной вероятности. P (y k ) и условные вероятности Все проблемы решения P (x| y k ) решены, так что можем ли мы решить желаемую апостериорную вероятность? Р (у к | х)?
Подумайте здесь две минуты
Ответ положительный. Мы продолжаем выше о Для вывода P (y k | x) подставьте [формулу 2] в [формулу 1], чтобы получить:
P (y k | x) = P (y k )∏ n i =1 P (x i | y k ) ∑ k P (y k )∏ n i =1 P (x i | y k )
Тогда наивный байесовский классификатор может быть выражен как:
f (x)=arg max y k P(y k | x)=a rg max y k P (y k )∏ n i =1 P (x i | y k ) ∑ k P (y k )∏ n i =1 P (x i | y k )
потому что для всех y k , значение знаменателя в приведенной выше формуле такое же (почему? Это легко понять, когда вы заметите полный символ плюса), поэтому вы можете игнорировать часть знаменателя, и наивный байесовский классификатор, наконец, выражается как:
f (x)=arg max P(y k )∏ n i =1 P (x i | y k )
о Р(ук) , Есть три общие модели для решения P (xi | y k ).
2. Три общие модели и программные реализации
2.1 Полиномиальная модель
Когда признаки дискретны, используется полиномиальная модель. Полиномиальные модели используются для расчета априорных вероятностей. P (y k ) и условные вероятности P (x i | y k ), сделает некоторыесглаживание, конкретная формула:
P (y k )=N y k +α N +kα
N — общее количество образцов, k — общее количество категорий, N y k – категория для количество выборок y k, α — сглаженное значение.
P (x i | y k )=N y k ,x i +α N y k +n α
— количество выборок с категорией , n — размерность признака, а — количество выборок со значением i-го признака измерения в выборке с категорией, которое является сглаженным значением.
В то время это называлось сглаживанием Лапласа, в то время это называлось сглаживанием Лидстоуна, и оно вообще не было сглажено.
Если сглаживание не выполняется, когда значение определенного признака размерности не появляется в обучающей выборке, это приведет к , в результате чего апостериорная вероятность будет равна 0. Добавление сглаживания может решить эту проблему.
2.1.1 Пример
Имеются следующие обучающие данные, 15 выборок, 2-мерные признаки, 2 категории - 1, 1. По тестовому образцу определите его категорию.
Ответ таков:
Используя полиномиальную модель, пусть
- Вычислить априорную вероятность
- Расчет различных условных вероятностей
- Для заданного вычислить:
Отсюда можно определить, что y=-1.
2.1.2 Программная реализация (на основе Python, Numpy)
Как видно из приведенного выше примера, при наличии тренировочного набора мы просто вычисляем все априорные и условные вероятности и сохраняем их (в виде таблицы поиска). Когда приходит тестовая выборка, мы вычисляем все ее возможные апостериорные вероятности, наибольшая из которых соответствует категории тестовой выборки, а вычисление апостериорной вероятности есть не что иное, как нахождение нужного значения в справочной таблице.
Мой код написан в соответствии с этой идеей. Определите класс MultinomialNB с двумя основными методами: fit(X,y) и predict(X). Метод подгонки на самом деле является обучением.Когда вызывается метод подгонки, задача заключается в построении таблицы поиска. Метод предсказания — это предсказание, и когда вызывается метод предсказания, задача состоит в том, чтобы вычислить все апостериорные вероятности и найти наибольшую из них. Кроме того, в конструкторе __init__() класса допускается задавать значение, а также задавать значение априорной вероятности. Конкретный код выглядит следующим образом:
"""
Created on 2015/09/06
@author: wepon (http://2hwp.com)
API Reference: http://scikit-learn.org/stable/modules/naive_bayes.html#naive-bayes
"""
import numpy as np
class MultinomialNB(object):
"""
Naive Bayes classifier for multinomial models
The multinomial Naive Bayes classifier is suitable for classification with
discrete features
Parameters
----------
alpha : float, optional (default=1.0)
Setting alpha = 0 for no smoothing
Setting 0 < alpha < 1 is called Lidstone smoothing
Setting alpha = 1 is called Laplace smoothing
fit_prior : boolean
Whether to learn class prior probabilities or not.
If false, a uniform prior will be used.
class_prior : array-like, size (n_classes,)
Prior probabilities of the classes. If specified the priors are not
adjusted according to the data.
Attributes
----------
fit(X,y):
X and y are array-like, represent features and labels.
call fit() method to train Naive Bayes classifier.
predict(X):
"""
def __init__(self,alpha=1.0,fit_prior=True,class_prior=None):
self.alpha = alpha
self.fit_prior = fit_prior
self.class_prior = class_prior
self.classes = None
self.conditional_prob = None
def _calculate_feature_prob(self,feature):
values = np.unique(feature)
total_num = float(len(feature))
value_prob = {}
for v in values:
value_prob[v] = (( np.sum(np.equal(feature,v)) + self.alpha ) /( total_num + len(values)*self.alpha))
return value_prob
def fit(self,X,y):
#TODO: check X,y
self.classes = np.unique(y)
#calculate class prior probabilities: P(y=ck)
if self.class_prior == None:
class_num = len(self.classes)
if not self.fit_prior:
self.class_prior = [1.0/class_num for _ in range(class_num)] #uniform prior
else:
self.class_prior = []
sample_num = float(len(y))
for c in self.classes:
c_num = np.sum(np.equal(y,c))
self.class_prior.append((c_num+self.alpha)/(sample_num+class_num*self.alpha))
#calculate Conditional Probability: P( xj | y=ck )
self.conditional_prob = {} # like { c0:{ x0:{ value0:0.2, value1:0.8 }, x1:{} }, c1:{...} }
for c in self.classes:
self.conditional_prob[c] = {}
for i in range(len(X[0])): #for each feature
feature = X[np.equal(y,c)][:,i]
self.conditional_prob[c][i] = self._calculate_feature_prob(feature)
return self
#given values_prob {value0:0.2,value1:0.1,value3:0.3,.. } and target_value
#return the probability of target_value
def _get_xj_prob(self,values_prob,target_value):
return values_prob[target_value]
#predict a single sample based on (class_prior,conditional_prob)
def _predict_single_sample(self,x):
label = -1
max_posterior_prob = 0
#for each category, calculate its posterior probability: class_prior * conditional_prob
for c_index in range(len(self.classes)):
current_class_prior = self.class_prior[c_index]
current_conditional_prob = 1.0
feature_prob = self.conditional_prob[self.classes[c_index]]
j = 0
for feature_i in feature_prob.keys():
current_conditional_prob *= self._get_xj_prob(feature_prob[feature_i],x[j])
j += 1
#compare posterior probability and update max_posterior_prob, label
if current_class_prior * current_conditional_prob > max_posterior_prob:
max_posterior_prob = current_class_prior * current_conditional_prob
label = self.classes[c_index]
return label
#predict samples (also single sample)
def predict(self,X):
#TODO1:check and raise NoFitError
#ToDO2:check X
if X.ndim == 1:
return self._predict_single_sample(X)
else:
#classify each sample
labels = []
for i in range(X.shape[0]):
label = self._predict_single_sample(X[i])
labels.append(label)
return labels
Давайте воспользуемся приведенным выше примером, чтобы проверить это.Обратите внимание, что S, M и L заменены на 4, 5 и 6 здесь:
import numpy as np
X = np.array([
[1,1,1,1,1,2,2,2,2,2,3,3,3,3,3],
[4,5,5,4,4,4,5,5,6,6,6,5,5,6,6]
])
X = X.T
y = np.array([-1,-1,1,1,-1,-1,-1,1,1,1,1,1,1,1,-1])
nb = MultinomialNB(alpha=1.0,fit_prior=True)
nb.fit(X,y)
print nb.predict(np.array([2,4]))#输出-1
2.2 Модель Гаусса
Когда признак является непрерывной переменной, использование полиномиальной модели приведет к многому (без сглаживания), в это время даже при выполнении сглаживания полученная условная вероятность трудно описывает реальную ситуацию. Следовательно, для работы с непрерывными переменными признаков следует использовать модель Гаусса.
2.2.1 Для иллюстрации на примере:
пример гендерной классификации
из вики
Ниже приведен набор статистических данных о физических характеристиках человека.
Пол | Высота (футы) | Вес в фунтах) | Футы (дюймы) |
---|---|---|---|
мужчина | 6 | 180 | 12 |
мужчина | 5.92 | 190 | 11 |
мужчина | 5.58 | 170 | 12 |
мужчина | 5.92 | 165 | 10 |
Женский | 5 | 100 | 6 |
Женский | 5.5 | 150 | 8 |
Женский | 5.42 | 130 | 7 |
Женский | 5.75 | 150 | 9 |
Известно, что рост человека 6 футов, вес 130 фунтов и длина ноги 8 дюймов. Это мужчина или женщина? Рассчитайте значение следующей формулы в соответствии с наивным байесовским классификатором.
P(身高|性别) x P(体重|性别) x P(脚掌|性别) x P(性别)
Трудность здесь заключается в том, что, поскольку рост, вес и подошвы ног являются непрерывными переменными, вероятность не может быть рассчитана с использованием дискретных переменных. А поскольку выборка слишком мала, ее нельзя разделить на интервальный расчет. что делать?
В это время можно предположить, что рост, вес и подошвы мужчин и женщин распределены нормально, а среднее значение и дисперсия вычисляются по выборкам, то есть получается функция плотности нормального распределения. С помощью функции плотности вы можете подставить значение и вычислить значение функции плотности в определенной точке.
Например, рост мужчин нормально распределяется со средним значением 5,855 и дисперсией 0,035. Итак, относительное значение вероятности того, что рост человека 6 футов, равно 1,5789 (больше 1 не имеет значения, поскольку это значение функции плотности, которая используется только для отражения относительной вероятности каждого значения ).
Среднее значение и дисперсию также можно рассчитать для массы подошвы и тела. Получив эти данные, вы можете рассчитать гендерную классификацию.
P(身高=6|男) x P(体重=130|男) x P(脚掌=8|男) x P(男)
= 6.1984 x e-9
P(身高=6|女) x P(体重=130|女) x P(脚掌=8|女) x P(女)
= 5.3778 x e-4
Можно видеть, что вероятность женщин почти в 10 000 раз выше, чем у мужчин, поэтому человек считается женщиной.
- Суммировать
Модель Гаусса предполагает, что каждое измерение имеет распределение Гаусса (нормальное распределение):
Представляет среднее значение признака i-го измерения в выборке класса .
Представляет дисперсию признака i-го измерения в выборке класса .
2.2.2 Программная реализация
Единственная разница между моделью Гаусса и полиномиальной моделью заключается в вычислении Модель Гаусса предполагает, что признаки каждого измерения подчиняются нормальному распределению, и что необходимо вычислить, так это среднее значение и дисперсию признаков каждого измерения. Итак, мы определяем класс GaussianNB, наследуемся от MultinomialNB и перегружаем соответствующие методы. код показывает, как показано ниже:
#GaussianNB differ from MultinomialNB in these two method:
# _calculate_feature_prob, _get_xj_prob
class GaussianNB(MultinomialNB):
"""
GaussianNB inherit from MultinomialNB,so it has self.alpha
and self.fit() use alpha to calculate class_prior
However,GaussianNB should calculate class_prior without alpha.
Anyway,it make no big different
"""
#calculate mean(mu) and standard deviation(sigma) of the given feature
def _calculate_feature_prob(self,feature):
mu = np.mean(feature)
sigma = np.std(feature)
return (mu,sigma)
#the probability density for the Gaussian distribution
def _prob_gaussian(self,mu,sigma,x):
return ( 1.0/(sigma * np.sqrt(2 * np.pi)) *
np.exp( - (x - mu)**2 / (2 * sigma**2)) )
#given mu and sigma , return Gaussian distribution probability for target_value
def _get_xj_prob(self,mu_sigma,target_value):
return self._prob_gaussian(mu_sigma[0],mu_sigma[1],target_value)
2.3 Модель Бернулли
Как и полиномиальная модель, модель Бернулли подходит для дискретных признаков, разница в том, что значения каждого признака в модели Бернулли могут быть только 1 и 0 (в качестве примера возьмем текстовую классификацию, слово в документе появляется , его собственное значение равно 1, иначе оно равно 0).
В модели Бернулли условная вероятность рассчитывается как:
Когда собственное значение равно 1,;
Когда собственное значение равно 0,;
2.3.1 Программная реализация
Модель Бернулли и полиномиальная модель согласуются друг с другом. БернуллиNB должен определить метод бинаризации больше, чем MultinomialNB.Этот метод будет принимать порог и бинаризировать входные функции (1, 0). Конечно, MultinomialNB также можно использовать напрямую, но входные признаки должны быть предварительно бинаризованы. Я не хочу писать это здесь, и программная реализация предоставляется читателю.
3 ссылки
- «Статистические методы обучения», Ли Ханг
- Машинное обучение, Том М. Митчелл
- Классификация пола в Википедии
- Три часто используемые модели наивного Байеса: гауссовская, полиномиальная, бернуллиевская.
- Приложения наивных байесовских классификаторов
- Красота математики: обычный и волшебный байесовский метод
Пожалуйста, укажите источник для перепечатки, спасибо:blog.CSDN.net/U012162613/…