机器学习之朴素贝叶斯分类

作用

贝叶斯 常用来做分类任务。比如 判断 垃圾邮件 ,拼写纠错 等任务。

熟悉以前所学的概念

在这里插入图片描述

S:S是样本空间,是所有可能事件的总和。
P(A):是样本空间S中A事件发生的概率,维恩图中绿色的部分。
P(B):是样本空间S中B事件发生的概率,维恩图中蓝色的部分。
P(A∩B):是样本空间S中A事件和B事件同时发生的概率,也就是A和B相交的区域。
P(A|B):是条件概率,是B事件已经发生时A事件发生的概率。

公式

在这里插入图片描述

条件 概率 解释:

P(A|B)

已知 B 发生的情况下 A 发生的概率 是多少?
P(“具有某特征”|“属于某类”)

如下图:
我们经常收到邮件 ,邮件中有很多词语 ,我们怎么判断 这个邮件是垃圾邮件呢?

假如 邮件中 含有 买房 , 贷款 ,办理 , 优惠 只含有这4个词 。

那么在条件概率下 分类 :垃圾邮件 , 正常邮件 二分类 。

特征就有: 买房 , 贷款 ,办理 , 优惠   4个特征。

在这里插入图片描述

在如下图: 比如 在垃圾邮件中  各个词 出现的次数: 总共加起来都是 10次。为了方便计算。

在这里插入图片描述
垃圾邮件:
以下都是约等于 。

P(垃圾邮件) = 22/40= 0.55

P( “”买房“” | 垃圾邮件) = 5 / 22 = 0.22 ;

P( “”办理“” | 垃圾邮件) = 6 / 22 = 0.28 ;

P( “”贷款“” | 垃圾邮件) = 7 / 22 = 0.32 ;

P( “”优惠“” | 垃圾邮件) = 4 / 22 = 0.18;

正常邮件:

P(正常邮件) =18 /40= 0.45
P( “”买房“” | 正常邮件) = 5 / 18 = 0.28 ;

P( “”办理“” | 正常邮件) = 4 / 18 = 0.22 ;

P( “”贷款“” | 正常邮件) = 3 / 18 = 0.17 ;

P( “”优惠“” | 正常邮件) = 6 / 18 = 0.33 ;

全概率公式解释:

全概率公式:P(A)

P( “”买房“”) = P( “”买房“” | 垃圾邮件) * P(垃圾邮件) + P( “”买房“” | 正常邮件) P(正常邮件) = 0.550.22+0.45*0.28 = 0.25

P( “”买房“”) =买房的数字 / 总词 数 = 10/40=0.25

所以计算 应该正确。

贝叶斯 公式 解释:

贝叶斯公式:P(Bi|A)

P( 垃圾邮件 | “”买房“”) 已知 特征 买房 这个词 出现的时候 求 是垃圾邮件的概率?
这是上面的 已知 和未知 反过来 求 分类 。

在这里插入图片描述

这也常称为 逆概思想

根据
在这里插入图片描述

