博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Naive Bayes 笔记
阅读量:5299 次
发布时间:2019-06-14

本文共 4993 字,大约阅读时间需要 16 分钟。

Naive Bayes (朴素贝叶斯) 属于监督学习算法, 它通过计算测试样本在训练样本各个分类中的概率来确定测试样本所属分类, 取最大概率为其所属分类.

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

基础概念

1. 条件概率
 P(A|B) 表示事件B已经发生的前提下, 事件A发生的概率, 即事件B发生下事件A的条件概率。
计算公式为: 
2. 贝叶斯公式
当 P(A|B) 比较容易计算, P(B|A) 比较难以计算时, 可以利用贝叶斯公式.
计算公式为: 

算法描述

1. 算法的核心就是计算 P(Ci|w), 其中 w 是测试样本, Ci 是某一个分类, 即计算 w 属于 Ci 的概率, 哪个概率大, 就属于哪个 Ci; 计算公式为:
2. P(w) 对于一个测试样本是固定值, 所以这里不进行考虑, 只需考虑分母即可. (代码72, 73行)
3. P(Ci) 表示的是测试样本中一个分类的概率, 这个也是可以直接求出来的.(即代码中的 pAbusive)
4. P(w|Ci) 中的 w 在本文中是指一个文档, 它由各个单词 W0, W1, W2...组成, W0, W1, W2...的相互之间是独立的, 所以有以下公式成立: 
5. 如果每次有一篇测试文档 w 进来后, 都把它拆分成 W0, W1, W2.. 再去计算 P(W0|Ci), P(W1|Ci), P(W2|Ci)..., 则会大大降低效率, 所以应该在训练阶段把所有出现过的词语 Wj 在各个 Ci 的概率都 P(Wj|Ci) 计算好, 在测试时直接使用即可. 
6. P(Wj|Ci) 的计算, 用 Wj 在 Ci 中出现的次数除以 Ci 中的总单词数即可. (代码第 62, 63 行)

算法流程图

