机器学习之贝叶斯

贝叶斯

概念

贝叶斯定理:在B出现的前提下,A出现的概率等于A和B同时出现的概率除以B出现的概率。公式如下:
P(A|B) = \frac{P(A)P(B|A)}{P(B) }

影响A的因素往往不止一个,即B(b_1,b_2,b_3...)。假设每个条件b互相独立,就是朴素贝叶斯

原理

贝叶斯用于分类,将A类比于类别C,B类比于特征F,则有:
P(C|F_1,F_2,...F_n) = \frac{P(C)P(F_1,F_2..F_n|C)}{P(F_1,F_2..F_n)}

在上式中,P(C) 可以根据概率得出,P(F_1,F_2,...F_n)是一个定值,不确定的为P(F_1,F_2...F_n|C)
由于b_1,b_2...b_n 互相独立,根据链式法则得:
P(F_1,F_2...F_n|C) = P(F_1|C)P(F_2|C)...P(F_n|C) = \prod_{i=1}^{n}{} P(F_i|C)
因为分类往往也不止一个,C = (C_1,C_2....C_k), 设P(F_1,F_2,...F_n)=Z,则:
P(C_j|F_1,F_2...F_n) = \frac{1}{Z}P(C)\prod_{i=1}^{n}{}P(F_i|C_j)

根据上述公式,假设对于样本s,有n个特征值,k个分类结果。提取样本的n个特征值F_1,F_2...F_n代入上式进行k次运算,
得到C_1,C_2...C_k的预测值,选择概率最大的那个即为分类结果。

所以我们现在的问题就变成了求P(F_i|C)的问题。这是一个条件概率的参数估计问题。我们假设:
P(F_i|C)符合某种分布,如高斯分布,那么P(F_i|C) =\frac{1}{\sqrt{2π}σ}e^{-\frac{(F_i-u)^2}{2σ^2}} (m_c为C类的样本数)
P(F_i|C)被参数θ_{c,i} 唯一指定,若是高斯分布,则θ_{c,i} = (u_{c,i},σ_{c,i}^2)
我们的样本集合中的每个样本都符合上两条。

设C类集合为D_c,样本个数为m_c,x_i 表示第i个特征值,x^{(j)}表示第j个样本。
则参数θ,的似然函数L(θ_{c,i}) ,表示为m_c个样本(X_1,X_2 ....X_{m_c}在第i个特征上的联合概率分布:
L(θ_{c,i}) = \prod_{i=1}^{m_c}P(x_i|C)

我们的目的就是要L(θ_{c,i})最大。为了方便计算,对两边取对数得:
LL(L(θ_{c,i}) = \sum_{i=1}^{m_c}log(P(x_i|C))

然后使用极大似然估计求解θ_{c,i}

以正态分布为例:
LL(θ_{c,i}) = \sum_{i=1}^{m_c}log(P(x_i|C))=\sum_{j=1}^{m_c}log(\frac{1}{\sqrt{2π}σ}e^{-\frac{(x_i^{(j)}-u)^2}{2σ^2}})
=LL(u_{c,i},σ_{c,i}^2) = -\frac{m_c}{2}log(2π)-\frac{m_c}{2}log(σ_{c,i}^2)-\frac{1}{2σ_{c,i}^2}\sum_{i=1}^{m_c}{}(x_i-u_{c,i})^2

然后对u和σ^2分别取偏导,并令偏导为0,得:
u_{c,i} = \frac{1}{m_c}\sum_{j=1}^{m_c}{} x_i^{(j)} = \overline{x_i}
σ_{c,i}^2 = \frac{1}{m_c}\sum_{i=1}^{n}{}(x_i^{(j)}-\overline{x_i})^2

使用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有两个参数值 μ和σ^2

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 为常数,可以不参与计算。因为对数的单调性与原函数单调性是一致的,所以这里计算对数概率,将连乘变成累加,方便计算。
所以,log(P(C|x_1,x_2..x_n)) = log(P(C))\sum_{i=1}^{n}{}log(P(x_i|C))

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

你可能感兴趣的:(机器学习之贝叶斯)