机器学习:多项式模型朴素贝叶斯分类器(原理+python实现)

Tricia ·
更新时间:2024-09-20
· 857 次阅读

简介

多项式朴素贝叶斯也是多用于文本处理,其原理和计算的流程和伯努利朴素贝叶斯基本一致,唯一的区别在于单词的计数方式,由《伯努利朴素贝叶斯》一文可知,在文本处理的环节中,我们将单词是否出现在词组作为特征,但在多项式朴素贝叶斯中,我们将单词在词组中出现的次数作为特征,因此只需要更改文中setOfWords2Vec的函数即可,变成如下方式:

def bagOfWords2VecMN(vocabList, inputSet): returnVec = [0] * len(vocabList) for word in inputSet: if word in vocabList: returnVec[vocabList.index(word)] += 1 return returnVec

下面我们就以实例来使用多项式朴素贝叶斯,这次我们使用最著名的贝叶斯应用:垃圾邮件分类。

准备数据

数据集点击这里,其提取码为x9ko

文本处理

首先将文本文件的字符变为我们想要的格式,即每个句子都生成单词组的列表,并将每个单词的字符变为小写,具体实现如下:

# 输入文本 def textParse(bigString): import re dataMat = [] for line in bigString: curLine = line.split() curLine = [tok.lower() for tok in curLine if len(tok) > 2] dataMat.append(curLine) return dataMat

接下来,就要构造多项式朴素贝叶斯并进行预测,这次选择50封邮件,其中随机抽取10封进行测试决策效果,以分类错误率为评价指标(即将垃圾邮件当作正常邮件的比例),此外,我们将错分的邮件进行输出,以便观察我们可以在哪个方面进行精度上的提升。

import numpy as np import random # 根据句子构建单词表 def createVocabList(dataSet): vocabSet = set([]) # 因为document也是[]结构 for document in dataSet: vocabSet = vocabSet | set(document) # 集合的并集 return list(vocabSet) # 将集合格式变为list格式 # 根据训练集,计算条件概率 def trainNB0(trainMatrix, trainCategory): numTrainDocs = len(trainMatrix) numWords = len(trainMatrix[0]) pAbusive = sum(trainCategory) / float(numTrainDocs) p0Num = np.ones(numWords); p1Num = np.ones(numWords) # change to ones() p0Denom = 2.0; p1Denom = 2.0 # change to 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 = np.log(p1Num / p1Denom) # change to log() p0Vect = np.log(p0Num / p0Denom) # change to log() return p0Vect, p1Vect, pAbusive # 进行分类 def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1): p1 = sum(vec2Classify * p1Vec) + np.log(pClass1) # element-wise mult p0 = sum(vec2Classify * p0Vec) + np.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 dataMat = [] for line in bigString: curLine = line.split() curLine = [tok.lower() for tok in curLine if len(tok) > 2] dataMat.extend(curLine) return dataMat # 进行测试 def spamTest(): # 读取txt文件 # 50封邮件大概有1758个单词,平均每个邮件有30多个字 docList = []; # 每个邮件的单词 classList = []; # 邮件的类别 fullText = [] # 所有邮件的单词 for i in range(1, 26): bigString = r'路径\email\spam\{}.txt'.format(i) wordList = textParse(open(bigString,'r',encoding='ISO-8859-15')) docList.append(wordList) fullText.extend(wordList) classList.append(1) bigString = r'路径\email\ham\{}.txt'.format(i) wordList = textParse(open(bigString,'r',encoding='ISO-8859-15')) docList.append(wordList) fullText.extend(wordList) classList.append(0) docList = [tok for tok in docList if len(tok) > 2] # 根据每封邮件的内容生成单词表 vocabList = createVocabList(docList) # 随机生成10封邮件作为测试 trainingSet = list(range(50)) # 训练集索引 testSet = [] # 测试集索引 for i in range(10): randIndex = int(random.uniform(0, len(trainingSet))) testSet.append(trainingSet[randIndex]) del (trainingSet[randIndex]) # 将训练集生成词向量 trainMat = [] trainClasses = [] for docIndex in trainingSet: # trainMat.append(bagOfWords2VecMN(vocabList, docList[docIndex])) trainClasses.append(classList[docIndex]) # 对训练集进行训练,输出每个单词在不同类别的概率 p0V, p1V, pSpam = trainNB0(np.array(trainMat), np.array(trainClasses)) # 计算测试集概率,计算分类失误率,即将垃圾邮件当作正常邮件的比例 errorCount = 0 for docIndex in testSet: wordVector = bagOfWords2VecMN(vocabList, docList[docIndex]) if classifyNB(np.array(wordVector), p0V, p1V, pSpam) != classList[docIndex]: errorCount += 1 print("classification error", docList[docIndex]) print('the error rate is: ', float(errorCount) / len(testSet))

大部分的情况下,分类失误率为0,当出错的时候,基本为0.1,其中一次分类错误的邮件内容如下所示:
在这里插入图片描述
一般而言,由于是随机划分的训练集和验证集,所以要经过一次数的重复训练,平均精度才能够较为准确的描述分类效果。

写在最后

通过上述的实践可以看出,对于文本处理而言,在一般情况下没有这么简单,单词之间往往夹杂着各自标点符号,因此数据清洗这项工作量往往是巨大的。在分类上,实际状况也很难像分类垃圾邮件这样取得较好的分类效果,这是因为在分析句子的时候,每个单词都是独立分割开来,忽略了单词和单词之间的语义联系。此外,在单词表中显示出高频率的词汇往往未必是重要的词汇,比如是一些结构辅助词汇,这样的词汇会干扰估计的精度,将这些高频词进行删减有时也会提升分类的效果。


作者:DocPark



朴素贝叶斯 学习 分类 模型 贝叶斯 贝叶斯分类器 分类器 机器学习 Python

需要 登录 后方可回复, 如果你还没有账号请 注册新账号