栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

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

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

1贝叶斯算法简介

        贝叶斯分类算法是统计学的一种分类方法,它是一类利用概率统计知识进行分类的算法。在许多场合,朴素贝叶斯(Naïve Bayes,NB)分类算法可以与决策树和神经网络分类算法相媲美,该算法能运用到大型数据库中,而且方法简单、分类准确率高、速度快。        

1.1贝叶斯算法优点

优点:在数据较少时仍有效,可处理多类别问题

1.2贝叶斯算法缺点

缺点:对输入数据准备方式敏感,如果输入的数据的各个特征之间是具有关联的,那么分类的效果可能不佳,反之,如果各个特征之间的关联度不大,则分类效果才可能不错

1.3贝叶斯算法思想        

 假设现在我们有一个数据集,它由两类数据组成,数据分布如上图所示:

我们现在用p1(x,y)表示数据点(x,y)属于类别1(图中圆点表示的类别)的概率,用p2(x,y)表示数据点(x,y)属于类别2(图中三角形表示的类别)的概率,那么对于一个新数据点(x,y),可以用下面的规则来判断它的类别:

如果p1(x,y) > p2(x,y),那么类别为1
如果p1(x,y) < p2(x,y),那么类别为2
也就是说,我们会选择高概率对应的类别。这就是贝叶斯决策理论的核心思想,即选择具有最高概率的决策。

适用决策树不会非常成功,和简单的概率计算相比,KNN计算量太大,因此对于上述问题,最佳选择是概率比较方法。

接下来,就是学习如何计算p1和p2概率。

2.概率公式 2.1 条件概率

条件概率(Condittional probability),就是指在事件B发生的情况下,事件A发生的概率,用P(A|B)来表示。

2.2 全概率

3 朴素贝叶斯定理 3.1贝叶斯推导

 对条件概率进行变形:

我们把P(A)称为”先验概率”(Prior probability),即在B事件发生之前,我们对A事件概率的一个判断。

P(A|B)称为”后验概率”(Posterior probability),即在B事件发生之后,我们对A事件概率的重新评估。

P(B|A)/P(B)称为”可能性函数”(Likelyhood),这是一个调整因子,使得预估概率更接近真实概率。

所以,条件概率可以理解成下面的式子:

后验概率=先验概率∗调整因子后验概率=先验概率∗调整因子
这就是贝叶斯推断的含义:我们先预估一个”先验概率”,然后加入实验结果,看这个实验到底是增强还是削弱了”先验概率”,由此得到更接近事实的”后验概率”。

在这里,如果”可能性函数”P(B|A)/P(B)>1,意味着”先验概率”被增强,事件A的发生的可能性变大;如果”可能性函数”=1,意味着B事件无助于判断事件A的可能性;如果”可能性函数”<1,意味着”先验概率”被削弱,事件A的可能性变小。


3.2朴素贝叶斯概念

“朴素”的解释:假设各个特征之间相互独立(在贝叶斯分类器上做了简化)
朴素贝叶斯的基础假设:

①每个特征相互独立;
②每个特征的权重(或重要性)都相等,即对结果的影响程度都相同。

3.2朴素贝叶斯计算条件概率

 4.实现代码

4.1词表到向量转换函数