P( 垃圾邮件 | “”买房“”) = P( “”买房“ | “垃圾邮件”) * P(“垃圾邮件”) / ( p(“买房")) = 0.22 *0.55 / 0.25 = 0.484

这只是根据一个词的 预测 文中 有很多个词。

P( 垃圾邮件 | “”买房“”, “办理“”,“”贷款“”,“”优惠“”) = P( “”买房“,“”办理“”,“”贷款“”,“”优惠“ | “垃圾邮件”) * P(“垃圾邮件”) / ( p(“”买房“,“”办理“”,“”贷款“”,“”优惠“))

朴素贝叶斯

P( “”买房“,“”办理“”,“”贷款“”,“”优惠“ | “垃圾邮件”) 这个概率 我们之前 没有求解过 也不知道 求解起来也麻烦 。

假设 各词之间 相互 独立的 。

P( “”买房“,“”办理“”,“”贷款“”,“”优惠“ | “垃圾邮件”) =P( “”买房“ | “垃圾邮件”) * P( “”办理“ | “垃圾邮件”) * P( “”贷款“ | “垃圾邮件”)* P( “”优惠“ | “垃圾邮件”)

这也称为 : 贝叶斯公式下面的各种特征条件 互相独立 没有影响 就称为 朴素贝叶斯 。

也大大简化了 公式难度。

判断 垃圾还是正常

我们求解 这封邮件 到底是 垃圾 还是 正常 邮件 通过对比:

P( 垃圾邮件 | “”买房“”, “办理“”,“”贷款“”,“”优惠“”) > P( 正常邮件 | “”买房“”, “办理“”,“”贷款“”,“”优惠“”)

表示 为 垃圾邮件 反之 正常邮件 。

因为

P( 垃圾邮件 | “”买房“”, “办理“”,“”贷款“”,“”优惠“”) = P( “”买房“,“”办理“”,“”贷款“”,“”优惠“ | “垃圾邮件”) * P(“垃圾邮件”) / ( p(“”买房“,“”办理“”,“”贷款“”,“”优惠“))

P( 正常邮件 | “”买房“”, “办理“”,“”贷款“”,“”优惠“”) = P( “”买房“,“”办理“”,“”贷款“”,“”优惠“ | “正常邮件”) * P(“正常邮件”) / ( p(“”买房“,“”办理“”,“”贷款“”,“”优惠“))

分母 都一样 所以 只用对比 分子 。

P( “”买房“,“”办理“”,“”贷款“”,“”优惠“ | “垃圾邮件”) * P(“垃圾邮件”) > P( “”买房“,“”办理“”,“”贷款“”,“”优惠“ | “正常邮件”) * P(“正常邮件”)

根据 朴素贝叶斯:

P( 垃圾邮件 | “”买房“”, “办理“”,“”贷款“”,“”优惠“”) ~= P( “”买房“ | “垃圾邮件”) * P( “”办理“ | “垃圾邮件”) * P( “”贷款“ | “垃圾邮件”)* P( “”优惠“ | “垃圾邮件”) * P(“垃圾邮件”)

P(垃圾邮件) = 22/40= 0.55

P( “”买房“” | 垃圾邮件) = 5 / 22 = 0.22 ;

P( “”办理“” | 垃圾邮件) = 6 / 22 = 0.28 ;

P( “”贷款“” | 垃圾邮件) = 7 / 22 = 0.32 ;

P( “”优惠“” | 垃圾邮件) = 4 / 22 = 0.18;

约等于 0.00195

P( “”买房“,“”办理“”,“”贷款“”,“”优惠“ | “正常邮件”) * P(“正常邮件”)

正常邮件:

P(正常邮件) =18 /40= 0.45
P( “”买房“” | 正常邮件) = 5 / 18 = 0.28 ;

P( “”办理“” | 正常邮件) = 4 / 18 = 0.22 ;

P( “”贷款“” | 正常邮件) = 3 / 18 = 0.17 ;

P( “”优惠“” | 正常邮件) = 6 / 18 = 0.33 ;

约等于 0.00155

0.00195 > 0.00155

所以 当同时 出现

“”买房“”, “办理“”,“”贷款“”,“”优惠“ 这些词的时候 大概上就能猜测是垃圾邮件 。

贝叶斯推断:

贝叶斯推断可以说明贝叶斯定理中两个条件概率之间的关系。换句话说就是我们为什么可以通过P(A|B),P(A),和P(B)三个概率计算出P(B|A)发生的概率。

在贝叶斯推断中,每一种概率都有一个特定的名字:

在这里插入图片描述

P(B)是”先验概率”(Prior probability)。
P(A)是”先验概率”(Prior probability),也作标准化常量(normalized constant)。
P(A|B)是已知B发生后A的条件概率,叫做似然函数(likelihood)。
P(B|A)是已知A发生后B的条件概率,是我们要求的值,叫做后验概率。
P(A|B)/P(A)是调整因子,也被称作标准似然度(standardised likelihood)。
贝叶斯推断中有几个关键的概念需要说明下:

第一个是先验概率,先验概率是指我们主观通过事件发生次数对概率的判断。
第二个是似然函数,似然函数是对某件事发生可能性的判断,与条件概率正好相反。通过事件已经发生的概率推算事件可能性的概率。
维基百科中对似然函数与概率的解释:
概率: 是给定某一参数值,求 某一结果的可能性 。

例如,抛一枚匀质硬币,抛10次,6次正面向上的可能性多大?

似然函数 :给定某一结果,求某一参数值的可能性。

例如,抛一枚硬币,抛10次,结果是6次正面向上,其是匀质的可能性多大?

第三个是调整因子:调整因子是似然函数与先验概率的比值,这个比值相当于一个权重,用来调整后验概率的值,使后验概率更接近真实概率。调整因子有三种情况,大于1,等于1和小于1。
调整因子P(A|B)/P(A)>1:说明事件可能发生的概率要大于事件已经发生次数的概率。
调整因子P(A|B)/P(A)=1:说明事件可能发生的概率与事件已经发生次数的概率相等。
调整因子P(A|B)/P(A)<1:说明事件可能发生的概率与事件小于已经发生次数的概率。
因此,贝叶斯推断可以理解为通过先验概率和调整因子来获得后验概率。其中调整因子是根据事件已经发生的概率推断事件可能发生的概率(通过硬币正面出现的次数来推断硬币均匀的可能性),并与已经发生的先验概率(硬币正面出现的概率)的比值。通过这个比值调整先验概率来获得后验概率。

后验概率 = 先验概率 x 调整因子

代码实践

思路:

1, 准备数据 词汇 和 标签
2,将每一个 单词 用 词袋 模型 表示 我们先用 最简单的表示方式:
比如 一句话中 各种词出现的次数 那么用下面这个向量表示 这个句子。
买房“”, “办理“”,“”贷款“”,“”优惠

1 0 0 1

多句话 就表示成矩阵 。
1001
1101
0011
3, 求解 每一个词 在 正常言论 和 侮辱言论中的概率。

4,预测 用贝叶斯 求解 当来了 一个 新句子 里面 各种词的 出现在
侮辱言论中的概率 和 正常言论 的概率 然后对比。 求解是 不是正常言论。

注意:代码中 对比 是用的 取log 避免了小数点溢出问题。  都取log 对比起来好对比。

#coding=utf-8

from numpy import *

def loadDataSet():
    '''
    postingList: 进行词条切分后的文档集合
    classVec:类别标签    
    '''
    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([])#使用set创建不重复词表库
    for document in dataSet:
        vocabSet = vocabSet | set(document) #创建两个集合的并集
    return list(vocabSet)

def setOfWords2Vec(vocabList, inputSet):
    returnVec = [0]*len(vocabList)#创建一个所包含元素都为0的向量
    #遍历文档中的所有单词,如果出现了词汇表中的单词,则将输出的文档向量中的对应值设为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
'''
我们将每个词的出现与否作为一个特征,这可以被描述为词集模型(set-of-words model)。
如果一个词在文档中出现不止一次,这可能意味着包含该词是否出现在文档中所不能表达的某种信息,
这种方法被称为词袋模型(bag-of-words model)。
在词袋中,每个单词可以出现多次,而在词集中,每个词只能出现一次。
为适应词袋模型,需要对函数setOfWords2Vec稍加修改,修改后的函数称为bagOfWords2VecMN
'''
def bagOfWords2VecMN(vocabList, inputSet):
    returnVec = [0]*len(vocabList)
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)] += 1
    return returnVec



