[西瓜书]朴素贝叶斯--numpy + python实现

2017-05-15 19:34:48来源:CSDN作者:pengjian444人点击

贝叶斯定理

现在假设有两个事件分别为A和B,贝叶斯定理则可以描述在事件A发生的前提下B发生的概率以及在事件B发生的前提下事件A发生的概率之间的关系。有点绕?画个图就能理解了~

这里写图片描述

现在假设事件A发生的概率为P(A) 事件B发生的概率为P(B),事件A和B同时发生的概率为P(C)。事件A发生的前提下B发生的概率就是 P(B|A)=P(C)P(A),在事件B发生的前提下A发生的概率为P(A|B)=P(C)P(B)。那么这两者之间存在什么样的关系呢?通过简单的变换我们可以得到下面的等式:
P(B|A)P(A)=P(A|B)P(B)

==>P(A|B)=P(A)P(B|A)P(B)
上述的公式就是贝叶斯公式。推到过程是不是很简单~

朴素贝叶斯概率模型

基本思想

回到分类的问题上,我们想要通过上面的公式解决具体的分类问题。首先,我们根据一般的分类问题将上面公式中提到的A和B具体化一下,我们指示A为样本,其包含样本所有的特征数据。B为分类的类别。为更好的对对应起来,我们用x代指一个样本数据,c代表一个分类类别。那么就有如下的贝叶斯公式:
P(c|x)=P(c)P(x|c)P(x)
这个公式的左边描述的是,在我们已知一个数据样本的情况下,其归属类别c的概率。很自然的我们就可以想到,将数据x和类别对应的一一计算,分别计算该样本在被分类到不同类别的概率,找到概率最大的那个类别,就是我们将要分类的类别了。

问题简化

确定解决的方向之后,因为需要实际的解决问题,我们当然希望计算的过程越简单越好,所以我们需要对问题模型进行适当的处理,而又尽量的保持原方法的理论准确率。

简化公式

公式方面,我们观察到P(x)和类别没有关系,也就是说对于任何类别的概率计算,p(x)都是一个常数,并不会影响最终的结果。所以我们可以将其从公式中删除掉,简化后得到下面的公式:
P(c|x)=P(c)P(x|c)

简化模型

从上面简化之后的公式中我们可以看出,其和联合分布其实有点类似
p(c,x1,x2...xn)=p(x1,x2..xn|c)p(c)=p(x2..xn|c,x1)p(c)p(x1|c)......
在实际情况中,如果考虑特征之间的关联性。我们通常没有办法直接计算p(x1,x2..xn|n),即使通过上面联合分布的公式处理依旧非常的复杂也有可能没办法计算结果。所以,这里为了方便计算,我们需要对模型进行简化,在世界的计算过程中我们忽略特征之间的额相关性,虽然他它们之间的相关性大多数时候是存在的。

这样忽略属性之间的相关性在周老师的书中被称之为“属性条件独立性假设(attribute conditional independence assumption)”。基于这样的前提,我们继续使用联系分布公式,以第二个等式为例:
p(x1,x2..xn|c)p(c)=p(x2..xn|c,x1)p(c)p(x1|c)=p(x2,..xn|c)p(c)p(x1|c)
继续分解下去我们可以得到
P(c|x)=P(c)P(x|c)=p(c)p(x1,x2,x3..xn|c)=p(c)p(x1|c)p(x2|c)p(x3|c)....p(xn|c)=p(c)i=1np(xi|c)

通过上面最后一个公式,我们可以很方便的计算出在已知一个样本的情况下,其归属于不同类别的概率。

那现在就让我们来编程实现一下吧:

python实现

"""朴素贝叶斯    基于贝叶斯公式,并添加了属性条件独立性假设。"""import numpy as npfrom sklearn.datasets import load_irisiris = load_iris()  # 加载数据y = iris.targetx = iris.datadef naive_bayes(x, y, predict):    unique_y = list(set(y))    label_num = len(unique_y)    sample_num, dim = x.shape    joint_p = [1] * label_num    # 把所有的类别都过一遍,计算P(c)    for (label_index, label) in enumerate(unique_y):        p_c = len(y[y == label]) / sample_num        for (feature_index, x_i) in enumerate(predict):            tmp = x[y == label]            joint_p[label_index] *= len(            [t for t in tmp[:, feature_index] if t == x_i]) / len(tmp)        joint_p[label_index] *= p_c    tmp = joint_p[0]    max_index = 0    for (i, p) in enumerate(joint_p):        if tmp < p:            tmp = p            max_index = i    return unique_y[max_index]# 测试所用的数据为数据集中最后一个数据,类别为2out = naive_bayes(x, y, np.array([5.9, 3., 5.1, 1.8]))print(out)

好了大功告成~希望对大家有帮助~

微信扫一扫

第七城市微信公众平台