机器学习——朴素贝叶斯算法详解与实战
机器学习——朴素贝叶斯算法详解与实战
一、朴素贝叶斯算法描述
1.1 算法的概念
朴素贝叶斯算法是一种基于贝叶斯定理和特征条件独立假设的分类算法。在机器学习领域中,朴素贝叶斯算法是一种简单且高效的分类方法,常用于文本分类、垃圾邮件过滤、情感分析等任务。其核心思想是基于训练数据学习类别间的概率分布,然后利用贝叶斯定理计算出测试样本属于各个类别的概率,最终将具有最大概率的类别作为分类结果。在朴素贝叶斯算法中,特征之间假定为条件独立,即给定类别的情况下,特征之间是互独立的。虽然这一假设在现实中并不总是成立,朴素贝叶斯算法仍然表现出色,并被广泛应用于各种分类问题中,分布如下图所示:
1.2 算法的优缺点
朴素贝叶斯算法的优点包括:
- 算法简单,实现容易:朴素贝叶斯算法是一种非常简单且易于实现的分类算法,适用于处理大规模数据集。
- 训练和预测速度快:由于朴素贝叶斯假设特征之间独立,因此算法的计算量相对较小,训练和预测速度很快。
- 对小规模数据表现良好:即便在数据规模较小的情况下,朴素贝叶斯也有较好的表现。
- 对缺失数据不敏感:朴素贝叶斯算法对缺失数据不敏感,在一定程度上可以处理缺失数据的情况。
朴素贝叶斯算法的缺点包括:
- 预测准确性较低:由于其对特征的独立性假设,在实际应用中可能影响分类效果。
- 对输入数据的分布假设较强:朴素贝叶斯算法假设特征之间相互独立,这一假设在某些情况下可能不成立,影响了算法的表现。
- 需要大量训练数据:在某些情况下,朴素贝叶斯算法需要大量的训练数据来准确估计先验概率和条件概率。
总的来说,朴素贝叶斯算法是一种简单且高效的分类算法,但在应用时需要考虑其特性和适用范围。
二、贝叶斯分类器
2.1 贝叶斯定理
在机器学习中,贝叶斯定理扮演着至关重要的角色,它提供了一种基于先验知识和数据观测来更新假设概率的方法。简而言之,贝叶斯定理允许我们根据新的证据来调整之前对某事件的信念或概率估计。在介绍贝叶斯定理前,先为大家引入先验概率、后验概率和条件概率的概念。
- 先验概率:是基于统计的概率,是基于以往历史经验和分析得到的结果,不需要依赖当前发生的条件。
- 条件概率:记事件A发生的概率为P(A),事件B发生的概率为P(B),则在事件B发生的前提下,事件A发生的概率即为条件概率,记为P(A|B)。条件概率公式:
- 后验概率:则是从条件概率而来,由因推果,是基于当下发生了事件之后计算的概率,依赖于当前发生的条件。
贝叶斯公式:假设有随机事件A和B,则贝叶斯公式如下:
其中,事件A是要考察的目标事件,P(A)是事件A的初始概率,称为先验概率,它是根据一些先前的观测或者经验得到的概率。
B是新出现的一个事件,它会影响事件A。P(B)表示事件B发生的概率。
P(B|A)表示在事件A发生的条件下事件B发生的概率,称之为条件概率。
P(A|B)表示当事件B发生时事件A发生的概率(也是条件概率),它是我们要计算的后验概率,指在得到一些观测信息后某事件发生的概率。
2.2 朴素贝叶斯
朴素贝叶斯算法的核心是基于贝叶斯定理计算条件概率,其公式如下所示:
其中:
- P(c|x) 表示在给定特征 x 的情况下类别 c 的概率,即后验概率;
- P(x|c) 表示在类别 c 的情况下特征 x 的概率,即条件概率;
- P(c) 表示类别 c 的先验概率;
- P(x) 表示特征 x 的先验概率。
根据贝叶斯定理,我们可以通过计算先验概率和条件概率来求得后验概率,从而进行分类预测。在朴素贝叶斯算法中,特征条件独立性假设使得条件概率的计算更加简单,即可以将 P(x|c)拆解为各个特征的条件概率的乘积。 具体而言,在朴素贝叶斯算法中,我们计算每个特征在每个类别下的条件概率,然后根据特征的取值将其求积,得到最终的类别概率。通过比较不同类别的概率,我们可以确定最可能的类别,从而进行分类预测。
三、案例实现(西瓜分类)
过程分析
- 获取数据集
- 数据处理
- 划分训练集和测试集
- 创建朴素贝叶斯
- 对结果进行修正
3.1.创建本次所要用到的西瓜数据集及其特征还有测试集
def createtraindata():
# 数据集
traindata = [
['青绿', '蜷缩', '浊响', '清晰', '凹陷', '硬滑', '好瓜'],
['乌黑', '蜷缩', '沉闷', '清晰', '凹陷', '硬滑', '好瓜'],
['乌黑', '蜷缩', '浊响', '清晰', '凹陷', '硬滑', '好瓜'],
['青绿', '蜷缩', '沉闷', '清晰', '凹陷', '硬滑', '好瓜'],
['浅白', '蜷缩', '浊响', '清晰', '凹陷', '硬滑', '好瓜'],
['青绿', '稍蜷', '浊响', '清晰', '稍凹', '软粘', '好瓜'],
['乌黑', '稍蜷', '浊响', '稍糊', '稍凹', '软粘', '好瓜'],
['乌黑', '稍蜷', '浊响', '清晰', '稍凹', '硬滑', '好瓜'],
['乌黑', '稍蜷', '沉闷', '稍糊', '稍凹', '硬滑', '坏瓜'],
['青绿', '硬挺', '清脆', '清晰', '平坦', '软粘', '坏瓜'],
['浅白', '硬挺', '清脆', '模糊', '平坦', '硬滑', '坏瓜'],
['浅白', '蜷缩', '浊响', '模糊', '平坦', '软粘', '坏瓜'],
['青绿', '稍蜷', '浊响', '稍糊', '凹陷', '硬滑', '坏瓜'],
['浅白', '稍蜷', '沉闷', '稍糊', '凹陷', '硬滑', '坏瓜'],
['乌黑', '稍蜷', '浊响', '清晰', '稍凹', '软粘', '坏瓜'],
['浅白', '蜷缩', '浊响', '模糊', '平坦', '硬滑', '坏瓜'],
['青绿', '蜷缩', '沉闷', '稍糊', '稍凹', '硬滑', '坏瓜']
]
# 测试集
test=[['青绿','蜷缩','沉闷','清晰','凹陷','硬滑'],['乌黑','硬挺','清脆','清晰','稍凹','硬滑']]
# 特征值列表
labels = ['色泽', '根蒂', '敲击', '纹理', '脐部', '触感']
return traindata,test,labels
3.2.计算先验概率
def calpriority(traindata):
# 计算好瓜和坏瓜的数量
total_count = len(traindata)
good_melon = 0
bad_melon = 0
for sample in traindata:
if sample[-1] == '好瓜':
good_melon += 1
else:
bad_melon += 1
p_good = good_melon/total_count
p_bad = bad_melon/total_count
print(f"P(好瓜)={p_good:.4f}")
print(f"P(坏瓜)={p_bad:.4f}")
return p_good,p_bad
P(好瓜)=0.4706
p(坏瓜)=0.5294
3.3.计算各个特征值的后验概率
def calposterior(traindata):
# 将原数据集划分为好瓜和坏瓜数据集
good_traindata = [sample for sample in traindata if sample[-1] == '好瓜']
bad_traindata = [sample for sample in traindata if sample[-1] == '坏瓜']
# 计算好瓜中的各个特征的后验概率(即条件概率)
good_length = len(good_traindata)
good_result = {}
# 统计个数并计算结果
for sample in good_traindata:
for word in sample:
if word not in ['好瓜']:
if word not in good_result:
good_result[word] = 1
else:
good_result[word] += 1
for word,count in good_result.items():
good_result[word] = count/good_length
for word,count in good_result.items():
print(f"P({word}|好瓜):{count:.3f}")
# 计算坏瓜中的各个特征的后验概率(即条件概率)
bad_length = len(bad_traindata)
bad_result = {}
# 统计个数并计算结果
for sample in bad_traindata:
for word in sample:
if word not in ['坏瓜']:
if word not in bad_result:
bad_result[word] = 1
else:
bad_result[word] += 1
for word,count in bad_result.items():
bad_result[word] = count/bad_length
for word,count in bad_result.items():
print(f"P({word}|坏瓜):{count:.4f}")
return good_result,bad_result,good_traindata,bad_traindata
3.4.对测试集计算并分类
def calresult(test, pgood, pbad, good_if, bad_if):
count1=0
for each in test:
count1 += 1
calgood = pgood
calbad = pbad
for sample in each:
# 计算测试集为好瓜的概率
flag = 0
for word,count in good_if.items():
if sample == word:
flag = 1
calgood *= count
break
if flag == 0 :
calgood *= 0
# 计算测试集为好瓜的概率
flag1 = 0
for word,count in bad_if.items():
if sample == word:
flag1 = 1
calbad *= count
break
if flag1 == 0 :
calbad *= 0
print(f"第{count1}个好瓜概率:{calgood:.4f}")
print(f"第{count1}个坏瓜概率:{calbad:.4f}")
if calgood > calbad:
print(f"第{count1}个测试集的预测结果为:好瓜")
else:
print(f"第{count1}个测试集的预测结果为:坏瓜")
3.5.拉普拉斯平滑技巧修正
def revision( traindata, good_traindata):
length = len(good_traindata)*2+1
for word,count in traindata.items():
if word in ['蜷缩','稍蜷']:
traindata[word] = (count + 1) / length
if word in ['浊响','沉闷']:
traindata[word] = (count + 1) / length
traindata['硬挺'] = 1 / length
traindata['清脆'] = 1 / length
print("更正后好瓜条件概率:")
for word, count in traindata.items():
print(f"P({word}|好瓜):{count:.4f}")
return traindata
概率不为0,修正成功!
四、实验总结
朴素贝叶斯(Naive Bayes)是一种简单但强大的机器学习算法,常用于文本分类、垃圾邮件过滤、情感分析等任务。在进行朴素贝叶斯实验后,可以得出以下小结:
- 数据预处理:在使用朴素贝叶斯算法之前,通常需要对数据进行预处理。这可能包括去除停用词、词干提取、向量化文本等步骤,以便算法能够有效地处理文本数据。
- 特征选择:朴素贝叶斯算法假设特征之间相互独立,因此在特征选择时应该考虑特征之间的相关性。一些特征选择方法,如信息增益、卡方检验、互信息等,可以帮助选择最相关的特征。
- 模型训练:朴素贝叶斯算法的训练速度通常很快,因为它只需统计各个类别下每个特征的频数。但在极端情况下,如果某个特征在训练集中没有出现过,会导致概率为零,这种情况可以通过平滑技术(如拉普拉斯平滑、Lidstone平滑)来处理。
- 模型评估:使用交叉验证等方法对训练得到的模型进行评估,以确保其在未见过的数据上的泛化能力。常见的评估指标包括准确率、精确率、召回率、F1 值等。
- 应对样本不平衡:在实际应用中,不同类别的样本数量可能存在较大差异,这会影响模型的性能。可以通过过采样、欠采样或使用基于成本的学习算法来解决样本不平衡的问题。
- 超参数调优:朴素贝叶斯算法中的超参数包括平滑参数等,调整这些参数可能会对模型性能产生影响。可以使用网格搜索、随机搜索等方法来选择最优的超参数组合。
- 实验结果分析:对实验结果进行分析,包括错误分析、特征重要性分析等,可以帮助深入理解模型的表现,并指导进一步的改进。
综上所述,朴素贝叶斯算法是一种简单而有效的分类算法,在处理文本数据等场景下表现优异。通过合适的数据预处理、特征选择、模型训练和评估等步骤,可以得到性能良好的朴素贝叶斯分类器。
本文原文来自CSDN