美文网首页
机器学习实战三(朴素贝叶斯)

机器学习实战三(朴素贝叶斯)

作者: 人机分离机 | 来源:发表于2017-10-29 14:32 被阅读0次

一、概述

1. 原理:

  • 工作机制:

2. 优缺点

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

3.条件概论:

  • 在B的条件下A出现的概率。
    p(A|B)=p(AB)/p(B)
  • 交换条件中的条件与结果:
    p(B|A)=p(A|B)*p(B)/p(A)

4.贝叶斯决策理论的核心思想:

  • 选择具有最高概论的决策

5.朴素贝叶斯算法的两个假设:

  • (1)每个特征之间都是独立的,这就使得公式:
  • p((f1,f2,...fn)|c)=p(f1|c)p(f2|c)...p(fn|c)
  • (2)每个特征同等重要,我们拿文本分类做例子,把文档中的单词作为特征。这种假设使得我们在进行分类的过程中无需考虑单词出现的次数,只考虑单词出现与否。这也就贝叶斯算法的贝努利模型实现方式。
  • 注:贝叶斯的另一种实现方式为多项式模型,在这种模型中则需要考虑单词的出现次数。

二、算法流程

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

三、算法实践

1.问题

  • 对是否属于侮辱性文章进行分类

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']]
    # 标注每条数据的分类,这里0表示正常言论,1表示侮辱性留言
    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):
    # 创建一个跟词汇表(vocabList)等长的向量,并将其元素都设为0
    returnVec = [0]*len(vocabList)
    # 遍历输入,将含有词汇表单词的文档向量设为1
    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
命令行
>>> import bayes
>>> listOPosts,listClasses = bayes.loadDataSet()
>>> myVocabList = bayes.createVocabList(listOPosts)
>>> myVocabList
>>> bayes.setOfWords2Vec(myVocabList,listOPosts[0])
>>> bayes.setOfWords2Vec(myVocabList,listOPosts[3])

3.训练算法:从词向量计算概率

# 朴素贝叶斯分类器训练函数
# 输入参数trainMatrix表示输入的文档矩阵,trainCategory表示每篇文档类别标签所构成的向量
def trainNB0(trainMatrix,trainCategory):
    # 留言数目
    numTrainDocs=len(trainMatrix)
    # 变换矩阵的列数目,即词汇表数目
    numWords=len(trainMatrix[0])
    # 侮辱性留言的概率
    pAbusive=sum(trainCategory)/float(numTrainDocs)
    # 将所有词的出现数初始化为1,将分母初始化为2,从而降低计算多个概率的乘积结果为零的影响
    p0Num=ones(numWords)
    p1Num=ones(numWords)
    p0Denom=2.0
    p1Denom=2.0
    for i in range(numTrainDocs):
        # 统计每类单词的数目,注意我们这里讨论的是一个二分问题
        # 所以可以直接用一个if...else...即可,如果分类较多,则需要更改代码
        if trainCategory[i] == 1:
            p1Num += trainMatrix[i]
            p1Denom += sum(trainMatrix[i])
        else:
            p0Num += trainMatrix[i]
            p0Denom += sum(trainMatrix[i])
    # 对每个类别除以该类中的总词数
    # 防止下溢出
    p1Vec = log(p1Num/p1Denom)
    p0Vec = log(p0Num/p0Denom)
    # 函数返回两个概率向量,及一个概率
    return p0Vec, p1Vec, pAbusive
>>> import bayes
>>> listOPosts,listClasses = bayes.loadDataSet()
# 该语句从预先加载值中调入数据
>>> myVocabList = bayes.creatVocabList(listOPosts)
>>> trainMat=[]
>>> for postinDoc in listOPosts:
...   trainMat.append(bayes.setOfWords2Vec(myVocabList,postinDoc))
...
# 下面给出属于侮辱性文章的概论以及两个类别的概论向量
>>> p0V,p1V,pAb=bayes.trainNB0(trainMat,listClasses)
>>> pAb
>>> p0V
>>> p1V

4.测试算法: 朴素贝叶斯分类函数

# 朴素贝叶斯分类函数
def classifyNB(vec2Classify, p0Vec, p1Vec, pClass):
    p1 = sum(vec2Classify*p1Vec)+log(pClass)
    p0 = sum(vec2Classify*p0Vec)+log(1-pClass)
    if p1 > p0:
        return 1
    else:
        return 0
  • 该函数是用来测试(封装了一些操作)
