我是靠谱客的博主 糊涂芝麻,这篇文章主要介绍机器学习实战第四章,现在分享给大家,希望可以做个参考。

基于概率论的分类方法:朴素贝叶斯

  • 说明:本章节所有代码使用版本为Python3

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

  概率论是许多机器学习算法的基础。本文首先从一个最简单的概率分类器开始,然后给出一些假设来学习朴素贝叶斯分类器,之所以称为 “朴素” ,是因为整个形式化过程只做最原始、最简单的假设。我们充分利用Python的文本处理能力将文档切分成词向量,然后利用词向量对文档进行分类,还将构建一个分类器,观察其在真实的垃圾邮件数据集中的过滤效果。最后介绍如何从个人发布的大量广告中学习分类器,并将学习结果转化成人类可以理解的信息。

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

  朴素贝叶斯是贝叶斯决策理论的一部分,贝叶斯决策理论的核心思想是选择具有最高概率的决策(使用概率比较的方法)。

条件概率

  设A,B是两个事件,且P(A)>0,称

P ( B ∣ A ) = P ( A B ) P ( A ) P(B|A)=dfrac{P(AB)}{P(A)} P(BA)=P(A)P(AB)

为事件A发生条件下事件B发生的条件概率。

  有效计算条件概率的方法称为贝叶斯准则,贝叶斯准则告诉我们如何交换条件概率中的条件与结果,即若已知P(x|c),要求P(c|x),那么可以使用下面的计算方法:

P ( c ∣ x ) = P ( A x ∣ c ) P ( c ) p ( x ) P(c|x)=dfrac{P(Ax|c)P(c)}{p(x)} P(cx)=p(x)P(Axc)P(c)

使用条件概率来分类

  我们真正需要解决的是:给定某个由x,y表示的数据点,那么该数据点来自类别 c 1 c_1 c1的概率是多少(即 p ( c 1 ∣ x , y ) p(c_1|x,y) p(c1x,y)),数据点来自类别 c 2 c_2 c2的概率是多少(即 p ( c 2 ∣ x , y ) p(c_2|x,y) p(c2x,y))。可以使用贝叶斯准则来交换概率中条件与结果,具体应用贝叶斯得到:

p ( c i ∣ x , y ) = P ( x , y ∣ c i ) P ( c i ) p ( x , y ) p(c_i|x,y)=dfrac{P(x,y|c_i)P(c_i)}{p(x,y)} p(cix,y)=p(x,y)P(x,yci)P(ci)

  使用这些定义,可以定义贝叶斯分类准则为:

  • P ( c 1 ∣ x , y ) > P ( c 2 ∣ x , y ) P(c_1|x,y) > P(c_2|x,y) P(c1x,y)>P(c2x,y),那么属于类别 c 1 c_1 c1
  • P ( c 1 ∣ x , y ) < P ( c 2 ∣ x , y ) P(c_1|x,y) < P(c_2|x,y) P(c1x,y)<P(c2x,y),那么属于类别 c 2 c_2 c2

  使用贝叶斯准则,可以通过已知的三个概率值来计算未知的概率值。

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

  机器学习的一个重要应用就是文档的自动分类。

朴素贝叶斯的一般流程

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

  独立 是指一个特征或者一个单词出现的可能性与它和其他单词相邻没有关系。朴素贝叶斯的一个假设是特征花之间相互独立,另一个假设是每个特征同等重要。

使用Python进行文档分类

  要从文本中获取特征,需要先拆分文本。具体流程:特征来自词条(字符的任意组合,可以是URL、IP地址或其他字符串),然后将每一个文本片段表示为一个词向量,接下来构建分类器,最后实现朴素贝叶斯过程中的需要考虑的问题。

1、准备数据:从文本中构建词向量

  把文本看成单词向量或词条向量,也就是将句子,转化成向量。

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

  重写贝叶斯准则,将之前的x,y替换成w,粗体的w表示向量,即它是由多个数值组成的。在本例中。数值个数与词汇表中的词个数相同。

p ( c i ∣ w ) = p ( w ∣ c i ) p ( c i ) p ( w ) p(c_i|textbf{w})=dfrac{p(textbf{w}|c_i)p(c_i)}{p(textbf{w})} p(ciw)=p(w)p(wci)p(ci)

  使用上述公式对每一类计算该值,然后比较这两个概率值的大小。

