贝叶斯
概念
贝叶斯定理:在B出现的前提下,A出现的概率等于A和B同时出现的概率除以B出现的概率。公式如下:
影响A的因素往往不止一个,即。假设每个条件b互相独立,就是朴素贝叶斯
原理
贝叶斯用于分类,将A类比于类别C,B类比于特征F,则有:
在上式中,P(C) 可以根据概率得出,,不确定的为
由于 互相独立,根据链式法则得:
因为分类往往也不止一个,, 设,则:
根据上述公式,假设对于样本s,有n个特征值,k个分类结果。提取样本的n个特征值代入上式进行k次运算,
得到的预测值,选择概率最大的那个即为分类结果。
所以我们现在的问题就变成了求的问题。这是一个条件概率的参数估计问题。我们假设:
符合某种分布,如高斯分布,那么
,若是高斯分布,则
我们的样本集合中的每个样本都符合上两条。
我们的目的就是要最大。为了方便计算,对两边取对数得:
然后使用极大似然估计求解
以正态分布为例:
然后对u和σ^2分别取偏导,并令偏导为0,得:
使用iris数据集,来实现一下
实现
Package
import numpy as np
from utils import calc_accuracy_class
from utils import fl_score
from sklearn import datasets
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import GaussianNB
import pandas as pd
加载数据
X,y = datasets.load_iris(return_X_y=True)
#将数据分为训练集和测试集
train_X,test_X,train_y,test_y = train_test_split(X,y,test_size = 0.20,random_state = 1)
print(f"train_X的大小为:{train_X.shape}")
print(f"tain_y的大小为:{train_y.shape}")
print(f"test_X的大小为:{test_X.shape}")
print(f"test_y的大小为:{test_y.shape}")
train_X的大小为:(120, 4)
tain_y的大小为:(120,)
test_X的大小为:(30, 4)
test_y的大小为:(30,)
先使用sklearn看效果
skmodel = GaussianNB()
skmodel.fit(train_X,train_y)
#预测
print("==== 训练集 ====== ")
pred_y = skmodel.predict(train_X)
fl_score(pred_y,train_y)
print("===== 测试集 ===== ")
pred_y = skmodel.predict(test_X)
fl_score(pred_y,test_y)
==== 训练集 ======
0 类的fl_score 为:1.0
1 类的fl_score 为:0.918918918918919
2 类的fl_score 为:0.9318181818181818
===== 测试集 =====
0 类的fl_score 为:1.0
1 类的fl_score 为:0.9600000000000001
2 类的fl_score 为:0.923076923076923
模型
def init_params(n_x,n_c):
'''
Function:
初始化theta
Arguments:
n_x -- 特征个数
n_c -- 分类个数
'''
theta = np.random.randn(n_c,n_x)
return theta
由贝叶斯的似然函数可知道,假设k个类C,特征值X有n个,则theta矩阵为 kn或nk
因为为高斯分布,所以每一个theta有两个参数值
def model(train_X,train_y):
'''
train_X -- shape is:(m,n)
train_y -- shape is (m,)
'''
m,n_x = train_X.shape
classes = set(train_y)
n_c = len(classes)
#初始化参数
pc_map={}
theta_map = {}
for c in classes:
#计算每个类的概率P(C)
m_c = np.sum(train_y == c)
pc = m_c/m
pc_map[c] = pc
#取子集
sub_rows = np.where(train_y == c)
sub_X = train_X[sub_rows]
#求每个特征在c分类上的平均值
mean = np.sum(sub_X,axis=0)/m_c #shape is (1,n_x)
mean = mean.reshape(1,-1)
# 求每个特征在c分类上的sigma^2
sigma = np.sum(np.square(sub_X - mean), axis=0)/m_c # shape is (1,n_x)
sigma = sigma.reshape(1,-1)
theta_map[c] = (mean,sigma)
return pc_map,theta_map
预测
1/Z 为常数,可以不参与计算。因为对数的单调性与原函数单调性是一致的,所以这里计算对数概率,将连乘变成累加,方便计算。
所以,
def cacl_simplelog_prob(X,pc,theta):
'''
Function:
计算某一个C类在特征值上的简化对数概率
Arguments:
X-- shape is (m,n_x)
pc -- 常量,C类的概率
theta -- C类的概率分布参数
Return:
X 在C类上的简化对数概率
'''
mean,sigma = theta
sqrt_sigma = np.sqrt(sigma)
part1 = np.log(np.sum(1/(np.sqrt(2*np.pi)*sqrt_sigma),axis=1))
part2 = -np.sum(np.square(X-mean)/(2*sigma),axis=1)
return pc *(part1+part2) #shape is (m,1)
def predict(X,pc_map,theta_map):
classes = pc_map.keys()
m,n_x = X.shape
results = np.zeros((m,1))
prob_pd = pd.DataFrame(results,columns=["result"])
for c in classes:
pc = pc_map[c]
theta = theta_map[c]
prob = cacl_simplelog_prob(X,pc,theta)
prob_pd[c] = prob
max_index = np.argmax(np.array(prob_pd.drop(columns="result")),axis=1)
pred_result = np.array(prob_pd.drop(columns="result").columns)[max_index]
prob_pd["result"] = pred_result.T
return pred_result
pc_map,theta_map = model(train_X,train_y)
print("===训练集验证====")
pred_y = predict(train_X,pc_map,theta_map)
fl_score(pred_y,train_y)
===训练集验证====
0 类的fl_score 为:1.0
1 类的fl_score 为:0.918918918918919
2 类的fl_score 为:0.9318181818181818
print("===测试集测试 ====")
pred_y = predict(test_X,pc_map,theta_map)
fl_score(pred_y,test_y)
0 类的fl_score 为:1.0
1 类的fl_score 为:0.9600000000000001
2 类的fl_score 为:0.923076923076923
网友评论