朴素贝叶斯法是基于贝叶斯定理和特征条件独立假设的分类方法。朴素贝叶斯法实现简单,学习与预测的效率都很高,被广泛应用于文本分类、垃圾邮件过滤、自然语言处理等场景。下面我们来介绍贝叶斯定理,在介绍贝叶斯定理之前,先介绍下条件概率和全概率公式。
条件概率
所谓条件概率,就是在事件 B B B 发生的条件下,事件 A A A 发生的概率,用 P ( A ∣ B ) P(A|B) P(A∣B) 来表示。在下面的文氏图中,定义了事件 A A A 和 B B B,以及他们的交集 A ∩ B A\cap B A∩B, A ‾ \overline A A 为 A A A 的补集。则在事件 B B B 发生的条件下,事件 A A A 发生的概率为 P ( A ∣ B ) P(A|B) P(A∣B) = P ( A ∩ B ) P ( B ) \displaystyle{P (A \cap B)} \over \displaystyle{P(B)} P(B)P(A∩B) => P ( A ∩ B ) = P ( A ∣ B ) P ( B ) P(A \cap B)=P(A|B)P(B) P(A∩B)=P(A∣B)P(B);同理可得, P ( B ∣ A ) P(B|A) P(B∣A) = $\displaystyle{P (A \cap B)} \over \displaystyle{P(A)} $ => P ( A ∩ B ) = P ( B ∣ A ) P ( A ) P(A \cap B)=P(B|A)P(A) P(A∩B)=P(B∣A)P(A),于是 P ( A ∣ B ) P ( B ) = P ( B ∣ A ) P ( A ) P(A|B)P(B) = P(B|A)P(A) P(A∣B)P(B)=P(B∣A)P(A)。
全概率公式
在上面的文氏图中, P ( B ) = P ( A ∩ B ) + P ( A ‾ ∩ B ) P(B) = P(A \cap B) + P(\overline A \cap B) P(B)=P(A∩B)+P(A∩B),代入上面的条件概率公式, P ( B ) = P ( A ) P ( B ∣ A ) + P ( A ‾ ) P ( B ∣ A ‾ ) P(B) = P(A)P(B|A) + P(\overline A)P(B|\overline A) P(B)=P(A)P(B∣A)+P(A)P(B∣A),这便是全概率公式。
贝叶斯定理
贝叶斯定理是 T h o m a s B a y e s Thomas Bayes ThomasBayes 为了解决一个逆概率问题所写的一篇文章。在当时,人们已经能够计算正向概率。例如,一个袋子里装有 m m m 个白球 和 n n n 个黑球,把手伸进去摸到白球的概率是多少?这就是一个正向概率问题,而逆概率问题正好反过来,我们事先并不知道袋子里黑球和白球的比例,而是不断伸手去摸球,根据摸到球的颜色来推测黑球与白球的比例。由上面的条件概率,我们可以推导出
这便是贝叶斯定理。 P ( A ) P(A) P(A) 称为先验概率, P ( A ∣ B ) P(A|B) P(A∣B) 称为后验概率,即在事件 B B B 发生之后,我们对事件 A A A 概率的重新评估。
朴素贝叶斯分类器
朴素贝叶斯的思想基础是,对于待分类项 x x x,求解在 x x x 出现的条件下各个类别出现的概率,哪个最大,就认为 x x x 属于哪个类别。设输入空间 $ \mathcal X \subseteq R^n$ 为 n n n 维向量的集合,输出空间为类标记集合 $ \mathcal Y = {c_1, c_2, …, c_k}$,输入为特征向量 x ∈ X x \in \mathcal X x∈X,输出为类标记 y ∈ Y y \in \mathcal Y y∈Y。 X X X 是定义在输入空间 X \mathcal X X 上的随机向量, Y Y Y 是定义在输出空间 Y \mathcal Y Y 上的随机变量。假设有一个待分类项 x x x,为了确定 x x x 属于哪个类别,我们需要计算 P ( Y = c k ∣ X = x ) , k = 1 , 2 , . . . , K P(Y=c_k|X=x), k=1, 2, ..., K P(Y=ck∣X=x),k=1,2,...,K,选取概率 P ( Y = c k ∣ X = x ) P(Y=c_k|X=x) P(Y=ck∣X=x) 最大时对应的类别为 x x x 对应的类别。基于贝叶斯定理可以写为:
基于此公式来估计后验概率 P ( Y = c k ∣ X = x ) P(Y=c_k|X=x) P(Y=ck∣X=x) 的主要困难在于:条件概率 P ( X = x ∣ Y = c k ) P(X=x|Y=c_k) P(X=x∣Y=ck) 是所有特征上的联合概率,难以从有限的训练样本直接估计而得。为避开这个障碍,朴素贝叶斯分类器采用了“特征条件独立假设”:对已知类别,假设所有特征相互独立。换言之,假设每个特征独立地对分类结果发生影响(这也是算法被叫做 朴素贝叶斯分类器的原因)。基于特征条件独立假设,可将上述公式重写为:
= ∏ j = 1 n P ( X ( j ) = x ( j ) ∣ Y = c k ) P ( Y = c k ) P ( X = x ) \displaystyle \prod_{j=1}^nP(X^{(j)}=x^{(j)}|Y=c_k)P(Y=c_k) \over \displaystyle P(X=x) P(X=x)j=1∏nP(X(j)=x(j)∣Y=ck)P(Y=ck), k = 1 , 2 , . . . , K k=1,2,...,K k=1,2,...,K
由于对所有的类别, P ( X = x ) P(X=x) P(X=x) 相同,所以
下面便是如何求得, P ( Y = c k ) P(Y=c_k) P(Y=ck) 和 P ( X ( j ) = x ( j ) ∣ Y = c k ) P(X^{(j)}=x^{(j)}|Y=c_k) P(X(j)=x(j)∣Y=ck)。
极大似然估计
在朴素贝叶斯分类器中,学习意味着估计 P ( Y = c k ) P(Y=c_k) P(Y=ck) 和 P ( X ( j ) = x ( j ) ∣ Y = c k ) P(X^{(j)}=x^{(j)}|Y=c_k) P(X(j)=x(j)∣Y=ck)。可以应用极大似然估计法估计相应的概率。我们先通过一个例子来了解下极大似然估计。假设一个袋子里装有黑白两种颜色的球,黑白球的数量以及比例未知,我们不可以一次把袋子中的球倒出来,只能每次从袋子中任意取一个球,记录球的颜色,然后将球放回袋子。假如我们重复取球 100 次之后,在取出的 100 个球中,有白球 60 个,黑球 40 个,那么请问袋子里黑白球的比例最有可能是多少?也许你会回答黑白球的比例为 4:6,那么这个答案背后的理论支撑是什么呢?我们假设袋子里黑球的比例为 p p p,那么白球的比例为 1 − p 1-p 1−p,因为每抽一个球出来,在记录颜色之后,把抽出的球放回了袋子里,所以每次抽出来的球的颜色服从同一独立分布。这里我们把一次抽出来球的颜色称为一次抽样。题目中在一百次抽样中,60 次是白球的,40 次为黑球事件的概率是 P ( 样 本 结 果 ∣ M ) P(样本结果|M) P(样本结果∣M)。如果第一次抽样的结果记为 x 1 x_1 x1,第二次抽样的结果记为 x 2 x_2 x2…,第一百次抽样的结果为 x 100 x_{100} x100。那么样本结果为 ( x 1 , x 2 . . . . . , x 100 ) (x_1,x_2.....,x_{100}) (x1,x2.....,x100)。这样,我们可以得到如下表达式:
P ( 样 本 结 果 ∣ M ) P(样本结果|M) P(样本结果∣M)
= P ( x 1 , x 2 , … , x 100 ∣ M ) = P(x_1,x_2,…,x_{100}|M) =P(x1,x2,…,x100∣M)
= P ( x 1 ∣ M ) P ( x 2 ∣ M ) … P ( x 100 ∣ M ) = < b r > p 40 ( 1 − p ) 60 = P(x_1|M)P(x_2|M)…P(x_{100}|M)=<br> p^{40}(1-p)^{60} =P(x1∣M)P(x2∣M)…P(x100∣M)=<br>p40(1−p)60,
由于最后的概率只和 p p p 有关,不同的 p p p 会导致不同的结果。那么如何求 p p p 的值呢?极大似然估计采取的方法是让这个样本结果出现的可能性最大,也就是使得 p 40 ( 1 − p ) 60 p^{40}(1-p)^{60} p40(1−p)60值最大,那么我们就可以看成是 p p p的方程,求导即可!令导数为0,即可求出 p = 0.4 p=0.4 p=0.4。这便是极大似然估计的思想。
先验概率 P ( Y = c k ) P(Y=c_k) P(Y=ck) 的极大似然估计是
P ( X ( j ) = a j l ∣ Y = c k ) P(X^{(j)}=a_{jl}|Y=c_k) P(X(j)=ajl∣Y=ck) = ∑ i = 1 N I ( x i ( j ) = a j l , y i = c k ) ∑ i = 1 N ( y i = c k ) \displaystyle\sum_{i=1}^NI(x_i^{(j)} = a_{jl}, y_i=c_k) \over \displaystyle\sum_{i=1}^N(y_i=c_k) i=1∑N(yi=ck)i=1∑NI(xi(j)=ajl,yi=ck), j = 1 , 2 , . . . , n ; l = 1 , 2 , . . . , S j ; k = 1 , 2 , . . . , K j=1,2,...,n;l=1,2,...,S_j;k=1,2,...,K j=1,2,...,n;l=1,2,...,Sj;k=1,2,...,K,
例子
下面我们通过一个例子来看下朴素贝叶斯分类器的工作过程,下表格包含了天气状况和是否去打高尔夫的关系,表中 outlook、temperature、humidity、windy 为特征,取值的集合分别为 {rainy, overcast, sunny},{hot, mild, cool},{high, normal},{false, true},playgolf 为类标记,取值为 {no, yes}。如果今天天气的状况为 (sunny, hot, normal, false),我们是否要去打高尔夫球呢?
outlook | temperature | humidity | windy | playgolf |
---|---|---|---|---|
rainy | hot | high | false | no |
rainy | hot | high | true | no |
overcast | hot | high | false | yes |
Sunny | mild | high | false | yes |
Sunny | cool | normal | false | yes |
Sunny | cool | normal | true | no |
overcast | cool | normal | true | yes |
rainy | mild | high | false | no |
rainy | cool | normal | false | yes |
Sunny | mild | normal | false | yes |
rainy | mild | normal | true | yes |
overcast | mild | high | true | yes |
overcast | hot | normal | false | yes |
Sunny | mild | high | true | no |
根据极大似然估计,容易计算下列概率:
P(playgolf=yes) = 9 14 9 \over 14 149,P(playgolf=no) = 5 14 5 \over 14 145
P(outlook=rainy|playgolf=yes) = 2 9 2 \over 9 92,P(outlook=overcast|playgolf=yes) = 4 9 4 \over 9 94,P(outlook=sunny|playgolf=yes) = 1 3 1 \over 3 31,
P(outlook=rainy|playgolf=no) = 3 5 3 \over 5 53,P(outlook=overcast|playgolf=no) = 0 5 0 \over 5 50,P(outlook=sunny|playgolf=no) = 2 5 2 \over 5 52,
P(temperature=hot|playgolf=yes) = 2 9 2 \over 9 92,P(temperature=mild|playgolf=yes) = 4 9 4 \over 9 94,P(temperature=cool|playgolf=yes) = 1 3 1 \over 3 31,
P(temperature=hot|playgolf=no) = 2 5 2 \over 5 52,P(temperature=mild|playgolf=no) = 2 5 2 \over 5 52,P(temperature=cool|playgolf=no) = 1 5 1 \over 5 51,
P(humidity=high|playgolf=yes) = 1 3 1 \over 3 31,P(humidity=normal|playgolf=yes) = 2 3 2 \over 3 32,
P(humidity=high|playgolf=no) = 4 5 4 \over 5 54,P(humidity=normal|playgolf=no) = 1 5 1 \over 5 51,
P(windy=false|playgolf=yes) = 2 3 2 \over 3 32,P(windy=true|playgolf=yes) = 1 3 1 \over 3 31,
P(windy=false|playgolf=no) = 2 5 2 \over 5 52,P(windy=true|playgolf=no) = 3 5 3 \over 5 53,
对给定的(sunny, hot, normal, false)计算:
P(playgolf=yes)P(outlook=sunny|playgolf=yes)P(temperature=hot|playgolf=yes)
P(humidity=Normal|playgolf=yes)P(windy=false|playgolf=yes)
= 9 14 9 \over 14 149 * 1 3 1 \over 3 31 * 2 9 2 \over 9 92 * 2 3 2 \over 3 32 * 2 3 2 \over 3 32 ≈ \approx ≈ 0.0211 0.0211 0.0211
P(playgolf=no)P(outlook=sunny|playgolf=no)P(temperature=hot|playgolf=no)
P(humidity=normal|playgolf=no)P(windy=false|playgolf=no)
= 5 14 5 \over 14 145 * 2 5 2 \over 5 52 * 2 5 2 \over 5 52 * 1 5 1 \over 5 51 * 2 5 2 \over 5 52 ≈ \approx ≈ 0.0046 0.0046 0.0046
由于 0.0211 > 0.0046 0.0211 > 0.0046 0.0211>0.0046,所以今天去打高尔夫。
贝叶斯估计
用极大似然估计可能会出现所要估计的概率值为 0 的情况。这时会影响到后验概率的计算结果,是分类产生偏差。解决这一问题的方法是采用贝叶斯估计。具体地,条件概率的贝叶斯估计是
P λ ( X ( j ) = a j l ∣ Y = c k ) P_\lambda(X^{(j)}=a_{jl}|Y=c_k) Pλ(X(j)=ajl∣Y=ck) = ∑ i = 1 N I ( x i ( j ) = a j l , y i = c k ) + λ ∑ i = 1 N ( y i = c k ) + S j λ \displaystyle\sum_{i=1}^NI(x_i^{(j)} = a_{jl}, y_i=c_k)+ \lambda \over \displaystyle\sum_{i=1}^N(y_i=c_k)+S_j\lambda i=1∑N(yi=ck)+Sjλi=1∑NI(xi(j)=ajl,yi=ck)+λ,式中 λ ≥ 0 \lambda \geq 0 λ≥0。
P(playgolf=yes) = 10 16 10 \over 16 1610,P(playgolf=no) = 6 16 6 \over 16 166
P(outlook=rainy|playgolf=yes) = 1 4 1 \over 4 41,P(outlook=Overcast|playgolf=yes) = 5 12 5 \over 12 125,
P(outlook=sunny|playgolf=yes) = 1 3 1 \over 3 31,P(outlook=rainy|playgolf=no) = 1 2 1 \over 2 21,P(outlook=Overcast|playgolf=no) = 1 8 1 \over 8 81,P(outlook=sunny|playgolf=no) = 3 8 3 \over 8 83,
P(temperature=hot|playgolf=yes) = 1 4 1 \over 4 41,P(temperature=mild|playgolf=yes) = 5 12 5 \over 12 125,
P(temperature=cool|playgolf=yes) = 1 3 1 \over 3 31,P(temperature=hot|playgolf=no) = 3 8 3 \over 8 83,P(temperature=mild|playgolf=no) = 3 8 3 \over 8 83,P(temperature=cool|playgolf=no) = 1 4 1 \over 4 41,
P(humidity=high|playgolf=yes) = 4 11 4 \over 11 114,P(humidity=normal|playgolf=yes) = 7 11 7 \over 11 117,
P(humidity=high|playgolf=no) = 5 7 5 \over 7 75,P(humidity=normal|playgolf=no) = 2 7 2 \over 7 72,
P(windy=false|playgolf=yes) = 7 11 7 \over 11 117,P(windy=true|playgolf=yes) = 4 11 4 \over 11 114,
P(windy=false|playgolf=no) = 3 7 3 \over 7 73,P(windy=true|playgolf=no) = 4 7 4 \over 7 74,
对给定的(sunny, hot, normal, false)计算:
P(playgolf=Yes)P(outlook=sunny|playgolf=yes)P(temperature=hot|playgolf=yes)
P(humidity=normal|playgolf=yes)P(windy=false|playgolf=yes)
= 10 16 10 \over 16 1610 * 1 3 1 \over 3 31 * 1 4 1 \over 4 41 * 7 11 7 \over 11 117 * 7 11 7 \over 11 117 ≈ \approx ≈ 0.0211
P(playgolf=no)P(outlook=sunny|playgolf=no)P(temperature=hot|playgolf=no)
P(humidity=normal|playgolf=no)P(windy=false|playgolf=no)
= 6 14 6 \over 14 146 * 2 5 2 \over 5 52 * 2 5 2 \over 5 52 * 1 5 1 \over 5 51 * 2 5 2 \over 5 52 ≈ \approx ≈ 0.0065
由于 0.0211 > 0.0065,所以今天去打高尔夫。
鸢尾花分类
- 导入库
import pandas as pd
from sklearn import metrics
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.preprocessing import StandardScaler
from sklearn.naive_bayes import GaussianNB
- 读取数据
iris_data = pd.read_csv('Iris.csv')
- 将数据集分成训练数据集和测试数据集
y = iris_data['Species']
x = iris_data[['SepalLengthCm', 'SepalWidthCm', 'PetalLengthCm', 'PetalWidthCm']]
train_x, test_x, train_y, test_y = train_test_split(x, y, test_size=0.3, random_state=33)
- 使用训练数据对模型进行训练,并使用得到的模型对测试数据进行测试。
gnb = GaussianNB()
gnb.fit(train_x, train_y)
predict_y = gnb.predict(test_x)
- 输出测试结果
print("NB准确率: %.4lf" % accuracy_score(test_y, predict_y))
- output
NB准确率: 0.9556
糖尿病的预测
糖尿病的预测是根据患者的一些信息来预测患者是否有糖尿病。下面我们通过 Scikit-learn 中的 k k k-NN 算法对患者是否患有糖尿病进行预测。
- 导入库
import pandas as pd
from sklearn import metrics
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.preprocessing import StandardScaler
- 读取数据
diabetes_data = pd.read_csv('diabetes.csv')
- 对数据进行清洗,对于某列数据中的0值,使用这一列值的平均值进行填充。
diabetes_data.replace({'Glucose': 0,'BloodPressure': 0,'SkinThickness': 0,'BMI': 0,'Insulin': 0
}, np.NaN, inplace=True)glucose_mean = diabetes_data['Glucose'].mean()
blood_pressure_mean = diabetes_data['BloodPressure'].mean()
skin_thickness_mean = diabetes_data['SkinThickness'].mean()
bmi_mean = diabetes_data['BMI'].mean()
insulin_mean = diabetes_data['Insulin'].mean()diabetes_data['Glucose'].replace(np.NaN, glucose_mean, inplace=True)
diabetes_data['BloodPressure'].replace(np.NaN, blood_pressure_mean, inplace=True)
diabetes_data['SkinThickness'].replace(np.NaN, skin_thickness_mean, inplace=True)
diabetes_data['BMI'].replace(np.NaN, bmi_mean, inplace=True)
diabetes_data['Insulin'].replace(np.NaN, insulin_mean, inplace=True)
- 将数据集分成训练数据集和测试数据集。
y = diabetes_data['Outcome']
x = diabetes_data[['Pregnancies', 'Glucose', 'BloodPressure', 'SkinThickness', 'Insulin', 'BMI', 'DiabetesPedigreeFunction', 'Age']]
train_x, test_x, train_y, test_y = train_test_split(x, y, test_size=0.2, random_state=0)
- 对数据进行规范化。
sc_x = StandardScaler()
train_x = sc_x.fit_transform(train_x)
test_x = sc_x.fit_transform(test_x)
- 使用训练数据对模型进行训练,并使用得到的模型对测试数据进行测试。
gnb = GaussianNB()
gnb.fit(train_x, train_y)
predict_y = gnb.predict(test_x)
- 输出测试结果
print("NB 准确率: %.4lf" % accuracy_score(test_y, predict_y))
- output
NB 准确率: 0.7835
总结
本文阐述了朴素贝叶斯法的理论知识,并通过两个例子介绍了朴素贝叶斯法的实际应用。