朴素贝叶斯法及python实现

文章目录

  • 朴素贝叶斯法概述
    • 1. 定理及公式推导
        • 1.1 定理:
        • 1.2 朴素贝叶斯
        • 1.3 条件独立的假设是:
        • 1.4 先验概率后验概率
        • 1.5 极大似然估计
    • 2. python实现

朴素贝叶斯法概述

朴素贝叶斯(naive Bayes)法是基于贝叶斯定理与特征条件独立假设的分类方法。

1. 定理及公式推导

1.1 定理:

设试验E的样本空间为 Ω \Omega Ω,A为事件 B 1 , B 2 , . . . , B i B_{1},B_{2},...,B_{i} B1,B2,...,Bi.为 Ω \Omega Ω的一个划分,且 P ( A ) , P ( B i ) > 0 P(A),P(B_{i})>0 P(A),P(Bi)>0,则
P ( B i ∣ A ) = P ( A ∣ B i ) P ( B i ) ∑ j = 1 n P ( A ∣ B j ) P ( B j ) ⋯ i = 1 , 2 , … , n P\left(B_{\mathrm{i}} \mid A\right)=\frac{P\left(A \mid B_{i}\right) P\left(B_{i}\right)}{\sum_{j=1}^{n} P\left(A \mid B_{j}\right) P\left(B_{j}\right)} \cdots i=1,2, \ldots, n P(BiA)=j=1nP(ABj)P(Bj)P(ABi)P(Bi)i=1,2,,n

1.2 朴素贝叶斯

其朴素的含义是:对条件概率分布作了条件独立的假设,用于分类的特征,在类确定的情况下都会条件独立的。

1.3 条件独立的假设是:

P ( X = x ∣ Y = c k ) = P ( X ( 1 ) = x ( 1 ) , … , X ( n ) = x ( n ) ∣ Y = c k ) = ∏ j = 1 n P ( X ( j ) = x ( j ) ∣ Y = c k ) P\left(X=x \mid Y=c_{k}\right)=P\left(X^{(1)}=x^{(1)}, \ldots, X^{(n)}=x^{(n)} \mid Y=c_{k}\right)=\prod_{j=1}^{n} P\left(X^{(j)}=x^{(j)} \mid Y=c_{k}\right) P(X=xY=ck)=P(X(1)=x(1),,X(n)=x(n)Y=ck)=j=1nP(X(j)=x(j)Y=ck)
朴素贝叶斯法分类时,对给定的输入 x x x,通过学习到的模型计算后验概率分布 P ( Y = c k ∣ X = x ) P\left(Y=c_{k} \mid X=x\right) P(Y=ckX=x),将后验概率最大的类作为 x x x的类输出。

1.4 先验概率后验概率

所谓后验概率,即根据结果推原因,以课堂上是否打网球例子来说,在知道某人没有去打网球的情况,推算今天的风是weak的概率。
先验概率,即根据原因推结果,还是以打网球为例,在知道今天的风是strong,推算某人去打网球的概率。
贝叶斯算法,学习意味着估计 P ( Y = c k ) P(Y=c_{k} ) P(Y=ck) P ( X ( j ) = x ( j ) ∣ Y = c k ) P\left(X^{(j)}=x^{(j)} \mid Y=c_{k}\right) P(X(j)=x(j)Y=ck)

1.5 极大似然估计

先验概率的极大似然估计:
P ( Y = c k ) = ∑ i = 1 N I ( y i = c k ) N ⋯ k = 1 , 2 , … , K P\left(Y=c_{k}\right)=\frac{\sum_{i=1}^{N} I\left(y_{i}=c_{k}\right)}{N} \cdots k=1,2, \ldots, K P(Y=ck)=Ni=1NI(yi=ck)k=1,2,,K
条件概率的极大似然估计:
P ( X ( j ) = a j l ∣ Y = c k ) = ∑ i = 1 N I ( x ( j ) = a j l , y i = c k ) ∑ i = 1 N I ( y i = c k ) P\left(X^{(j)}=a_{j l} \mid Y=c_{k}\right)=\frac{\sum_{i=1}^{N} I\left(x^{(j)}=a_{j l}, y_{i}=c_{k}\right)}{\sum_{i=1}^{N} I\left(y_{i}=c_{k}\right)} P(X(j)=ajlY=ck)=i=1NI(yi=ck)i=1NI(x(j)=ajl,yi=ck)
j = 1 , 2 , … , n ; ⋅ l = 1 , 2 , … , S j ⋯   ; k = 1 , 2 , … , K j=1,2, \ldots, n ; \cdot l=1,2, \ldots, S_{j} \cdots ; k=1,2, \ldots, K j=1,2,,n;l=1,2,,Sj;k=1,2,,K
其中 x ( j ) x^{(j)} x(j)是第 j j j个样本的第个特征; a j l a_{jl} ajl是第 j j j个特征可能取的第 l l l个值; I I I为指示函数。
在实际训练中,会出现训练集实例少,分类类别较多,可能会出现类别中没有训练集实例的情况,这时候,用极大似然估计可能会出现所要估计的概率值为0的情况,这时,会影响到后验概率的计算,使分类产生偏差。通常采用贝叶斯估计:
P λ ( X ( j ) = a j l ∣ Y = c k ) = ∑ i = 1 N I ( x ( j ) = a j l , y i = c k ) + λ ∑ i = 1 N I ( y i = c k ) + S j λ ⋅ , 其中  λ ≥ 0 P_{\lambda}\left(X^{(j)}=a_{j l} \mid Y=c_{k}\right)=\frac{\sum_{i=1}^{N} I\left(x^{(j)}=a_{j l}, y_{i}=c_{k}\right)+\lambda}{\sum_{i=1}^{N} I\left(y_{i}=c_{k}\right)+S_{j} \lambda} \cdot \text {, 其中 } \lambda \geq 0 Pλ(X(j)=ajlY=ck)=i=1NI(yi=ck)+Sjλi=1NI(x(j)=ajl,yi=ck)+λ其中 λ0

