《机器学习实战》基于概率论的分类方法:朴素贝叶斯

本章内容

使用概率分布进行分类
学习朴素贝叶斯分类器
解析RSS源数据
使用朴素贝叶斯来分析不同地区的态度

朴素贝叶斯

优点:在数据较少的情况下仍然有效,可以处理多类别问题。
缺点:对于输入数据的准备方式较为敏感。
适用数据类型:标称型数据。

朴素贝叶斯是贝叶斯决策理论的一部分。
贝叶斯决策理论的核心思想是:选择具有最高概率的决策。
贝叶斯概率理论:贝叶斯概率引入先验知识和逻辑推理来处理不确定命题。另一种概率解释称为频数概率,它只从数据本身获得结论,并不考虑逻辑推理及先验知识。
使用贝叶斯准则来交换概率中条件与结果:
在这里插入图片描述
朴素贝叶斯分类器中的一个假设:每个特征同等重要

示例一:文档分类

朴素贝叶斯的一般过程
(1)收集数据:可以使用任何方法。本章使用RSS源。
(2)准备数据:需要数值型或布尔型数据。
(3)分析数据:有大量特征时,绘制特征作用不大,此时使用直方图效果更好。
(4)训练算法:计算不同的独立特征的条件概率。
(5)测试算法:计算错误率。
(6)使用算法:一个常见的朴素贝叶斯应用是文档分类。可以在任意的分类场景中使用朴素贝叶斯分类器,不一定非要是文本。

'''----------------------------程序一:词集模型(示例1:文档分类)-------------------------------'''
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
'''
@Project -> File   :ML_in_action -> bayes
@IDE    :PyCharm
@Author :NatW
@Date   :2019/11/27 13:58'''

from numpy import *
# 示例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]    #1 代表侮辱性文字,0 代表正常言论
    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:
            returnVec[vocabList.index(word)] = 1
        else: print('the world: %s is not in my Vocabulary!'%word)
    return returnVec

# 训练算法:从词向量计算概率
# 朴素贝叶斯分类器训练函数
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
    # 拉普拉斯平滑解决问题:多个乘积相乘,不被一个为零的数影响
    p0Num = ones(numWords);p1Num = 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 = p1Num/p1Denom
    # p0Vect = p0Num/p0Denom
    # 用对数运算处理下溢出问题
    p1Vect = log(p1Num/p1Denom)
    p0Vect = log(p0Num/p0Denom)
    return p0Vect,p1Vect,pAbusive

def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1):
    p1 = sum(vec2Classify*p1Vec)+log(pClass1)
    p0 = sum(vec2Classify*p0Vec)+log(1.0-pClass1)
    if p1 > p0: return 1
    else:return 0

#   测试算法
def testingNB():
    # 训练:准备数据
    listOPosts, listClasses = loadDataSet()
    myVocabList = createVocabList(listOPosts)
    # print(myVocabList)
    # 测试:训练算法
    trainMat = []
    for postinDoc in listOPosts:
        trainMat.append(setOfWords2Vec(myVocabList, postinDoc))
    # p0v,p1v,pAb = trainNB0(trainMat,listClasses)
    p0v, p1v, pAb = trainNB0(array(trainMat), array(listClasses))
    # print(pAb);print(p0v);print(p1v)
    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))

if __name__ == '__main__':
    testingNB()
示例二:使用朴素贝叶斯过滤垃圾邮件

收集数据:提供文本文件。
准备数据:将文本解析成词条向量
分析数据:检查词条确保解析的正确性
训练算法:使用我们之前建立的trainNB0()函数
测试算法:使用classsifyNB(),并且构建一个新的测试函数来计算文档集的错误率
使用算法:构建一个完整的程序对一组文档进行分类,将错分的文档输出到屏幕上。

from numpy import *
# 示例2:垃圾邮件过滤
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:
            returnVec[vocabList.index(word)] = 1
        else: print('the world: %s is not in my Vocabulary!'%word)
    return returnVec
# 词袋模型
def bagOfWords2Vec(vocabList,inputSet):
    returnVec = [0]*len(vocabList)      #创建一个其中所含元素都为0的向量
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)] += 1
    return returnVec


# 训练算法:从词向量计算概率
# 朴素贝叶斯分类器训练函数
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
    # 拉普拉斯平滑解决问题:多个乘积相乘,不被一个为零的数影响
    p0Num = ones(numWords);p1Num = 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 = p1Num/p1Denom
    # p0Vect = p0Num/p0Denom
    # 用对数运算处理下溢出问题
    p1Vect = log(p1Num/p1Denom)
    p0Vect = log(p0Num/p0Denom)
    return p0Vect,p1Vect,pAbusive

def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1):
    p1 = sum(vec2Classify*p1Vec)+log(pClass1)
    p0 = sum(vec2Classify*p0Vec)+log(1.0-pClass1)
    if p1 > p0: return 1
    else:return 0

# 测试算法:使用朴素贝叶斯进行交叉验证
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=[]
    for i in range(1,26):
        wordList = textParse(open('email/spam/%d.txt'%i).read())
        docList.append(wordList)
        fullText.extend(wordList)
        classList.append(1)     # 垃圾邮件
        wordList = textParse(open('email/ham/%d.txt'%i).read())
        docList.append(wordList)
        fullText.extend(wordList)
        classList.append(0)     # 非垃圾广告邮件
    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=[];trainClasses=[]
    for docIndex in trainingSet:
        trainMat.append(setOfWords2Vec(vocablist,docList[docIndex]))
        trainClasses.append(classList[docIndex])
    p0V,p1V,pSpam = trainNB0(array(trainMat),array(trainClasses))
    errorCount = 0
    for docIndex in testSet:
        wordVector = setOfWords2Vec(vocablist,docList[docIndex])
        if classifyNB(array(wordVector),p0V,p1V,pSpam) != classList[docIndex]:
            errorCount += 1
    errorRate = float(errorCount)/len(testSet)
    print('the error rate is: %.3f'%errorRate)
    return errorRate

#   测试算法
if __name__ == '__main__':
    errorRateSum = 0.0
    for i in range(10):
        errorRate = spamTest()
        errorRateSum += errorRate
    errorRateAvg = float(errorRateSum)/10.0
    print(errorRateAvg)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值