def loadDataSet():
    """
    Function:   创建实验样本

    Args:       无

    Returns:    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 is abusive, 0 not
    #词条切分后的文档集合和类别标签结合
    return postingList,classVec
def createVocabList(dataSet):
    """
    Function:   创建一个包含所有文档中出现的不重复词的列表

    Args:       dataSet:数据集

    Returns:    list(vocabSet):返回一个包含所有文档中出现的不重复词的列表
    """
    #创建一个空集
    vocabSet = set([])
    #将新词集合添加到创建的集合中
    for document in  dataSet:
        #操作符 | 用于求两个集合的并集
        vocabSet = vocabSet | set(document)
    #返回一个包含所有文档中出现的不重复词的列表
    return list(vocabSet)

def setOfWords2Vec(vocabList, inputSet):
    """
    Function:   词表到向量的转换

    Args:       vocabList:词汇表
                inputSet:某个文档

    Returns:    returnVec:文档向量
    """
    #创建一个所含元素都为0的向量
    returnVec = [0]*len(vocabList)
    #遍历文档中词汇
    for word in inputSet:
        #如果文档中的单词在词汇表中,则相应向量位置置1
        if word in vocabList:
            returnVec[vocabList.index(word)] = 1
        #否则输出打印信息
        else: print("the word: %s is not in my Vocablary!" % word)
    #向量的每一个元素为1或0,表示词汇表中的单词在文档中是否出现
    return returnVec

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

def trainNB0(trainMatrix, trainCategory):
    """
    Function:   朴素贝叶斯分类器训练函数

    Args:       trainMatrix:文档矩阵
                trainCategory:类别标签向量

    Returns:    p0Vect:非侮辱性词汇概率向量
                p1Vect:侮辱性词汇概率向量
                pAbusive:侮辱性文档概率
    """
    #获得训练集中文档个数
    numTrainDocs = len(trainMatrix)
    #获得训练集中单词个数
    numWords = len(trainMatrix[0])
    #计算文档属于侮辱性文档的概率
    pAbusive = sum(trainCategory)/float(numTrainDocs)
    #初始化概率的分子变量
    p0Num = zeros(numWords); p1Num = zeros(numWords)
    #初始化概率的分母变量
    p0Denom = 0.0; p1Denom = 0.0
    #遍历训练集trainMatrix中所有文档
    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
    #返回两个类别概率向量和一个概率
    return p0Vect, p1Vect, pAbusive

4.3朴素贝叶斯分类函数

def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
    """
    Function:   朴素贝叶斯分类函数

    Args:       vec2Classify:文档矩阵
                p0Vec:非侮辱性词汇概率向量
                p1Vec:侮辱性词汇概率向量
                pClass1:侮辱性文档概率

    Returns:    1:侮辱性文档
                0:非侮辱性文档
    """
    #向量元素相乘后求和再加到类别的对数概率上,等价于概率相乘
    p1 = sum(vec2Classify * p1Vec) + log(pClass1)
    p0 = sum(vec2Classify * p0Vec) + log(1.0 - pClass1)
    #分类结果
    if p1 > p0:
        return 1
    else:
        return 0

def testingNB():
    """
    Function:   朴素贝叶斯分类器测试函数

    Args:       无

    Returns:    testEntry:测试词汇列表
                classifyNB(thisDoc, p0V, p1V, pAb):分类结果
    """
    #从预先加载中调入数据
    listOPosts, listClasses = loadDataSet()
    #构建一个包含所有词的列表
    myVocabList = createVocabList(listOPosts)
    #初始化训练数据列表
    trainMat = []
    #填充训练数据列表
    for postinDoc in listOPosts:
        trainMat.append(setOfWords2Vec(myVocabList, postinDoc))
    #训练
    p0V, p1V, pAb = trainNB0(trainMat, 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))

4.4构建词袋模型

def bagOfWords2VecMN(vocabList, inputSet):
    """
    Function:   词袋到向量的转换

    Args:       vocabList:词袋
                inputSet:某个文档

    Returns:    returnVec:文档向量
    """
    #创建一个所含元素都为0的向量
    returnVec = [0]*len(vocabList)
    #将新词集合添加到创建的集合中
    for word in inputSet:
        #如果文档中的单词在词汇表中,则相应向量位置加1
        if word in vocabList:
            returnVec[vocabList.index(word)] += 1
    #返回一个包含所有文档中出现的词的列表
    return returnVec

4.5准备数据验证

def textParse(bigString):
    """
    Function:   切分文本

    Args:       bigString:输入字符串

    Returns:    [*]:切分后的字符串列表
    """
    import re
    #利用正则表达式,来切分句子,其中分隔符是除单词、数字外的任意字符串

    listOfTokens = re.split(r'W*', bigString)
    
    #返回切分后的字符串列表
    return [tok.lower() for tok in listOfTokens if len(tok) > 2]

def spamTest():
    """
    Function:   贝叶斯垃圾邮件分类器

    Args:       无

    Returns:    float(errorCount)/len(testSet):错误率
                vocabList:词汇表
                fullText:文档中全部单词
    """
    #初始化数据列表
    docList = []; classList = []; fullText = []
    #导入文本文件
    for i in range(1, 26):
        #切分文本
        wordList = textParse(open('email/spam/%d.txt' % i).read())
        #切分后的文本以原始列表形式加入文档列表
        docList.append(wordList)
        #切分后的文本直接合并到词汇列表
        fullText.extend(wordList)
        #标签列表更新
        classList.append(1)
        #切分文本
        #print('i = :', i)
        wordList = textParse(open('email/ham/%d.txt' % i).read())
        #切分后的文本以原始列表形式加入文档列表
        docList.append(wordList)
        #切分后的文本直接合并到词汇列表
        fullText.extend(wordList)
        #标签列表更新
        classList.append(0)
    #创建一个包含所有文档中出现的不重复词的列表
    vocabList = createVocabList(docList)
    #初始化训练集和测试集列表
    trainingSet = list(range(50)); testSet = []
    #随机构建测试集,随机选取十个样本作为测试样本,并从训练样本中剔除
    for i in range(10):
        #随机得到Index
        randIndex = int(random.uniform(0, len(trainingSet)))
        #将该样本加入测试集中
        testSet.append(trainingSet[randIndex])
        #同时将该样本从训练集中剔除
        del(trainingSet[randIndex])
    #初始化训练集数据列表和标签列表
    trainMat = []; trainClasses = []
    #遍历训练集
    for docIndex in trainingSet:
        #词表转换到向量,并加入到训练数据列表中
        trainMat.append(setOfWords2Vec(vocabList, docList[docIndex]))
        #相应的标签也加入训练标签列表中
        trainClasses.append(classList[docIndex])
    #朴素贝叶斯分类器训练函数
    p0V, p1V, pSpam = trainNB0(array(trainMat), array(trainClasses))
    #初始化错误计数
    errorCount = 0
    #遍历测试集进行测试
    for docIndex in testSet:
        #词表转换到向量
        wordVector = setOfWords2Vec(vocabList, docList[docIndex])
        #判断分类结果与原标签是否一致
        if classifyNB(array(wordVector), p0V, p1V, pSpam) != classList[docIndex]:
            #如果不一致则错误计数加1
            errorCount += 1
            #并且输出出错的文档
            print("classification error",docList[docIndex])
    #打印输出信息
    print('the erroe rate is: ', float(errorCount)/len(testSet))
    #返回词汇表和全部单词列表
    #return vocabList, fullText

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/503730.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号