一、朴素贝叶斯(naive Bayes)法是基于贝叶斯定理与特征条件独立假设的分类方法。对于给定的训练数据集,首先基于特征条件独立假设学习输入输出的联合概率分布;然后基于此模型,对给定的输入x,利用贝叶斯定理求出后验概率最大的输出y。朴素贝叶斯法实现简单,学习与预测的效率都很高,是一种常用的方法。
那么在掌握朴素贝叶斯算法之前,我们必须了解条件概率和全概率。
1.1、条件概率公式如下:
1.2、全概率公式如下:
指若事件{A1,A2,…,An}构成一个完备事件组且都有正概率,则对任意一个事件B都有:
则有
二、贝叶斯定理:
一种有效计算条件概率的方法称为 贝叶斯定理 。贝叶斯定理告诉我们如何 交换条件概率中的条件与结果 ,即如果已知 P(X|Y)
,要求 P(Y|X)
:
这里的每个概率都有其特定的名称:
P ( Y ) :先验概率。先验概率(prior probability)是指事情还没有发生,求这件事情发生的可能性的大小,是先验概率。它往往作为"由因求果"问题中的"因"出现。
P ( Y ∣ X ) :后验概率。后验概率是指事情已经发生,求这件事情发生的原因是由某个因素引起的可能性的大小。后验概率的计算要以先验概率为基础
P ( X ∣ Y ) :条件概率,又叫似然概率,一般是通过历史数据统计得到。一般不把它叫做先验概率,但从定义上也符合先验定义。
三、贝叶斯推论:
结合条件概率可推导出如下公式:
即为贝叶斯公式。把P(Ai)称为先验概率(Prior probability),即在B事件发生之前,我们对A事件概率的一个判断。
P(Ai|B)称为后验概率(Posterior probability),即在B事件发生之后,我们对A事件概率的重新评估。
P(B|Ai)/P(B)称为可能性函数(Likelyhood),这是一个调整因子,使得预估概率更接近真实概率。
所以条件概率可以理解为:后验概率 = 先验概率 × 调整因子
如果"可能性函数">1,意味着先验概率被增强,事件A的发生的可能性变大;
如果"可能性函数"=1,意味着B事件无助于判断事件A的可能性;
如果"可能性函数"<1,意味着"先验概率"被削弱,事件A的可能性变小。
四、朴素贝叶斯法是典型的生成学习方法。生成方法由训练数据学习联合概率分布P(X,Y),然后求得后验概率分布P(Y|X)。具体来说,利用训练数据学习P(X|Y)和P(Y)的估计,得到联合概率分布:
P(X,Y)=P(Y)P(X|Y)
概率估计方法可以是极大似然估计或贝叶斯估计。
五、朴素贝叶斯法的基本假设是条件独立性,
这是一个较强的假设。由于这一假设,模型包含的条件概率的数量大为减少,朴素贝叶斯法的学习与预测大为简化。因而朴素贝叶斯法高效,且易于实现。其缺点是分类的性能不一定很高。
六、朴素贝叶斯算法如下:
视频截图:
程序如下:
import numpy as np def createDataSet(): dataSet = [[0, 0, 0, 0, 'no'], #数据集 [0, 0, 0, 1, 'no'], [0, 1, 0, 1, 'yes'], [0, 1, 1, 0, 'yes'], [0, 0, 0, 0, 'no'], [1, 0, 0, 0, 'no'], [1, 0, 0, 1, 'no'], [1, 1, 1, 1, 'yes'], [1, 0, 1, 2, 'yes'], [1, 0, 1, 2, 'yes'], [2, 0, 1, 2, 'yes'], [2, 0, 1, 1, 'yes'], [2, 1, 0, 1, 'yes'], [2, 1, 0, 2, 'yes'], [2, 0, 0, 0, 'no']] labels = ['年龄', '有工作', '有自己的房子', '信贷情况'] #特征标签 return dataSet, labels #返回数据集和分类属性 # 获取概率模型, 输入feat np.array格式 大小[N,D] def trainPbmodel_X(feats): N,D = np.shape(feats) model = {} # 对每一维度的特征进行概率统计 for d in range(D): data = feats[:,d].tolist() keys = set(data) N = len(data) model[d] ={} for key in keys: model[d][key] = float(data.count(key)/N) return model # datas: list格式 每个元素表示1个特征序列 # labs: list格式 每个元素表示一个标签 def trainPbmodel(datas,labs): # 定义模型 model = {} # 获取分类的类别 keys = set(labs) for key in keys: # 获得P(Y) Pbmodel_Y = labs.count(key)/len(labs) # 收集标签为Y的数据 index = np.where(np.array(labs)==key)[0].tolist() feats = np.array(datas)[index] # 获得 P(X|Y) Pbmodel_X = trainPbmodel_X(feats) # 模型保存 model[key]={} model[key]["PY"] = Pbmodel_Y model[key]["PX"] = Pbmodel_X return model # feat : list格式 一条输入特征 # model: 训练的概率模型 # keys :考察标签的种类 def getPbfromModel(feat,model,keys): results ={} eps = 0.00001 for key in keys: # 获取P(Y) PY = model.get(key,eps).get("PY") # 分别获取 P(X|Y) model_X = model.get(key,eps).get("PX") list_px=[] for d in range(len(feat)): pb = model_X.get(d,eps).get(feat[d],eps) list_px.append(pb) result = np.log(PY) + np.sum(np.log(list_px)) results[key]= result return results if __name__ == '__main__': '''实验一 自制贷款数据集''' # # 获取数据集 # dataSet, labels = createDataSet() # # 截取数据和标签 # datas = [i[:-1] for i in dataSet] # labs = [i[-1] for i in dataSet] # # 获取标签种类 # keys = set(labs) # # 进行模型训练 # model = trainPbmodel(datas,labs) # print(model) # # 根据输入数据获得预测结果 # feat = [0,1,0,1] # result = getPbfromModel(feat,model,keys) # print(result) # # 遍历结果找到概率最大值进行数据 # for key,value in result.items(): # if(value == max(result.values())): # print("预测结果是",key) # '''实验二 隐形眼睛数据集''' # 读取数据文件 截取数据和标签 with open("train-lenses.txt",'r',encoding="utf-8") as f: lines = f.read().splitlines() dataSet = [line.split('\t') for line in lines] datas = [i[:-1] for i in dataSet] labs = [i[-1] for i in dataSet] # 获取标签种类 keys = set(labs) # 进行模型训练 model = trainPbmodel(datas,labs) print(model) # 测试 # 读取测试文件 with open("test-lenses.txt",'r',encoding="utf-8") as f: lines = f.read().splitlines() # 逐行读取数据并测试 for line in lines: data = line.split('\t') lab_true = data[-1] feat = data[:-1] result = getPbfromModel(feat,model,keys) key_out = "" for key,value in result.items(): if(value == max(result.values())): key_out=key print("输入特征:") print(data) print(result) print("预测结果 %s 医生推荐 %s"%(key_out,lab_true))
运行结果如下: