机器学习算法-贝叶斯分类

贝叶斯分类算法介绍:

贝叶斯分类算法是统计学的一种概率分类方法,朴素贝叶斯分类是贝叶斯分类中最简单的一种。 其分类原理就是利用贝叶斯公式根据某特征的先验概率计算出其后验概率,然后选择具有最大后验概率的类作为该特征所属的类。之所以称之为"朴素",是因为贝叶斯分类只做最原始、最简单的假设:所有的特征之间是统计独立的。假设某样本X有a1, a2.,…an个属性,那么有P(X)= P(a1,a2…,an)= P(a1)* P(a2) P(an),满足样的公式就说明特征统计独立。

条件概率公式

条件概率(Condittional probability), 就是指在事件B发生的情况下,事件A发生的概率,P(A| B)来表示。

在这里插入图片描述
根据文氏图可知:在事件B发生的情况下,事件A发生的概率就是 在这里插入图片描述除以在这里插入图片描述
在这里插入图片描述
等式两边同时乘以P(B),可以得到P(AB)的表现形式。 同理可得:
在这里插入图片描述
这就是朴素贝斯公式的表现形式

全概率公式:

接着看全概率公式,如果事件A1, A2, A… An构成一个完备事件且都有正概率,那么对于任意一个事件B则
在这里插入图片描述

贝叶斯推断

根据条件概率和全概率公式,可以得到贝叶斯公式如下:
在这里插入图片描述
当分类中有多个类别的时候我们采用第二种的贝叶斯计算公式来计算其概率。
**P(A)称为"先验概率" (Prior probability),即在B事件发生之前,我们对A事件概率的一个判断。
P(A| B)称为"后验概率" (Posterior probability),即在B事件发生之后,我们对A事件概率的重新评估。
P(B|A)/P(B)称为"可能性函数" (Likely hood),这是一个调整因子, 使得预估概率更接近真实概率。
所以条件概率可以理解为:后验概率=先验概率*调整因子
如果"可能性函数">1,意味着"先验概率"被增强,事件A的发生的可能性变大;
如果"可能性函数"=1,意味着B事件无助于判断事件A的可能性;
如果"可能性函数"<1,意味着"先验概率被削弱,事件A的可能性变小。
**

GaussianNB

GaussianNB就是先验为高斯分布(正态分布)的朴素贝叶斯,假设每个标签的数据都服从简单的正态分布:

在这里插入图片描述
其中 在这里插入图片描述 为Y的第k类类别。 在这里插入图片描述在这里插入图片描述 为需要从训练集计算的值。分别表示数据的期望和方差。

MultinomialNB

MultinomialNB就是先验为多项式分布的朴素贝叶斯。它假设特征是由一个简单多项式分布生成的。 多项分布可以描述各种类型样本出现次数的概率,因此多项式朴素贝叶斯非常适合用于描述出现次数或者出现次数比例的特征。该模型常用于文本分类,特征表示的是次数,例如某个词语的出现次数。多项式分布公式如下:

在这里插入图片描述

上述式子表示:是第k个类别的第j维特征的第I个取值条件概率。mk是训练集中输出为第k类的样本个数。入为一个大于0的常数,常常取为1,即拉普拉斯平滑。也可以取其他值。

BernoulliNB

BernoulliNB就是先验为伯努利分布的朴素贝叶斯。假设特征的先验概率为二元伯努利分布,即如下式:

在这里插入图片描述

此时l两种取值。xjl只能取值0或者1。
在伯努利模型中,每个特征的取值是布尔型的,即true和false, 或者1和0。在文本分类中,就是一个特征有没有在一个文档中出现。

例子(以西瓜书上面的例子进行讲解):

训练样本:

在这里插入图片描述

测试样本:

在这里插入图片描述

朴素贝叶斯解决的步骤:
首先估计先验概率P©:
P(好瓜=是)=8/17=0.471
P(好瓜=否)=9/17=0.529
然后计算每一个属性的估计条件概率P(xi|c):

在这里插入图片描述

最后分别计算是好瓜和坏瓜的概率:

在这里插入图片描述

由于好瓜的概率大于坏瓜的概率,因此朴素贝叶斯分类器将测试样本判别为好瓜

代码实现

贝叶斯分类算法解决鸢尾花分类:
import pandas as pd
import numpy as np
import random
dataset=pd.read_csv('iris.txt',header=None);
# print(dataset.head())
#print(dataset)
def randSplist(dataset,rate):
    l=list(dataset.index)#
    random.shuffle(l);
    dataset.index=l
    n=dataset.shape[0]
    m=int(n*rate)
    train=dataset.loc[range(m),:];
    test=dataset.loc[range(m,n),:]
    dataset.index=range(dataset.shape[0]);
    test.index=range(test.shape[0])
    return train,test;