3、测试算法:根据现实情况修改分类器

  利用贝叶斯算法对文档进行分类时,要计算多个概率的乘积以获得文档属于某个类别的概率即计算 p ( w 0 ∣ 1 ) p ( w 1 ∣ 1 ) p ( w 2 ∣ 1 ) p(w_0|1)p(w_1|1)p(w_2|1) p(w01)p(w11)p(w21)。若其中一个为0的话,最后的乘积也为0,为降低这种影响,可以将所有词出现数初始化为1,并将分母初始化为2。
  另一个问题是下溢,这是由于太多很小的数相乘造成的。一种解决的办法是对乘积取自然对数。

4、准备数据:文档词袋模型

  我们将每一个词的出现与否作为一个特征,这可以被描述为词集模型。若一个词在文档中出现不止一次,这可能意味着包含该词是否出现在文档中所不能表达的某种信息,这种方法被称为词袋模型。在词袋中,每个词可以出现多次,而词集中,每个词只能出现一次。

5、完整示例代码

from numpy import *
import numpy as np
# 自己定义数据集
def loadDataSet():
postingList = [['my', 'dog', 'has', 'flea', 'problem', '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 代表侮辱性文字,0 代表正常言论
return postingList, classVec
# 创建词向量,且每一个元素都不会重复
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:
returnVec[vocabList.index(word)] = 1
# 若出现了词汇表中的单词则将对应值设为1
else:
print("The word: %s is not in my Vocablary!" % word)
return returnVec
# 返回在词汇列表vocabList中出现的位置是1,没有出现的为0,作为文档向量
# 朴素贝叶斯词袋模型
def bagOfWords2VecMN(vocabList, inputSet):
# 参数为词汇列表和文档
returnVec = [0] * len(vocabList)
# 创建一个其中所含元素都为0的向量
for word in inputSet:
if word in vocabList:
returnVec[vocabList.index(word)] += 1
# 若出现了词汇表中的单词则将对应值都进行加1
return returnVec
# 说明bagOfWords2VecMN函数与setOfWords2Vec函数是一样的,
# 不同的是每当遇到一个单词时,它会增加词向量的对应值,而不是将其设为1
# 朴素贝叶斯分类器训练函数
def trainNB0(trainMatrix, trainCategory):
# trainMatrix是文档矩阵,trainCategory是文档标签所构成的向量
numTrainDocs = len(trainMatrix)
# 获得文档矩阵的长度,即文档个数
numWords = len(trainMatrix[0])
# 一个文档中的单词数
pAbusive = np.sum(trainCategory) / float(numTrainDocs)
# 计算文档为侮辱性文档的概率,因为侮辱为1,所以计算的是p(1)的概率
# ----------更改之前的代码(start)----------
# p0Num=zeros(numWords)
# p1Num=zeros(numWords)
# p0Denom=0.0
# p1Denom=0.0
# 以上四行皆为初始化概率
# -----------更改之前的代码(end)-----------
p0Num = ones(numWords)
p1Num = ones(numWords)
p0Denom = 2.0
p1Denom = 2.0
# 以上四行皆为初始化概率
for i in range(numTrainDocs):
if trainCategory[i] == 1:
p1Num += trainMatrix[i]
# 若文档标签是侮辱性的词向量,则将本文本与p1文档矩阵相加
p1Denom += np.sum(trainMatrix[i])
# 句子所有侮辱词个数相加
else:
p0Num += trainMatrix[i]
# 若文档标签是不是侮辱性的词向量,则将本文本与p0文档矩阵相加
p0Denom += np.sum(trainMatrix[i])
# 句子所有非侮辱词个数相加
# ----------更改之前的代码(start)----------
# p1Vect=p1Num/p1Denom
# p0Vect=p0Num/p0Denom
# -----------更改之前的代码(end)-----------
p1Vect = np.log(p1Num / p1Denom)
# 数组除以数,正例时,每个词出现概率:p(1)概率(即侮辱词出现的概率)
p0Vect = np.log(p0Num / p0Denom)
# 每个词出现概率:p(0)概率(即非侮辱词出现的概率)
return p0Vect, p1Vect, pAbusive
# p0Vect非侮辱词向量概率,p1Vect侮辱词向量概率,pAbusive是p(1)的概率
# 朴素贝叶斯分类函数
def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
p1 = np.sum(vec2Classify * p1Vec) + np.log(pClass1)
# vec2Classify与侮辱性词集相乘(对应元素相乘),并求和,算出其概率
p0 = np.sum(vec2Classify * p0Vec) + np.log(1.0 - pClass1)
# vec2Classify与非侮辱性词集相乘,并求和,算出其概率
if p1 > p0:
return 1
else:
return 0
# 哪个概率大,则返回哪一个
def testingNB():
listOPosts, listClasses = loadDataSet()
# 载入数据
myVocabList = createVocabList(listOPosts)
# 创建词向量myVocabList(无重复元素)
trainMat = []
for postinDos in listOPosts:
trainMat.append(setOfWords2Vec(myVocabList, postinDos))
# 每经过一轮的遍历就将myVocabList中出现的postInDoc所在位置的数值设为1,并将形成的列表追加到trainMat
p0V, p1V, pAB = trainNB0(array(trainMat), array(listClasses))
# trainMat是numpy.ndarray类型,要进行转化;同理listClasses也是
# 获取非侮辱词向量概率,侮辱词向量概率和p(1)的概率
testEntry = ['love', 'my', 'dalamtion']
thisDoc = array(setOfWords2Vec(myVocabList, testEntry))
# 输出文档向量testEntry在myVocabList中的位置,即将testEntry按照myVocabList转化成0,1相间的数组
print(testEntry, 'classified as:', classifyNB(thisDoc, p0V, p1V, pAB))
# classifyNB函数按照特征进行分类并返回结果,以下三行同理
testEntry = ['stupid', 'garbage']
thisDoc = array(setOfWords2Vec(myVocabList, testEntry))
print(testEntry, 'classified as:', classifyNB(thisDoc, p0V, p1V, pAB))
print(testingNB())

示例:使用朴树贝叶斯过滤垃圾邮件

示例:使用朴素贝叶斯对电子邮件进行分类

  1. 收集数据:提供文本文件
  2. 准备数据:将文本文件解析成词条向量
  3. 分析数据:检查词条确保解析的正确性
  4. 训练算法:使用之前建立的trainNB0函数
  5. 测试算法:使用classifyNB,并且构建一个新的测试函数来计算文档的错误率
  6. 使用算法:构建一个完整的程序对一组文档进行分类,讲错分的文档输入到屏幕上

1、准备数据:切分文本

  使用Python的string.split()方法进行切分。

2、测试算法:使用朴素贝叶斯进行交叉验证

  随机选择数据的一部分作为训练集,而剩下的部分作为测试集的过程称为留存交叉验证

3、完整代码示例

import re
import numpy as np
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:
returnVec[vocabList.index(word)] = 1
# 若出现了词汇表中的单词则将对应值设为1
else:
print("The word: %s is not in my Vocablary!" % word)
return returnVec
# 返回在词汇列表vocabList中出现的位置是1,没有出现的为0,作为文档向量
# 朴素贝叶斯分类函数
def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
p1 = np.sum(vec2Classify * p1Vec) + np.log(pClass1)
# vec2Classify与侮辱性词集相乘(对应元素相乘),并求和,算出其概率
p0 = np.sum(vec2Classify * p0Vec) + np.log(1.0 - pClass1)
# vec2Classify与非侮辱性词集相乘,并求和,算出其概率
if p1 > p0:
return 1
else:
return 0
# 哪个概率大,则返回哪一个
# 朴素贝叶斯分类器训练函数
def trainNB0(trainMatrix, trainCategory):
# trainMatrix是文档矩阵,trainCategory是文档标签所构成的向量
numTrainDocs = len(trainMatrix)
# 获得文档矩阵的长度,即文档个数
numWords = len(trainMatrix[0])
# 一个文档中的单词数
pAbusive = np.sum(trainCategory) / float(numTrainDocs)
# 计算文档为侮辱性文档的概率,因为侮辱为1,所以计算的是p(1)的概率
p0Num = np.ones(numWords)
p1Num = np.ones(numWords)
p0Denom = 2.0
p1Denom = 2.0
# 以上四行皆为初始化概率
for i in range(numTrainDocs):
if trainCategory[i] == 1:
p1Num += trainMatrix[i]
# 若文档标签是侮辱性的词向量,则将本文本与p1文档矩阵相加
p1Denom += np.sum(trainMatrix[i])
# 句子所有侮辱词个数相加
else:
p0Num += trainMatrix[i]
# 若文档标签是不是侮辱性的词向量,则将本文本与p0文档矩阵相加
p0Denom += np.sum(trainMatrix[i])
# 句子所有非侮辱词个数相加
p1Vect = np.log(p1Num / p1Denom)
# 数组除以数,正例时,每个词出现概率:p(1)概率(即侮辱词出现的概率)
p0Vect = np.log(p0Num / p0Denom)
# 每个词出现概率:p(0)概率(即非侮辱词出现的概率)
return p0Vect, p1Vect, pAbusive
# p0Vect非侮辱词向量概率,p1Vect侮辱词向量概率,pAbusive是p(1)的概率
# 将文本进行切片
def textParse(bigString):
listOfTokens = re.split(r'W+', bigString)
# 注意py2与py3的区别,py2使用W*来进行单词切片,py3使用W+来进行单词切片
return [tok.lower() for tok in listOfTokens if len(tok) > 2]
# lower()将所有的单词字母变成小写,除去标点符号与空格
# 交缠验证函数
def spamTest():
docList = []
# 文档列表初始化
classList = []
# 分类列表初始化,即判断是否为侮辱性言论的列表,是为1,否为0
fullText = []
# 初始化所有在邮件中出现的单词
for i in range(1, 26):
wordList = textParse(open('email/spam/%d.txt' % i).read())
# 读取一个邮件内容并切片
docList.append(wordList)
# 将邮件的内容添加到docList中
fullText.extend(wordList)
# 追加内容时,保持邮件的原格式文本
classList.append(1)
# 分类标签为有侮辱性单词
# 下面四行与上面四行一样,只是最后一行为无侮辱性单词标签
wordList = textParse(open('email/ham/%d.txt' % i).read())
docList.append(wordList)
fullText.extend(wordList)
classList.append(0)
vocabList = createVocabList(docList)
# 创建词向量(去重复单词)
trainingSet = range(50)
# range返回的是range对象,,不返回数组对象
testSet = []
# 初始化数据集列表
for i in range(10):
randIndex = int(np.random.uniform(0, len(trainingSet)))
# 获得0~len(trainingSet)(50)的一个随机数
testSet.append(trainingSet[randIndex])
# 追加到测试集中,即随机构建训练集
del(list(trainingSet)[randIndex])
# 删除本次选中的数据,防止随机选择时再次被选中
# 注意这里采用的是py3写法,py2应写成:del(trainingSet[randIndex])
trainMat = []
trainClasses = []
for docIndex in trainingSet:
# trainingSet就是0-49,docList包含有所有的邮件单词文本
trainMat.append(setOfWords2Vec(vocabList, docList[docIndex]))
# setOfWords2Vec返回文档向量,将所有的词向量信息追加到trainMat中
trainClasses.append(classList[docIndex])
# trainClasses与classList信息是一样的,都是分类的标签,1,0相间
p0V, p1V, pSpam = trainNB0(array(trainMat), array(trainClasses))
# trainNB0朴素贝叶斯分类器训练器,获得P(0)和P(1)的概率
errorCount = 0
for docIndex in testSet:
wordVector = setOfWords2Vec(vocabList, docList[docIndex])
# 获取某一次的文档向量,为后续的分类准备
if classifyNB(array(wordVector), p0V, p1V, pSpam) != classList[docIndex]:
# classifyNB表示朴素贝叶斯分类结果,要是classifyNB的结果与标签不同,则错误率加一
errorCount += 1
print("The error rate is:", float(errorCount)/len(testSet))
spamTest()

示例:使用朴树贝叶斯分类器从个人广告中获取区域倾向

示例:使用朴素贝叶斯来发现地域相关的用词

  1. 收集数据:从RSS源收集内容,这里需要对RSS源构建一个接口
  2. 准备数据:将文本文件解析成词条向量
  3. 分析数据:检查词条确保解析的正确性
  4. 训练算法:使用之前建立的trainNB0函数
  5. 测试算法:观察错误率,确保分类器可用。可以修改切分程序,以降低错误率,提高分类结果
  6. 使用算法:构建一个完整的程序,封装所有的内容,给定两个RSS源,该程序会显示最常用的公共词

1、收集数据:导入RSS源

2、分析数据:显示地域相关的用词

3、完整示例代码展示

import feedparser
import operator
import numpy as np
from numpy import *
# 创建词向量,且每一个元素都不会重复
def createVocabList(dataSet):
vocabSet = set([])
# 创建一个空集合
for document in dataSet:
vocabSet = vocabSet | set(document)
# 创建两个集合的并集,防止有重复的单词,每次运行会有一定的随机性
return list(vocabSet)
# 朴素贝叶斯词袋模型
def bagOfWords2VecMN(vocabList, inputSet):
# 参数为词汇列表和文档
returnVec = [0] * len(vocabList)
# 创建一个其中所含元素都为0的向量
for word in inputSet:
if word in vocabList:
returnVec[vocabList.index(word)] += 1
# 若出现了词汇表中的单词则将对应值都进行加1
return returnVec
# 说明bagOfWords2VecMN函数与setOfWords2Vec函数是一样的,
# 不同的是每当遇到一个单词时,它会增加词向量的对应值,而不是将其设为1
# 朴素贝叶斯分类器训练函数
def trainNB0(trainMatrix, trainCategory):
# trainMatrix是文档矩阵,trainCategory是文档标签所构成的向量
numTrainDocs = len(trainMatrix)
# 获得文档矩阵的长度,即文档个数
numWords = len(trainMatrix[0])
# 一个文档中的单词数
pAbusive = np.sum(trainCategory) / float(numTrainDocs)
# 计算文档为侮辱性文档的概率,因为侮辱为1,所以计算的是p(1)的概率
p0Num = np.ones(numWords)
p1Num = np.ones(numWords)
p0Denom = 2.0
p1Denom = 2.0
# 以上四行皆为初始化概率
for i in range(numTrainDocs):
if trainCategory[i] == 1:
p1Num += trainMatrix[i]
# 若文档标签是侮辱性的词向量,则将本文本与p1文档矩阵相加
p1Denom += np.sum(trainMatrix[i])
# 句子所有侮辱词个数相加
else:
p0Num += trainMatrix[i]
# 若文档标签是不是侮辱性的词向量,则将本文本与p0文档矩阵相加
p0Denom += np.sum(trainMatrix[i])
# 句子所有非侮辱词个数相加
p1Vect = np.log(p1Num / p1Denom)
# 数组除以数,正例时,每个词出现概率:p(1)概率(即侮辱词出现的概率)
p0Vect = np.log(p0Num / p0Denom)
# 每个词出现概率:p(0)概率(即非侮辱词出现的概率)
return p0Vect, p1Vect, pAbusive
# p0Vect非侮辱词向量概率,p1Vect侮辱词向量概率,pAbusive是p(1)的概率
# 朴素贝叶斯分类函数
def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
p1 = np.sum(vec2Classify * p1Vec) + np.log(pClass1)
# vec2Classify与侮辱性词集相乘(对应元素相乘),并求和,算出其概率
p0 = np.sum(vec2Classify * p0Vec) + np.log(1.0 - pClass1)
# vec2Classify与非侮辱性词集相乘,并求和,算出其概率
if p1 > p0:
return 1
else:
return 0
# 哪个概率大,则返回哪一个
# 高频词排序
def calcMostFreq(vocabList,fullText):
# vocabList去重之后的所有单词,fullText去重之前的所有单词
freqDict={}
#创建一个空词典,用来存储单词及其出现的次数
for token in vocabList:
freqDict[token]=fullText.count(token)
# 得到词典键,以及出现的次数
sortedFreq=sorted(freqDict.items(),key=operator.itemgetter(1),reverse=True)
# sorted(对象,排序值,reverse=True/False),reverse默认值为False,表示正序,reverse=True表示倒序。
# 按照每个key的值对每对keyvalue进行降序排序,operator.itemgetter(1):得到item中的第二个位置的值
return sortedFreq[:30]
# 返回排序最高的前30个词
# RSS源分类器及高频词去除
def localWords(feed1,feed0):
docList=[]
# 文档列表初始化
classList=[]
# 分类列表初始化,即判断是否为侮辱性言论的列表,是为1,否为0
fullText=[]
# 初始化所有在RSS网页内容中出现的单词
minLen=min(len(feed1['entries']),len(feed0['entries']))
for i in range(minLen):
wordList=feedparser.textParser(feed1['entries'][i]['summary'])
# 读取一个RSS网页内容并切片,feed1['entries'][i]['summary']是标签文本的具体位置
docList.append(wordList)
# 将RSS网页内容添加到docList中
fullText.extend(wordList)
# 追加内容时,保持RSS网页内容的原格式文本
classList.append(1)
# 分类标签为有侮辱性单词
# 下面四行与上面四行一样,只是最后一行为无侮辱性单词标签
wordList=feedparser.textParser(feed0['entries'][i]['summary'])
docList.append(wordList)
fullText.extend(wordList)
classList.append(0)
vocabList=createVocabList(docList)
# 创建词向量(去重复单词)
top30Words=calcMostFreq(vocabList,fullText)
# 获取词频出现最多的前30个
for pairW in top30Words:
if pairW[0] in vocabList:
vocabList.remove(pairW[0])
# 去掉出现次数最高的前30个的词(可以理解为停词库)
trainingSet=range(2*minLen)
# range返回的是range对象,不返回数组对象,大小是minLen的二倍
testSet=[]
# 初始化数据集列表
trainMat = []
trainClasses = []
for docIndex in trainingSet:
# trainingSet保存训练样本数据集,docList包含有所有的邮件单词文本
trainMat.append(bagOfWords2VecMN(vocabList, docList[docIndex]))
# setOfWords2Vec返回文档向量,将所有的词向量信息追加到trainMat中
trainClasses.append(classList[docIndex])
# trainClasses与classList信息是一样的,都是分类的标签,1,0相间
p0V, p1V, pSpam = trainNB0(array(trainMat), array(trainClasses))
# trainNB0朴素贝叶斯分类器训练器,获得P(0)和P(1)的概率
errorCount = 0
for docIndex in testSet:
wordVector = bagOfWords2VecMN(vocabList, docList[docIndex])
# 获取某一次的文档向量,为后续的分类准备
if classifyNB(array(wordVector), p0V, p1V, pSpam) != classList[docIndex]:
# classifyNB表示朴素贝叶斯分类结果,要是classifyNB的结果与标签不同,则错误率加一
errorCount += 1
print("The error rate is:", float(errorCount)/len(testSet))
return vocabList,p0V,p1V
# spamTest与localWords在本质上都是一样的,
# 但是不同的是spamTest访问的是本地的文件,而localWords使用的是RSS源
# 最具表征性的词汇显示函数
def getTopWords(ny,sf):
vocabList,p0V,p1V=localWords(ny,sf)
# 获得p1V和p0V的大小
topNY=[]
topSF=[]
for i in range(len(p0V)):
if p0V > -6.0:
topSF.append((vocabList[i],p0V[i]))
# 不含侮辱性词的概率(的对数)>-6.0的单词
if p1V > -6.0:
topSF.append((vocabList[i],p1V[i]))
# 含侮辱性词的概率(的对数)>-6.0的单词
sortedSF=sorted(topSF,key=lambda pair:pair[1],reverse=True)
# 排序,lambda函数是匿名函数:匿名函数并非不是没有名字,而是将函数名作为函数结果返回
# sorted(d.items(), key = lambda x : x[1] ):d.items() 为需要进行排序的对象,key=lambda 变量:变量[维数]
# 其中x:x[ ]字母可以随意修改,排序方式按照中括号[]里面的维度进行排序,[0]按照第一维排序,
# [1] 按照第二维排序,[2]按照第三维排序,依次类推。reverse=True降序排列
# 参考资料:https://blog.csdn.net/weixin_52626164/article/details/116676414
print("*SF**SF**SF**SF**SF**SF**SF**SF**SF**SF**SF**SF*")
for item in sortedSF:
print(item[0])
# 输出item元组的单词项
# 以下四行同上面四行是一样
sortedNY=sorted(topNY,key=lambda pair:pair[1],reverse=True)
print("*NY**NY**NY**NY**NY**NY**NY**NY**NY**NY**NY**NY*")
for item in sortedNY:
print(item[0])
ny=feedparser.parse('https://newyork.craigslist.org/d/rooms-shares/search/roo?format=rss')
sf=feedparser.parse('https://newyork.craigslist.org/d/rooms-shares/search/roo?format=rss')
# 注意以上两行代码并没有跑通,因为已经失效了,笔者也在网上找了相关替代,但是没有找到
# 重要的是学习算法的思想,并将其运用,要是理解了思想可以采用其他的数据进行验证
print(ny,sf)
vocabList,pSF,pNY=localWords(ny,sf)
getTopWords(ny,sf)

小结

  对于分类而言,使用概率有时要比使用硬规则更为有效。贝叶斯概率及贝叶斯准则提供了一种利用已知值来估计未知概率的有效方法。
  可以通过特征之间的条件独立性假设,降低对数据的需求。独立性假设是指一个词的出现概率不依赖于文档中的其他词,尽管独立性假设并不正确,但是朴树贝叶斯任然是一种有效的分类器。考虑因素:下溢出可以通过对概率取对数来解决;词袋模型在解决文档分类问题上比词集模型有所提高。

最后

以上就是糊涂芝麻最近收集整理的关于机器学习实战第四章的全部内容,更多相关机器学习实战第四章内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(144)

评论列表共有 0 条评论

立即
投稿
返回
顶部