拉普拉斯修正的朴素贝叶斯分类器及AODE分类器

下面的一些原理来着周志华老师的西瓜书。

***************************************************************************************************************

拉普拉斯修正的朴素贝叶斯分类器主要目的是为了避免遇到某些特征属性为空时,使得相关后验概率为0的情况。其相关计算公式如下:


其中Dc表示训练集中第c类样本的集合,P(c)表示c类的先验概率,N表示标签的类别数;Dcxi表示第i个属性上位属性xi的集合,Ni表示第i个属性的类别数。

判别函数如下(公式1):

AODE是一种基于集成学习机制、更为强大的独依赖分类器,为半朴素贝叶斯分类器。其相关的计算公式如下:



通过以上的两个关键函数12,判断各个关键概率的大小来判断类别。当连乘过小的时候,可采用开方或者取对数的方式。

使用的数据如下:
编号	色泽	根蒂	敲声	纹理	脐部	触感	密度	含糖量	好瓜
1	青绿	蜷缩	浊响	清晰	凹陷	硬滑	0.697	0.46	是
2	乌黑	蜷缩	沉闷	清晰	凹陷	硬滑	0.774	0.376	是
3	乌黑	蜷缩	浊响	清晰	凹陷	硬滑	0.634	0.264	是
4	青绿	蜷缩	沉闷	清晰	凹陷	硬滑	0.608	0.318	是
5	浅白	蜷缩	浊响	清晰	凹陷	硬滑	0.556	0.215	是
6	青绿	稍蜷	浊响	清晰	稍凹	软粘	0.403	0.237	是
7	乌黑	稍蜷	浊响	稍糊	稍凹	软粘	0.481	0.149	是
8	乌黑	稍蜷	浊响	清晰	稍凹	硬滑	0.437	0.211	是
9	乌黑	稍蜷	沉闷	稍糊	稍凹	硬滑	0.666	0.091	否
10	青绿	硬挺	清脆	清晰	平坦	软粘	0.243	0.267	否
11	浅白	硬挺	清脆	模糊	平坦	硬滑	0.245	0.057	否
12	浅白	蜷缩	浊响	模糊	平坦	软粘	0.343	0.099	否
13	青绿	稍蜷	浊响	稍糊	凹陷	硬滑	0.639	0.161	否
14	浅白	稍蜷	沉闷	稍糊	凹陷	硬滑	0.657	0.198	否
15	乌黑	稍蜷	浊响	清晰	稍凹	软粘	0.36	0.37	否
16	浅白	蜷缩	浊响	模糊	平坦	硬滑	0.593	0.042	否
17	青绿	蜷缩	沉闷	稍糊	稍凹	硬滑	0.719	0.103	否



# -*- coding: utf-8 -*-
"""
Created on Wed Jan  4 21:05:48 2017

@author: ZQ
"""

import numpy as np
from math import pi as PI


def loadData(filename):
    file = open(filename)
    lines = file.readlines()
    data = []
    for line in lines[1:]:
        d = line.strip().split('\t')
        d = d[1:]
        data.append(d)
    return np.array(data)

#所有计算采用拉普拉斯修正,朴素贝叶斯分类   
#计算先验概率
def calcpro(data):
    data_count = len(data)
    s_l = set(data[:,-1])
    N = len(s_l)
    yes_count = 0
    for vec in data:
        if vec[-1] == '是':
            yes_count += 1
    return (yes_count+1)/(data_count+N)

#用于计算标签的条件概率
def calcLabelpro(data,i,value):
    data_yes_len = 0
    fec_yes = 0
    fec_no = 0
    s_f = set(data[:,i])
    Ni = len(s_f)
    for vec in data:
        if vec[-1] == '是':
            data_yes_len += 1
        if vec[i] == value:            
            if vec[-1] == '是':
                fec_yes += 1
            else:
                fec_no += 1
    #print(fec_yes,fec_no,data_yes_len)
    return (fec_yes+1)/(data_yes_len+Ni),(fec_no+1)/(len(data)-data_yes_len+Ni)