# #测试切分情况
# ceshi1=randSplist(dataset,0.8);
# print(ceshi1);
#构建朴素贝叶斯分类器
def gbg_fenleiqi(train,test):
    labels=train.iloc[:,-1].value_counts().index
    # print(labels);
    mean=[]
    std=[]
    reasult=[]
    for j in labels:
        item=train.loc[train.iloc[:,-1]==j,:];
        m=item.iloc[:,:-1].mean()
        s=np.sum((item.iloc[:,:-1]-m)**2)/(item.shape[0])
        mean.append(m);
        std.append(s)
        # print(mean);
        # print(std)
    means=pd.DataFrame(mean,index=labels)
    stds=pd.DataFrame(std,index=labels);
    # print(means);
    # print(stds)
    for j in range(test.shape[0]):
        jset=test.iloc[j,:-1].tolist();
        jprob=np.exp(-1*(jset-means)**2/(stds*2))/(np.sqrt(2*np.pi*stds));
        # print(jprob)
        #正态分布公式
        prob=1;
        for k in range(test.shape[1]-1):
            prob*=jprob[k];
            # print(prob)
            cla=prob.index[np.argmax(prob.values)]
            # print(cla)
        # print('--------------------')
        # print(cla)
        reasult.append(cla);
    test['predict']=reasult;
    acc=(test.iloc[:,-1]==test.iloc[:,-2]).mean()
#计算预测准确率
    print(f"模型的预测准确率为{acc}");
    #return test;
#测试构建情况
# train,test=randSplist(dataset,0.8);
# ceshi2=gbg_fenleiqi(train,test);
# print(ceshi2);
#系统测试
for i in range(3):
    train,test=randSplist(dataset,0.9);
    ceshi1=gbg_fenleiqi(train,test);
由于鸢尾花数据集比较纯净,朴素贝叶斯对其分类效果比较好

在这里插入图片描述

用scikit-learn相关的包进行鸢尾花分类并比较高斯朴素贝叶斯、多项式分布朴素贝叶斯和伯努利朴素贝叶斯的效果
高斯朴素贝叶斯代码实现
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import GaussianNB
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=0)
gnb = GaussianNB()
y_pred = gnb.fit(X_train, y_train).predict(X_test)
print("测试集数目为:%d 预测出错的数目为: %d" % (X_test.shape[0], (y_test != y_pred).sum()))
print('分类的准确率为%s'%(1-((y_test != y_pred).sum()/X_test.shape[0])));
结果:

在这里插入图片描述

多项式分布朴素贝叶斯代码实现
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import ComplementNB
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=0)
cnb = ComplementNB()
y_pred = cnb.fit(X_train, y_train).predict(X_test)
print("测试集数目为:%d 预测出错的数目为: %d" % (X_test.shape[0], (y_test != y_pred).sum()))
print('分类的准确率为%s'%(1-((y_test != y_pred).sum()/X_test.shape[0])));
结果:

在这里插入图片描述

伯努利朴素贝叶斯代码实现
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import BernoulliNB
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=0)
bnb = BernoulliNB()
y_pred = bnb.fit(X_train, y_train).predict(X_test)
print("测试集数目为:%d 预测出错的数目为: %d" % (X_test.shape[0], (y_test != y_pred).sum()))
print('分类的准确率为%s'%(1-((y_test != y_pred).sum()/X_test.shape[0])));
结果:

在这里插入图片描述

结论:

通过比较这三种方法的效果,我们可以得出高斯朴素贝叶斯对鸢尾花分类效果最好。
一般来说, 如果样本特征的分布大部分是连续值,使用GaussianNB会比较好。
如果如果样本特征的分布大部分是多元离散值,使用MultinomialNB比较合适。
而如果样本特征是二元离散值或者很稀疏的多元离散值,应该使用BernoulliNB。

例子二:来对皮马印第安人糖尿病进行分类

我们采用的是皮马印第安人糖尿病数据集,共有九个字段,八个属性。
'''
皮马印第安人糖尿病数据集
怀孕次数
口服葡萄糖耐量试验中血浆葡萄糖浓度
舒张压(mm Hg)
三头肌组织褶厚度(mm)
2小时血清胰岛素(μU/ ml)
体重指数(kg/(身高(m))^ 2)
糖尿病系统功能
年龄(岁)
'''
代码实现:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.naive_bayes import GaussianNB  # 导入sklearn的贝叶斯算法
from sklearn.model_selection import train_test_split

