朴素贝叶斯
一.朴素贝叶斯概念
朴素贝叶斯(Naive Bayes)是一种基于贝叶斯定理的分类算法。它的“朴素”之处在于假设所有特征之间都是独立的,即给定类别的情况下,特征之间是条件独立的。虽然这个假设在现实中并不总是成立,但在实践中,朴素贝叶斯通常表现出令人满意的性能,并且具有简单、高效、易于实现的特点。
1.1朴素贝叶斯分类器的基本组成
1.1.1贝叶斯定理
贝叶斯定理:朴素贝叶斯分类器建立在贝叶斯定理的基础上。该定理描述了在已知先验概率的情况下,如何通过新的证据来更新我们对事件的概率估计。
公式:P(A∣B)= P(B∣A)×P(A)/P(B)
1.1.2特征向量
特征向量:朴素贝叶斯分类器使用特征向量来描述数据实例。这些特征可以是离散的、连续的或二元的。例如,在文本分类任务中,特征向量可能表示文档中单词的频率或出现与否。
1.1.3类别
类别:朴素贝叶斯分类器将数据实例分配到预定义的类别中。在训练过程中,需要提供一组已知类别的数据样本,以便分类器学习如何从特征中推断出类别。
1.1.4先验概率
先验概率:这是指在没有任何特征信息的情况下,各个类别的概率分布。通常假设先验概率是相等的,但也可以基于数据的先验知识来设置。比若本实验的统计最终结果好瓜和坏瓜的占比就是求先验概率。
1.1.5条件概率
条件概率:这是指在给定类别的情况下,每个特征出现的概率。朴素贝叶斯分类器假设各个特征之间是条件独立的,因此可以将每个特征的条件概率独立地估计。
条件概率的计算公式为:𝑃(𝐵∣𝐴)=𝑃(𝐴∩𝐵)/𝑃(𝐴)
1.1.6后验概率
后验概率:根据贝叶斯定理计算得到的,在给定特征向量的情况下,属于每个类别的概率。后验概率用于决定数据实例应该分配到哪个类别。
二.算法流程
2.1流程
算法流程
(1)计算每个类别的先验概率,即某个样本属于某一类别的概率。在朴素贝叶斯中,先验概率可以根据样本集中每个类别的样本数计算得到。
(2)计算每个特征与目标变量之间的条件概率。这就相当于计算每个类别下的每个特征值的概率。在朴素贝叶斯中,条件概率可以使用频率来估计,即将训练集中某个类别下某个特征值出现的次数除以该类别下总的样本数。
(3)对于待预测的新样本,根据所属类别的后验概率,将其分类为概率最大的那一类。
三.算法实现
3.1准备数据
def DataSet():
labels = ['色泽', '根蒂', '敲声', '纹理', '脐部', '触感', '密度', '含糖率'] # 特征
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] # 测试样本
return dataSet, testSet, labels
其中labels是属性标签,testset是待测样本。
3.2计算先验概率
根据公式统计好瓜和坏瓜在总样本中的个数来进行先验概率的计算
def xianyan():
dataSet = DataSet()[0]
countG = 0 # 初始化好瓜=0
countB = 0 # 初始化坏瓜=0
countAll = len(dataSet)
for item in dataSet: # 好瓜个数
if item[-1] == "好瓜":
countG += 1
for item in dataSet: # 坏瓜个数
if item[-1] == "坏瓜":
countB += 1
P_G = round(countG/countAll, 3)
P_B = round(countB/countAll, 3)
print(f"先验概率P(好瓜)= {P_G:.2f}")
print(f"先验概率p(坏瓜)= {P_B:.2f}")
return P_G,P_B
运行结果:
3.3条件概率计算
根据待测样本的数据,分别计算在每一个特征下面该瓜是好瓜和坏瓜的概率
公式:P(xi|c)
def P(index, cla):
dataSet, testSet, labels = DataSet()
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])]
P = round(len(lst)/(countG if cla=="好瓜" else countB), 3) # 计算条件概率
print(f"特征 {index} 在类别 {cla} 下的条件概率为: {P}")
return P
运行结果:
3.4计算后验概率
后验概率的计算非常简单,就是将前面每个特征算出得到的条件概率和先验概率相乘,以此得到后验概率。
#计算后验概率
isGood = P_G * P0_G * P1_G * P2_G * P3_G * P4_G * P5_G * P6_G * P7_G # 好瓜的后验概率
isBad = P_B * P0_B * P1_B * P2_B * P3_B * P4_B * P5_B * P6_B * P7_B # 坏瓜的后验概率
return isGood,isBad
计算运行结果:
完整代码:
import numpy as np
import math
import pandas as pd
def DataSet():
labels = ['色泽', '根蒂', '敲声', '纹理', '脐部', '触感', '密度', '含糖率'] # 特征
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] # 测试样本
return dataSet, testSet, labels
def xianyan():
dataSet = DataSet()[0]
countG = 0 # 初始化好瓜=0
countB = 0 # 初始化坏瓜=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)
print(f"先验概率P(好瓜)= {P_G:.2f}")
print(f"先验概率p(坏瓜)= {P_B:.2f}")
return P_G,P_B
def P(index, cla):
dataSet, testSet, labels = DataSet()
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) # 计算条件概率
print(f"特征 {index} 在类别 {cla} 下的条件概率为: {P}")
return P
def bys():
#计算类先验概率
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(硬滑|坏瓜)
P6_G = P(6, "好瓜") # P(0.697|好瓜)
P6_B = P(6, "坏瓜") # P(0.697|坏瓜)
P7_G = P(7, "好瓜") # P(0.46|好瓜)
P7_B = P(7, "坏瓜") # P(0.46|坏瓜)
#计算后验概率
isGood = P_G * P0_G * P1_G * P2_G * P3_G * P4_G * P5_G * P6_G * P7_G # 计算是好瓜的后验概率
isBad = P_B * P0_B * P1_B * P2_B * P3_B * P4_B * P5_B * P6_B * P7_B # 计算是坏瓜的后验概率
return isGood,isBad
if __name__=='__main__':
dataSet, testSet, labels = DataSet()
print(f"测试样本:\n{testSet}")
isGood, isBad = bys()
print("后验概率:")
print(f"P(好瓜|textSet) = {isGood}")
print(f"P(坏瓜|testSet) = {isBad}")
print("预测结果 : 好瓜" if (isGood > isBad) else "预测结果 : 坏瓜")
全部运行结果:
四.实验小结
朴素贝叶斯算法是一种简单而有效的分类算法,它基于贝叶斯定理进行分类,具有许多优点和适用性,它的算法通常计算效率高,适用于大规模数据集和实时分类任务。它的计算复杂度较低,训练和预测速度快。虽然朴素贝叶斯算法假设特征之间是条件独立的,这在实际数据中并不总是成立,但在许多情况下,这个简化假设仍然能够产生良好的结果。并且由于其简单的数学模型和基于概率的分类原理,朴素贝叶斯算法的结果通常易于解释和理解。这使得它在一些需要解释性强的场景下有很好的应用前景。