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

分类器可能产生错误分类,要求分类器给出一个最优的类别猜测结果并给出这个猜测的概率估计值。

朴素贝叶斯的特点:

优点:在数据较少的情况下依然有效,可以处理多类别问题;

缺点:对于输入数据的准备方式较为敏感;

适用数据类型:标称型数据

条件概率:在A条件下发生B结果的概率:

P(B|A) = P(A&B)/P(A)  在A条件下发生B结果的概率等于A和B同时发生的概率除以A发生的概率

P(A&B) = P(A)*P(B|A)  A和B同时发生的概率等于A发生的概率乘以A条件下B发生的概率

P(A&B) = P(A)*P(B|A)=P(B)*P(A|B)

贝叶斯公式:

P(B|A)=P(B)*P(A|B)/P(A)  

P(c1|x,y)  给定某个由(x,y)表示的数据点,那么该数据点来自类别c1的概率

P(c2|x,y)  给定某个由(x,y)表示的数据点,那么该数据点来自类别c2的概率

计算公式:

P(ci|x,y)=p(x,y|ci)*P(ci)/P(x,y)

判定原则:
如果P(c1|x,y)>P(c2|x,y),那么类别属于c1

如果P(c1|x,y)<P(c2|x,y),那么类别属于c2



朴素贝叶斯:整个形式化过程只做最原始最简单的假设。

使用朴素贝叶斯进行文档分类:

假设:

1、特征之间相互独立,即一个特征或者单词出现的可能与它和其他单词相邻没有关系

2、每个特征同等重要

要从文本中获取特征,首先要拆分文本。文本的特征是词条,即为单词,1表示词条出现在文档中,0表示词条未出现。分类结果为侮辱性和非侮辱性,用1和0表示。

准备数据:从文本中构建词向量,将一组单词转化为一组数字。

from numpy import *
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):   #创建一个包含在所有文档中出现的不重复词的列表,词向量列表,输入的是处理过的文本,例如postingList
    vacabSet=set([])
    for document in dataset:
        vacabSet=vacabSet|set(document)     #并集
    return list(vacabSet)
def setOfWordsToVec(vocabList,inputSet):    #输入词汇表和某个文档,输出文档向量,向量的每一元素为0或1,表示词汇表中的单词在输入文档中是否出现
    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

用以上函数得到的数字计算概率的方法:将之前的(x,y)替换成w,w表示向量,有多个数值组成。在这个例子中,数值个数与词汇表中的词个数相等。

  p(ci|w)=p(w|ci)*p(ci)/p(w)

ci表示不同的类别(侮辱性和非侮辱性),

p(ci)为ci类别文档的概率,等于ci类别的文档个数除以所有文档的个数

因为假设所有特征相互独立,所以

  p(w|ci)=p(w0|ci)*p(w1|ci)*p(w2|ci)...*p(wn|ci)

极大简化了p(w|ci)的计算过程。

朴素贝叶斯分类器训练函数:

def trainNB0(trainMatrix,trainCategory):    #输入文档矩阵、每篇文档类别标签构成的向量
    #trainMatrix是由原文档列表转化为多维文档向量,即每个元素均为1或者0,每行元素个数都相同,等于词汇列表的长度,行数即为文本个数
    numTrainDocs = len(trainMatrix) #文档的行数
    numWords = len(trainMatrix[0])  #第一行文本的长度,每行文本的长度相同
    pAbusive = sum(trainCategory)/float(numTrainDocs)   #侮辱性文本概率P=侮辱性文本个数/文本总数
    p0Num = zeros(numWords)     #zeros()是numpy的方法,产生的是数组
    p1Num = zeros(numWords)
    p0Denom = 0.0
    p1Denom = 0.0
    for i in range(numTrainDocs):   #遍历文档内的每条文本
        if trainCategory[i] == 1:   #第i行文本的类别是侮辱性
            p1Num += trainMatrix[i]     #数组对应元素相加
            p1Denom += sum(trainMatrix[i])  #p1Denom表示侮辱性文本包含的总词数,如果不同文本有同样的词汇则重复计数
        else:
            p0Num += trainMatrix[i]
            p0Denom += sum(trainMatrix[i])
    p1Vect = p1Num/p1Denom  #p1Num是向量,p1Denom是侮辱性文本的总词数,p1Vect表示在侮辱性文本的条件下出现某些词汇的概率
    p0Vect = p0Num/p0Denom  #p0Vect表示在非侮辱性文本的条件下出现某些词汇的概率
    return p0Vect,p1Vect,pAbusive

目前,已经建立了贝叶斯训练函数,可以求取给定文档列表的侮辱性文本概率、在侮辱性文本的条件下出现某些词汇的条件概率和在非侮辱性文本的条件下出现某些词汇的概率,测试并输出:

