下面的一些原理来着周志华老师的西瓜书。
***************************************************************************************************************
拉普拉斯修正的朴素贝叶斯分类器主要目的是为了避免遇到某些特征属性为空时,使得相关后验概率为0的情况。其相关计算公式如下:
其中Dc表示训练集中第c类样本的集合,P(c)表示c类的先验概率,N表示标签的类别数;Dc,xi表示第i个属性上位属性xi的集合,Ni表示第i个属性的类别数。
判别函数如下(公式1):
AODE是一种基于集成学习机制、更为强大的独依赖分类器,为半朴素贝叶斯分类器。其相关的计算公式如下:
通过以上的两个关键函数1和2,判断各个关键概率的大小来判断类别。当连乘过小的时候,可采用开方或者取对数的方式。
使用的数据如下:
编号 色泽 根蒂 敲声 纹理 脐部 触感 密度 含糖量 好瓜
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)