侧边栏壁纸
  • 累计撰写 25 篇文章
  • 累计创建 7 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

python 朴素贝叶斯算法

Vera
2025-03-11 / 0 评论 / 0 点赞 / 6 阅读 / 0 字 / 正在检测是否收录...

python朴素贝叶斯算法(sklearn.naive_bayes),会通过了解什么是朴素贝叶斯、贝叶斯公式推导、实际案例去讲解。也同时记录学习的过程帮组大家一起学习如果实际应该贝叶斯算法去分析。

贝叶斯解决问题介绍:

贝叶斯算法是英国数学家贝叶斯(约1701-1761)Thomas Bayes,生前提出为解决“逆概”问题写的一篇文章。
“逆概”就是逆向概率,有逆向概率就会有正向概率。举个简单的例子就能理解什么是正向概率和逆向概率:

  • 正向概率:假设袋子里面有两种球N个白球和M个黑球,你伸手进去摸一个,摸出黑球的概率有多大?正向算概率我们就用黑球的个数除以球的总数就等于摸出黑球的概率。

  • 逆向概率:如果我们事先不知道袋子里有多少个球,也不知道黑白球的比例。而是闭着眼睛随便摸一个(或者摸多个)球,观察这些取出来的球的颜色之后。那么我们可以就此对袋子里面的黑白球的比例作出推测。

现实世界本身就是不确定的,人类的观察能力有限。我们日常所观察到的只是事物表面上的结果,因此我们需要提供一个猜测。这个就是贝叶斯需要解决的问题。

逆向概率例子:

有一个学校男生女生比例分别为60%和40%,男生100%穿长裤,女生50%会穿长裤剩下的会穿裙子。远处的校门口走来一个穿长裤的学生,无法判断性别。求这个学生是女生的概率有多大?

我们先按自己现在方式进行思考一下,要求这个穿长裤的学生是女生的概率。

案例公式推导:
因为不知道学校总人数是多少,我们就假设总人数为U
穿长裤的男生人数:
P(Boy)男生的概率,P(Pants|Boy)男生穿长裤的概率
U∗P(Boy)∗P(Pants∣Boy)UP(Boy)∗P(Pants∣Boy)
穿长裤的女生人数:
P(Girl)女生的概率,P(Pants|Girl)女生穿长裤的概率
U∗P(Girl)∗P(Pants∣Girl)UP(Girl)∗P(Pants∣Girl)
穿长裤的总人数:
U∗P(Boy)∗P(Pants∣Boy)+U∗P(Girl)∗P(Pants∣Girl)UP(Boy)∗P(Pants∣Boy)+UP(Girl)∗P(Pants∣Girl)
那么女生穿长裤的概率:穿长裤的女生数/穿长裤的总人数U∗P(Girl)∗P(Pants∣Girl)U∗P(Boy)∗P(Pants∣Boy)+U∗P(Girl)∗P(Pants∣Girl)U∗P(Boy)∗P(Pants∣Boy)+U∗P(Girl)∗P(Pants∣Girl)U∗P(Girl)∗P(Pants∣Girl)
公式化简:
P(Girl)∗P(Pants∣Girl)P(Girl)∗P(Pants∣Girl)+P(Boy)∗P(Pants∣Boy)P(Girl)∗P(Pants∣Girl)+P(Boy)∗P(Pants∣Boy)P(Girl)∗P(Pants∣Girl)
所以最终走过了穿长裤可能是女生的概率为:
0.4∗0.50.6∗1+0.4∗0.5=0.20.8=0.250.6∗1+0.4∗0.50.4∗0.5​=0.80.2​=0.25

贝叶斯公式介绍:

P(A∣B)=P(B∣A)P(A)P(B)P(A∣B)=P(B)P(B∣A)P(A)
结合上面我们讲女生穿裤子的概率问题来带入一下,我们拟定:
A1:女生,A2:男生
B1:穿裤子,B2:未穿裤子
P(A1):就是女生的概率,已知条件0.40.4
P(B1):就是穿裤子的概率,男生穿裤子的概率+女生穿裤子的概率及0.6∗1+0.4∗0.50.6∗1+0.4∗0.5
我们要求的P(A1|B1):穿裤子中是女生的概率
P(B1|A1):就是女生穿裤子的概率,已知条件0.50.5
P(A1∣B1)=P(B1∣A1)P(A1)P(B)=0.5∗0.40.6∗1+0.5∗0.4=0.25P(A1∣B1)=P(B)P(B1∣A1)P(A1)​=0.6∗1+0.5∗0.40.5∗0.4​=0.25
所以带入公式就得到上面通推导的结果,穿裤子的女生概率为0.25。这个地方有点绕,需要多多理解一下。

