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

这篇具有很好参考价值的文章主要介绍了【机器学习实战】-基于概率论的分类方法:朴素贝叶斯。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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


【机器学习实战】读书笔记
**朴素贝叶斯:**称为“朴素”的原因,整个形式化过程只做最原始、最简单的假设,特征之间没有关联,是统计意义上的独立。
**优点:**在数据较少的情况下仍然有效,可以处理多类别问题。
**缺点:**对于输入数据的准备方式较为敏感。
**适用数据类型:**标称型数据。

基于贝叶斯决策理论的分类方法

贝叶斯是贝叶斯决策理论的一部分,假设有两类数据p1(x, y)表示数据点(x, y)属于类别1的概率,p2(x, y)表示数据点属于类别2的概率,对一个新的数据点A(x, y),用下面的规则来判断它的类别:

  • 如果p1(x, y) > p2(x, y),那么类别为1。
  • 如果p2(x, y) > p1(x, y),那么类别为2。

以上原则体现出了贝叶斯决策论的核心思想,选择最高概率的决策。贝叶斯概率引入先验知识和逻辑推理来处理不确定命题。另一种概率解释称为频数概率(frequency probability),它只从数据本身获得结论,并不考虑逻辑推理及先验知识

条件概率(贝叶斯准则)

贝叶斯准则
如果已知P(x|c),要求P(c|x),可以使用下面的计算方法:
p ( c ∣ x ) = p ( x ∣ c ) p ( c ) p ( x ) p(c|x)=\frac{p(x|c)p(c)}{p(x)} p(cx)=p(x)p(xc)p(c)
在这给出简单证明:
∵ p ( x ∣ c ) = p ( x c ) p ( c ) ∴ p ( x ∣ c ) p ( c ) = p ( x c ) → p ( c ∣ x ) = p ( x c ) p ( x ) ∴ p ( c ∣ x ) = p ( x ∣ c ) p ( c ) p ( x ) 原命题得证 \because p(x|c)=\frac{p(xc)}{p(c)}\\ \therefore p(x|c)p(c)=p(xc) \to p(c|x)=\frac{p(xc)}{p(x)}\\ \therefore p(c|x)=\frac{p(x|c)p(c)}{p(x)}原命题得证 p(xc)=p(c)p(xc)p(xc)p(c)=p(xc)p(cx)=p(x)p(xc)p(cx)=p(x)p(xc)p(c)原命题得证
语言通俗解释,p(x|c)p( c)获得就是c和x同时发生的概率,除以x发生的概率,就是在x的前提下c发生的概率。

使用条件概率来分类

对上面的点就可以使用贝叶斯分类来计算属于某个类c的概率
p ( c i ∣ x , y ) = p ( x , y ∣ c i ) p ( c i ) p ( x , y ) p(c_i|x,y)=\frac{p(x,y|c_i)p(c_i)}{p(x,y)} p(cix,y)=p(x,y)p(x,yci)p(ci)
使用这些定义,可以定义贝叶斯分类准则为:

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

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

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

书中还提到了独立的概念,独立指的是统计意义上的独立,即一个特征或者单词出现的可能性与它和其他单词相邻没有关系。这个假设正是朴素贝叶斯分类器中朴素(naive)一词的含义。朴素贝叶斯分类器中的另一个假设是,每个特征同等重要。举了个例子,如果每个特征需要N个样本,那么对于10个特征将需要N^10的样本,当特征为1000时,那就是N的1000次方,所需样本数随着特征数目的增大而迅速增大,如果特征之间相互独立,那么数据量就变为10特征时为10×N,特征数为1000时为1000×N,因为有关联的时候是十个特征共同构建一个模型,所以空间就是N的10次方,但是独立时,每个特征可以用N个数据单独建立,最后组合起来就可以了,所以是10×N。

朴素贝叶斯分类器通常有两种实现方式:一种基于贝努利模型实现,一种基于多项式模型实现。这里采用前一种实现方式。该实现方式中并不考虑词在文档中出现的次数,只考虑出不出现,因此在这个意义上相当于假设词是等权重的。后面给出的实际上是多项式模型,它考虑词在文档中的出现次数。

使用python进行文本分类

