贝叶斯公式
由条件概率公式:
P
(
Y
∣
X
)
=
P
(
X
∣
Y
)
P
(
Y
)
P
(
X
)
P(Y|X) = \frac{P(X|Y)P(Y)}{P(X)}
P(Y∣X)=P(X)P(X∣Y)P(Y)
其中,
P
(
Y
)
P(Y)
P(Y)是Y的先验概率,
P
(
X
∣
Y
)
P(X|Y)
P(X∣Y)是样本
X
X
X对类标记为
Y
Y
Y的条件概率,也称为似然。
P
(
X
)
P(X)
P(X)是用于归一化的证据因子。
用于一般分类模型,可表示为:
P
(
类别
∣
特征
)
=
P
(
特征
∣
类别
)
P
(
类别
)
P
(
特征
)
P(类别|特征) = \frac{P(特征|类别)P(类别)}{P(特征)}
P(类别∣特征)=P(特征)P(特征∣类别)P(类别)
举例
以鸢尾花数据为例
有一鸢尾花的特征数据为[4.8, 3.0, 1.4, 0.1],试判断其所属类别(0,1,2)。
要判断鸢尾花的所属类别,可通过计算其在该特征的条件下属于各个类别的可能性,在哪个类别的可能性最大,就把鸢尾花类别判断为该类别。
由贝叶斯公式,我们可知,当对于某一确定特征的鸢尾花,要比较
P
(
类别
∣
特征
)
P(类别|特征)
P(类别∣特征),只需要比较
P
(
特征
∣
类别
)
P
(
类别
)
P(特征|类别)P(类别)
P(特征∣类别)P(类别)。
P
(
类别
)
P(类别)
P(类别)可通过计算样本中个类别出现的频率来估计概率。对
P
(
特征
∣
类别
)
P(特征|类别)
P(特征∣类别),这里,我们由4个特征变量,表示为
P
(
A
,
B
,
C
,
D
∣
类别
)
P(A,B,C,D|类别)
P(A,B,C,D∣类别),若假设变量A,B,C,D相互独立,则
P
(
A
,
B
,
C
,
D
∣
类别
)
=
P
(
A
∣
类别
)
P
(
B
∣
类别
)
P
(
C
∣
类别
)
P
(
D
∣
类别
)
P(A,B,C,D|类别)=P(A|类别)P(B|类别)P(C|类别)P(D|类别)
P(A,B,C,D∣类别)=P(A∣类别)P(B∣类别)P(C∣类别)P(D∣类别)
对于单个特征,由于我们样本特征为连续数值,这里需要考虑使用概率分布来估计条件概率。
P
(
X
∣
Y
)
=
1
2
π
σ
2
e
−
(
x
−
u
)
2
2
σ
2
P(X|Y)=\frac{1}{\sqrt{2\pi\sigma^2}}e^{-\frac{(x-u)^2}{2\sigma^2}}
P(X∣Y)=2πσ21e−2σ2(x−u)2
比如,对第一个特征为4.8,类别为0的样本,我们需要根据样本计算其平均值、方差,这样我们就可以得到
P
(
X
1
=
4.8
∣
类别
=
0
)
P(X_1=4.8|类别=0)
P(X1=4.8∣类别=0)。
算法总结
- 计算每种特征的平均值、方差,按照假设的正态分布,估计 P ( 特征 ∣ 类别 ) P(特征|类别) P(特征∣类别)
- 计算训练样本的每个类别的频率,估计 P ( 类别 ) P(类别) P(类别)
- 把1和2得到的数据带入,计算每一种可能类别的概率,取出现可能性最大的类别。
算法实现
- 加载数据
from sklearn.datasets import load_iris
import pandas as pa
import numpy as np
from sklearn.model_selection import train_test_split
iris = load_iris()
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target,test_size=0.2)
X = np.array(x_train)
y = np.array(y_train)
#合并训练样本X,y
df = np.column_stack((X,y))
- 计算每个类别下,不同特征的样本的均值,方差
#计算样本的均值和方差
def cal_guass(df):
#mean_x = np.mean(x_train, axis=0)
#std_x = np.sum((x_train - mean_x)**2, axis=0)/x_train.shape[0]
mean_x=[]
std_x=[]
for i in range(3):
mean_x.append(np.mean(df[df[:,4]==i], axis=0))
std_x.append( np.sum((df[df[:,4]==i] - np.mean(df[df[:,4]==i], axis=0))**2, axis=0)/df[df[:,4]==i].shape[0])
m1 = np.vstack(mean_x)
s1 = np.vstack(std_x)
return m1,s1
m1每行表示在类别0,1,2下的不同特征的均值
s1表示在类别0,1,2下的不同特征的样本的方差
- 带入概率密度函数
#表示正态分布的概率密度函数
def norm_pdf(m1,s1,x_test):
m1 = m1[:,:4]
s1 = s1[:,:4]
x_new0 = []#类别0下的不同特征的概率
x_new1=[]#类别1下
x_new2=[]#类别2下
for i in range(4):
x_new0.append((1/math.sqrt(2*math.pi*s1[0,i])) * np.exp(-(x_test[:,i] - m1[0,i])**2 / (2*s1[0,i])))
x_new1.append((1/math.sqrt(2*math.pi*s1[1,i])) * np.exp(-(x_test[:,i] - m1[1,i])**2 / (2*s1[1,i])))
x_new2.append((1/math.sqrt(2*math.pi*s1[2,i])) * np.exp(-(x_test[:,i] - m1[2,i])**2 / (2*s1[2,i])))
x_new0 = np.vstack(x_new0)
x_new1 = np.vstack(x_new1)
x_new2 = np.vstack(x_new2)
return x_new0, x_new1, x_new2
- 对测试集的样本计算 P ( 特征 ∣ 类别 ) P(特征∣类别) P(特征∣类别)
#计算P(特征|类别)
#对测试集计算P(特征|类别)
def cal_tz_lb(x_test, x_new0, x_new1, x_new2):
x_new0 = x_new0.reshape(len(x_new0)//4,4)
x_new1 = x_new0.reshape(len(x_new1)//4,4)
x_new2 = x_new0.reshape(len(x_new2)//4,4)
p_condition = []
for i in range(3):
p_condition.append(np.prod(eval(f'x_new{i}'), axis=0))#对应特征的概率相乘
p_combined = np.vstack(p_condition)
return p_combined
- 计算 P ( 类别 ) P(类别) P(类别)
# 计算个类别概率
lb_cout = len(y_train)
cout_0 = sum(df[:,4]==0)
cout_1 = sum(df[:,4]==1)
cout_2 = sum(df[:,4]==2)
p_0 = cout_0/lb_cout
p_1 = cout_1/lb_cout
p_2 = cout_2/lb_cout
- 计算每一种可能类别的概率,并进行比较
p_0_tz = p_combined[0] * p_0
p_1_tz = p_combined[1] * p_1
p_2_tz = p_combined[2] * p_2
result =[]
for i in range(len(p_0_tz)):
arr = [p_0_tz[i],p_1_tz[i],p_2_tz[i]]
max_index = arr.index(max(arr))
result.append(max_index)
- 计算正确率
result = np.array(result)
correct = sum(result == y_test)/len(y_test)
拓展
对于公式 P ( A , B , C , D ∣ 类别 ) = P ( A ∣ 类别 ) P ( B ∣ 类别 ) P ( C ∣ 类别 ) P ( D ∣ 类别 ) P(A,B,C,D|类别)=P(A|类别)P(B|类别)P(C|类别)P(D|类别) P(A,B,C,D∣类别)=P(A∣类别)P(B∣类别)P(C∣类别)P(D∣类别), 我们是在假设特征 A , B , C , D A,B,C,D A,B,C,D相互独立的情况下才成立。 事实上,在大多数数据里面某些特征可能不再独立,这时我们就可能需要考虑不同特征之间的联系,这里可以使用贝叶斯网络。