#高斯概率密度
def gass(x,u,d):
    pro = (2*PI)**0.5*d**0.5
    pro = 1/pro
    pro = pro*np.exp(-(x-u)**2/(2*d))
    return pro
#用于计算连续数值的概率密度
def calcNumpro(data,i,value):
    data_yes = []
    data_no = []
    for vec in data:
        if vec[-1] == '是':
            data_yes.append(vec[i])
        else:
            data_no.append(vec[i])
            
    num_yes = list(map(float,data_yes))
    num_no = list(map(float,data_no))
    num_yes = np.array(num_yes)
    num_no = np.array(num_no)
    #print(num_yes.mean(),num_yes.var()**0.5)
    #计算均值与方差
    mean_yes = num_yes.mean()
    var_yes = num_yes.var()
    mean_no = num_no.mean()
    var_no = num_no.var()
    
    pro_yes = gass(value,mean_yes,var_yes)
    pro_no = gass(value,mean_no,var_no)
    
    return pro_yes,pro_no

def Bayes(train_data,test_data):
    #获得先验概率
    pro_yes = calcpro(train_data)
    pro_no = 1 - pro_yes
    for i in range(len(test_data)-1):
        if i < 6:
           py,pn = calcLabelpro(data,i,test_data[i])
           pro_yes = pro_yes*py
           pro_no = pro_no*pn
        else:
            py,pn = calcNumpro(data,i,float(test_data[i]))
            pro_yes = pro_yes*py
            pro_no = pro_no*pn
    if pro_yes > pro_no:
        print('是')
    else:
        print('否')
    print(test_data[-1])
    
#AODE分类器,未实现连续属性(使用每个属性作为超父来构建SPODE)
#首先计算P(C,Xi)
def calcP_C_Xi(data,i,value):
    D = len(data)
    label_set = set(data[:,-1])
    N = len(label_set)
    i_set = set(data[:,i])
    Ni = len(i_set)
    Xi_yes_count = 0
    Xi_no_count = 0
    for vec in data:
        if vec[i] == value:
            if vec[-1] == '是':
                Xi_yes_count += 1
            else:
                Xi_no_count += 1
    P_y = (Xi_yes_count+1)/(D + N*Ni)
    P_n = (Xi_no_count+1)/(D + N*Ni)
    return P_y,P_n
#其次计算P(Xj|C,Xi)
def calcP_Xj_C_Xi(data,j,i,value_j,value):
    j_set = set(data[:,j])
    Nj = len(j_set)
    Xi_y_count = 0
    Xi_n_count = 0
    Xij_y_count = 0
    Xij_n_count = 0
    for vec in data:
        if vec[i] == value:
            if vec[-1] == '是':
                Xi_y_count += 1
            else:
                Xi_n_count += 1
            if vec[j] == value_j:
                if vec[-1] == '是':
                    Xij_y_count += 1
                else:
                    Xij_n_count += 1
    p_y = (Xij_y_count + 1)/(Xi_y_count + Nj)
    p_n = (Xij_n_count + 1)/(Xi_n_count + Nj)
    return p_y,p_n
def AODE(train_data,test_data):
    p_y_list = []
    p_n_list = []
    p_y = 1
    p_n = 1
    for i in range(6):
        P_c_Xi_y,P_c_Xi_n = calcP_C_Xi(data,i,test_data[i])
        for j in range(6):            
            P_c_Xji_y,P_c_Xji_n = calcP_Xj_C_Xi(data,j,i,test_data[j],test_data[i])
            p_y = p_y * P_c_Xji_y
            p_n = p_n * P_c_Xji_n
        p_y_list.append(p_y*P_c_Xi_y)
        p_n_list.append(p_n*P_c_Xi_n)
    if sum(p_y_list) > sum(p_n_list):
        print('是')
    else:
        print('否')
    print(test_data[-1])

if __name__ == '__main__':
    data = loadData('watermelon3.0.txt')
    test_data = data[3,:]
    Bayes(data,test_data)
    AODE(data,test_data)



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值