美文网首页
蓝皮书系列之 朴素贝叶斯

蓝皮书系列之 朴素贝叶斯

作者: 脑荼地 | 来源:发表于2018-04-01 20:17 被阅读0次

李航的蓝皮书《统计学习方法》,可谓是机器学习的中文经典。其中所设计的一些算法,是机器学习的基础。这篇博文将要讲述蓝皮书中的第四章朴素贝叶斯法。

Part i 算法原理

朴素贝叶斯方法的整体思路是相对容易理解的:通过样本知识,可以求得先验概率,然后根据全概率公式,计算出所求事件的概率。朴素贝叶斯的算法框架如下:
=============================朴素贝叶斯=============================
输入:样本集X,标签y
输出:某个样本的分类
==================================================================
Step.1 计算先验概率和条件概率


图片来源于《统计学习方法》

Step.2 对于给定样本,计算该样本属于各类的概率


图片来源于《统计学习方法》
Step.3 确定样本属于哪一类
图片来源于《统计学习方法》
==================================================================
虽然整个算法非常简单,但是在实际操作中会存在一些细小的问题,如
1.在计算某个条件概率时如果出现了0的情况,则很有可能会影响到厚颜概率的计算。
2.对于离散变量可以很好的计算概率,可是对于连续变量就存在问题。
面对上述两个问题,问题一通常的解决方法是加入一个系数lambda,使概率不为0。故而对Step.1 中的公式进行如下的更改:

图片来源于《统计学习方法》

问题二的通常解决方法是假设其满足某个分布,通常为正太分布,则通过样本集来估计该分布的参数。在测试集中,根据实例的数值,来计算其在该分布下的概率。

Part ii Python 代码实现

定义一个NaiveBayes(object)类,初始化参数λ=1

def __init__(self,lamda=1):
        self.lamda = lamda

训练模型,训练模型的过程,其实就是计算各个概率的过程。对于离散变量直接其概率,对于连续变量,则计算他们的均值和方差。当然为了简化,额外设置了两个输入参数class_numind,其中class_num表示类别的数目,而ind表示离散变量的标号。
在这里以一个字典的形式记录下各个概率。

def fit(self,x,y,class_num,ind):
        total_num,Len = x.shape
        Feat_Len = np.max(x,axis=0)+1
        prob = dict()
        for i in range(class_num):
            y_category_num = np.sum(y==i)   
            prob.update( {str(i+1):(y_category_num+self.lamda)/(total_num+class_num*self.lamda) } )
            for j in range(Len):
                temp_x = x[y==i,j]
                if j in ind:
                    for k in range(Feat_Len[j]):                     
                        feat_category_num = np.sum(temp_x==k)
                        prob.update( {str(100*(i+1)+10*(j+1)+k+1): (feat_category_num + self.lamda) / (y_category_num + Feat_Len[j]*self.lamda)  }  )
                if j not in ind:
                    mu = np.mean( temp_x)
                    prob.update( {str(100*(i+1)+10*(j+1)+1):mu} )
                    sigma = np.std( temp_x,ddof=1)
                    prob.update( {str(100*(i+1)+10*(j+1)+2):sigma} )
        self.prob_matrix = prob
        self.class_num = class_num
        self.ind = ind

为了使模型能够预测,定义了一个predict(self,x)的函数,直接输出预测数据的种类

def predict(self,x):
        try:
            Num,Len = x.shape
        except:
            Len = len(x)  
            Num = 1
            x = x.reshape([1,-1])
        p_pred =  np.zeros([Num,self.class_num])
        prob_matrix = self.prob_matrix
        for n in range(Num):
            for i in range(self.class_num):
                pb = prob_matrix[str(i+1)]
                print( prob_matrix[str(i+1)] )
                for j in range(Len):
                    if j in self.ind:
                        pb *=  prob_matrix[ str(100*(i+1)+10*(j+1)+x[n,j]+1) ]
                        print( prob_matrix[ str(100*(i+1)+10*(j+1)+x[n,j]+1) ] )
                    if j not in self.ind:
                        pb *= stats.norm.pdf(x[n,j], prob_matrix[str(100*(i+1)+10*(j+1)+1)], prob_matrix[str(100*(i+1)+10*(j+1)+2)])
                        print(stats.norm.pdf(x[n,j], prob_matrix[str(100*(i+1)+10*(j+1)+1)], prob_matrix[str(100*(i+1)+10*(j+1)+2)]) )
                print('==================================')
                p_pred[n,i] = pb
            
        self.predict_prob_ = p_pred
        return np.argmax(p_pred,axis=1)