文本中获取特征,需要拆分文本,特征是来自文本的词条(token),一个词条是字符的任意组合。将每一个文本片段表示为一个词条向量,其中值为1表示词条出现在文档中,0表示词条未出现。

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']
    ]
    # 1代表侮辱性文字,0代表正常言论
    classVec = [0, 1, 0, 1, 0, 1]
    return postingList, classVec

def createVocaList(dataSet):
    # 创建一个空集
    vocabSet = set([])
    # 创建并返回两个集合的并集
    for document in dataSet:
        vocabSet = vocabSet | set(document)
    return list(vocabSet)

# 词集模型,每个词的出现与否作为一个特征
def setOfWords2Vec(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

loadDataSet()函数创建一些实验样本,返回的第一个变量是词条切分后的文档集合,第二个返回的变量是类别标签集合,有两类,侮辱性和非侮辱性。createVocaList()函数使用set集合的形式,把文档中出现的不重复的词作为集合返回。而setOfWord2Vec()函数输入参数是词汇表vocabList和文档inputSet,创建一个为0的词汇表向量,来记录文档在当前词汇表所形成的向量,若文档中的词在词汇表中出现,则对应的词汇表向量标记为1,如果文档中的词条没在词汇表中,则不标记,最后返回文档对应的词汇表向量。
书中提到目前的setOfWord2Vec()函数是把词的出现与否作为一个特征,为词集模型(set-of-words model)。如果一个词在文档中出现不止一次,这可能意味着包含该词是否出现在文档中所不能表达的某种信息,这种方法被称为词袋模型(bag-of-words model)。在词袋中,每个单词可以出现多次,而在词集中,每个词只能出现一次。词袋模型对应的词集模型(文档词向量标记函数)如下更修改

# 词袋模型,每个词出现的次数做为特征
def setOfWords2Vec1(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

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

原理:重写贝叶斯准则,将之前的x、y替换为ww表示是一个向量,有多个数值组成,在这个例子中,数值个数与词汇表中的词的个数相同即 p ( w ) = 1 p(w) = 1 p(w)=1,重写的贝叶斯准则也如下所示:
p ( c i , w ) = p ( w ∣ c i ) p ( c i ) p ( w ) p(c_i, w) = \frac{p(w|c_i)p(c_i)}{p(w)} p(ci,w)=p(w)p(wci)p(ci)
公式中p(w)已知,p(ci)可以直接根据标签量计算出来,唯一不好计算的就是p(w|ci),这里使用朴素贝叶斯的假设,将w展开为一个个独立的特征,就实现以下转换
p ( w 0 , w 1 , w 2 . . . w N ∣ c i ) = p ( w 0 ∣ c i ) p ( w 1 ∣ c i ) p ( w 2 ∣ c i ) … p ( w N ∣ c i ) p(w_0, w_1,w_2...w_N|c_i)=p(w_0|c_i)p(w_1|c_i)p(w_2|c_i) \dots p(w_N|c_i) p(w0,w1,w2...wNci)=p(w0ci)p(w1ci)p(w2ci)p(wNci)
转换成计算每个类别的词条出现的概率。
伪代码如下:

计算每个类别中的文档数目
对每篇训练文档:
    对每个类别:
        如果词条出现在文档中->增加改词条的计数值
        增加所有词条的计数值
     对每个类别:
         对每个词条:
             将该词条的数目除以总词条数目得到条件概率
     返回每个类别的条件概率

代码如下:

# 朴素贝叶斯分类器
def trainNB0(trainMatrix, trainCategory):
    """
    :param trainMatrix: 对应标签的词组向量类似于[0,1,0,1,0,0,1]这种,记录每个标签对应的词条出现情况
    :param trainCategory: 文档标签
    :return:标签1的log(概率),标签2的log(概率),类别1的概率
    """
    numTrainDocs = len(trainMatrix)
    numWords = len(trainMatrix[0])
    pAbusive = sum(trainCategory)/float(numTrainDocs)
    # p0Num = zeros(numWords); p1Num = zeros(numWords)
    # p0Denom = 0.0; p1Denom = 0.0
    # 上面两个公式是假设每个特征独立,如果有个特征为0,则全部特征为0,为避免这种情况,将所有词出现数初始化为1,将分母初始化为2
    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 = log(p1Num/p1Denom)
    p0Vect = log(p0Num/p0Denom)
    return p0Vect, p1Vect, pAbusive

numTrainDocs记录文本数量,numWords记录词汇表的数量,pAbusive记录类别为1的比例是多少,p0Num、p0Denom分别记录类别为0的词汇量的个数,和词汇量的总数,同理类比p1Num和p1Denom。因为使用朴素贝叶斯假设,所以防止一个概率为0其他都为0,都初始化为1,分母初始化为2。因为大部分因子都非常小,防止程序下溢或浮点数舍入导致错误,采用自然对数进行处理,这样概率大的还是大,不会影响最终结果,所以采用log。

3.朴素贝叶斯分类函数

代码:

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 = createVocaList(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))

classifyNB是计算贝叶斯规则的,输入分别是要分类的向量vec2Classify,p(w|c0),p(w|c1),P(c1),多个参数构成w,所以使用numpy向量来计算,使用log函数,相乘等于各元素相加,sum()将要预测分类的向量含有可能的概率加起来,再加上分类概率就是最终概率。
testingNB()是测试函数,加载词汇表和标签,然后将词汇表合并成一个词条向量,把训练词汇数据标记为向量的形式存在trainMat中,然后计算类别1类别0等的概率,输入要预测的词汇向量,转换为向量形式,然后使用classifyNB进行预测。
运行效果:
【机器学习实战】-基于概率论的分类方法:朴素贝叶斯,机器学习,概率论,分类

4.项目完整代码

'''简单的朴素贝叶斯分类器'''
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']
    ]
    # 1代表侮辱性文字,0代表正常言论
    classVec = [0, 1, 0, 1, 0, 1]
    return postingList, classVec

