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

《机器学习实战》学习笔记第四章-朴素贝叶斯

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

《机器学习实战》学习笔记第四章-朴素贝叶斯

目录

贝叶斯决策理论

进行文本分类

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

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

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

 文档词袋类型

使用贝叶斯过滤垃圾邮件


贝叶斯决策理论

比较一个确定的点属于不同类别的概率,哪个概率大,属于哪一类。

优点:在数据较少的情况下仍然有效,可以处理多类别问题。

缺点:对于输入数据的准备方式较为敏感。

适用数据类型:标称型数据

一般过程:

1.收集数据

2.准备数据:需要数值型或布尔型数据

3.分析数据:有大量特征时,使用直方图效果更好

4.训练算法:计算不同的独立特征的条件概率

5.测试算法:计算错误率

6.使用算法:一个常见的朴素贝叶斯应用是文档分类。

贝叶斯公式:

  • P(A|B)是已知B发生后A的条件概率,也由于得自B的取值而被称作A的后验概率,表示事件B发生后,事件A发生的置信度。
  • P(A)是A的先验概率或边缘概率,表示事件A发生的置信度。
  • P(B|A)是已知A发生后B的条件概率,也由于得自A的取值而被称作B的后验概率,也被称作似然函数。
  • P(B)是B的先验概率或边缘概率,称为标准化常量。
  • P(B|A)P(B)称为标准似然比,表示事件B为事件A发生提供的支持程度。

最大似然估计:完全从样本入手,使得观测数据(样本)发生概率最大的参数,即P(X|θ)最大的参数θ就是最好的参数,如抛硬币10次6次正,最大似然估计认为抛一次为正的概率为0.6

最大后验概率估计:事先知道抛硬币为正的概率是0.5,认为使P(X|θ)P(θ)取最大值的θ就是最好的θ,因此以0.5和最大似然估计计算得到θ=0.57

贝叶斯估计:在最大后验估计的基础上,不是估计θ的值,而是估计一个范围,约为0.5625

参考自:贝叶斯估计、最大似然估计、最大后验概率估计 | SnailTyan (noahsnail.com)

进行文本分类

要从文本中获取特征,需要先拆分文本。具体的特征词条可以是URL、IP地址或者任意字符串,1表示词条出现,0表示未出现。

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

从文本中构建词向量,将句子转化成向量。

以在线社区留言板为例,我们要屏蔽侮辱性言论,侮辱类词汇为1,非侮辱类为0

下面是从表到向量的转换函数:

#创建数据集
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] 
    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 #某词汇出现过,0变成1
        else:
            print(f'the word: {word} is not in my Vocabulary!')
    return returnVec #输出一个0或1组成的列表,表示数据集中所有出现过的词汇 在某个数据中是否出现(1,0)

正常情况下不会出现  某词汇在集合中不存在的情况

listOPosts,listClasses = loadDataSet()
myVocabList = createVocabList(listOPosts)
print(setOfWords2Vec(myVocabList,listOPosts[3]))

输出:[0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]  

训练算法:从词向量计算概率
#输入参数为文档矩阵trainMatrix(即上面函数输出的returnVec),和先验的每篇文档类别标签所构成的向量trainCategory
def trainNB0(trainMatrix,trainCategory):
    numTrainDocs = len(trainMatrix) #训练数据量
    numWords = len(trainMatrix[0]) #每个数据要训练多少个词
    pAbusive = sum(trainCategory)/float(numTrainDocs)#p(class=1),p(class=0)=1-p(class=1)
    p0Num = np.zeros(numWords)
    p1Num = np.zeros(numWords)
    p0Denom = 0.0
    p1Denom = 0.0
    for i in range(numTrainDocs):
        if trainCategory[i] == 1:
            p1Num += trainMatrix[i] #向量形式统计class=1中所有词出现的次数[2,3,4,0...]
            p1Denom += sum(trainMatrix[i]) #单数形式统计class=1中所有词出现的次数9
        else:
            p0Num += trainMatrix[i]
            p0Denom += sum(trainMatrix[i])
    p1Vect = p1Num/p1Denom #class=1中每个词出现占所有词出现总次数的比例,即p(wi|c=1)
    p0Vect = p0Num/p0Denom
    return p0Vect,p1Vect,pAbusive
