一、贝叶斯定理
贝叶斯定理由英国数学家贝叶斯 ( Thomas Bayes 1702-1761 ) 发展,用来描述两个条件概率之间的关系,比如 P(A|B) 和 P(B|A)。按照乘法法则,可以立刻导出:
P(A∩B) = P(A)P(B|A)=P(B)P(A|B)。如上公式也可变形为:P(A|B)=P(B|A)*P(A)/P(B)。
二、朴素贝叶斯分类器
先验概率P(X):先验概率是指根据以往经验和分析得到的概率。
后验概率P(Y|X):事情已发生,要求这件事情发生的原因是由某个因素引起的可能性的大小,后验分布P(Y|X)表示事件X已经发生的前提下,事件Y发生的概率,称事件X发生下事件Y的条件概率。
后验概率P(X|Y):在已知Y发生后X的条件概率,也由于知道Y的取值而被称为X的后验概率。
朴素:朴素贝叶斯算法是假设各个特征之间相互独立,也是朴素这词的意思,那么贝叶斯公式中的P(X|Y)可写成:
朴素贝叶斯公式:
朴素贝叶斯分类器:朴素贝叶斯分类器(Naïve Bayes Classifier)采用了“属性条件独立性假设” ,即每个属性独立地对分类结果发生影响。为方便公式标记,不妨记P(C=c|X=x)为P(c|x),基于属性条件独立性假设,贝叶斯公式可重写为:
三、朴素贝叶斯分类的优缺点:
优点:
1、对待预测样本进行预测,过程简单速度快。
2、对于多分类问题也同样很有效,复杂度也不会有大程度上升。
3、在分布独立这个假设成立的情况下效果好。
4、对于类别类的输入特征变量效果好。
缺点:
1、对于测试集中的一个类别变量特征,如果在训练集里没见过,直接算的话概率就是0了,预测功能就失效了。
2、朴素贝叶斯有分布独立的假设前提。
四、拉普拉斯修正
由于若某个属性值在训练集中没有与某个类同时出现过,则训练后的模型会出现 over-fitting 现象,为了避免其他属性携带的信息,被训练集中未出现的属性值“抹去”,在估计概率值时通常要进行“拉普拉斯修正”:令 N 表示训练集 D 中可能的类别数,𝑁_𝑖表示第i个属性可能的取值数,则贝叶斯公式可修正为:
五、实现垃圾邮件分类
1、准备数据:从文本中构建词向量
点击查看代码
def loadDataSet():
postingList=[['my', 'dog', 'has', 'flea', 'problems', 'help', 'please'],
['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'],
['my', 'dalmation', 'is', 'so', 'cute', 'I', 'love', 'him'],
['stop', 'posting', 'stupid', 'worthless', 'garbage'],
['mr', 'licks', 'ate', 'my', 'steak', 'how', 'to', 'stop', 'him'],
['quit', 'buying', 'worthless', 'dog', 'food', 'stupid']]
classVec = [0, 1, 0, 1, 0, 1]
return postingList, classVec
# 创建不重复词库列表
def createVocabList(dataSet):
vocabSet = set([]) #创建一个空集
for document in dataSet:
vocabSet = vocabSet | set(document) #创建两个集合的并集
return list(vocabSet)
# 输出文档向量
def setOfWords2Vec(vocabList, inputSet):
returnVec = [0]*len(vocabList) #创建一个元素都为0的向量
#遍历数据集单词
for word in inputSet:
#存在单词在词袋中则
if word in vocabList:
#index用于找到第一个与之匹配的下标
returnVec[vocabList.index(word)] = 1
else:
print ("the word: %s is not in my Vocabulary!" % word)
return returnVec
2、训练算法:从词向量计算概率
伪代码如下:
计算每个类别中的文档数目
对每篇训练文档:
对每个类别:
如果词条出现在文档中->增加该词条的计数值
增加所有词条的计数值
对每个类别:
对每个词条:
将该词条的数目除以总词条的数目得到条件概率
返回每个类别的条件概率
代码如下:
点击查看代码
def trainNB0(trainMatrix,trainCategory):
numTrainDocs = len(trainMatrix)
numWords = len(trainMatrix[0])
pAbusive = sum(trainCategory)/float(numTrainDocs)
# 初始化概率
p0Num = zeros(numWords); p1Num = zeros(numWords)
p0Denom = 0.0; p1Denom = 0.0
# 遍历文档,向量相加
for i in range(numTrainDocs):
if trainCategory[i] == 1: # 侮辱类文档,向量相加
p1Num += trainMatrix[i]
p1Denom += sum(trainMatrix[i])
else: # 非侮辱类文档向量相加
p0Num += trainMatrix[i]
p0Denom += sum(trainMatrix[i])
p1Vect = p1Num/p1Denom # 各个单词在侮辱类中出现的概率
p0Vect = p0Num/p0Denom # 各个单词在非侮辱类中出现的概率
return p0Vect,p1Vect,pAbusive
点击查看代码
def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
#计算abusive的概率
p1 = sum(vec2Classify * p1Vec) + log(pClass1)
#计算not abusive概率
p0 = sum(vec2Classify * p0Vec) + log(1.0 - pClass1)
#看哪个概率大
if p1 > p0:
return 1
else:
return 0
def testingNB():
# test_list=[]; test_class=[0,1]
#加载数据集
listOPosts,listClasses = loadDataSet()
#创建词汇袋
myVocabList = createVocabList(listOPosts)
trainMat=[]
for postinDoc in listOPosts:
trainMat.append(setOfWords2Vec(myVocabList, postinDoc))
p0V,p1V,pAb = trainNB0(array(trainMat),array(listClasses))
testEntry = ['love', 'my', 'dalmation']
thisDoc = array(setOfWords2Vec(myVocabList, testEntry))
print (testEntry,'classified as: ',classifyNB(thisDoc,p0V,p1V,pAb))
testEntry = ['stupid', 'garbage']
thisDoc = array(setOfWords2Vec(myVocabList, testEntry))
print (testEntry,'classified as: ',classifyNB(thisDoc,p0V,p1V,pAb))
效果截图:
文件解析及完整的垃圾邮件测试函数
点击查看代码
def textParse(bigString):
import re
listOfTokens = re.split(r'\W+', bigString)
return [tok.lower() for tok in listOfTokens if len(tok) > 2]
def spamTest():
# 定义docList文档列表,classList类别列表,fullText所有文档词汇
docList=[]; classList = []; fullText =[]
#遍历文件夹内文件
for i in range(1,26):
# 定义并读取垃圾邮件文件的词汇分割列表
wordList = textParse(open('D:\\email/spam/%d.txt' % i).read())
# 将词汇列表加到文档列表中
docList.append(wordList)
# 将所有词汇列表汇总到fullText中
fullText.extend(wordList)
# 文档类别为1,spam
classList.append(1)
# 读取非垃圾邮件的文档
wordList = textParse(open('D:\\email/ham/%d.txt' % i).read())
# 添加到文档列表中,注意append和extend的区别,append直接加列表,extend加元素
docList.append(wordList)
# 添加到所有词汇列表中
fullText.extend(wordList)
# 类别为0,非垃圾邮件
classList.append(0)
# 创建词汇列表
vocabList = createVocabList(docList)
# 定义训练集的索引和测试集
trainingSet = list(range(50)); testSet=[]
# 随机的选择10个作为测试集
for i in range(10):
#随机索引
randIndex = int(random.uniform(0,len(trainingSet)))
#将随机选择的文档加入测试集
testSet.append(trainingSet[randIndex])
#从训练集中删除随机选择的文档
del(trainingSet[randIndex])
#定义训练集的矩阵和类别
trainMat=[]; trainClasses = [];
# test_list=[];test_class=[]
#遍历训练集,求先验概率和条件概率
for docIndex in trainingSet:
#将词汇列表变成向量放到trainList中
trainMat.append(bagOfWords2VecMN(vocabList, docList[docIndex]))
#添加训练集的类标签
trainClasses.append(classList[docIndex])
#计算先验概率,条件概率
p0V,p1V,pSpam = trainNB0(array(trainMat),array(trainClasses))
errorCount = 0
#对测试集分类
for docIndex in testSet: #classify the remaining items
#将测试集向量化
wordVector = bagOfWords2VecMN(vocabList, docList[docIndex]) #bagOfWords2VecMN函数将词汇向量化和计算次数 setOfWords2Vec将词汇向量化
# 对测试数据进行分类
if classifyNB(array(wordVector),p0V,p1V,pSpam) != classList[docIndex]:
#错误的话错误计数加一
errorCount += 1
print( "classification error",docList[docIndex])
print ('the error rate is: ',float(errorCount)/len(testSet))
print('错误率:%.2f%%' % (float(errorCount) / len(testSet) * 100))
return vocabList,fullText
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏
· Manus爆火,是硬核还是营销?