data = pd.read_csv('pima-indians-diabetes.data',header=None)
# print(data);
# print(data.shape)
# panda的describe描述属性,展示了每一个字段的,
# 【count条目统计,mean平均值,std标准值,min最小值,25%,50%中位数,75%,max最大值】
# print(data.describe())
y = data[8]
X = data.iloc[:,0:8]
X_train,X_test,y_train,y_test = train_test_split(X,y,stratify=y,random_state=11)
nb = GaussianNB()
nb.fit(X_train,y_train)
print('准确率是:',nb.score(X_test,y_test))

为了检验随机因子对分类效果的影响,我们循环迭代随机因子(0-100),进行准确率的判断,并用可视化的将结果表示出来:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.naive_bayes import GaussianNB  # 导入sklearn的贝叶斯算法
from sklearn.model_selection import train_test_split

data = pd.read_csv('pima-indians-diabetes.data',header=None)
# print(data);
# print(data.shape)
# panda的describe描述属性,展示了每一个字段的,
# 【count条目统计,mean平均值,std标准值,min最小值,25%,50%中位数,75%,max最大值】
# print(data.describe())
y = data[8]
X = data.iloc[:,0:8]

x=range(100)
score_total=[]
index=0
max_acc=0
for i in range(100):
    X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, random_state=i)
    nb = GaussianNB()
    nb.fit(X_train, y_train)
    score=nb.score(X_test, y_test)
    print('准确率是:',score)
    if score >=max_acc:
        max_acc=score;
        index=i;
    score_total.append(score)
plt.plot(x,score_total,'yo-')
plt.show()
print('最大的准确率为:',max_acc,'随机因子为:',index)
结果:
部分结果如下:

在这里插入图片描述

可视化效果图:

在这里插入图片描述

由于不同的随机因子会导致模型的准群率的不同,因此我们在模型训练的同时要不断调整随机因子,使其的准确率达到最大化。

例子三(将上述的皮马印第安人糖尿病的分类分别用贝叶斯算法和逻辑回归来进行代码实现,来检验其效果)

代码实现;
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.linear_model import LogisticRegression
from sklearn.naive_bayes import GaussianNB
from sklearn.model_selection import train_test_split
data = pd.read_csv('pima-indians-diabetes.data',header=None)
y = data[8]
X = data.iloc[:,0:8]
X_train,X_test,y_train,y_test = train_test_split(X,y,stratify=y,random_state=11)
lr = LogisticRegression()
nb = GaussianNB()
lr_score = []
nb_score = []
train_sizes = range(10,len(X_train),10)
for train_size in train_sizes:
    X_slice,_,y_slice,_ = train_test_split(X_train,y_train,train_size=train_size,stratify=y_train,random_state=11)
    nb.fit(X_slice,y_slice)
    nb_score.append(nb.score(X_test,y_test))
    lr.fit(X_slice,y_slice)
    lr_score.append(lr.score(X_test,y_test))
plt.plot(train_sizes,nb_score,label='native bayes')
plt.plot(train_sizes,lr_score,linestyle='--',label='logistic regression')
plt.xlabel('Number of training instances')
plt.ylabel('Test set accuracy')
plt.show()


可视化结果:

在这里插入图片描述

分析:
我们可以看出,在数据集较小的情况下朴素贝叶斯的分类效果要比逻辑回归分类要准确,但是随着数据集的增加,逻辑回归的准确率会不断的增加

朴素贝叶斯改进之拉普拉斯平滑

利用贝叶斯分类器对文档进行分类时,要计算多个概率的乘积以获得文档属于某个类别的概率,即计算p(w0| 1)p(w1 |1)p(w2|1)。如果其中有一个概率值为0,那么最后的成绩也为0。显然,这样是不合理的,为了降低这种影响,可以将所有词的出现数初始化为1,并将分母初始化为2。这种做法就叫做拉普拉斯平滑(LaplaceSmoothing)又被称为加1平滑,是比较常用的平滑方法,它就是为了解决0概率问题。另外一个遇到的问题就是下溢出,这是由于太多很小的数相乘造成的。我们在计算乘积时,由于大部分因子都很小,所以程序会下溢或者得不到正确答案。为了解决这个问题,对乘积结果取自然对数。通过求对数可以避免下溢出或者浮点数舍入导致的错误。同时,采用自然对数进行处理不会有任何损失。下图给出函数f(x)和In(f()x)的曲线。

在这里插入图片描述

检查这两条曲线就会发现它们在相同区域内同时增加或者减少,并且在相同点上取到极值。它们的取值虽然不同,但不影响最终结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值