trainMat = [] #是数据集中所有数据行  用我们的数据集合表示的列表[[1,0,1,0...],[],[]...]
for postinDoc in listOPosts:
    trainMat.append(setOfWords2Vec(myVocabList,postinDoc))
p0v,p1v,pab = trainNB0(trainMat,listClasses)

p0v=

pab=0.5

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

 要计算多个概率的乘积以获得文档属于某个类别的概率,即计算p(w0|c=1)p(w1|c=1)p(w2|c=1)。如果其中一个概率值为0,那么最后乘积也是0,所以将所有词出现的初始化为1,总数初始为2。

    p0Num = np.ones(numWords)
    p1Num = np.ones(numWords)
    p0Denom = 2.0
    p1Denom = 2.0

另一个问题是下溢出,即计算结果太小会近似为0,,用对数解决:

p1Vect = log(p1Num/p1Denom)
p0Vect = log(p0Num/p0Denom)

分类算法:

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 testingNB():
    listOPosts,listClasses = loadDataSet()
    myVocabList = createVocabList(listOPosts)
    trainMat = [] #是数据集中所有数据行  用我们的数据集合表示的列表[[1,0,1,0...],[],[]...]
    for postinDoc in listOPosts:
        trainMat.append(setOfWords2Vec(myVocabList,postinDoc))
    p0v,p1v,pab = trainNB0(trainMat,listClasses)
    testEntry = ['love','my','dalmation']
    thisDoc = np.array(setOfWords2Vec(myVocabList,testEntry))
    print(testEntry,'classified as: ',classifyNB(thisDoc,p0v,p1v,pab))
    testEntry = ['stupid','garbage']
    thisDoc = np.array(setOfWords2Vec(myVocabList,testEntry))
    print(testEntry,'classified as: ',classifyNB(thisDoc,p0v,p1v,pab))

结果:

 文档词袋类型

词集模型:每个词出现与F否

词袋模型:每个词出现次数

对函数sefOfWords2Vec修改:

def bagOfWords2Vec(vocabList,inputSet): 
    returnVec = [0]*len(vocabList) 
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)] += 1 #某词汇出现过,+1
        else:
            print(f'the word: {word} is not in my Vocabulary!')
    return returnVec

使用贝叶斯过滤垃圾邮件

准备数据:切分文本

#准备数据
def textParse(bigString):
    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):
        wordList = textParse(open('email/spam/%d.txt'%i).read())
        docList.append(wordList)
        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 = list(range(50)) #共50个样本
    testSet = []
    for i in range(10): #随机取10个样本做测试集,存入testSet
        randIndex = int(np.random.uniform(0,len(trainingSet)))
        testSet.append(trainingSet[randIndex])
        del(trainingSet[randIndex]) #trainingSet中剩下的是训练集
    trainMat = []
    trainClass = []
    for docIndex in trainingSet:
        trainMat.append(setOfWords2Vec(vocabList,docList[docIndex]))
        trainClass.append(classList[docIndex])
    p0v,p1v,pspam = trainNB0(np.array(trainMat),np.array(trainClass))
    errorcount = 0
    for docIndex in testSet:
        wordVector = setOfWords2Vec(vocabList,docList[docIndex])
        if classifyNB(np.array(wordVector),p0v,p1v,pspam)!=classList[docIndex]:
            errorcount+=1
    print(f'error rate:{float(errorcount)/len(testSet)}')

一直输出0.6!正则表达式的问题!改成‘/w’就好了!

由于测试集是随机抽取10封,因此,多次运行程序,结果不同,多为0,偶尔为0.1、0.2

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

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

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