ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

朴素贝叶斯

2021-11-22 20:01:44  阅读:140  来源: 互联网

标签:__ 概率 append 贝叶斯 朴素 np 邮件


一、贝叶斯定理

1、简介

         贝叶斯理论是以18世纪的一位神学家托马斯贝叶斯(Thomas Bayes)命名。通常,事件A在事件B(发生)的条件下的概率,与事件B在事件A(发生)的条件下的概率是不一样的;然而,这两者是有确定的关系的,贝叶斯定理就是这种关系的陈述。

2、优缺点

        优点:在数据较少时仍有效,可处理多类别问题

        缺点:对输入数据准备方式较敏感。

 假设现在我们有一个数据集,它由两类数据组成,数据分布如下图所示:

         我们现在用p1(x,y)表示数据点(x,y)属于类别1(图中圆点表示的类别)的概率,用p2(x,y)表示数据点(x,y)属于类别2(图中三角形表示的类别)的概率,那么对于一个新数据点(x,y),可以用下面的规则来判断它的类别:

        如果p1(x,y) > p2(x,y),那么类别为1
        如果p1(x,y) < p2(x,y),那么类别为2


        也就是说,我们会选择高概率对应的类别。这就是贝叶斯决策理论的核心思想,即选择具有最高概率的决策。

        适用决策树不会非常成功,和简单的概率计算相比,KNN计算量太大,因此对于上述问题,最佳选择是概率比较方法。

        接下来,为了学习如何计算p1和p2概率,我们有必要讨论一下条件概率。

二、概率公式

1、条件概率

        条件概率是指事件A在事件B发生的条件下发生的概率。条件概率表示为:P(A|B),读作“A在B发生的条件下发生的概率”。若只有两个事件A,B,那么,

2、全概率公式

        若事件A1,A2,…构成一个完备事件组且都有正概率,则对任意一个事件B,有如下公式成立:

P(B)=P(BA1)+P(BA2)+...+P(BAn)=P(B|A1)P(A1) + P(B|A2)P(A2) + ... + P(B|An)P(An).

此公式即为全概率公式。

特别地,对于任意两随机事件A和B,有如下成立:

 

三、朴素贝叶斯

1、公式推导

通过条件概率公式变形得出公式:

我们把P(A)称为”先验概率”,即在B事件发生之前,我们对A事件概率的一个判断。

P(A|B)称为”后验概率”,即在B事件发生之后,我们对A事件概率的重新评估。

P(B|A)/P(B)称为”可能性函数”,这是一个调整因子,使得预估概率更接近真实概率。

先验概率是指根据以往经验和分析得到的概率,例如全概率公式 ,它往往作为“由因求果”问题中的“因”出现。后验概率是指在得到“结果”的信息后重新修正的概率,是“执果寻因”问题中的“因” 。后验概率是基于新的信息,来修正原来的先验概率后所获得的更接近实际情况的概率估计                

所以,条件概率可以理解成下面的式子:

后验概率=先验概率∗调整因子后验概率=先验概率∗调整因子
这就是贝叶斯推断的含义:我们先预估一个”先验概率”,然后加入实验结果,看这个实验到底是增强还是削弱了”先验概率”,由此得到更接近事实的”后验概率”。

如果”可能性函数”P(B|A)/P(B)>1,意味着”先验概率”被增强,事件A的发生的可能性变大;

如果”可能性函数”=1,意味着B事件无助于判断事件A的可能性;

如果”可能性函数”<1,意味着”先验概率”被削弱,事件A的可能性变小。

                                       

四、代码实现(垃圾邮件过滤)

1 流程说明
朴素贝叶斯分类器模型的训练:首先提供两组已经识别好的邮件,一组是正常邮件,另一组是垃圾邮件,然后用这两组邮件对过滤器进行“训练”。首先解析所有邮件,提取每一个词,然后计算每个词语在正常邮件和垃圾邮件中出现的概率。例如,我们假定“cute”这个词在词数(不重复)为4000的垃圾邮件中出现200次,那么该词在垃圾邮件中出现的频率就是5%;而在词数(不重复)为4000的正常邮件中出现1000次,那么该词在正常邮件中出现的频率就是25%。此时就已经初步建立了关于“cute”这个词的过滤模型。
使用朴素贝叶斯分类器模型进行过滤测试:读入一封未进行分类的新邮件,然后该邮件进行解析,发现其中包含了“cute”这个词,用P(W|S)和P(W|H)分别表示这个词在垃圾邮件和正常邮件中出现的概率。随后将邮件中解析出来的每个词(已建立对应的训练模型)属于正常邮件和垃圾邮件的概率分别进行累乘,最后比较该邮件属于正常邮件和垃圾邮件的概率大小,可将该邮件归类为概率较大的那一类。

2、构建词向量

我们把文本看成单词向量或者词条向量,也就是说将句子转换为向量。考虑出现在所有文档中的所有单词,再决定将哪些词纳入词汇表或者说所要的词汇集合,然后必须要将每一篇文档转换为词汇表上的向量。

# 创建实验样本
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):
    # 创建一个其中所含元素都为0的列表
    returnVec = [0]*len(vocabList)
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)] = 1
        else:
            print('the word: %s is not in my Vocabulary!' % word)
    return returnVec