# -*- coding: utf-8 -* from numpy import * # 加载已分好词的数据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']]    # 这里分别指明 postingList 中的各个项是否为侮辱性语言    # 0 表示不是侮辱性语言, 1 表示是    classVec = [0,1,0,1,0,1]        return postingList,classVec                   # 把 dataSet 中的单词存到 list 中, 同时去除所有重复单词def createVocabList(dataSet):    vocabSet = set([])  #create empty set    for document in dataSet:        vocabSet = vocabSet | set(document) #union of the two sets    return list(vocabSet)  # 将 inputSet 转成向量, 即一个长度为 len(vocabList) 的向量# 与 inputSet 中单词相同处为 1, 其余为 0def setOfWords2Vec(vocabList, inputSet):    returnVec = [0]*len(vocabList)    for word in inputSet:        if word in vocabList:            returnVec[vocabList.index(word)] = 1        else: print "the word: %s is not in my Vocabulary!" % word    return returnVec  # 朴素贝叶斯核心训练函数, 训练结果为所有单词在各个分类中的概率即 P(w|Ci)# 本函数最后得到两个长度为 N 的数组, N 为 trainMatrix 的列数, 即所有文档中的中单词数# p1Vect/p0Vect 即为任意文档属于侮辱性/非侮辱性文档时, 各个单词出现的概率,即为 P(w|Ci)# 返回的 pAbusive 为侮辱性语句占总语句的百分比, 即 P(Ci)def trainNB0(trainMatrix,trainCategory):    numTrainDocs = len(trainMatrix)     # 行数    numWords = len(trainMatrix[0])      # 列数     # 因为 trainCategory 中为 1 的是侮辱性, 为 0 的不是, 所以求 sum 后就是侮辱性的个数    # 再除以总的集合数, 就行到侮辱性所占百分比    pAbusive = sum(trainCategory)/float(numTrainDocs)     # p1Num/p0Num 为所有侮辱性/非侮辱性语句对应向量的和    # p1Denom/p0Denom 为所有侮辱性/非侮辱性语句中包含的单词数    p0Num = ones(numWords); p1Num = ones(numWords)      # 全为 1, 避免乘 0    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 = log(p1Num/p1Denom)          # 求对数, 避免极小数相乘, 最后得0    p0Vect = log(p0Num/p0Denom)          # change to log()    return p0Vect,p1Vect,pAbusive  # 对 vec2Classify 进行分类, 看它是属于 p1Vec 还是 p0Vecdef classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):    # log 求加, 实际上就是贝叶斯公式分子中的求乘    # 因为 vec2Classify 对于出现的单词为 1, 未出现的单词为 0    # 所以两者相乘实际上就是 P(w|Ci)    p1 = sum(vec2Classify * p1Vec) + log(pClass1)    #element-wise mult    p0 = sum(vec2Classify * p0Vec) + log(1.0 - pClass1)     if p1 > p0:        return 1    else:         return 0      # 另一种 inputSet 生成向量方法(与 setOfWords2Vec)# 这里是每个单词出现一次, 就在相应位置 +1# setOfWords2Vec 是对于出现过的单词, 设置相应位置为 1def bagOfWords2VecMN(vocabList, inputSet):    returnVec = [0]*len(vocabList)    for word in inputSet:        if word in vocabList:            returnVec[vocabList.index(word)] += 1    return returnVec  # 测试朴素贝叶斯def testingNB():    # 加载数据并进行向量化    # 每个 list0Posts 中的项都生成一个向量, 最后 trainMat 是一个矩阵    listOPosts,listClasses = loadDataSet()    myVocabList = createVocabList(listOPosts)    trainMat=[]    for postinDoc in listOPosts:        trainMat.append(setOfWords2Vec(myVocabList, postinDoc))     # 训练    p0V,p1V,pAb = trainNB0(array(trainMat),array(listClasses))     # 测试 1, 结果应为 非侮辱    testEntry = ['love', 'my', 'dalmation']    thisDoc = array(setOfWords2Vec(myVocabList, testEntry))    print testEntry,'classified as: ',classifyNB(thisDoc,p0V,p1V,pAb)     # 测试 2, 结果应为 侮辱    testEntry = ['stupid', 'garbage']    thisDoc = array(setOfWords2Vec(myVocabList, testEntry))    print testEntry,'classified as: ',classifyNB(thisDoc,p0V,p1V,pAb)  # 按空格拆分字符串, 只取长度大于 2 的单词def textParse(bigString):    #input is big string, #output is word list    import re    listOfTokens = re.split(r'\W*', bigString)    return [tok.lower() for tok in listOfTokens if len(tok) > 2]           if __name__ == "__main__":    testingNB()

说明

本文为《Machine Leaning in Action》第四章(Classifying with probability theory: naïve Bayes)读书笔记, 代码稍作修改及注释.

好文参考

1.《》 

转载 http://my.oschina.net/zenglingfan/blog/177517

转载于:https://www.cnblogs.com/chenying99/p/4604504.html

你可能感兴趣的文章
[QT_QML]qml假如调试信息 qDebug console.debug
查看>>
波浪子序列 (Wavio Sequence,UVa 10534)
查看>>
apache简介与安装
查看>>
从头开始写框架(二):孕育框架的种子_下
查看>>
华为手机在开发Android调试时logcat不显示输出信息的解决办法
查看>>
TCP 建立连接为什么要握 3 次手?
查看>>
android:ToolBar详解
查看>>
window.print 打印指定 div
查看>>
拼多多2018/8/5算法工程师笔试
查看>>
【LINUX】——FreeBSD中的一些常规配置
查看>>
GreenDao3.0新特性解析(配置、注解、加密)
查看>>
JSON数组分配输出每个li
查看>>
request属性 request.getAttribute()
查看>>
Android应用开发基础篇(16)-----ScaleGestureDetector(缩放手势检测)
查看>>
iOS状态栏变文字颜色改变
查看>>
Entity framework code first
查看>>
Vue中登录模块
查看>>
正则表达式1--特殊字符
查看>>
python基础(四)
查看>>
2018 ACM南京网络赛H题Set解题报告
查看>>