Part iii 实验结果:

为了验证代码的准确性,采用了两个例子,一个是蓝皮书上的数据,另一个此网址的数据

蓝皮书训练集.png
网络数据集
令蓝皮书中的S=0,M=1,L=2,令网络数据集中的有房=1,无房=0,单身=0,已婚=1,离婚=2,拖欠贷款=1,不拖欠贷款=0,则定义的两个数据集量化后如下表示:
def data_set(self,data):
        if data == 1:
            X = np.array([[1,1,1,1,1,2,2,2,2,2,3,3,3,3,3],[1,2,2,1,1,1,2,2,3,3,3,2,2,3,3]]).T -1
            y = np.array([-1,-1,1,1,-1,-1,-1,1,1,1,1,1,1,1,-1])  
            y[y==-1]=0  
            ind= [0,1]
            x_te = np.array([1,0])
        else:
            X = np.array([[1,0,0,1,0,0,1,0,0,0],[0,1,0,1,2,1,2,0,1,0],[125,100,70,120,95,60,220,85,75,90]]).T
            y = np.array( [0,0,0,0,1,0,0,1,0,1] )
            ind = [0,1]
            x_te = np.array([0,1,120])
        return X,y,ind,x_te

对这两组数据分别进行训练和预测:

print('蓝皮书数据集')
nb = NaiveBayes()
X,y,ind,x_te = nb.data_set(1)
nb.fit(X,y,2,ind)
x_te = np.array( [[1,0]] )
p1 = nb.predict(x_te)
print( '各类概率:',p1,'识别结果:', nb.predict_prob_)

print('网络数据集')
nb = NaiveBayes(lamda=0)
X,y,ind,x_te = nb.data_set(0)
nb.fit(X,y,2,ind)
p2 = nb.predict_prob(x_te)
print( '各类概率:',p2,'识别结果:',nb.predict_prob_)

最终的结果和书本保持一致。


程序运行结果

相关文章

  • 蓝皮书系列之 朴素贝叶斯

    李航的蓝皮书《统计学习方法》,可谓是机器学习的中文经典。其中所设计的一些算法,是机器学习的基础。这篇博文将要讲述蓝...

  • 算法笔记(7)-朴素贝叶斯算法及Python代码实现

    朴素贝叶斯算法有三种类型,分别是贝努利朴素贝叶斯、高斯贝叶斯、多项式朴素贝叶斯。 贝叶斯公式 贝努利朴素贝叶斯 适...

  • 朴素贝叶斯法

    朴素贝叶斯法 朴素贝叶斯法的学习与分类 朴素贝叶斯法的参数估计 朴素贝叶斯实现 高斯朴素贝叶斯实现 使用 skle...

  • 朴素贝叶斯(NBM)之后验概率最大化的含义 | 统计学习方法

    朴素贝叶斯 - 贝叶斯估计Python复现: 舟晓南:朴素贝叶斯(Bayes)模型python复现 - 贝叶斯估计...

  • 朴素贝叶斯算法介绍及优化

    朴素贝叶斯(Naive Bayes) 贝叶斯公式 朴素贝叶斯算法其实原理很简单,要理解朴素贝叶斯算法我们首先得知道...

  • 朴素贝叶斯法(NaiveBayes)

    朴素贝叶斯法(Naive Bayes) 朴素贝叶斯法是基于贝叶斯定力和特征条件独立假设的分类方法。 朴素贝叶斯法实...

  • 朴素贝叶斯算法

    问题 1. 什么是朴素贝叶斯 2. 怎么理解贝叶斯公式和朴素贝叶斯公式 3. 朴素贝叶斯算法流程是怎样...

  • 深度学习知识点汇总-机器学习基础(6)

    2.6 逻辑回归与朴素贝叶斯有什么区别? 逻辑回归是判别模型, 朴素贝叶斯是生成模型。 朴素贝叶斯属于贝叶斯,逻辑...

  • 朴素贝叶斯

    朴素贝叶斯 用处:朴素贝叶斯主要解决的是而分类的问题。 为什么叫朴素贝叶斯: 因为贝叶斯分类只做最原始,最简单的假...

  • sklearn-朴素贝叶斯

    朴素贝叶斯分为三种:高斯朴素贝叶斯、多项式朴素贝叶斯、伯努利朴素贝叶斯。这三种的不同之处在于求条件概率的公式不同。...

网友评论

      本文标题:蓝皮书系列之 朴素贝叶斯

      本文链接:https://www.haomeiwen.com/subject/zhyacftx.html