如果不清楚的可以看李永乐老师讲贝叶斯

sklearn中的贝叶斯模块

参考博主:https://blog.csdn.net/brucewong0516/article/details/78798359
朴素贝叶斯是一类比较简单的算法,scikit-learn中朴素贝叶斯类库的使用也比较简单。相对于决策树,KNN之类的算法,朴素贝叶斯需要关注的参数是比较少的,这样也比较容易掌握。在scikit-learn中,常用的有3个朴素贝叶斯的分类算法类。分别是GaussianNBMultinomialNBBernoulliNB。这三个类适用的分类场景各不相同其中:

  • GaussianNB:就是先验为高斯分布的朴素贝叶斯,一般来说如果样本特征的分布大部分是连续值,使用GaussianNB会比较好

  • MultinomialNB:就是先验为多项式分布的朴素贝叶斯,如果如果样本特征的分大部分是多元离散值,使用MultinomialNB比较合适。

  • BernoulliNB:就是先验为伯努利分布的朴素贝叶斯,而如果样本特征是二元离散值或者很稀疏的多元离散值,应该使用。

naive_bayes.GaussianNB

GaussianNB类的主要参数仅有一个,即先验概率priors,对应Y的各个类别的先验概率P(Y=Ck)。这个值默认不给出,如果不给出此时P(Y=Ck)=mk/m。其中m为训练集样本总数量,mk为输出为第k类别的训练集样本数。如果给出的话就以priors 为准。 在使用GaussianNB的fit方法拟合数据后,我们可以进行预测。此时预测有三种方法,包括predict,predict_log_proba和predict_proba

  • predict:方法就是我们最常用的预测方法,直接给出测试集的预测类别输出。

  • predict_proba:则不同,它会给出测试集样本在各个类别上预测的概率。容易理解,predict_proba预测出的各个类别概率里的最大值对应的类别,也就是predict方法得到类别。

  • predict_log_proba:和predict_proba类似它会给出测试集样本在各个类别上预测的概率的一个对数转化。转化后predict_log_proba预测出的各个类别对数概率里的最大值对应的类别,也就是predict方法得到类别。

    • 三者区别举例

    import numpy as np
    X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
    Y = np.array([1, 1, 1, 2, 2, 2])
    from sklearn.naive_bayes import GaussianNB
    clf = GaussianNB()
    #拟合数据
    clf.fit(X, Y)
    print("==Predict result by predict==")
    print(clf.predict([[-0.8, -1]]))
    print("==Predict result by predict_proba==")
    print(clf.predict_proba([[-0.8, -1]]))
    print("==Predict result by predict_log_proba==")
    print(clf.predict_log_proba([[-0.8, -1]]))
    
    ==Predict result by predict==
    [1]
    ==Predict result by predict_proba==
    [[  9.99999949e-01   5.05653254e-08]]
    ==Predict result by predict_log_proba==
    [[ -5.05653266e-08  -1.67999998e+01]]
    
    

此外,GaussianNB一个重要的功能是有 partial_fit方法,这个方法的一般用在如果训练集数据量非常大,一次不能全部载入内存的时候。这时我们可以把训练集分成若干等分,重复调用partial_fit来一步步的学习训练集,非常方便。后面讲到的MultinomialNB和BernoulliNB也有类似的功能

naive_bayes.MultinomialNB

MultinomialNB参数比GaussianNB多,但是一共也只有仅仅3个。其中,参数alpha即为上面的常数λ,如果你没有特别的需要,用默认的1即可。如果发现拟合的不好,需要调优时,可以选择稍大于1或者稍小于1的数。布尔参数fit_prior表示是否要考虑先验概率,如果是false,则所有的样本类别输出都有相同的类别先验概率。否则可以自己用第三个参数class_prior输入先验概率,或者不输入第三个参数class_prior让MultinomialNB自己从训练集样本来计算先验概率,此时的先验概率为P(Y=Ck)=mk/m。其中m为训练集样本总数量,mk为输出为第k类别的训练集样本数