朴素贝叶斯法高效易于实现,但存在着条件独立这个很强的假设,在实际的样本中往往不成立,实际数据样本特别是样本数量多且样本属性之间关联较强时,朴素贝叶斯法的分类效果不好。

2. python实现

程序代码:环境python3.7

import numpy as np
from collections import Counter
data=[[1,'S',-1],[1,'M',-1],[1,'M',1],[1,'S',1],[1,'S',-1],[2,'S',-1],[2,'M',-1],[2,'M',1],[2,'L',1],[2,'L',1],[3,'L',1],[3,'L',1],[3,'M',1],[3,'M',1],[3,'L',-1]]
data_new=np.array(data)
x=[]
count_x=[]
x_num=[]
x_elem=[]
lam=1
for i in range(len(data_new[0,:])-1):
    x.append(data_new[:,i])
    count_x.append(Counter(x[i]))
    x_num.append(len(count_x[i]))#对应特征可能取值数[3,3]
    x_elem.append(list(count_x[i]))#特征中的元素[['1', '2', '3'], ['S', 'M', 'L']]
y=data_new[:,-1]
count_y=Counter(y) #标签元素及对应的个数 Counter({'1': 9, '-1': 6})
y_num=len(count_y) #y的类别数  2
y_elem=list(count_y)#标签中的元素[-1,1]
p_y=[]
p_x_y=[]
for i in range(y_num):
    p_y.append((count_y[y_elem[i]]+lam)/(len(y)+y_num*lam))
    print('此时先验概率P(Y={})={}'.format(y_elem[i],p_y[i]))
    
for i in range(len(x)):
    p_xi_j=[]
    for j in range(x_num[i]):
        p_xj_y=[]
        for k in range(y_num):
            x_val = np.where(x[i] == x_elem[i][j])[0] #np.where(condiction )输出满足条件的元素坐标
            y_val = np.where(y == y_elem[k])[0]
            intersect_x_y = list(set(y_val).intersection(set(x_val))) #set创建一个无序不重复的元素集 y-val与x_val的交集
            p_temp = (len(intersect_x_y)+lam) /( count_y[y_elem[k]]+x_num[i]*lam) #条件概率
            print('条件概率P(X{}={}|Y={})={}'.format(i+1,x_elem[i][j],y_elem[k],p_temp))
            p_xj_y.append(p_temp)
        p_xi_j.append(p_xj_y)
    p_x_y.append(p_xi_j)
    
data_pred=[2,'S']
def predict(data_pred,p_x_y,p_y,x_elem,y_elem):
    x_num=len(p_x_y)
    x=[]
    x_index=[]
    x_elem=np.array(x_elem)
    for i in range(x_num):
        x.append(str(data_pred[i]))
        x_index.append(np.where(x_elem[i]==x[i])[0])
    p_y_pred=[]
    p_y_max=0
    index=1000
    for i in range(len(p_y)):
        p=p_y[i]
        for j in range(x_num):
            p*=p_x_y[j][x_index[j][0]][i]
            
        p_y_pred.append(p)
        print('y={}的概率为:{}'.format(y_elem[i],p))
        if p>p_y_max:
            p_y_max=p
            index=i
    return index
index=predict(data_pred,p_x_y,p_y,x_elem,y_elem)
print('此时测试集数据所属类别为:',y_elem[index])

运行结果
朴素贝叶斯法及python实现_第1张图片

你可能感兴趣的:(python,机器学习,人工智能)