机器学习—朴素贝叶斯(Naive Bayes)

朴素贝叶斯概述

朴素贝叶斯是一种简单但功能惊人的预测建模算法。
该模型由两种可以直接从训练数据中计算的概率组成: 1) 每个类的概率; 2) 给定每个x值后每个类的条件概率。 一旦计算出概率模型,就可以用贝叶斯定理对新数据进行预测。当你的数据是实值时,通常假设一个高斯分布(钟形曲线),这样你就可以很容易地估计这些概率。

机器学习—朴素贝叶斯(Naive Bayes)_第1张图片
朴素贝叶斯(Naive Bayes)

朴素贝叶斯之所以称“朴素”,是因为它假设每个输入变量是独立的。这对于真实数据来说是一个很强的、不切实际的假设,然而,该技术对于大量复杂问题非常有效。

举个在 NLP (Natural Language Processing)的应用

给一段文字,返回情感分类,这段文字的态度是positive,还是negative。


机器学习—朴素贝叶斯(Naive Bayes)_第2张图片

为了解决这个问题,可以只看其中的一些单词。


机器学习—朴素贝叶斯(Naive Bayes)_第3张图片

这段文字,将仅由一些单词和它们的计数代表。
机器学习—朴素贝叶斯(Naive Bayes)_第4张图片

原始问题是:给你一句话,它属于哪一类,
通过 bayes rules 变成一个比较简单容易求得的问题。


机器学习—朴素贝叶斯(Naive Bayes)_第5张图片

问题变成,这一类中这句话出现的概率是多少,当然,别忘了公式里的另外两个概率。
栗子:单词 love 在 positive 的情况下出现的概率是 0.1,在 negative 的情况下出现的概率是 0.001。


机器学习—朴素贝叶斯(Naive Bayes)_第6张图片

朴素贝叶斯分类算法案例

大体计算方法:
P(好评 | 单词1,单词2,单词3) = P(单词1,单词2,单词3 | 好评) * P(好评) / P(单词1,单词2,单词3)
因为分母都相同,所以只用比较分子即可--->P(单词1,单词2,单词3 | 好评) P(好评)
每个单词之间都是相互独立的---->P(单词1 | 好评)P(单词2 | 好评)P(单词3 | 好评)*P(好评)
P(单词1 | 好评) = 单词1在样本好评中出现的总次数/样本好评句子中总的单词数
P(好评) = 样本好评的条数/样本的总条数

同理:
P(差评 | 单词1,单词2,单词3) = P(单词1,单词2,单词3 | 差评) * P(差评) / P(单词1,单词2,单词3)
因为分母都相同,所以只用比较分子即可--->P(单词1,单词2,单词3 | 差评) P(差评)
每个单词之间都是相互独立的---->P(单词1 | 差评)P(单词2 | 差评)P(单词3 | 差评)*P(差评)

#!/usr/bin/python
# coding=utf-8
from numpy import *

# 过滤网站的恶意留言  侮辱性:1     非侮辱性:0
# 创建一个实验样本
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:
            # returnVec[vocabList.index(word)] = 1     # index函数在字符串里找到字符第一次出现的位置  词集模型
            returnVec[vocabList.index(word)] += 1      # 文档的词袋模型    每个单词可以出现多次
        else: print("the word: %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);   # 避免一个概率值为0,最后的乘积也为0
    p1Num = ones(numWords);   # 用来统计两类数据中,各词的词频
    p0Denom = 2.0;  # 用于统计0类中的总数
    p1Denom = 2.0  # 用于统计1类中的总数
    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)    # 在类1中,每个次的发生概率
    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)
    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))

# 调用测试方法----------------------------------------------------------------------
testingNB()

运行结果:


机器学习—朴素贝叶斯(Naive Bayes)_第7张图片

朴素贝叶斯算法小结

朴素贝叶斯算法的主要原理基本已经做了总结,这里对朴素贝叶斯的优缺点做一个总结。

朴素贝叶斯的主要优点有

  • 1)朴素贝叶斯模型发源于古典数学理论,有稳定的分类效率。
  • 2)对小规模的数据表现很好,能个处理多分类任务,适合增量式训练,尤其是数据量超出内存时,我们可以一批批的去增量训练。
  • 3)对缺失数据不太敏感,算法也比较简单,常用于文本分类。

朴素贝叶斯的主要缺点有

  • 1) 理论上,朴素贝叶斯模型与其他分类方法相比具有最小的误差率。但是实际上并非总是如此,这是因为朴素贝叶斯模型给定输出类别的情况下,假设属性之间相互独立,这个假设在实际应用中往往是不成立的,在属性个数比较多或者属性之间相关性较大时,分类效果不好。而在属性相关性较小时,朴素贝叶斯性能最为良好。对于这一点,有半朴素贝叶斯之类的算法通过考虑部分关联性适度改进。
  • 2)需要知道先验概率,且先验概率很多时候取决于假设,假设的模型可以有很多种,因此在某些时候会由于假设的先验模型的原因导致预测效果不佳。
  • 3)由于我们是通过先验和数据来决定后验的概率从而决定分类,所以分类决策存在一定的错误率。
  • 4)对输入数据的表达形式很敏感。

以上就是朴素贝叶斯算法的一个总结,希望可以帮到朋友们。

你可能感兴趣的:(机器学习—朴素贝叶斯(Naive Bayes))