fit_prior

class_prior

最终先验概率

False

填或不填没有意义

P(Y=Ck)=1/kp(Y=Ck)=1/kP(Y=Ck)=1/kp(Y=Ck)=1/k

True

不填

P(Y=Ck)=mk/mp(Y=ck)=mk/mP(Y=Ck)=mk/mp(Y=ck)=mk/m

True

P(Y=Ck)=p(Y−ck)=classpriorP(Y=Ck)=p(Y−ck)=classprior

naive_bayes.BernoulliNB

BernoulliNB一共有4个参数,其中3个参数的名字和意义和MultinomialNB完全相同。唯一增加的一个参数是binarize。这个参数主要是用来帮BernoulliNB处理二项分布的,可以是数值或者不输入。如果不输入,则BernoulliNB认为每个数据特征都已经是二元的。否则的话,小于binarize的会归为一类,大于binarize的会归为另外一类。

在使用BernoulliNB的fit或者partial_fit方法拟合数据后,我们可以进行预测。此时预测有三种方法,包括predict,predict_log_proba和predict_proba。由于方法和GaussianNB完全一样,这里就不累述了。

贝叶斯的主要优缺点

贝叶斯的主要优点

  • 朴素贝叶斯模型发源于古典数学理论,有稳定的分类效率。

  • 对小规模的数据表现很好,能个处理多分类任务,适合增量式训练,尤其是数据量超出内存时,我们可以一批批的去增量训练。

  • 对缺失数据不太敏感,算法也比较简单,常用于文本分类。

贝叶斯的主要缺点

  • 理论上,朴素贝叶斯模型与其他分类方法相比具有最小的误差率。但是实际上并非总是如此,这是因为朴素贝叶斯模型假设属性之间相互独立,这个假设在实际应用中往往是不成立的,在属性个数比较多或者属性之间相关性较大时,分类效果不好。而在属性相关性较小时,朴素贝叶斯性能最为良好。

  • 需要知道先验概率,且先验概率很多时候取决于假设,假设的模型可以有很多种,因此在某些时候会由于假设的先验模型的原因导致预测效果不佳。

  • 由于我们是通过先验和数据来决定后验的概率从而决定分类,所以分类决策存在一定的错误率。

  • 对输入数据的表达形式很敏感。

实际案例

本文案例数据点击下载
之前使用过决策树算法对该数据进行分析决策树算法点这里查看,现在我们用同样的数据但是使用贝叶斯来看看。
数据背景是有一组关于天气、是否是周末、有没有促销对销量高低的影响数据,我们先来看一下代码。

import pandas as pd
data=pd.read_excel(r'C:\Users\huangjunwen\Desktop\sales_data.xls',index_col='序号')
#导入数据,将序号列转变成索引
data_new=data.replace(['坏','否','低','好','是','高'],[-1,-1,-1,1,1,1]) 
#将数据内容转化成可以计算的数字,-1代表:坏、否、低;1代表:好、是、高
from sklearn.utils import shuffle
#这是一个可以将数据重新随机排序的模块
data_new=shuffle(data_new)
#对数据进行重新随机排列
data_train=data_new.iloc[:20,:3]
#创建训练集
data_test=data_new.iloc[:20,3:]
#创建测试的标签集
data_predict=data_new.iloc[20:,]
#创建最后要预测并检验结果准确的预测集
from sklearn.naive_bayes  import GaussianNB
#导入高斯分布的贝叶斯
clf=GaussianNB()
#创建高斯分布的贝叶斯模型
clf.fit(data_train,data_test)
#将训练数据及标签数据放入模型进行训练
data_predict['贝叶斯拟合']=clf.predict(data_predict.iloc[:,:3])
#预测结果并赋值到预测集进行模型与实际标签比对
print(len(data_predict[data_predict['销量']==data_predict['贝叶斯拟合']])/len(data_predict))
#算出模型准确率

0

评论区