机器学习实验5——朴素贝叶斯
本次课程主要学习了朴素贝叶斯分类器的原理,朴素贝叶斯分类算法主要基于贝叶斯公式,利用概率学来解决分类问题,此算法简单易实现,能快速预测出结果,但是此算法是在假设条件独立的情况下实现的,在现实中很少有符合条件独立的例子,因此此算法所分类的结果可能会因此而受到影响。
一.算法概述
1.1算法简介
朴素贝叶斯(Naive Bayes)是一种基于贝叶斯定理和特征条件独立性假设的简单而有效的分类算法。它被称为“朴素”,是因为它假设数据的各特征在类别已知的情况下是相互独立的(假设事件间条件独立),这一假设在实际情况中通常不完全成立,但算法在很多任务中仍然表现良好,它是一种有监督学习算法,常用于文本分类、垃圾邮件过滤、情感分析等问题。
1.2先验概率
基于统计的概率,是基于以往历史经验和分析得到的结果,不需要依赖当前发生的条件,表示事件Cj本身的概率
公式:
1.3条件概率
记事件A发生的概率为P(A),事件B发生的概率为P(B),则在B事件发生的前提下,A事件发生的概率即为条件概率,记为P(A|B)。
公式:
1.4后验概率
在贝叶斯统计中,后验概率是在考虑新信息之后事件发生的修正或更新概率。 后验概率通过使用贝叶斯定理更新先验概率来计算。 用统计术语来说,后验概率是假设事件B已经发生的情况下事件A发生的概率。
公式:
![]()
1.5朴素贝叶斯
朴素贝叶斯分类器的原理基于贝叶斯定理,即根据已知类别的数据来估计特征与类别之间的概率分布,然后使用这些概率来对新样本进行分类。
朴素贝叶斯算法是假设各个特征之间相互独立,也是朴素这词的意思。那么贝叶斯公式中P(X|Y)可写成
![]()
那么贝叶斯公式中的P(Y|X)就可以写为:
![]()
1.6朴素贝叶斯的优缺点
优点:
1.简单易实现:基于贝叶斯定理,计算简单,容易实现。
2.计算高效:条件独立性假设大大降低了计算复杂度。
缺点:
条件独立假设:特征完全独立的假设在实际数据中很少成立,可能影响分类性能
二.算法实现
1.准备数据集
def loadDataSet():
dataSet=[['青绿', '蜷缩', '浊响', '清晰', '凹陷', '硬滑', 0.697, 0.460, '好瓜'],
['乌黑', '蜷缩', '沉闷', '清晰', '凹陷', '硬滑', 0.774, 0.376, '好瓜'],
['乌黑', '蜷缩', '浊响', '清晰', '凹陷', '硬滑', 0.634, 0.264, '好瓜'],
['青绿', '蜷缩', '沉闷', '清晰', '凹陷', '硬滑', 0.608, 0.318, '好瓜'],
['浅白', '蜷缩', '浊响', '清晰', '凹陷', '硬滑', 0.556, 0.215, '好瓜'],
['青绿', '稍蜷', '浊响', '清晰', '稍凹', '软粘', 0.403, 0.237, '好瓜'],
['乌黑', '稍蜷', '浊响', '稍糊', '稍凹', '软粘', 0.481, 0.149, '好瓜'],
['乌黑', '稍蜷', '浊响', '清晰', '稍凹', '硬滑', 0.437, 0.211, '好瓜'],
['乌黑', '稍蜷', '沉闷', '稍糊', '稍凹', '硬滑', 0.666, 0.091, '坏瓜'],
['青绿', '硬挺', '清脆', '清晰', '平坦', '软粘', 0.243, 0.267, '坏瓜'],
['浅白', '硬挺', '清脆', '模糊', '平坦', '硬滑', 0.245, 0.057, '坏瓜'],
['浅白', '蜷缩', '浊响', '模糊', '平坦', '软粘', 0.343, 0.099, '坏瓜'],
['青绿', '稍蜷', '浊响', '稍糊', '凹陷', '硬滑', 0.639, 0.161, '坏瓜'],
['浅白', '稍蜷', '沉闷', '稍糊', '凹陷', '硬滑', 0.657, 0.198, '坏瓜'],
['乌黑', '稍蜷', '浊响', '清晰', '稍凹', '软粘', 0.360, 0.370, '坏瓜'],
['浅白', '蜷缩', '浊响', '模糊', '平坦', '硬滑', 0.593, 0.042, '坏瓜'],
['青绿', '蜷缩', '沉闷', '稍糊', '稍凹', '硬滑', 0.719, 0.103, '坏瓜']]
testSet= ['青绿', '蜷缩', '浊响', '清晰', '凹陷', '硬滑', 0.697, 0.460] # 待测集
labels = ['色泽', '根蒂', '敲声', '纹理', '脐部', '触感', '密度', '含糖率'] # 特征
return dataSet, testSet, labels
2.计算含糖量、密度的均值与标准差
def mean_std(feature, cla):#feature:传入指定将要计算其均值的标准差的特征名称,cla:好瓜或坏坏瓜
dataSet, testSet, labels = loadDataSet()
lst = [item[labels.index(feature)] for item in dataSet if item[-1]==cla] #类别为cla中指定特征feature组成的列表
mean = round(np.mean(lst), 3) # 均值
std = round(np.std(lst), 3) # 标准差
return mean, std
3.计算先验概率
def prior():
dataSet = loadDataSet()[0] # 载入数据集
countG = 0
countB = 0
countAll = len(dataSet)
for item in dataSet: # 好瓜个数
if item[-1] == "好瓜":
countG += 1
for item in dataSet: # 坏瓜个数
if item[-1] == "坏瓜":
countB += 1
# 计算先验概率P(c)
P_G = round(countG/countAll, 3)
P_B = round(countB/countAll, 3)
return P_G,P_B
4.计算条件概率
#计算离散属性条件概率P(xi|c)
def P(index, cla):
dataSet, testSet, labels = loadDataSet() #载入数据集
countG = 0 #初始化好瓜数量
countB = 0 #初始化坏瓜数量
for item in dataSet: #统计好瓜个数
if item[-1] == "好瓜":
countG += 1
for item in dataSet: #统计坏瓜个数
if item[-1] == "坏瓜":
countB += 1
lst = [item for item in dataSet if (item[-1] == cla) & (item[index] == testSet[index])] # lst为cla类中第index个属性上取值为xi的样本组成的集合
P = round(len(lst)/(countG if cla=="好瓜" else countB), 3) # 计算条件概率
return P
#计算连续属性的条件概率p(xi|c)
def p():
dataSet, testSet, labels = loadDataSet() #载入数据集
denG_mean, denG_std = mean_std("密度", "好瓜") #好瓜密度的均值、标准差
denB_mean, denB_std = mean_std("密度", "坏瓜") #坏瓜密度的均值、标准差
sugG_mean, sugG_std = mean_std("含糖率", "好瓜") #好瓜含糖率的均值、标准差
sugB_mean, sugB_std = mean_std("含糖率", "坏瓜") #坏瓜含糖率的均值、标准差
#p(密度|好瓜)
p_density_G = (1/(math.sqrt(2*math.pi)*denG_std))*np.exp(-(((testSet[labels.index("密度")]-denG_mean)**2)/(2*(denG_std**2))))
p_density_G = round(p_density_G, 3)
#p(密度|坏瓜)
p_density_B = (1/(math.sqrt(2*math.pi)*denB_std))*np.exp(-(((testSet[labels.index("密度")]-denB_mean)**2)/(2*(denB_std**2))))
p_density_B = round(p_density_B, 3)
#p(含糖率|好瓜)
p_sugar_G = (1/(math.sqrt(2*math.pi)*sugG_std))*np.exp(-(((testSet[labels.index("含糖率")]-sugG_mean)**2)/(2*(sugG_std**2))))
p_sugar_G = round(p_sugar_G, 3)
#p(含糖率|坏瓜)
p_sugar_B = (1/(math.sqrt(2*math.pi)*sugB_std))*np.exp(-(((testSet[labels.index("含糖率")]-sugB_mean)**2)/(2*(sugB_std**2))))
p_sugar_B = round(p_sugar_B, 3)
return p_density_G, p_density_B, p_sugar_G, p_sugar_B
5.计算后验概率
def bayes():
#计算类先验概率
P_G, P_B = prior()
#计算离散属性的条件概率
P0_G = P(0, "好瓜") #P(青绿|好瓜)
P0_B = P(0, "坏瓜") #P(青绿|坏瓜)
P1_G = P(1, "好瓜") #P(蜷缩|好瓜)
P1_B = P(1, "坏瓜") #P(蜷缩|坏瓜)
P2_G = P(2, "好瓜") #P(浊响|好瓜)
P2_B = P(2, "坏瓜") #P(浊响|坏瓜)
P3_G = P(3, "好瓜") #P(清晰|好瓜)
P3_B = P(3, "坏瓜") #P(清晰|坏瓜)
P4_G = P(4, "好瓜") #P(凹陷|好瓜)
P4_B = P(4, "坏瓜") #P(凹陷|坏瓜)
P5_G = P(5, "好瓜") #P(硬滑|好瓜)
P5_B = P(5, "坏瓜") #P(硬滑|坏瓜)
#计算连续属性的条件概率
p_density_G, p_density_B, p_sugar_G, p_sugar_B = p()
#计算后验概率
isGood = P_G * P0_G * P1_G * P2_G * P3_G * P4_G * P5_G * p_density_G * p_sugar_G #计算是好瓜的后验概率
isBad = P_B * P0_B * P1_B * P2_B * P3_B * P4_B * P5_B * p_density_B * p_sugar_B #计算是坏瓜的后验概率
return isGood,isBad
完整代码:
import numpy as np
import math
import pandas as pd
def loadDataSet():
dataSet=[['青绿', '蜷缩', '浊响', '清晰', '凹陷', '硬滑', 0.697, 0.460, '好瓜'],
['乌黑', '蜷缩', '沉闷', '清晰', '凹陷', '硬滑', 0.774, 0.376, '好瓜'],
['乌黑', '蜷缩', '浊响', '清晰', '凹陷', '硬滑', 0.634, 0.264, '好瓜'],
['青绿', '蜷缩', '沉闷', '清晰', '凹陷', '硬滑', 0.608, 0.318, '好瓜'],
['浅白', '蜷缩', '浊响', '清晰', '凹陷', '硬滑', 0.556, 0.215, '好瓜'],
['青绿', '稍蜷', '浊响', '清晰', '稍凹', '软粘', 0.403, 0.237, '好瓜'],
['乌黑', '稍蜷', '浊响', '稍糊', '稍凹', '软粘', 0.481, 0.149, '好瓜'],
['乌黑', '稍蜷', '浊响', '清晰', '稍凹', '硬滑', 0.437, 0.211, '好瓜'],
['乌黑', '稍蜷', '沉闷', '稍糊', '稍凹', '硬滑', 0.666, 0.091, '坏瓜'],
['青绿', '硬挺', '清脆', '清晰', '平坦', '软粘', 0.243, 0.267, '坏瓜'],
['浅白', '硬挺', '清脆', '模糊', '平坦', '硬滑', 0.245, 0.057, '坏瓜'],
['浅白', '蜷缩', '浊响', '模糊', '平坦', '软粘', 0.343, 0.099, '坏瓜'],
['青绿', '稍蜷', '浊响', '稍糊', '凹陷', '硬滑', 0.639, 0.161, '坏瓜'],
['浅白', '稍蜷', '沉闷', '稍糊', '凹陷', '硬滑', 0.657, 0.198, '坏瓜'],
['乌黑', '稍蜷', '浊响', '清晰', '稍凹', '软粘', 0.360, 0.370, '坏瓜'],
['浅白', '蜷缩', '浊响', '模糊', '平坦', '硬滑', 0.593, 0.042, '坏瓜'],
['青绿', '蜷缩', '沉闷', '稍糊', '稍凹', '硬滑', 0.719, 0.103, '坏瓜']]
testSet= ['青绿', '蜷缩', '浊响', '清晰', '凹陷', '硬滑', 0.697, 0.460] # 待测集
labels = ['色泽', '根蒂', '敲声', '纹理', '脐部', '触感', '密度', '含糖率'] # 特征
return dataSet, testSet, labels
#计算含糖量、密度均值、标准差
def mean_std(feature, cla):#feature:传入指定将要计算其均值的标准差的特征名称,cla:好瓜或坏坏瓜
dataSet, testSet, labels = loadDataSet()
lst = [item[labels.index(feature)] for item in dataSet if item[-1]==cla] #类别为cla中指定特征feature组成的列表
mean = round(np.mean(lst), 3) # 均值
std = round(np.std(lst), 3) # 标准差
return mean, std
#计算先验概率P(c) (计算好瓜与坏瓜的概率)
def prior():
dataSet = loadDataSet()[0] #载入数据集
countG = 0
countB = 0
countAll = len(dataSet)
for item in dataSet: #好瓜个数
if item[-1] == "好瓜":
countG += 1
for item in dataSet: #坏瓜个数
if item[-1] == "坏瓜":
countB += 1
# 计算先验概率P(c)
P_G = round(countG/countAll, 3)
P_B = round(countB/countAll, 3)
return P_G,P_B
#计算离散属性条件概率P(xi|c)
def P(index, cla):
dataSet, testSet, labels = loadDataSet() #载入数据集
countG = 0 #初始化好瓜数量
countB = 0 #初始化坏瓜数量
for item in dataSet: #统计好瓜个数
if item[-1] == "好瓜":
countG += 1
for item in dataSet: #统计坏瓜个数
if item[-1] == "坏瓜":
countB += 1
lst = [item for item in dataSet if (item[-1] == cla) & (item[index] == testSet[index])] # lst为cla类中第index个属性上取值为xi的样本组成的集合
P = round(len(lst)/(countG if cla=="好瓜" else countB), 3) # 计算条件概率
return P
#计算连续属性的条件概率p(xi|c)
def p():
dataSet, testSet, labels = loadDataSet() #载入数据集
denG_mean, denG_std = mean_std("密度", "好瓜") #好瓜密度的均值、标准差
denB_mean, denB_std = mean_std("密度", "坏瓜") #坏瓜密度的均值、标准差
sugG_mean, sugG_std = mean_std("含糖率", "好瓜") #好瓜含糖率的均值、标准差
sugB_mean, sugB_std = mean_std("含糖率", "坏瓜") #坏瓜含糖率的均值、标准差
#p(密度|好瓜)
p_density_G = (1/(math.sqrt(2*math.pi)*denG_std))*np.exp(-(((testSet[labels.index("密度")]-denG_mean)**2)/(2*(denG_std**2))))
p_density_G = round(p_density_G, 3)
#p(密度|坏瓜)
p_density_B = (1/(math.sqrt(2*math.pi)*denB_std))*np.exp(-(((testSet[labels.index("密度")]-denB_mean)**2)/(2*(denB_std**2))))
p_density_B = round(p_density_B, 3)
#p(含糖率|好瓜)
p_sugar_G = (1/(math.sqrt(2*math.pi)*sugG_std))*np.exp(-(((testSet[labels.index("含糖率")]-sugG_mean)**2)/(2*(sugG_std**2))))
p_sugar_G = round(p_sugar_G, 3)
#p(含糖率|坏瓜)
p_sugar_B = (1/(math.sqrt(2*math.pi)*sugB_std))*np.exp(-(((testSet[labels.index("含糖率")]-sugB_mean)**2)/(2*(sugB_std**2))))
p_sugar_B = round(p_sugar_B, 3)
return p_density_G, p_density_B, p_sugar_G, p_sugar_B
#预测后验概率P(c|xi)
def bayes():
#计算类先验概率
P_G, P_B = prior()
#计算离散属性的条件概率
P0_G = P(0, "好瓜") #P(青绿|好瓜)
P0_B = P(0, "坏瓜") #P(青绿|坏瓜)
P1_G = P(1, "好瓜") #P(蜷缩|好瓜)
P1_B = P(1, "坏瓜") #P(蜷缩|坏瓜)
P2_G = P(2, "好瓜") #P(浊响|好瓜)
P2_B = P(2, "坏瓜") #P(浊响|坏瓜)
P3_G = P(3, "好瓜") #P(清晰|好瓜)
P3_B = P(3, "坏瓜") #P(清晰|坏瓜)
P4_G = P(4, "好瓜") #P(凹陷|好瓜)
P4_B = P(4, "坏瓜") #P(凹陷|坏瓜)
P5_G = P(5, "好瓜") #P(硬滑|好瓜)
P5_B = P(5, "坏瓜") #P(硬滑|坏瓜)
#计算连续属性的条件概率
p_density_G, p_density_B, p_sugar_G, p_sugar_B = p()
#计算后验概率
isGood = P_G * P0_G * P1_G * P2_G * P3_G * P4_G * P5_G * p_density_G * p_sugar_G #计算是好瓜的后验概率
isBad = P_B * P0_B * P1_B * P2_B * P3_B * P4_B * P5_B * p_density_B * p_sugar_B #计算是坏瓜的后验概率
return isGood,isBad
if __name__=='__main__':
dataSet, testSet, labels = loadDataSet()
testSet = [testSet]
isGood, isBad = bayes()
print("后验概率:")
print(f"P(好瓜|xi) = {isGood}")
print(f"P(坏瓜|xi) = {isBad}")
print("预测结果:好瓜" if (isGood > isBad) else "预测结果:坏瓜")
结果展示:

三.实验总结
本次课程主要学习了朴素贝叶斯分类器的原理,朴素贝叶斯分类算法主要基于贝叶斯公式,利用概率学来解决分类问题,此算法简单易实现,能快速预测出结果,但是此算法是在假设条件独立的情况下实现的,在现实中很少有符合条件独立的例子,因此此算法所分类的结果可能会因此而受到影响。
更多推荐


所有评论(0)