当前位置: 代码迷 >> 综合 >> 朴素贝叶斯法(Naive Bayes,NB)及python实现
  详细解决方案

朴素贝叶斯法(Naive Bayes,NB)及python实现

热度:33   发布时间:2023-12-19 04:27:06.0

1 朴素贝叶斯模型

朴素贝叶斯法是基于贝叶斯定理、特征条件独立假设的分类方法。在预测时,对输入x,找出对应后验概率最大的 y 作为预测。

NB模型:

  • 输入:
    先验概率分布: P ( Y = c k ) , k = 1 , 2 , ? , K P\left(Y=c_{k}\right), \quad k=1,2, \cdots, K P(Y=ck?),k=1,2,?,K
    条件概率分布: P ( X = x ∣ Y = c k ) = P ( X ( 1 ) = x ( 1 ) , ? , X ( n ) = x ( n ) ∣ Y = c k ) , k = 1 , 2 , ? , K P\left(X=x | Y=c_{k}\right)=P\left(X^{(1)}=x^{(1)}, \cdots, X^{(n)}=x^{(n)} | Y=c_{k}\right), \quad k=1,2, \cdots, K P(X=xY=ck?)=P(X(1)=x(1),?,X(n)=x(n)Y=ck?),k=1,2,?,K
    其中,输入数据 X 维度为 n n n.

  • 输出:测试数据的后验概率
    根据 后 验 = 似 然 ? 先 验 / 归 一 化 后验 = 似然*先验/归一化 =?/, 有:
    P ( Y = c k ∣ X = x ) = P ( X = x ∣ Y = c k ) P ( Y = c k ) ∑ k P ( X = x ∣ Y = c k ) P ( Y = c k ) P\left(Y=c_{k} | X=x\right)=\frac{P\left(X=x | Y=c_{k}\right) P\left(Y=c_{k}\right)}{\sum_{k} P\left(X=x | Y=c_{k}\right) P\left(Y=c_{k}\right)} P(Y=ck?X=x)=k?P(X=xY=ck?)P(Y=ck?)P(X=xY=ck?)P(Y=ck?)?

NB分类器即为:
y = f ( x ) = arg ? max ? c k P ( Y = c k ) ∏ j P ( X ( j ) = x ( j ) ∣ Y = c k ) ∑ k P ( Y = c k ) ∏ j P ( X ( j ) = x ( j ) ∣ Y = c k ) y=f(x)=\arg \max _{c_{k}} \frac{P\left(Y=c_{k}\right) \prod_{j} P\left(X^{(j)}=x^{(j)} | Y=c_{k}\right)}{\sum_{k} P\left(Y=c_{k}\right) \prod_{j} P\left(X^{(j)}=x^{(j)} | Y=c_{k}\right)} y=f(x)=argck?max?k?P(Y=ck?)j?P(X(j)=x(j)Y=ck?)P(Y=ck?)j?P(X(j)=x(j)Y=ck?)?

其中,分母是归一化因子,可以忽略。
朴素贝叶斯可以分为高斯朴素贝叶斯、多项式朴素贝叶斯、贝努利朴素贝叶斯等多种。

2 朴素贝叶斯的参数估计

朴素贝叶斯需要估计先验概率 P ( Y = c k ) P\left(Y=c_{k}\right) P(Y=ck?) 和条件概率 P ( X ( j ) = x ( j ) ∣ Y = c k ) P\left(X^{(j)}=x^{(j)} | Y=c_{k}\right) P(X(j)=x(j)Y=ck?).以下只考虑离散属性情形。

2.1 极大似然法(MLE)

使用极大似然法估计(Maximum Likehood Estimation)先验概率:
P ( Y = c k ) = ∑ i = 1 N I ( y i = c k ) N , k = 1 , 2 , ? , K P\left(Y=c_{k}\right)=\frac{\sum_{i=1}^{N} I\left(y_{i}=c_{k}\right)}{N}, \quad k=1,2, \cdots, K P(Y=ck?)=Ni=1N?I(yi?=ck?)?,k=1,2,?,K
条件概率:
P ( X ( j ) = a j l ∣ Y = c k ) = ∑ i = 1 N I ( x i j = a j l , y i = c k ) ∑ i = 1 N I ( y i = c k ) j = 1 , 2 , ? , n ; l = 1 , 2 , ? , S j ; k = 1 , 2 , ? , K \begin{aligned} &P\left(X^{(j)}=a_{jl} | Y=c_{k}\right)=\frac{\sum_{i=1}^{N} I\left(x_{i}^{j}=a_{j l}, y_{i}=c_{k}\right)}{\sum_{i=1}^{N} I\left(y_{i}=c_{k}\right)}\\ &j=1,2, \cdots, n ; \quad l=1,2, \cdots, S_{j}; \quad k=1,2, \cdots, K \end{aligned} ?P(X(j)=ajl?Y=ck?)=i=1N?I(yi?=ck?)i=1N?I(xij?=ajl?,yi?=ck?)?j=1,2,?,n;l=1,2,?,Sj?;k=1,2,?,K?

2.2 贝叶斯估计