if __name__ == '__main__':
    postingList, classVec = loadDataSet()
    myVocabList = createVocabList(postingList)
    print('myVocabList:\n', myVocabList)
    print(setOfWords2Vec(myVocabList, postingList[0]))

 3、词向量计算概率

记w表示一个向量(可理解为经过向量化后的一封邮件),它由多个数值组成。在该例中数值个数与词汇表中的词条个数相同,则贝叶斯公式可表示为:

                                                      

 

def trainNBO(trainMatrix,trainCategory):
    #文档数目(6)
    numTrainDocs = len(trainMatrix) 
    #词数
    numWords = len(trainMatrix[0])
    ##初始化概率     
    pAbusive = sum(trainCategory) / float(numTrainDocs)
    #使用zeros()初始化后的数组如果其中一个概率值为0则最后的结果也为0,因此使用ones() 
    # numpy中的ndarray对象用于存放同类型元素的多维数组。
    p0Num = np.ones(numWords)
    p1Num = np.ones(numWords)
    p0Denom = 2.0
    p1Denom = 2.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 = np.log(p1Num/p1Denom)
    p0Vect = np.log(p0Num/p0Denom)
    return p0Vect,p1Vect,pAbusive
if __name__ == '__main__':
    postingList, classVec = loadDataSet()
    myVocabList = createVocabList(postingList)
    trainMat = []
    for postinDoc in postingList:
        trainMat.append(setOfWords2Vec(myVocabList, postinDoc))
    p0Vect, p1Vect, pAbusive = trainNBO(trainMat, classVec)
    print('p0Vect:\n', p0Vect)
    print('p1Vect:\n', p1Vect)
    print('文档属于侮辱性文档的概率:', pAbusive)

4、朴素贝叶斯分类函数

def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1):
    p1 = sum(vec2Classify * p1Vec) + np.log(pClass1)
    p0 = sum(vec2Classify * p0Vec) + np.log(1.0 - pClass1)
    if p1 > p0:
        return 1
    else:
        return 0
if __name__ == '__main__':
    postingList, classVec = loadDataSet()
    myVocabList = createVocabList(postingList)
    trainMat = []
    for postinDoc in postingList:
        trainMat.append(setOfWords2Vec(myVocabList, postinDoc))
    p0V,p1V,pAb = trainNBO(np.array(trainMat),np.array(classVec))
    testEntry = ['love', 'my', 'dalmation']                                    
    thisDoc = np.array(setOfWords2Vec(myVocabList, testEntry))
    if classifyNB(thisDoc,p0V,p1V,pAb):
         print(testEntry,'属于侮辱类')
    else:
         print(testEntry,'属于非侮辱类')                                          
    testEntry = ['stupid', 'love', 'cute']                                    
    thisDoc = np.array(setOfWords2Vec(myVocabList, testEntry))                
    if classifyNB(thisDoc,p0V,p1V,pAb):
        print(testEntry,'属于侮辱类')
    else:
        print(testEntry,'属于非侮辱类')

 在这里插入图片描述

 5、使用朴素贝叶斯进行交叉验证

def bagOfWords2Vec(vocabList,inputSet):
    returnVec = [0] * len(vocabList)
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)] += 1
    return returnVec

def textParse(bigString):
    #将非数字、单词外的任意字符串作为切分标志
    listOfTokens = re.split('\\W*',bigString)       
    #为了使所有词的形式统一,除了单个字母,例如大写的I,其余的单词变成小写
    return [tok.lower() for tok in listOfTokens if len(tok) > 2]

def spamTest():
    docList = [];classList = [];fullTest = []
    #导入并解析50个文件,并记录对应的标签值,垃圾邮件标记为1
    for i in range(1,26):
        wordList = textParse(open('C:/Users/cool/Desktop/mach/email/spam/%d.txt'% i,'r').read())
        docList.append(wordList)
        fullTest.append(wordList)
        classList.append(1)
        wordList = textParse(open('C:/Users/cool/Desktop/mach/email/ham/%d.txt'% i,'r').read())
        docList.append(wordList)
        fullTest.append(wordList)
        classList.append(0)
    #获得50个文件构成的词列表
    vocabList = createVocabList(docList)
    trainingSet = list(range(50))
    testSet = []
    #随机选取测试集合,并从训练集中去除,留存交叉验证
    for i in range(10):
        randIndex = int(random.uniform(0,len(trainingSet)))
        testSet.append(trainingSet[randIndex])
        del(trainingSet[randIndex])
    trainMat = [];trainClass = []
    #构建训练集词向量列表,训练集标签
    for docIndex in trainingSet:
        trainMat.append(setOfWords2Vec(vocabList,docList[docIndex]))
        trainClass.append(classList[docIndex])
    #训练算法,计算分类所需的概率
    p0V,p1V,pSpam = trainNBO(np.array(trainMat),np.array(trainClass))
    #分类错误个数初始化为0
    errorCount = 0
    #,遍历测试集,验证算法错误率
    for docIndex in testSet:
        wordVector = setOfWords2Vec(vocabList,docList[docIndex]) 
        if classifyNB(np.array(wordVector),p0V,p1V,pSpam) != classList[docIndex]:
            errorCount += 1
    print('错误率:%.2f%%'%(float(errorCount)/len(testSet)*100))
if __name__ == '__main__':
    spamTest()

在这里插入图片描述

 

标签:__,概率,append,贝叶斯,朴素,np,邮件
来源: https://blog.csdn.net/shirakami00/article/details/121461270

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有