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

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:这里可以添加本文要记录的大概内容:

例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。


提示:以下是本篇文章正文内容,下面案例可供参考

一、朴素贝叶斯模型

1.条件概率

在这里插入图片描述

2.先验概率

在这里插入图片描述

3.后验概率

在这里插入图片描述

4.朴素贝叶斯公式

在这里插入图片描述

5.朴素贝叶斯分类器

朴素贝叶斯分类器(Naïve Bayes Classifier)采用了“属性条件独立性假设” ,即每个属性独立地对分类结果发生影响。为方便公式标记,不妨记P(C=c|X=x)为P(c|x),基于属性条件独立性假设,贝叶斯公式可重写为:

在这里插入图片描述
其中d为属性数目,x_i 为 x 在第 i 个属性上的取值。

由于对所有类别来说 P(x)相同,因此MAP判定准则可改为:
在这里插入图片描述
其中 P © 和 P(x_i|c) 为目标参数。

朴素贝叶斯分类器的训练器的训练过程就是基于训练集D估计类先验概率 P© ,并为每个属性估计条件概率 P(x_i|c) 。

令 D_c 表示训练集D中第c类样本组合的集合,则类先验概率 :
在这里插入图片描述

二、垃圾邮件分类

1.数据集准备

在这里插入图片描述

2.朴素贝叶斯算法

from numpy import *
 
# 创建不重复词的列表 ———— 词汇表
def createVocabList(dataSet):
    vocabSet = set([])                       # 创建一个空集
    for document in dataSet:
        vocabSet = vocabSet | set(document)  # 创建两个集合的并集
    return list(vocabSet)                    # 返回不重复的词条列表
 
# 输出文档向量
def setOfWords2Vec(vocabList, inputSet):
    returnVec = [0] * len(vocabList)             # 创建一个其中所含元素都为0的向量
    for word in inputSet:                        # 遍历文档中的所有单词
        if word in vocabList:                    # 如果出现了词汇表中的单词,则将输出的文档向量中的对应值设为1
            returnVec[vocabList.index(word)] = 1
        else:
            print("单词 %s 不在词汇表中!" % word)
    return returnVec
 
# 朴素贝叶斯分类器训练函数
def trainNB0(trainMatrix, trainCategory):
    numTrainDocs = len(trainMatrix)                      # 获得训练的文档总数
    numWords = len(trainMatrix[0])                       # 获得每篇文档的词总数
    pAbusive = sum(trainCategory) / float(numTrainDocs)  # 计算文档是侮辱类的概率
    p0Num = ones(numWords)                               # 创建numpy.ones数组,初始化概率
    p1Num = ones(numWords)                               # 创建numpy.ones数组,初始化概率
    p0Denom = 2.0                                        # 初始化为2.0
    p1Denom = 2.0                                        # 初始化为2.0
    for i in range(numTrainDocs):
        if trainCategory[i] == 1:
            p1Num += trainMatrix[i]                      # 向量相加,统计侮辱类的条件概率的数据,即P(w0|1),P(w1|1),P(w2|1)···
            p1Denom += sum(trainMatrix[i])
        else:
            p0Num += trainMatrix[i]                      # 向量相加,统计非侮辱类的条件概率的数据,即P(w0|0),P(w1|0),P(w2|0)···
            p0Denom += sum(trainMatrix[i])
    p1Vect = log(p1Num / p1Denom)                        # 侮辱类,每个元素除以该类别中的总词数
    p0Vect = log(p0Num / p0Denom)                        # 非侮辱类,每个元素除以该类别中的总词数
    return p0Vect, p1Vect, pAbusive                      # p0Vect非侮辱类的条件概率数组、p1Vect侮辱类的条件概率数组、pAbusive文档属于侮辱类的概率
 
# 朴素贝叶斯分类器分类函数
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 bagOfWords2VecMN(vocabList, inputSet):
    returnVec = [0] * len(vocabList)
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)] += 1
    return returnVec
 
# 文件解析
def textParse(bigString):  # 输入字符串, 输出单词列表
    import re
    listOfTokens = re.split(r'[\W*]', bigString)                    # 字符串切分,去掉除单词、数字外的任意字符串
    return [tok.lower() for tok in listOfTokens if len(tok) > 2]    # 除了单个字母外,其他字符串全部转换成小写
 
