Python实现朴素贝叶斯分类器

1.朴素贝叶斯概念

在所有的机器学习分类算法中,朴素贝叶斯和其他绝大多数的分类算法都不同。对于大多数的分类算法,比如决策树,KNN,逻辑回归,支持向量机等,他们都是判别方法,也就是直接学习出特征输出Y和特征X之间的关系,要么是决策函数Y=f(X),要么是条件分布P(Y|X)。但是朴素贝叶斯却是生成方法,也就是直接找出特征输出Y和特征X的联合分布P(X,Y),然后用P(Y|X)=P(X,Y)/P(X)得出。
具体算法思想过程如下图:
在这里插入图片描述

2.朴素贝叶斯算法

根据以上公式算法,python实现朴素贝叶斯算法思想过程如下:
我们先计算 P ( Y = c k ) P(Y=c_k) 的概率,再计算每一个特征 P ( x y ) P(x|y) 的概率得到每一列x中的特征出现概率,最终形成y_p及yx_p,针对新数据查询这两个概率矩阵,得到每一种Y=c_k时的概率,概率最大的那个分类就是预测结果,需要注意的是:P(c|x)=P©P(x|c)/P(x),同一组数据,对所有分类来说分母相同,所已只比较分子大小即可。

# -*- coding: utf-8 -*-
"""
 @Time    : 2018/11/09 09:07
 @Author  : hanzi5
 @Email   : **@163.com
 @File    : NaiveBayes.py
 @Software: PyCharm
"""

import numpy as np
import pandas as pd
#import matplotlib.pyplot as plt
from collections import Counter

def get_p_matrix(arr_data):
    # 获得y中分类标签的唯一值
    y_lables = np.unique(arr_data[:,-1]) 
    #y_lables = set(arr_data[:,-1])  # 同上,两种写法均可
    
    y_counts=len(arr_data) # y总数据条数
    y_p={}             # y中每一个分类的概率,字典初始化为空,y分类数是不定的,按字典存储更方便取值
    for y_lable in y_lables:
        y_p[y_lable]=len(arr_data[arr_data[:,-1]==y_lable])/y_counts  # y中每一个分类的概率(其实就是频率)
        
    yx_cnt=[] # 固定y以后的,x中每一种特征出现的次数,此数据量并不大,y分类数*x维度列数,按list存储即可
    for y_lable in y_p.keys():# 先固定y,遍历y中每一个分类
        y_lable_cnt=len(arr_data[arr_data[:,-1]==y_lable]) # 此y分类数据条数
        for x_j in range(0,arr_data.shape[1]-1): # 在固定x特征列,遍历每列x中的特征
            x_j_count=Counter(arr_data[arr_data[:,-1]==y_lable][:,x_j]) # 按列统计每种特征出现的次数,因为某一列的特征数是不固定的,所以按dict类型存储
            yx_cnt.append([y_lable,y_lable_cnt,x_j,dict(x_j_count)])
            
    yx_p=[] # 将统计次数处理为概率
    for i in range(0,len(yx_cnt)):
        #print(yx_cnt[i])
        #print(yx_cnt[i][3])
        p={} # 将每列x特征出现的次数转换为概率
        for key in yx_cnt[i][3].keys():
            p[key]=yx_cnt[i][3][key] / yx_cnt[i][1]
        yx_p.append([yx_cnt[i][0],yx_cnt[i][1],yx_cnt[i][2],p])
    return y_p,yx_p

if __name__ == "__main__":
    df_data=pd.read_csv('D:/python_data/naivebayes_data.csv')
    arr_data=np.array(df_data.values) # 数据处理为numpy.array类型,其实pandas.Dataframe类型更方便计算
    
    #调用函数,计算概率矩阵
    y_p,yx_p=get_p_matrix(arr_data)
    # 查看概率矩阵
    print('y_p:\n',y_p)
    print('yx_p:\n',yx_p)
    
    # 测试数据一条,x1,x2
    features = [2,'S']
    
    # 朴素贝叶斯分类器,数据[2,'S']手动计算过程
    # P(c|x)=P(c)P(x|c)/P(x),同一组数据,对所有分类来说分母相同,所已只比较分子大小即可
    # c=1, 0.6*0.3333*0.1111=0.022217778
    # c=-1,0.4*0.3333*0.5=0.06666
    # 比较c=1及c=-1时概率大小,数据[2,'S']数据c=-1类
    yx_p_arr=np.array(yx_p)
    
    # 编程计算每个分类的概率值
    res={}
    for key in y_p.keys():
        res[key]=1*y_p[key]
        for i in range(0,len(features)):
            res[key]=res[key]*yx_p_arr[(yx_p_arr[:,0]==key)&(yx_p_arr[:,2]==i)][:,3][0][features[i]]
            
    print('测试数据:',features,',预测结果为:',max(res,key=res.get))    

数据来源自《统计学习方法》李航,表4.1,复制以下数据另存为naivebayes_data.csv文件即可。

x1,x2,Y
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,M,1
3,M,1
3,L,1
3,L,-1

参考资料:
1、Machine-Learning-With-Python
2、《机器学习实战》Peter Harrington著
3、《机器学习》西瓜书,周志华著
4、 斯坦福大学公开课 :机器学习课程
5、机器学习视频,邹博
6、[吴恩达_UFLDL中文教程]
7、朴素贝叶斯算法–python实现

猜你喜欢

转载自blog.csdn.net/weixin_43383558/article/details/83933583