listOPosts,listClasses=loadDataset()    #首先获取文档列表、文档内的文本分类标签列表
myVocabList=createVocabList(listOPosts)     #从文档列表获取词汇列表,无重复词汇
trainMat=[]     #trainMat是用来表示文档的向量
for postinDoc in listOPosts:
    trainMat.append(setOfWordsToVec(myVocabList,postinDoc)) #对比词汇列表和文本获得文本的向量表示,再获得文档的向量表示,trainMat是多维数组
p0v,p1v,pAb=trainNB0(trainMat,listClasses)
print(‘侮辱性文本概率:‘,pAb)
print(‘在非侮辱性文本的条件下出现某些词汇的概率:‘,p0v)
print(‘在侮辱性文本的条件下出现某些词汇的概率‘,p1v)

输出:

侮辱性文本概率: 0.5
在非侮辱性文本的条件下出现某些词汇的概率: [0.04166667 0.04166667 0.125      0.04166667 0.         0.
 0.04166667 0.         0.04166667 0.04166667 0.04166667 0.04166667
 0.         0.04166667 0.         0.04166667 0.         0.04166667
 0.         0.         0.         0.04166667 0.04166667 0.
 0.04166667 0.04166667 0.04166667 0.         0.04166667 0.04166667
 0.04166667 0.08333333]
在侮辱性文本的条件下出现某些词汇的概率 [0.         0.         0.         0.         0.05263158 0.15789474
 0.         0.05263158 0.         0.         0.         0.
 0.05263158 0.         0.05263158 0.05263158 0.05263158 0.
 0.05263158 0.05263158 0.05263158 0.05263158 0.         0.05263158
 0.10526316 0.         0.         0.10526316 0.         0.
 0.         0.05263158]

目前计算出了p(wi|c0)、p(wi|c1)、p(ci)。

测试算法:

问题1:计算p(w|ci)=p(w0|ci)*p(w1|ci)*p(w2|ci)...*p(wn|ci)时,任何p(wj|ci)为0就导致p(w|ci)为0,为了降低此影响,将所有词的出现次数初始化为1,并将分母初始化为2.

将:

修改为:

问题2:p(w|ci)=p(w0|ci)*p(w1|ci)*p(w2|ci)...*p(wn|ci)中各项都很小,计算过程中可能会出现下溢出(多个很小的数相乘结果为0),一种解决办法是对乘积取自然对数。

  ln(a*b)=ln(a)+ln(b)

代码做如下修改:

将:

p1Vect = p1Num/p1Denom
p0Vect = p0Num/p0Denom

修改为:

p1Vect = log(p1Num/p1Denom)
p0Vect = log(p0Num/p0Denom)

numpy模块的log(a)即为对a取自然对数。

使用分类器:

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(setOfWordsToVec(myVocabList, postinDoc))
    p0V,p1V,pAb = trainNB0(array(trainMat),array(listClasses))
    testEntry = [‘love‘, ‘my‘, ‘dalmation‘]

    thisDoc = array(setOfWordsToVec(myVocabList, testEntry))
    print(testEntry,‘classified to be: ‘,classifyNB(thisDoc,p0V,p1V,pAb))
    testEntry = [‘stupid‘, ‘garbage‘]
    thisDoc = array(setOfWordsToVec(myVocabList, testEntry))
    print(testEntry,‘classified to be: ‘,classifyNB(thisDoc,p0V,p1V,pAb))

现在,执行testingNB得到如下结果:

[‘love‘, ‘my‘, ‘dalmation‘] classified to be:  0
[‘stupid‘, ‘garbage‘] classified to be:  1

目前为止,我们将每个词的出现与否作为一个特征,这可以被描述为“词集模型”,无论待测文本里某个词汇出现多少次,其对应的数值均为1,在概率计算中会引入误差,解决方法:词袋模型

词袋中每个词汇可以出现多次,修改setOfWordsToVec为bagOfWordsToVec:

setOfWordsToVec:

def setOfWordsToVec(vocabList,inputSet):    #输入词汇表和某个文档,输出文档向量,向量的每一元素为0或1,表示词汇表中的单词在输入文档中是否出现
    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

bagOfWordsToVec:

def bagOfWordsToVec(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

所有代码:

from numpy import *
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):   #创建一个包含在所有文档中出现的不重复词的列表,词向量列表,输入的是处理过的文本,例如postingList
    vacabSet=set([])
    for document in dataset:
        vacabSet=vacabSet|set(document)     #并集
    return list(vacabSet)
def setOfWordsToVec(vocabList,inputSet):    #输入词汇表和某个文档,输出文档向量,向量的每一元素为0或1,表示词汇表中的单词在输入文档中是否出现
    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