def trainNB0(trainMatrix,trainCategory):
    '''
    朴素贝叶斯分类器训练函数(此处仅处理两类分类问题)
    trainMatrix:文档矩阵
    trainCategory:每篇文档类别标签
    '''
    numTrainDocs = len(trainMatrix)
    numWords = len(trainMatrix[0])
    pAbusive = sum(trainCategory)/float(numTrainDocs)
    #初始化所有词出现数为1,并将分母初始化为2,避免某一个概率值为0
    p0Num = ones(numWords); p1Num = ones(numWords)#
    p0Denom = 2.0; p1Denom = 2.0 #

    '''
     稀疏矩阵中  每一个单词 在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])

    print("p1Num==",p1Num,p1Denom)
    #将结果取自然对数,避免下溢出,即太多,很小的数相乘造成的影响
    p1Vect = log(p1Num/p1Denom)#change to log()
    p0Vect = log(p0Num/p0Denom)#change to log()
    return p0Vect,p1Vect,pAbusive




def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
    '''
    分类函数
    vec2Classify:要分类的向量
    p0Vec, p1Vec, pClass1:分别对应trainNB0计算得到的3个概率
    '''
    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))

    print("trainMat==",trainMat)
    print("listClasses==",listClasses)
    #训练模型,注意此处使用array
    p0V,p1V,pAb = trainNB0(array(trainMat),array(listClasses))

    print(p0V,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))

    print("thisDoc ==",thisDoc)



testingNB()

参考文献

https://www.tuicool.com/articles/F3Ujemi

https://blog.csdn.net/qq_39422642/article/details/78389063

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值