一:贝叶斯公式:
1、 先验概率:
P(cj)代表还没有训练模型之前,根据历史数据/经验估算cj拥有的初始概率。P(cj)常被称为cj的先验概率(prior probability) ,它反映了cj的概率分布,该分布独立于样本。
通常可以用样例中属于cj的样例数|cj|比上总样例数|D|来近似,即:
2、后验概率:给定数据样本x时cj成立的概率P(cj | x )被称为后验概率(posterior probability),因为它反映了在看到数据样本 x后 cj 成立的置信度。
例:西瓜好坏的概率和其属性有关
当观测到西瓜样本(属性取值)x时,它为好瓜概率是多少?
p(y=1|x), p(y=0|x)
后验概率:观测到 x 后对结果 y 的估计。
3、贝叶斯定理
已知两个独立事件A和B,事件B发生的前提下,事件A发生的概率可以表示为P(A|B),这个在概率论中我们也称为条件概率。如下图:
P(A|B)在图中所表示的即为A和B中间相交区域所占B全部区域的比例。
4、机器学习的两个视角
机器学习的两个主要视角分别是:生成式和判别式建模。
判别式建模:
判别式模型专注于对条件概率分布P(Y|X)进行建模,即给定输入X下输出Y的概率分布。判别式模型直接对决策面进行建模,以便最大化对观测数据的分类准确性。
生成式建模:
生成式模型试图对观测数据和标记之间的联合概率分布进行建模,即P(X, Y)。在分类问题中,生成式模型会尝试估计出每个类别的条件概率分布P(X|Y)和类别的先验概率P(Y),然后利用贝叶斯定理计算后验概率P(Y|X)。
二:朴素贝叶斯分类器
MAP分类准则:
x 属于类别 c* 的概率:
利用贝叶斯准则转化为:
朴素贝叶斯分类器(Naïve Bayes Classifier)采用了“属性条件独立性假设”,即每个属性独立地对分类结果发生影响。
为方便公式标记,不妨记P(C=c|X=x)为P(c|x),基于属性条件独立性假设,贝叶斯公式可重写为:
其中d为属性数目,x_i 为 x 在第i个属性上的取值。
三:拉普拉斯修正
在概率估计中,当某个事件在训练数据中没有出现时,使用最大似然估计等方法会导致该事件的概率估计为零。
拉普拉斯修正通过向所有计数中添加一个平滑项,来解决零概率问题。
为了避免其他属性携带的信息,被训练集中未出现的属性值“抹去”,在估计概率值时通常要进行“拉普拉斯修正”:
令 N 表示训练集 D 中可能的类别数,N_i表示第i个属性可能的取值数,则贝叶斯公式可修正为:
四、垃圾文件分类:
对于老师给出的ham与spam的文件进行相关分类:
代码:
def load_file(path):
cab=[]
for i in range(1, 25):
data=open(path %i)
for line in data.readlines():
cab.append(line.strip().split(','))
cab_f=[]
for i in range(len(cab)):
for j in range(len(cab[i])):
if cab[i][j]!='':
cab_f.append(cab[i][j].strip())
cab_final=[]
for i in cab_f:
for j in i.split(' '):
cab_final.append(j)
return cab_final
def bayes(test):
path1='C:/Users/76518/Desktop/machinelearning/Ch04/email/ham/%d.txt'
path2='C:/Users/76518/Desktop/machinelearning/Ch04/email/spam/%d.txt'
ham_data=load_file(path1)
spam_data=load_file(path2)
p_ham = 1.0
p_spam = 1.0
for word in test:
count_ham = ham_data.count(word) + 1.0
count_spam = spam_data.count(word) + 1.0
p_ham *= count_ham / (len(ham_data) + len(set(ham_data)))
p_spam *= count_spam / (len(spam_data) + len(set(spam_data)))
if p_ham > p_spam:
return 'ham'
else:
return 'spam'
def test_email(path, ham_data, spam_data):
data = open(path)
email = []
for line in data.readlines():
email.append(line.strip().split(','))
email_words = [word for sublist in email for word in sublist if word != '']
return bayes(email_words, ham_data, spam_data) # type: ignore
if __name__ == '__main__':
ham_training_path = 'C:/Users/76518/Desktop/machinelearning/Ch04/email/ham/%d.txt'
spam_training_path = 'C:/Users/76518/Desktop/machinelearning/Ch04/email/spam/%d.txt'
ham_training_data = load_file(ham_training_path)
spam_training_data = load_file(spam_training_path)
print(test_email('C:/Users/76518/Desktop/machinelearning/Ch04/email/ham/%d.txt', ham_training_data, spam_training_data))
print(test_email('C:/Users/76518/Desktop/machinelearning/Ch04/email/spam/%d.txt', ham_training_data, spam_training_data))
# 计算训练集的分类正确率
correct_ham_count = sum(1 for i in range(1, 25) if test_email(ham_training_path % i, ham_training_data, spam_training_data) == 'ham')
correct_spam_count = sum(1 for i in range(1, 25) if test_email(spam_training_path % i, ham_training_data, spam_training_data) == 'spam')
print('ham分类正确率:', correct_ham_count / 24)
print('spam分类正确率:', correct_spam_count / 24)
运行结果:
五、实验总结
-
算法原理:贝叶斯算法是基于贝叶斯定理的分类算法,通过计算给定特征下某个类别的条件概率来进行分类。在垃圾邮件分类中,计算特定单词在垃圾邮件和正常邮件中出现的概率,然后利用贝叶斯定理计算新邮件属于垃圾邮件和正常邮件的概率,从而进行分类。
-
拉普拉斯平滑:为了避免因为某个单词在训练集中未出现导致的概率为零,使用了拉普拉斯平滑来解决这个问题,即为所有单词的出现次数加上一个平滑参数。
-
分类准确率:通过对训练集进行测试,可以计算出该算法在训练集上的分类准确率。这个准确率可以帮助我们评估算法的性能和效果。
优势:
1、贝叶斯算法的原理相对简单,易于理解和实现。
2、可以很好地处理小样本数据,不需要大量的训练样本就可以进行准确的分类。
3、贝叶斯算法对噪声和缺失数据具有较好的鲁棒性。
不足:
1、朴素贝叶斯算法假设所有特征之间是相互独立的,这在某些情况下可能不符合实际情况。
2、贝叶斯算法对于数据不平衡问题较为敏感。如果分类目标的数量差异很大,会导致模型对少数类别的分类效果较差。