zoukankan      html  css  js  c++  java
  • 朴素贝叶斯——文本分类

    朴素贝叶斯是基于贝叶斯定理于独立分布假设的分类算法

    1 优点:在数据较少的情况下仍然有效,可以处理多分类问题。
    2 缺点:对入输入数据的准备方式较为敏感。
    3 使用数据类型:标称型数据。

    标称型数据和数值型数据的区别:

    1 标称型:标称型目标变量的结果只在有限目标集中取值,如真与假(标称型目标变量主要用于分类)一般在有限的数据中取,而且只存在‘是’和‘否’两种不同的结果(一般用于分类)
    2 数值型:数值型目标变量则可以从无限的数值集合中取值,如0.100,42.001等 (数值型目标变量主要用于回归分析)

    使用下面数据解释贝叶斯

    头发声音性别

    我们得到下面的概率分布:

    性别头发长声音粗
    1/3 1
    3/5 3/5

    假设头发和声音都是相互独立

    1 男生头发长声音粗的概率=3/8*1/3*1=1/8 
    2 女生头发长声音粗的概率=5/8*3/5*3/5=9/40 
    3 因为1/8<9/40所以如果一个人,头发长,声音粗,那么这个人更可能是女生,于是出现这些特征就是女生。其他特征依次类推

    条件概率:

    贝叶斯公式:

     由条件概率可得:

     因此得到贝叶斯的常规形式:

    全概率和贝叶斯公式结合:

    公式中,事件Bi的概率为P(Bi),事件Bi已发生条件下事件A的概率为P(A│Bi),事件A发生条件下事件Bi的概率为P(Bi│A)

    判断头发长的人性别: 

    1 P(男|头发长)=P(头发长|男)*P(男)/P(头发长) 
    2 P(女|头发长)=P(头发长|女)*P(女)/P(头发长) 

    判断头发长、声音粗的人性别: 

    1 P(男|头发长声音粗)=P(头发长|男)P(声音粗|男)*P(男)/P(头发长声音粗) 
    2 P(女|头发长声音粗)=P(头发长|女)P(声音粗|女)*P(女)/P(头发长声音粗) 

    可以看到,比较最后比较概率,只用比较分子即可。也就是前面计算头发长声音粗的人是男生女生的概率

    # -*- coding: utf-8 -*-
    """
    Created on Mon May 18 17:53:32 2020
    
    @author: Admin
    """
    
    
    from numpy import *
    import re
    import random
    
    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]  #1代表脏话
        return postingList, classVec
    
    def createVocabList(dataSet):  #创建词库 这里就是直接把所有词去重后,当作词库
        vocabSet = set([])
        for document in dataSet:
            vocabSet = vocabSet | set(document)
        return list(vocabSet)
    
    #得到一个和词库长度一样的向量,该词在词库里存在,则该词在词库中的位置将被赋值1,否则0
    def setOfWords2Vec(vocabList, inputSet):  #文本词向量。词库中每个词当作一个特征,文本中就该词,该词特征就是1,没有就是0
        returnVec = [0] * len(vocabList)
        for word in inputSet:
            if word in vocabList:
                returnVec[vocabList.index(word)] = 1  #首先找到该词在词库中的位置索引,然后赋值为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)  #label的值相加(等于3),除以向量中共有多少行(6)
        p0Num = ones(numWords) #防止某个类别计算出的概率为0,导致最后相乘都为0,所以初始词都赋值1,分母赋值为2.
        p1Num = ones(numWords)
        p0Denom = 2
        p1Denom = 2
        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)  #这里使用了Log函数,方便计算,因为最后是比较大小,所有对结果没有影响。
        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-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))
    
    if __name__=='__main__':
        testingNB()

    问题:如果是晴天,这个人就能出去玩。这个说法是不是正确的?

    P(是|晴朗)=P(晴朗|是)×P(是)/P(晴朗)

    在这里,P(晴朗|是)= 3/9 = 0.33,P(晴朗)= 5/14 = 0.36,P(是)= 9/14 = 0.64

    现在,P(是|晴朗)=0.33×0.64/0.36=0.60,具有较高的概率。

  • 相关阅读:
    sql笔记
    [ACTF2020 新生赛]Include
    [极客大挑战 2019]Http
    [极客大挑战 2019]Knife
    [极客大挑战 2019]Secret File
    [HCTF 2018]admin
    [极客大挑战 2019]Havefun
    [RoarCTF 2019]Easy Calc
    ascll码转化
    《逆向工程核心原理》笔记第一章到第十一章
  • 原文地址:https://www.cnblogs.com/cgmcoding/p/13453175.html
Copyright © 2011-2022 走看看