def bagOfWordsToVec(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
# listOPosts,listClasses=loadDataset()
# myVocabList=createVocabList(listOPosts)
# print(myVocabList)
# result=setOfWordsToVec(myVocabList,listOPosts[0])
# print(result)
def trainNB0(trainMatrix,trainCategory):    #输入文档矩阵、每篇文档类别标签构成的向量
    #trainMatrix是由原文档列表转化为多维文档向量,即每个元素均为1或者0,每行元素个数都相同,等于词汇列表的长度,行数即为文本个数
    numTrainDocs = len(trainMatrix) #文档的行数
    numWords = len(trainMatrix[0])  #第一行文本的长度,每行文本的长度相同
    pAbusive = sum(trainCategory)/float(numTrainDocs)   #侮辱性文本概率P=侮辱性文本个数/文本总数
    p0Num = ones(numWords)     #zeros()是numpy的方法,产生的是数组
    p1Num = ones(numWords)
    p0Denom = 2.0
    p1Denom = 2.0
    for i in range(numTrainDocs):   #遍历文档内的每条文本
        if trainCategory[i] == 1:   #第i行文本的类别是侮辱性
            p1Num += trainMatrix[i]     #数组对应元素相加
            p1Denom += sum(trainMatrix[i])  #p1Denom表示侮辱性文本包含的总词数,如果不同文本有同样的词汇则重复计数
        else:
            p0Num += trainMatrix[i]
            p0Denom += sum(trainMatrix[i])
    p1Vect = log(p1Num/p1Denom)  #p1Num是向量,p1Denom是侮辱性文本的总词数,p1Vect表示在侮辱性文本的条件下出现某些词汇的概率
    p0Vect = log(p0Num/p0Denom)  #p0Vect表示在非侮辱性文本的条件下出现某些词汇的概率
    return p0Vect,p1Vect,pAbusive
# listOPosts,listClasses=loadDataset()    #首先获取文档列表、文档内的文本分类标签列表
# myVocabList=createVocabList(listOPosts)     #从文档列表获取词汇列表,无重复词汇
# trainMat=[]     #trainMat是用来表示文档的向量
# for postinDoc in listOPosts:
#     trainMat.append(setOfWordsToVec(myVocabList,postinDoc)) #对比词汇列表和文本获得文本的向量表示,再获得文档的向量表示,trainMat是多维数组
# p0v,p1v,pAb=trainNB0(trainMat,listClasses)
# print(‘侮辱性文本概率:‘,pAb)
# print(‘在非侮辱性文本的条件下出现某些词汇的概率:‘,p0v)
# print(‘在侮辱性文本的条件下出现某些词汇的概率‘,p1v)
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(bagOfWordsToVec(myVocabList, postinDoc))
    p0V,p1V,pAb = trainNB0(array(trainMat),array(listClasses))
    testEntry = [‘love‘, ‘my‘, ‘dalmation‘,‘fucking‘]

    thisDoc = array(bagOfWordsToVec(myVocabList, testEntry))
    # print(thisDoc)
    # print(p0V)
    # print(p1V)
    # print(pAb)
    print(testEntry,‘classified to be: ‘,classifyNB(thisDoc,p0V,p1V,pAb))
    # testEntry = [‘stupid‘, ‘garbage‘]
    # thisDoc = array(setOfWordsToVec(myVocabList, testEntry))
    # print(testEntry,‘classified to be: ‘,classifyNB(thisDoc,p0V,p1V,pAb))
testingNB()

bayes.py python3.5

原文地址:https://www.cnblogs.com/zhhy236400/p/9859048.html

时间: 2024-08-05 19:53:14

机器学习 基于概率论的分类方法:朴素贝叶斯的相关文章

第四章:基于概率论的分类方法: 朴素贝叶斯

本章内容□使用概率分布进行分类□学习朴素贝叶斯分类器□解析RSS源数据口使用朴素贝叶斯来分析不同地区的态度 前两章我们要求分类器做出艰难决策,给出“该数据实例属于哪一类”这类问题的明确答案.不过,分类器有时会产生错误结果,这时可以要求分类器给出一个最优的类别猜测结果,同时给出这个猜测的概率估计值.       概率论是许多机器学习算法的基础,所以深刻理解这一主题就显得十分重要.第3章在计算特征值取某个值的概率时涉及了一些概率知识,在那里我们先统计特征在数据集中取某个特定值的次数,然后除以数据集的

基于概率论的分类方法:朴素贝叶斯算法实践学习

      关于本文说明,本人原博客地址位于http://blog.csdn.net/qq_37608890,本文来自笔者于2017年12月12日 13:03:46所撰写内容(http://blog.csdn.net/qq_37608890/article/details/78738552).             本文根据最近学习机器学习书籍 网络文章的情况,特将一些学习思路做了归纳整理,详情如下.如有不当之处,请各位大拿多多指点,在此谢过.          通过前两篇文章,我们对于k-近

机器学习四 -- 基于概率论的分类方法:朴素贝叶斯

基于概率的分类方法:朴素贝叶斯 贝叶斯决策理论 朴素贝叶斯是贝叶斯决策理论的一部分,所以在讲解朴素贝叶斯之前我们先快速简单了解一下贝叶斯决策理论知识. 贝叶斯决策理论的核心思想:选择具有最高概率的决策.比如我们毕业选择就业方向,选择C++方向的概率为0.3,选择Java的概率为0.2,选择机器学习的概率为0.5.那么我们就把这样的一位毕业生就业方向归类为机器学习方向. 条件概率 什么是条件概率?事件A在另一个事件B已知发生条件下的发生概率,记为P(A|B),读作“在B条件下A的概率”. 例子1:

机器学习实战读书笔记(四)基于概率论的分类方法:朴素贝叶斯

4.1 基于贝叶斯决策理论的分类方法 朴素贝叶斯 优点:在数据较少的情况下仍然有效,可以处理多类别问题 缺点:对于输入数据的准备方式较为敏感 适用数据类型:标称型数据 贝叶斯决策理论的核心思想:选择具有最高概率的决策. 4.2 条件概率 4.3 使用条件概率来分类 4.4 使用朴素贝叶斯进行文档分类 朴素贝叶斯的一般过程: 1.收集数据 2.准备数据 3.分析数据 4.训练算法 5.测试算法 6.使用算法 朴素贝叶斯分类器中的另一个假设是,每个特征同等重要. 4.5 使用Python进行文本分类

机器学习(基于概率论的分类方法:朴素贝叶斯)

概率论是许多机器学习算法的基础,因而本篇将会用到一些概率论知识,我们先统计在数据集中取某个特定值的次数,然后除以数据集的实例总数,就得到了取该值的概率. 优点:在数据较少的情况下仍然有效,可以处理多类别问题 缺点:对输入数据的准备方式比较敏感 适用于标称型数据 如果P1(X,Y)>P2(X,Y),那么属于类别1 如果P2(X,Y)>P1(X,Y),那么属于类别2 也就是说我们会选择高概率对应的类别.这就是贝叶斯决策理论的核心思想,即选择具有最高概率的决策 朴素贝叶斯的朴素就是特征之间相互独立

【简单认识】机器学习常见分类算法——朴素贝叶斯

贝叶斯在1763年,<机会学说中一个问题的解>中提出了贝叶斯定理. 生活中不乏分类,比如我们经常通过一些人的衣着,来下意识的区别某些人是杀马特亦或是文艺青年.我们是如何做出这些判断或者说是分类的呢?这些判断大多来自我们的“经验之谈”,即,我们首先脑海中会先存有“某类人通常会如何着装打扮”的概念,然后当遇到这类显著特征之后,便会下意识的对其进行分类. 那么如何让机器进行这种类似的判断区分呢? 朴素贝叶斯分类法是一种相对简单易理解的机器分类方法.它的思想是首先对一些已知分类的样本进行采样(机器学习

斯坦福机器学习实现与分析之六(朴素贝叶斯)

朴素贝叶斯(Naive Bayes)适用于离散特征的分类问题,对于连续问题则需将特征离散化后使用.朴素贝叶斯有多元伯努利事件模型和多项式事件模型,在伯努利事件模型中,特征每一维的值只能是0或1,而多项式模型中特征每一维的值可取0到N之间的整数,因此伯努利模型是多项式模型的一种特例,下面的推导就直接使用伯努利模型. 朴素贝叶斯原理推导 与GDA类似,朴素贝叶斯对一个测试样本分类时,通过比较p(y=0|x)和p(y=1|x)来进行决策.根据贝叶斯公式: \( \begin{aligned} p(y=

斯坦福《机器学习》Lesson5感想———2、朴素贝叶斯算法

朴素贝叶斯算法与上篇中写到到生成学习算法的思想是一致的.它不需要像线性回归等算法一样去拟合各种假设的可能,只需要计算各种假设的概率,然后选择概率最高的那种假设分类类别.其中还添入了一个贝叶斯假定:在给定目标值y时属性值x之间相互独立.这样的分类算法被称为朴素贝叶斯分类器(Naive Bayes classifier)  . 1.朴素贝叶斯算法 在朴素贝叶斯算法的模型里,给定的训练集为, 可计算,.因为贝叶斯假定,可以计算出联合似然概率函数: 最大化联合似然概率函数可得到: 然后我们就可以对新的数

4 基于概率论的分类方法:朴素贝叶斯

4.5 使用Python进行文本分类 4.5.1 准备数据:从文本中构建词向量 #coding:utf-8 from numpy import * #准备数据:从文本中构建词向量 def loadDataSet(): postingList = [['my', 'dog', 'has', 'flea', 'problems', 'help', 'please'], ['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'], ['