#内嵌测试函数
def testingNB():
    listOPosts, listClasses=loadDataSet()
    myVocabList = createVocabList(listOPosts)
    trainMat = []
    for postinDoc in listOPosts:
      trainMat.append(setOfWords2Vec(myVocabList, postinDoc))
    p0V, p1V, p1 = trainNB0(trainMat, listClasses)
    testEntry = ['love', 'my', 'dalmation']
    thisDoc = setOfWords2Vec(myVocabList, testEntry)
    print(testEntry, "classified as:", classifyNB(thisDoc, p0V, p1V, p1))
    testEntry = ['garbage', 'stupid']
    thisDoc = setOfWords2Vec(myVocabList, testEntry)
    print(testEntry, "classified as:", classifyNB(thisDoc, p0V, p1V, p1))
命令行
import bayes
>>> bayes.testingNB()
['love', 'my', 'dalmation'] classified as: 0
['garbage', 'stupid'] classified as: 1

5.词袋模型的转换函数(准备数据中优化)

  • 之前的算法我们只考虑了单词出现与否,使用的是一种词集模型。
  • 贝叶斯有两种实现方式,另一种多项式模型,需要考虑每个单词出现的次数,就是所谓的词袋模型。
  • 为了适应这种词袋模型,我们需要对函数setOfWords2Vec作一下修改
#词袋模型的转换函数  
def bagOfWords2VecMN(vocabList,inputSet):  
    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  

四、示例:使用朴素贝叶斯进行垃圾邮件过滤

1.准备数据,切分文本

# 该函数将每个句子都解析成单词,并忽略空格,标点符号以及长度小于3的单词
def textParse(bigString):
    import re
    listOfTokens = re.split(r'\W*', bigString)
    return [tok.lower() for tok in listOfTokens if len(tok) > 2]

2.分类器

错误信息合集(参考)

# 检测垃圾邮件
def spamTest():
    # 存放输入数据
    docList = []
    #存放类别标签
    classList = []
    # 所有的文本
    fullText = []
    # 分别读取邮件内容
    for i in range(1, 26):
        wordList = textParse(open('email/spam/%d.txt' % i, "rb").read().decode('GBK','ignore') )
        docList.append(wordList)
        fullText.extend(wordList)
        classList.append(1)
        wordList = textParse(open('email/ham/%d.txt' % i,  "rb").read().decode('GBK','ignore') )
        docList.append(wordList)
        fullText.extend(wordList)
        classList.append(0)
    vocabList = createVocabList(docList)
    # range(50)表示从0到50,不包括50
    trainingSet = list(range(50))
    # 测试集
    testSet = []
    # 随机抽取是个作为测试集
    for i in range(10):
        # 从50个数据集中随机选取十个作为测试集,并把其从训练集中删除
        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
            print("Classification error:")
            print(docList[docIndex])
    print(errorCount)
    print("the error rate is:", float(errorCount)/len(testSet))

github代码

相关文章

  • 机器学习实战 朴素贝叶斯

    title: 朴素贝叶斯 机器学习实战date: 2019-07-28tags: 机器学习 贝叶斯categori...

  • 朴素贝叶斯法解析实践

    教材选用《统计学习方法》,第一版,李航著;代码取自《机器学习实战》,人民邮电出版社; 朴素贝叶斯介绍 朴素贝叶斯法...

  • 机器学习数学原理(4)——朴素贝叶斯模型

    机器学习数学原理(4)——朴素贝叶斯模型 朴素贝叶斯模型(Naive Bayes Model),是一种基于贝叶斯定...

  • 朴素贝叶斯

    学习机器学习最简单的算法可以说就是 朴素贝叶斯了,今天分享下自己的学习心得。 什么是贝叶斯,什么是朴素贝叶斯 贝叶...

  • 机器学习实战三(朴素贝叶斯)

    一、概述 1. 原理: 工作机制: 2. 优缺点 优点:在数据少的情况下有效,可以处理多类别问题 缺点: 对于输入...

  • 机器学习实战-朴素贝叶斯

    前两章我们要求分类器作出艰难的抉择,不过分类器有时候会产生错误,这时会产生错误结果,这是可以要求分类器给出一个最优...

  • 机器学习实战-朴素贝叶斯

    朴素贝叶斯算法(Naive Bayes) 前两章学习的knn和决策树分类都直接给出了答案,但是不能避免一些分类错误...

  • 机器学习实战-朴素贝叶斯

    对于特征向量,拥有标签,即分类个数。我们对每一类标签计算概率:然后取概率最大的那个标签作为我们的分类。 为了实现这...

  • 朴素贝叶斯法

    朴素贝叶斯法 朴素贝叶斯法的学习与分类 朴素贝叶斯法的参数估计 朴素贝叶斯实现 高斯朴素贝叶斯实现 使用 skle...

  • 朴素贝叶斯

    机器学习实战 朴素贝叶斯算法可以要求分类器给出一个最优的类别猜测结果,同时给出这个猜测的概率估计值。 基于贝叶斯决...

网友评论

      本文标题:机器学习实战三(朴素贝叶斯)

      本文链接:https://www.haomeiwen.com/subject/dwjypxtx.html