def createVocaList(dataSet):
    # 创建一个空集
    vocabSet = set([])
    # 创建并返回两个集合的并集
    for document in dataSet:
        vocabSet = vocabSet | set(document)
    return list(vocabSet)

# 词集模型,每个词的出现与否作为一个特征
def setOfWords2Vec(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

# 词袋模型,每个词出现的次数做为特征
def setOfWords2Vec1(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

# 朴素贝叶斯分类器
def trainNB0(trainMatrix, trainCategory):
    """
    :param trainMatrix: 对应标签的词组向量类似于[0,1,0,1,0,0,1]这种,记录每个标签对应的词条出现情况
    :param trainCategory: 文档标签
    :return:标签1的log(概率),标签2的log(概率),类别1的概率
    """
    numTrainDocs = len(trainMatrix)
    numWords = len(trainMatrix[0])
    pAbusive = sum(trainCategory)/float(numTrainDocs)
    # p0Num = zeros(numWords); p1Num = zeros(numWords)
    # p0Denom = 0.0; p1Denom = 0.0
    # 上面两个公式是假设每个特征独立,如果有个特征为0,则全部特征为0,为避免这种情况,将所有词出现数初始化为1,将分母初始化为2
    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 = log(p1Num/p1Denom)
    p0Vect = log(p0Num/p0Denom)
    return p0Vect, p1Vect, pAbusive

# listOPosts, listClasses = loadDataSet()
# myVocablist = createVocaList(listOPosts)

# 创建列表包含所有词
# trainMat = []
# for postinDoc in listOPosts:
#     trainMat.append(setOfWords2Vec(myVocablist, postinDoc))
#
# 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 = createVocaList(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()

总结与反思

这个例子主要是来讲解朴素贝叶斯怎么进行文本情感分类,基于条件概率和特征独立来计算词条向量的情感概率值,有很多地方都进行了简化,像开始例子就提供了词汇表,不需要分词,自己在做文本情感分析的时候上来就需要分词,建立词汇向量表,预测文本也得做分词处理形成分词向量,这里简化了。
如有错误欢迎指正,加油,时间不等人。文章来源地址https://www.toymoban.com/news/detail-843285.html

到了这里,关于【机器学习实战】-基于概率论的分类方法:朴素贝叶斯的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【概率论理论】协方差,协方差矩阵理论(机器学习)

      在许多算法中需要求出两个分量间相互关系的信息。协方差就是描述这种相互关联程度的一个特征数。   设 ( X , Y ) (X,Y) ( X , Y ) 是一个二维随机变量,若 E [ ( X − E ( X ) ) ( Y − E ( Y ) ) ] E[(X-E(X))(Y-E(Y))] E [ ( X − E ( X ) ) ( Y − E ( Y ) ) ] 存在,则称此数学期望为 X X X 与

    2024年02月14日
    浏览(49)
  • 【算法小记】——机器学习中的概率论和线性代数,附线性回归matlab例程

    内容包含笔者个人理解,如果错误欢迎评论私信告诉我 线性回归matlab部分参考了up主DR_CAN博士的课程 在回归拟合数据时,根据拟合对象,可以把分类问题视为一种简答的逻辑回归。在逻辑回归中算法不去拟合一段数据而是判断输入的数据是哪一个种类。有很多算法既可以实现

    2024年01月24日
    浏览(45)
  • 【算法原理和代码实战】德州扑克计算概率4-2法则原理(基于概率论和统计学的基本原理),详细计算步骤,具体算法代码实例。

    德州扑克计算概率的4-2法则是一种简便的计算方法,用于估算在德州扑克中获得某种牌型的概率。4-2法则的原理是基于概率论和统计学的基本原理,通过观察德州扑克中的牌型组合和可能性,得出一个简单的计算公式。 在德州扑克的前三张公共牌(翻牌圈)之后,如果你需要

    2024年02月14日
    浏览(53)
  • 机器学习之概率论

            最近,在了解机器学习相关的数学知识,包括线性代数和概率论的知识,今天,回顾了概率论的知识,贴上几张其他博客的关于概率论的图片,记录学习过程。                            

    2024年02月12日
    浏览(42)
  • 概率论-1-概率机器人 Probabilistic Robotics

    基本概念 随机变量 静态的 可以做随机试验 随机过程 动态 离散随机变量 概率质量函数 probability mass function 连续随机变量 概率密度函数 probability density function PDF 联合概率 P ( X = x 且 Y = y ) = P ( x , y ) 若 X 和 Y 独立: P ( x , y ) = P ( x ) P ( y ) P(X=x 且 Y=y) = P(x,y)\\\\ 若 X 和 Y 独立:

    2024年03月22日
    浏览(54)
  • 概率论学习笔记全网最全!!!!

    第01回:一些基本概念 1. 随机试验 满足下列条件的试验称为随机试验. 可以在相同的条件下重复地进行; 每次试验的可能结果不止一个,并且能事先明确试验的所有可能结果; 进行一次试验之前不能确定哪一个结果会出现. 2. 样本空间 ​ 我们研究随机现象的方法其实就是利用

    2024年02月03日
    浏览(60)
  • 《概率论与数理统计》学习笔记

    重温《概率论与数理统计》进行查漏补缺,并对其中的概念公式等内容进行总结,以便日后回顾。 目录 第一章 概率论的基本概念 第二章 随机变量及其分布 第三章  多维随机变量及其分布 第四章  随机变量的数字特征 第五章  大数定律及中心极限定理 第六章  样本及抽样

    2024年02月03日
    浏览(41)
  • 概率论的学习和整理--番外12:2个概率选择比较的题目

    目录 1 要解决的题目 2 先说结论,后面解释原因 2.1 先考虑期望,期望要尽量大,但比然有限制 2.2  再考虑方差,在期望给定前提下,尽量减小方差,稳定体验 2.3 结论:先考虑期望,再考虑方差 3 算法 3.1 错误算法 3.2  正确算法1,直接解方程 3.3 正确算法2,用条件期望求解

    2024年02月16日
    浏览(42)
  • 深度学习-必备的数学知识-概率论4

    概率论 我们将接着上一篇文章继续讲解。 在接下来的文章中,将会把随机变量本身写作大写字母,随机变量的值写作小写字母。 期望、方差和协方差 期望(expectation)是指随机变量X所有可能取值的平均或期望值。期望可以看作随机变量的中心或平均位置。换句话说期望是随

    2024年02月04日
    浏览(48)
  • 深度学习-必备的数学知识-概率论3

    概率论 我们将接着上一篇文章继续讲解。 条件概率 大家还记得上一篇文章的提到的联合概率分布吗?定义在一组变量的联合概率分布的子集上的概率分布被称为边缘概率分布(marginal probability distribution)。 对于离散型随机变量x和y,如果我们有 P ( x , y ) P(x,y) P ( x , y ) ,则可

    2024年02月03日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包