赞
踩
贝叶斯定理是18世纪英国数学家托马斯·贝叶斯(Thomas Bayes)提出得重要概率论理论。在该定理提出之前,人们已经能够计算“正向概率”,如“假设袋子里面有 N 个白球,M 个黑球,你伸手进去摸一把,摸出黑球的概率是多大”。而一个自然而然的问题是反过来:“如果我们事先并不知道袋子里面黑白球的比例,而是闭着眼睛摸出一个(或好几个)球,观察这些取出来的球的颜色之后,那么我们可以就此对袋子里面的黑白球的比例作出什么样的推测”。这个问题,就是所谓的逆向概率问题。
1 条件概率(后验概率):就是事件A在另一个事件B已经发生的条件下发生概率,公式表示为P(A|B),读作“在B条件下A的概率”。
公式:
2 联合概率:表示两件事情共同发生的概率,A与B的联合概率表示为P(A,B)。
3 边缘概率(又称先验概率):
边缘概率是指某个事件发生的概率,而与其它事件无关,它是由联合概率边缘化得到的,即在联合概率中,把最终结果不需要的事件合并成事件全概率而消失。例如P(A,B1)表示事件A与事件B1同时发生的概率,P(A,B2)表示事件A与事件B2同时发生的概率,若事件B1与B2合在一起为B事件发生的全部情况,则A 的边缘概率P(A)=p(A,B1)+P(A,B2)。
贝叶利公式:
P(A)是 A 的先验概率,之所以称为“先验”是因为它不考虑任何 B 方面的因素。
P(A|B)是已知 B 发生后 A 的条件概率,也由于得自 B 的取值而被称作 A 的后验概率。
P(B|A)是已知 A 发生后 B 的条件概率,也由于得自 A 的取值而被称作 B 的后验概率。
P(B)是 B 的先验概率,也作标淮化常量(normalizing constant)。
所以贝叶斯公式可以表示为:后验概率=先验概率 * 调整因子
如果调整因子>1,则表示先验概率被增强,事件A发生的可能性变大。
如果调整因子=1,则表示事件B对判断事件A发生的概率没有帮助。
如果调整因子<1,则表示先验概率被削弱,事件A发生的可能性变小。
贝叶斯算法的工作流程如下:
1 邮件数据读取
- import numpy as np # 导入NumPy库,用于数值计算
- import re # 导入re库,用于正则表达式操作
- import random # 导入random库,用于生成随机数
-
- # 定义一个函数textParse,用于处理文本数据
- def textParse(input_string):
- listofTokens = re.split(r'\W+', input_string) # 使用正则表达式切分输入的字符串
- return [tok.lower() for tok in listofTokens if len(listofTokens) > 2] # 返回切分后的单词列表,转换为小写并去除长度小于等于2的单词
-
- # 定义一个函数spam,用于处理垃圾邮件数据
- def spam():
- doclist = [] # 创建一个空列表,用于存储文档数据
- classlist = [] # 创建一个空列表,用于存储类别信息
- for i in range(1, 26): # 循环处理1到25号文档
- # 处理垃圾邮件文档
- wordlist = textParse(open('email/spam/%d.txt' % i, 'r').read()) # 读取并处理垃圾邮件文档
- doclist.append(wordlist) # 将处理后的单词列表添加到文档列表
- classlist.append(1) # 将类别标签1(表示垃圾邮件)添加到类别列表
-
- # 处理非垃圾邮件文档
- wordlist = textParse(open('email/ham/%d.txt' % i, 'r').read()) # 读取并处理非垃圾邮件文档
- doclist.append(wordlist) # 将处理后的单词列表添加到文档列表
- classlist.append(0) # 将类别标签0(表示非垃圾邮件)添加到类别列表
-
- ......
定义主函数spam执行以下步骤:
2 预料表与特征向量构建
- # 定义一个函数,用于创建词汇表
- def creatVocablist(doclist):
- vocabSet = set([]) # 创建一个空集合,用于存储所有文档中出现的不重复单词
- for document in doclist: # 遍历文档列表中的每个文档
- vocabSet = vocabSet | set(document) # 将文档中的单词添加到词汇表集合中(去重)
- return list(vocabSet) # 将词汇表集合转换为列表并返回
-
- # 定义一个函数,将文本数据转换为词向量
- def setOfWord2Vec(vocablist, inputSet):
- returnVec = [0] * len(vocablist) # 创建一个与词汇表长度相同的零向量
- for word in inputSet: # 遍历输入的单词列表
- if word in vocablist: # 如果单词在词汇表中出现
- returnVec[vocablist.index(word)] = 1 # 将词向量中对应位置的值设为1
- return returnVec # 返回生成的词向量
-
- # 定义主函数spam,处理垃圾邮件数据
- def spam():
- # ...
-
- vocablist = creatVocablist(doclist) # 创建词汇表
- trainSet = list(range(50)) # 创建训练集索引列表,初始包含前50个文档的索引
- testSet = [] # 创建测试集索引列表,初始为空
- for i in range(10): # 从训练集中随机选择10个样本作为测试集
- randIndex = int(random.uniform(0, len(trainSet))) # 随机选择一个索引
- testSet.append(trainSet[randIndex]) # 将选择的索引添加到测试集
- del(trainSet[randIndex]) # 在训练集中删除已选择的索引
- trainMat = [] # 创建训练矩阵,用于存储训练数据的词向量
- trainClass = [] # 创建训练类别标签列表,用于存储训练数据的类别
- for docIndex in trainSet: # 遍历训练集中的每个文档索引
- trainMat.append(setOfWord2Vec(vocablist, doclist[docIndex])) # 将文档转换为词向量并添加到训练矩阵
- trainClass.append(classlist[docIndex]) # 添加文档的类别标签
- p0Vec, p1Vec, p1 = trainNB(np.array(trainMat), np.array(trainClass)) # 使用朴素贝叶斯算法进行训练
- errorCount = 0 # 初始化错误计数器
- for docIndex in testSet: # 遍历测试集中的每个文档索引
- wordVec = setOfWord2Vec(vocablist, doclist[docIndex]) # 将测试文档转换为词向量
- if classifyNB(np.array(wordVec), p0Vec, p1Vec, p1) != classlist[docIndex]: # 使用贝叶斯分类器进行分类
- errorCount += 1 # 如果分类错误,错误计数加1
- print('当前10个测试样本,错了:', errorCount) # 输出错误计数
3 分类别统计词频
- # 定义朴素贝叶斯分类器的训练函数
- def trainNB(trainMat, trainClass):
- numTrainDocs = len(trainMat) # 训练文档的数量
- numWords = len(trainMat[0]) # 特征向量的长度(词汇表的大小)
- p1 = sum(trainClass) / float(numTrainDocs) # 计算类别1(垃圾邮件)的概率
-
- # 初始化类别0和类别1的计数器和分母
- p0Num = np.ones((numWords)) # 初始化类别0的计数器,进行拉普拉斯平滑处理
- p1Num = np.ones((numWords)) # 初始化类别1的计数器,进行拉普拉斯平滑处理
- p0Denom = 2 # 初始化类别0的分母,通常设置为类别个数
- p1Denom = 2 # 初始化类别1的分母,通常设置为类别个数
-
- for i in range(numTrainDocs): # 遍历训练文档
- if trainClass[i] == 1: # 如果文档属于垃圾邮件类别
- p1Num += trainMat[i] # 增加类别1的计数器,统计词汇在垃圾邮件中出现的次数
- p1Denom += sum(trainMat[i]) # 增加类别1的分母,统计垃圾邮件中的总词数
- else: # 如果文档属于非垃圾邮件类别
- p0Num += trainMat[i] # 增加类别0的计数器,统计词汇在非垃圾邮件中出现的次数
- p0Denom += sum(trainMat[i]) # 增加类别0的分母,统计非垃圾邮件中的总词数
-
- # 计算类别0和类别1中每个词汇的条件概率
- p0Vect = np.log(p0Num / p0Denom) # 类别0的条件概率向量
- p1Vect = np.log(p1Num / p1Denom) # 类别1的条件概率向量
-
- return p0Vect, p1Vect, p1 # 返回条件概率向量和类别1的概率
4 贝叶斯公式对数变换
- def trainNB(trainMat,trainClass):
- ......
- p1Vec = np.log(p1Num/p1Denom)
- p0Vec = np.log(p0Num/p0Denom)
- return p0Vec,p1Vec,p1
-
-
- def classifyNB(wordVec,p0Vec,p1Vec,p1_class):
- p1 = np.log(p1_class) + sum(wordVec*p1Vec)
- p0 = np.log(1.0 - p1_class) + sum(wordVec*p0Vec)
- if p0>p1:
- return 0
- else:
- return 1
贝叶斯公式的用途在于通过己知三个概率来推测第四个概率。它的内容是:在 B 出现的前提下,A 出现的概率等于 A 出现的前提下 B 出现的概率乘以 A 出现的概率再除以 B 出现的概率。通过联系 A 与 B,计算从一个事件发生的情况下另一事件发生的概率,即从结果上溯到源头(也即逆向概率)。总的来说,贝叶斯算法提供了一种基于概率的框架,可以有效地处理分类问题和概率估计问题。它的优点包括简单、易于实现,适用于各种数据类型,尤其在处理高维数据和大规模文本数据时表现出色。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。