如果想了解更多的知识,可以去我的机器学习之路 The Road To Machine Learning通道
第4章 朴素贝叶斯法
1.朴素贝叶斯法是典型的生成学习方法。生成方法由训练数据学习联合概率分布
P(X,Y),然后求得后验概率分布P(Y|X)。具体来说,利用训练数据学习P ( X ∣ Y ) 和P ( Y )的估计,得到联合概率分布:
概率估计方法可以是极大似然估计或贝叶斯估计。
2.朴素贝叶斯法的基本假设是条件独立性,
这是一个较强的假设。由于这一假设,模型包含的条件概率的数量大为减少,朴素贝叶斯法的学习与预测大为简化。因而朴素贝叶斯法高效,且易于实现。其缺点是分类的性能不一定很高。
3.朴素贝叶斯法利用贝叶斯定理与学到的联合概率模型进行分类预测。
将输入x 分到后验概率最大的类y
后验概率最大等价于0-1损失函数时的期望风险最小化。
模型:
- 高斯模型
- 多项式模型
- 伯努利模型
朴素贝叶斯法与贝叶斯估计(Bayesian estimation)是不同的概念。
后验概率最大化的含义
朴素贝叶斯将实例分到后验概率最大的类中,等价于期望风险最小化。假设我们选择了0 − 1损失函数
对于我们的期望风险函数,我们可以对齐取条件期望,可以得到
然后为了使期望风险最小化,我们可以对每一个X = x 逐个极小化,可以得到
这样我们就可以得到期望风险最小化等价于后验概率最大化准则
极大似然估计
为了估计状态变量的条件分布,利用贝叶斯法则,有
其中P(X|Y)为给定Y 下X 的后验概率(Posterior), P(Y|X)称为似然(Likelyhood),P ( X )称为先验(Prior)。
- 后验概率最大化的含义
朴素贝叶斯法将实例分到后验概率最大的类中, 这等价于期望风险最小化。
贝叶斯估计
对于x的某个特征的取值没有在先验中出现的情况 ,如果用极大似然估计就会出现所要估计的概率值为0的情况。这样会影响后验概率的计算结果,使分类产生偏差
为了解决这一问题,我们就采用贝叶斯估计
其中我们的λ ≥ 0 ,等价于在随机变量的各个取值的频数上赋予一个整数λ > 0 ,其实就是为了覆盖样本全空间
当λ = 0时,就是极大似然估计
当λ = 1时,这被称为拉普拉斯平滑(Laplacian smoothing)
GaussianNB 高斯朴素贝叶斯
特征的可能性被假设为高斯
概率密度函数:
数学期望(mean):μ
方差:
高斯模型
接着我们利用朴素贝叶斯的方法来解决iris分类问题
首先对我们的数据进行处理,取出前100个数据进行分类,并且分为训练集和测试集,测试集占30%
import numpy as np import pandas as pd from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split import math def create_data(): iris = load_iris() df = pd.DataFrame(iris.data, columns=iris.feature_names) df['label'] = iris.target df.columns = ['sepal length', 'sepal width', 'petal length', 'petal width', 'label'] data = np.array(df.iloc[:100, :]) # print(data) return data[:,:-1], data[:,-1] X, y = create_data() X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
接着可以用我们朴素贝叶斯的方法来解决这个分类问题
class NaiveBayes: def __init__(self): self.model = None # 数学期望 @staticmethod def mean(x): return sum(x)/float(len(x)) # 标准差 def std(self,x): avg = self.mean(x) return math.sqrt(sum(math.pow(x_i-avg,2) for x_i in x)/float(len(x))) # 概率密度函数 def gaussian_prob(self,x,mean,std): exp = math.pow(math.e, -1*(math.pow(x - mean,2))/(2*std)) return (1/(math.sqrt(2*math.pi*std)))*exp # 计算训练的均值和方差 def mean_and_std(self,x): mean_and_std=[(self.mean(i),self.std(i)) for i in zip(*x)] return mean_and_std # 分类别求出数学期望和标准差 def fit(self,x,y): labels = list(set(y)) data = {label:[] for label in labels} for f,label in zip(x,y): data[label].append(f) self.model = {label:self.mean_and_std(value) for label,value in data.items()} print("GaussianNB train Done!") # 计算概率 def prob(self,data): probabillity = {} for label,value in self.model.items(): probabillity[label] = 1 for i in range(len(value)): mean,std = value[i] probabillity[label] *= self.gaussian_prob(data[i],mean,std) return probabillity # 类别 def predict(self,x_test): #print(self.prob(x_test)) label = sorted(self.prob(x_test).items(),key=lambda x:x[-1])[-1][0] return label def score(self,x_test,y_test): right = 0 for x,y in zip(x_test,y_test): label = self.predict(x) if label == y: right+=1 return right / float(len(x_test)) model = NaiveBayes() model.fit(X_train,y_train) #print(model.model) print(model.predict([4.4,3.2,1.3,0.2])) print("在测试集中的准确率:") print(str(100*(model.score(X_test, y_test)))+"%")
GaussianNB train Done! 0.0 在测试集中的准确率: 100.0%
在编写程序的时候,我们有一些小技巧,第一个技巧是使用 zip ()函数,它将从每个提供的参数中聚合元素。我们使用 * 操作符将数据集传递给 zip ()函数,该操作符将数据集(即列表列表)分离到每一行的单独列表中。函数的作用是: 遍历每一行的每一个元素,并从数据集中返回一列数字,一个聪明的小把戏
scikit-learn实
除此之外,我们可以利用scikit-learn实现我们的模型,除了高斯模型,还有伯努利模型,多项式模型等等
# scikit-learn 实现 from sklearn.naive_bayes import GaussianNB # 高斯模型 from sklearn.naive_bayes import BernoulliNB # 伯努利模型 from sklearn.naive_bayes import MultinomialNB # 多项式模型 clf = GaussianNB() # clf = BernoulliNB() # clf = MultinomialNB() clf.fit(X_train,y_train) print(clf.predict([[4.4,3.2,1.3,0.2]]))
例4.1
我们同样可以用高斯模型来解决我们的例题4.1
import numpy as np # SML分别对应为123 X = np.array([[1, 1], [1, 2], [1, 2], [1, 1], [1, 1], [2, 1], [2, 2], [2, 2], [2, 3], [2, 3], [3, 3], [3,2], [3,2], [3, 3], [3, 3]]) Y = np.array([-1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1]) from sklearn.naive_bayes import GaussianNB clf = GaussianNB() #拟合数据 clf.fit(X, Y) print(clf.predict([[2, 1]])) print(clf.predict_proba([[2,1]]))
[-1] [[0.74566865 0.25433135]]
我们可以看到我们的结果是-1,并且这里给出了{ − 1 , 1 }的概率,大约是0.75和0.25。
第4章朴素贝叶斯法-习题
习题4.1
用极大似然估计法推出朴素贝叶斯法中的概率估计公式(4.8)及公式 (4.9)。
解答:
**第1步:**证明公式(4.8)
由于朴素贝叶斯法假设Y YY是定义在输出空间Y上的随机变量,因此可以定义P ( Y = c k )概率为p 。令m = ∑ i = 1 N I ( y i = c k ) ,得出似然函数:
使用微分求极值,两边同时对p 求微分:
可求解得到p = 0 , p = 1 , p = m /N
显然公式(4.8)得证。
**第2步:**证明公式(4.9)
令得出似然函数:
使用微分求极值,两边同时对p 求微分:
可求解得到p = 0 , p = 1 , p = q /m
显然公式(4.9)得证。
习题4.2
用贝叶斯估计法推出朴素贝叶斯法中的慨率估计公式(4.10)及公式(4.11)
贝叶斯估计和传统的极大似然估计的区别就是,参数值是固定的还是也当做随机变量。传统的极大似然估计,把参数θ 当做固定的一个值,不变的,只是目前还不知道,通过最大化L 求出θ;贝叶斯估计认为参数θ 也是随机变量,它也服从一个分布(β分布)
解答:
**第1步:**证明公式(4.11)
加入先验概率,在没有任何信息的情况下,可以假设先验概率为均匀概率(即每个事件的概率是相同的)。
可得
根据习题4.1得出先验概率的极大似然估计是
存在参数λ \lambdaλ使得( 1 ) ⋅ λ + ( 2 ) = 0
所以有
可得公式(4.11)得证。
**第2步:**证明公式(4.10)
根据第1步,可同理得到
公式(4.11)得证。