极大似然法可能出现概率值为 0 情况,贝叶斯估计使用了拉普拉斯平滑.
先验概率的贝叶斯估计为:
P λ ( Y = c k ) = ∑ i = 1 N I ( y i = c k ) + λ N + K λ P_{\lambda}\left(Y=c_{k}\right)=\frac{\sum_{i=1}^{N} I\left(y_{i}=c_{k}\right)+\lambda}{N+K \lambda} Pλ?(Y=ck?)=N+Kλi=1N?I(yi?=ck?)+λ?
条件概率的贝叶斯估计为:
P λ ( X ( j ) = a j l ∣ Y = c k ) = ∑ l = 1 N I ( x i ( j ) = a j l , y i = c k ) + λ ∑ i = 1 N I ( y i = c k ) + S j λ P_{\lambda}\left(X^{(j)}=a_{j l} | Y=c_{k}\right)=\frac{\sum_{l=1}^{N} I\left(x_{i}^{(j)}=a_{j l} ,y_{i}=c_{k}\right)+\lambda}{\sum_{i=1}^{N} I\left(y_{i}=c_{k}\right)+S_{j} \lambda} Pλ?(X(j)=ajl?Y=ck?)=i=1N?I(yi?=ck?)+Sj?λl=1N?I(xi(j)?=ajl?,yi?=ck?)+λ?

Q1:这里极大似然估计和贝叶斯估计感觉描述没什么区别?
A1:《机器学习》书中,没有提拉普拉斯平滑当作贝叶斯估计,还是有点疑问。

3 朴素贝叶斯实现

3.1 高斯朴素贝叶斯实现

高斯朴素贝叶斯用于连续数据的预测,原理是假设训练集各个特征满足高斯分布,获得不同类别数据集对应不同特征的高斯分布均值和方差,然后计算测试样本各个特征属于相应高斯分布的概率,从而获得其属于某个类别的概率,并把概率最大的标签作为这个样本的标签。

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
import pandas as pd
from sklearn.model_selection import train_test_split
import mathsqrt, exp, pi = np.sqrt, np.exp, np.pidef createData():iris = load_iris()df = pd.DataFrame(iris.data, columns = iris.feature_names)df['label'] = iris.targetdf.columns = ['sepal length', 'sepal width', 'petal length', 'petal width', 'label']return df.iloc[:,:-1],df.iloc[:,-1]X,y = createData()
Xtrain, Xtest, Ytrain, Ytest = train_test_split(X, y, test_size = 0.5, random_state = 1028)class GaussianNaiveBayes(object):'''高斯朴素贝叶斯,用于处理连续数据,输入使用numpy.array.'''def __init__(self):self.model = None@staticmethoddef mean(x):'''求array类型的特征(列)平均值'''return sum(x)/float(len(x))def var(self, x):'''求特征的方差'''return sum(pow(x-self.mean(x),2)*1.0/len(x))def gaussianProba(self, x, mean, var):'''使用高斯概率密度,求测试集属于某个特征的值'''return 1/(sqrt(2*pi*var))*exp(-pow(x-mean,2)/(2.0*var))def summarize(self, data):'''返回训练集每个特征的平均值,方差。'''data = np.array(data)return [self.mean(data),self.var(data)]def fit(self, x, y):'''获得训练集每个标签对应每个特征的平均值,方差。'''labels = np.unique(y)data = {
    label:[] for label in labels}for f, label in zip(x, y):data[label].append(f.tolist())self.model = {
    label: self.summarize(value) for label,value in data.items()}return data,self.modeldef calculateProba(self, data):'''计算测试集对应在每个类别的概率。'''prob = {
    }     data = data.transpose()for label, value in self.model.items():prob[label] = 1for i in range(len(data)):prob[label] *= self.gaussianProba(data[i], value[0][i], value[1][i])return probdef predict(self, data):'''把概率最高的值作为样本的标签。'''res = []for label, value in self.calculateProba(data).items():res.append(value)res = np.array(res)return np.argmax(res, axis = 0)def score(self, x, y):'''计算预测的准确率。'''score = 0label = self.predict(x)for i in range(len(label)):if label[i] ==y[i]:score+=1return score*1.0/len(label)if __name__ == '__main__':model = GaussianNaiveBayes()data, m1 = model.fit(Xtrain.values, Ytrain.values)prob = model.calculateProba(Xtest.values)label = model.predict(Xtest.values)score = model.score(Xtest.values, Ytest.values)print('accuary', score)

结果:accuary 0.9466666666666667

3.2 多项式朴素贝叶斯MultinomialNB

多项式朴素贝叶斯可以用于离散数据的分类中。
调用sklearn API:

import numpy as np
rng = np.random.RandomState(1)
X = rng.randint(5, size=(6, 100))
y = np.array([1, 2, 3, 4, 5, 6])
from sklearn.naive_bayes import MultinomialNB
clf = MultinomialNB()
clf.fit(X, y)print(clf.predict(X[2:3]))

4. 拓展:极大似然估计与贝叶斯估计的区别

贝叶斯是假定模型参数服从某种分布,然后对模型参数分布进行估计。这和极大似然法非常不同(极大似然法假设参数是某个值,只是对参数估计,属于点估计范围)。
贝叶斯估计应用分为两种,对离散数据的估计及对连续数据的估计,其实差别不大,只是参数分布假设不同,连续数据时模型参数多假设为高斯分布。


参考:

  1. GitHub贝叶斯详解及代码;
  2. CSDN.关于朴素贝叶斯法;
  3. 黄海广 GitHub代码;
  4. wepon大神blog;
  5. Bayes 课件 Utdallas.edu;
  6. Bayes MLE MAP 区别 cmu;
  7. MLE 解释 英文;
  8. sklearn Naive Bayes;