贝叶斯分类numpy实现

概述

贝叶斯属于生成模型的一种,其实现很简单,就是应用贝叶斯公式。这是一种指定先验分布,求后验的方法。
概率论课本里著名的贝叶斯公式如下
在这里插入图片描述
p(ci)是i类在数据集的占比,(数一下就可,易)
p(x|ci)是从数据集所有的标记为i的数据中,抽出x的概率(核心)
p(ci|x)即x属于ci的概率
通过argmax(p(ci|x))就可分类了。
所以只要解决p(x|ci)的计算,就ok了。我们假定p(x|ci)是服从多元高斯分布的。如下。其中D为feature数,Σ是(nfeature*nfeature)的协方差矩阵,μ是(nfeature)均值。当然也可以取别的分布。
在这里插入图片描述
在这里插入图片描述
高斯分布的密度图如上所示,μ决定中心位置,Σ的对角线元素就是维度上的方差,决定了上面椭圆状密度图的长轴短轴比,Σ其余元素是协方差,决定椭圆状密度图的倾斜。
为得到每个类的Σ,μ,可以用极大似然估计来做。已经证明了估计结果就是data的mean 和 cov。故至此,我们就可算出数据集每一类的p(x|ci)函数,p(ci|x)自然也就得到了。
预测新点很简单,只需要计算对每个类的p(ci|x),最大的就是其归类。

实现

关于测试数据

使用sklearn的鸢尾花数据集
https://www.cnblogs.com/meelo/p/4272036.html
鸢尾花数据集背景:鸢尾花数据集是原则20世纪30年代的经典数据集。它是用统计进行分类的鼻祖。样本数目150,特征数目4,分别是花萼长度(cm)、花萼宽度(cm)、花瓣长度(cm)、花瓣宽度(cm)。类数为3,是花的名字,每类正好50样本。对前三维可视化如下,可见还是很好分的
在这里插入图片描述

code

代码如下,采用120训练集,30测试集

import numpy as np
from sklearn import datasets
iris = datasets.load_iris()
from sklearn.naive_bayes import GaussianNB
data=iris.data.copy()
target=iris.target.copy().reshape(-1,1)
np.random.seed(1)#!!!seed值的有效次数仅为一次
np.random.shuffle(data) 
np.random.seed(1)
np.random.shuffle(target)

train_x=data[0:120]#120*4
test_x=data[120:150]#30*4
train_tar=target[0:120].reshape(-1,1)#(120, 1)
test_tar=target[120:150].reshape(-1,1)#(30 ,1)
print(train_x[0])

class Native_Bayes:
    def __init__(self):
    	#这几个变量由fit函数写,predict函数取用
        self.P_x_c_fun=None
        self.c_num=None
        self.P_c=None
    def fit(self,train_x,train_tar):
        #计算P(c)
        n=len(train_x)
        c_num=len(np.unique(train_tar))#分类数
        self.c_num=c_num
        P_c=[sum(train_tar==i)/n for i in range(c_num)]
        P_c=np.array(P_c).reshape(1,-1)#1*c_num
        self.P_c=P_c
        
        #计算P(x|c)
        P_x_c_fun=[]
        #计算分布参数,给出概率计算函数
        for i in range(c_num):
            data=train_x[(train_tar==i).flatten()]
            mu=data.mean(axis=0)#(nfeature,)
            sigma=np.cov(data.T)#(nfeature,nfeature)
            sigma_det=(np.linalg.det(sigma))
            sigma_inv=(np.linalg.inv(sigma))
            temp=(1/(((2*np.pi)**(c_num/2))*(sigma_det**0.5)))
            #小心闭包错误
            def g(mu,sigma,sigma_det,sigma_inv,temp):
                def fun(x):
                    nonlocal temp,mu,sigma_inv
                    x=x.reshape(1,-1)
                    res=float(temp*(np.exp(-0.5*(x-mu).dot(sigma_inv).dot((x-mu).T))))
                    return res
                return fun
            P_x_c_fun.append(g(mu,sigma,sigma_det,sigma_inv,temp))
        self.P_x_c_fun=P_x_c_fun
        
        P_x_c=np.empty((n,c_num))
        for i in range(n):
            for j in range(c_num):
                P_x_c[i,j]=P_x_c_fun[j](train_x[i])
                
        #计算p(c|x)
        PP=P_x_c*P_c
        PP=PP/PP.sum(axis=1,keepdims=True)#注意keepdims,不然无法自动扩展
        c_head=np.argmax(PP,axis=1)
        return c_head
    def predict(self,test_x):
        n=len(test_x)
        P_x_c_fun=self.P_x_c_fun
        P_x_c=np.empty((n,self.c_num))
        for i in range(n):
            for j in range(self.c_num):
                P_x_c[i,j]=P_x_c_fun[j](test_x[i])
        PP=P_x_c*self.P_c
        PP=PP/PP.sum(axis=1,keepdims=True)
        c_head=np.argmax(PP,axis=1)
        return c_head
model=Native_Bayes()
res=model.fit(train_x,train_tar)
print('训练集正确率:{}/120'.format(np.sum(res==train_tar.flatten())))
res=model.predict(test_x)
print('测试集正确率:{}/30'.format(np.sum(res==test_tar.flatten())))
#对比工业实现
gnb = GaussianNB()
res=gnb.fit(train_x, train_tar.flatten()).predict(test_x)
np.sum(res==test_tar.flatten())

结果:
训练集正确率:118/120
测试集正确率:28/30

总结

踩坑:
np.random.seed(1)#!!!seed值的有效次数仅为一次
np.cov输入(nfeaturen)->(nfeaturenfeature)的cov矩阵
其他:
通常这种简单生成模型的效果不会好于逻辑回归之类的方法,但当数据集数量很少时,优势就较为明显,故在数据集比较小时可以考虑。同时可以看到生成模型的空间占用和计算速度都很不错。

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值