# 完整的垃圾邮件测试函数
def spamTest():
    docList = []                 # 文档列表
    classList = []               # 文档标签
    fullText = []                # 全部文档内容集合
    for i in range(1, 26):                                           # 遍历垃圾邮件和非垃圾邮件各25个
        wordList = textParse(open('email/spam/1 (%d).txt' % i).read())   # 读取垃圾邮件,将大字符串并将其解析为字符串列表
        docList.append(wordList)                                     # 垃圾邮件加入文档列表
        fullText.extend(wordList)                                    # 把当前垃圾邮件加入文档内容集合
        classList.append(1)                                          # 1表示垃圾邮件,标记垃圾邮件
        wordList = textParse(open('email/ham/1 (%d).txt' % i).read())    # 读非垃圾邮件,将大字符串并将其解析为字符串列表
        docList.append(wordList)                                     # 非垃圾邮件加入文档列表
        fullText.extend(wordList)                                    # 把当前非垃圾邮件加入文档内容集合
        classList.append(0)                                          # 0表示垃圾邮件,标记非垃圾邮件,
 
    vocabList = createVocabList(docList)                             # 创建不重复的词汇表
    trainingSet = list(range(50))                                    # 为训练集添加索引
    testSet = []                                                     # 创建测试集
    for i in range(10):                                              # 目的为了从50个邮件中,随机挑选出40个作为训练集,10个做测试集
        randIndex = int(random.uniform(0, len(trainingSet)))         # 随机产生索引
        testSet.append(trainingSet[randIndex])                       # 添加测试集的索引值
        del (trainingSet[randIndex])                                 # 在训练集中,把加入测试集的索引删除
 
    trainMat = []                                                    # 创建训练集矩阵训练集类别标签系向量
    trainClasses = []                                                # 训练集类别标签
    for docIndex in trainingSet:                                     # for循环使用词向量来填充trainMat列表t
        trainMat.append(bagOfWords2VecMN(vocabList, docList[docIndex]))  # 把词集模型添加到训练矩阵中
        trainClasses.append(classList[docIndex])                     # 把类别添加到训练集类别标签中
    p0V, p1V, pSpam = trainNB0(array(trainMat), array(trainClasses)) # 朴素贝叶斯分类器训练函数
 
    print('词表:\n', vocabList)
    print('p0V:\n', p0V)
    print('p1V:\n', p1V)
    print('pSpam:\n', pSpam)
 
    errorCount = 0                                                   # 用于计数错误分类
    for docIndex in testSet:                                         # 循环遍历训练集
        wordVector = bagOfWords2VecMN(vocabList, docList[docIndex])  # 获得测试集的词集模型
        if classifyNB(array(wordVector), p0V, p1V, pSpam) != classList[docIndex]:
            errorCount += 1                                          # 预测值和真值不一致,则错误分类计数加1
            print("分类错误集", docList[docIndex])
    print('错误率: ', float(errorCount) / len(testSet))
    # return vocabList,fullText



    # 邮件分类器
def classifyEmail():
    docList = []                 # 文档列表
    classList = []               # 文档标签
    fullText = []                # 全部文档内容集合
    for i in range(1, 26):                                           # 遍历垃圾邮件和非垃圾邮件各25个
        wordList = textParse(open('email/spam/1 (%d).txt' % i).read())   # 读取垃圾邮件,将大字符串并将其解析为字符串列表
        docList.append(wordList)                                     # 垃圾邮件加入文档列表
        fullText.extend(wordList)                                    # 把当前垃圾邮件加入文档内容集合
        classList.append(1)                                          # 1表示垃圾邮件,标记垃圾邮件
        wordList = textParse(open('email/ham/1 (%d).txt' % i).read())    # 读非垃圾邮件,将大字符串并将其解析为字符串列表
        docList.append(wordList)                                     # 非垃圾邮件加入文档列表
        fullText.extend(wordList)                                    # 把当前非垃圾邮件加入文档内容集合
        classList.append(0)                                          # 0表示垃圾邮件,标记非垃圾邮件,
 
    vocabList = createVocabList(docList)                             # 创建不重复的词汇表
    trainingSet = list(range(50))                                    # 为训练集添加索引
    trainMat = []                                                    # 创建训练集矩阵训练集类别标签系向量
    trainClasses = []                                                # 训练集类别标签
    for docIndex in trainingSet:                                     # for循环使用词向量来填充trainMat列表
        trainMat.append(bagOfWords2VecMN(vocabList, docList[docIndex]))  # 把词集模型添加到训练矩阵中
        trainClasses.append(classList[docIndex])                     # 把类别添加到训练集类别标签中
    p0V, p1V, pSpam = trainNB0(array(trainMat), array(trainClasses)) # 朴素贝叶斯分类器训练函数
 
    testList = textParse(open('email/test/1 (1).txt').read())            # 读取邮件,将大字符串并将其解析为字符串列表
    testVector = bagOfWords2VecMN(vocabList, testList)               # 获得测试集的词集模型
    if classifyNB(array(testVector), p0V, p1V, pSpam):
        result = "垃圾邮件"
    else:
        result = "正常邮件"
    print("输入邮件内容为: ")
    print(' '.join(testList))
    print('该邮件被分类为: ', result)



if __name__ == '__main__':
    classifyEmail()

3.运行结果

在这里插入图片描述

三、总结

优点:
1、朴素贝叶斯模型发源于古典数学理论,有着坚实的数学基础,以及稳定的分类效率。
2、NBC模型所需估计的参数很少,对缺失数据不太敏感,算法也比较简单。
缺点:
1、理论上,NBC模型与其他分类方法相比具有最小的误差率。但是实际上并非总是如此,这是因为NBC模型假设属性之间相互独立,这个假设在实际应用中往往是不成立的(可以考虑用聚类算法先将相关性较大的属性聚类),这给NBC模型的正确分类带来了一定影响。在属性个数比较多或者属性之间相关性较大时,NBC模型的分类效率比不上决策树模型。而在属性相关性较小时,NBC模型的性能最为良好。
2、需要知道先验概率。
3、分类决策存在错误率

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值