朴素贝叶斯(Naive Bayesian)是最为广泛使用的分类方法,它以概率论为基础,是基于贝叶斯定理和特征条件独立假设的分类方法。

原理

朴素贝叶斯(Naive Bayesian)是基于贝叶斯定理和特征条件独立假设原则的分类方法。通过给出的特征计算分类的概率,选取概率大的情况进行分类。也是基于概率论的一种机器学习分类方法。分类目标确定,属于监督学习。

通过概率来衡量事件发生的可能性。概率论和统计学恰好是两个相反的概念,统计学是抽取部分样本进行统计来估算总体的情况,而概率论是通过总体情况来估计单个事件或者部分事情的发生情况。因此,概率论需要已知的数据去预测未知的事件。
例如,我们看到天气乌云密布,电闪雷鸣并阵阵狂风,在这样的天气特征(F)下,我们推断下雨的概率比不下雨的概率大,也就是p(下雨)>p(不下雨),所以认为待会儿会下雨。这个从经验上看对概率进行判断。
而气象局通过多年长期积累的数据,经过计算,今天下雨的概率p(下雨)=85%,p(不下雨)=15%,同样的,p(下雨)>p(不下雨),因此今天的天气预报肯定预报下雨。这是通过一定的方法计算概率从而对下雨事件进行判断。
复制代码

为什么叫朴素贝叶斯:简单,易于操作,基于特征独立性假设,也即各个特征彼此独立,互相不影响发生。

条件概率

某个事件已发生的情况下另外一个事件发生的概率。计算公式如下:P(A|B)=P(A∩B) / P(B) 简单理解:画维恩图,两个圆圈相交的部分就是A发生B也发生了,因为求的是B发生下A发生的概率。B相当于一个新的样本空间。AB/B即可。

概率相乘法则:P(A∩B)=P(A)P(B|A) or P(A∩B)=P(B)P(A|B) 独立事件的概率:P(A∩B)=P(A)P(B)

贝叶斯定理

如果有穷k个互斥事件,B1, B2,,,Bk 并且 P(B1)+P(B2)+⋅⋅⋅+P(Bk)=1和一个可以观测到的事件A,那么有:

分类原理

基于概率论,二分类问题如下: 如果p1 > p2, 分入类别1; 否则分入类别2。

其次,贝叶斯定理,有 p(ci|x,y) = p(x,y|ci) * p(ci) / p(x,y) x, y 表示特征变量,如下例子中的单词。Ci表示类别。p(ci | x, y) 即表示在特征x, y出现的情况下,分入类别Ci的概率。结合如上: p(ci | x, y) > p(cj | x, y), 分入类别i, 否则分入类别j。

贝叶斯定理最大的好处是可以用已知的三个概率去计算未知的概率,而如果仅仅是为了比较p(ci|x,y)和p(cj|x,y)的大小,只需要已知两个概率即可,分母相同,比较p(x,y|ci)p(ci)和p(x,y|cj)p(cj)即可。

特征条件独立性假设原则

朴素贝叶斯常用与对文档分类。根据文档中出现的词汇,判断文章属于什么类别。将词汇出现的特征条件用词向量W表示,由多个值组成,值的个数和训练集中的词汇表个数相同。 上面的贝叶斯公式可以表示为: p(ci|ω)=p(ω|ci) * p(ci) / p(ω) 各个单词的出现不会相互影响,则p(ω|ci) = p(ω0|ci)*p(ω1|ci)*...* p(ωk|ci)

算法实现

import numpy as np
np.seterr(divide='ignore', invalid='ignore')  #消除向量中除以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] #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 = np.zeros(len(vocabList)) #生成零向量的arrayfor word in inputSet:if word in vocabList:returnVec[vocabList.index(word)] = 1 #有单词,该位置填充1else:print("the word: %s is not in my Vocabulary" % word)# passreturn returnVec  #返回0,1的向量if __name__ == '__main__':listPosts, listClasses = loadDataSet()myVocabList = createVocabList(listPosts)print(myVocabList)复制代码

输出结果如下: ['flea', 'ate', 'how', 'licks', 'quit', 'problems', 'dog', 'I', 'garbage', 'help', 'is', 'cute', 'steak', 'to', 'worthless', 'please', 'has', 'posting', 'buying', 'love', 'food', 'so', 'my', 'take', 'dalmation', 'stop', 'park', 'not', 'stupid', 'him', 'mr', 'maybe'], 表示不同类别言论去重后得到的词向量。 [ 1. 0. 0. 0. 0. 0. 1. 0. 0. 0. 1. 1. 1. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]: 表示词汇集1中的单词是否在词向量中出现。

如上,这个方法只记录了每个词是否出现,并没有记录出现次数,成为词集模型。如果记录词出现的次数,这样的词向量构建方法称为词袋模型,如下。本文只使用词集模型。

# 词袋模型
def bagofWords2VecMN(vocabList, inputSet):returnVec = [0] * len(vocabList)for word in inputSet:if word in vocabList:returnVec[vocabList.index(word)] += 1return vocabList #返回非负整数的词向量
复制代码

运用词向量计算概率:

def trainNB0(trainMatrix, trainCategory):numTrainDocs = len(trainMatrix)  #文档数目numWord = len(trainMatrix[0])  #词汇表数目print(numTrainDocs, numWord)pAbusive = sum(trainCategory) / len(trainCategory) #p1, 出现侮辱性评论的概率 [0, 1, 0, 1, 0, 1]p0Num = np.zeros(numWord)p1Num = np.zeros(numWord)p0Demon = 0p1Demon = 0for i in range(numTrainDocs):if trainCategory[i] == 0:p0Num += trainMatrix[i] #向量相加p0Demon += sum(trainMatrix[i]) #向量中1累加其和else:p1Num += trainMatrix[i]p1Demon += sum(trainMatrix[i])p0Vec = p0Num / p0Demonp1Vec = p1Num / p1Demonreturn p0Vec, p1Vec, pAbusiveif __name__ == '__main__':listPosts, listClasses = loadDataSet()myVocabList = createVocabList(listPosts)trainMat = []trainMat = []for postinDoc in listPosts:trainMat.append(setOfWords2Vec(myVocabList, postinDoc))print(trainMat)p0Vec, p1Vec, pAbusive = trainNB0(trainMat, listClasses)print(p0Vec, p1Vec, pAbusive)
复制代码

输出结果稍微有点多,慢慢来看: trainMat:表示数据中六个给定的特征在词集模型中的出现情况。

array([ 0.,  0.,  0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,  1.,  1.,  0.,0.,  0.,  1.,  0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,0.,  0.,  0.,  0.,  1.,  1.]), array([ 0.,  0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,0.,  1.,  0.,  1.,  1.,  1.,  0.,  0.,  0.,  1.,  0.,  0.,  0.,0.,  0.,  1.,  0.,  0.,  0.]), array([ 1.,  0.,  0.,  0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,1.,  0.,  0.,  1.,  0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.,1.,  1.,  0.,  0.,  0.,  1.]), array([ 0.,  1.,  1.,  1.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,  0.,  0.,0.,  0.,  0.,  0.,  0.,  0.]), array([ 0.,  1.,  0.,  0.,  0.,  0.,  0.,  1.,  0.,  1.,  0.,  0.,  0.,0.,  0.,  0.,  1.,  0.,  0.,  1.,  0.,  1.,  0.,  0.,  0.,  0.,0.,  0.,  1.,  1.,  0.,  1.]), array([ 0.,  0.,  1.,  0.,  1.,  0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,0.,  0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,  1.,0.,  0.,  0.,  0.,  0.,  0.])]
复制代码

print(numTrainDocs, numWord): 6 32 (6个文档,一共32个词汇) print(p0Vec, p1Vec, pAbusive):pAbusive是文档中是侮辱性言论的概率,为0.5。 而p0Vec表示类别0(非侮辱言论)中的词在词向量中出现的概率:

[ 0.  0.04166667  0.04166667  0.04166667  0.04166667  0.0.08333333  0.04166667  0.          0.04166667  0.          0.041666670.          0.04166667  0.          0.          0.04166667  0.041666670.04166667  0.04166667  0.04166667  0.          0.          0.041666670.04166667  0.04166667  0.          0.125       0.          0.041666670.04166667  0.04166667]
复制代码

算法的改进:

  1. 部分概率为0,用于上面计算独立特征概率相乘是永远为0.因此,将所有词出现的次数初始化为1,某类词项初始化为2.
  2. 由于计算得到的概率太小,不断的相乘可能会导致结果溢出。因此对其取对数,单调性相同,不会影响最后对结果的比较。函数如下:
def trainNB1(trainMatrix, trainCategory):numTrainDocs = len(trainMatrix)  #文档数目numWord = len(trainMatrix[0])  #词汇表数目pAbusive = sum(trainCategory) / len(trainCategory) #p1, 出现侮辱性评论的概率p0Num = np.ones(numWord)  #修改为1p1Num = np.ones(numWord)p0Demon = 2 #修改为2p1Demon = 2for i in range(numTrainDocs):if trainCategory[i] == 0:p0Num += trainMatrix[i] #向量相加p0Demon += sum(trainMatrix[i]) #向量中1累加其和else:p1Num += trainMatrix[i]p1Demon += sum(trainMatrix[i])p0Vec = np.log(p0Num / p0Demon)  #求对数p1Vec = np.log(p1Num / p1Demon)return p0Vec, p1Vec, pAbusive
复制代码

注意:这里得到p0Vec可能是没有规律的,但其对最后的概率比较没有影响。

运用分类器函数进行文档分类

def classifyNB(vec2Classify, p0Vc,  p1Vc, pClass1):p1 = sum(vec2Classify * p1Vc) * pClass1p0 = sum(vec2Classify * p0Vc) * (1-pClass1)# p1 = sum(vec2Classify * p1Vc) + np.log(pClass1)    #取对数,防止结果溢出# p0 = sum(vec2Classify * p0Vc) + np.log(1 - pClass1)if p1 > p0:return 1else:return 0
复制代码

解释一下:vec2Classify是所需分类文档的词量。根据公式 p(ci|ω)=p(ω|ci)p(ci) / p(ω), 已知特征向量求分类的概率等于 p(ω|ci)p(ci)。忽略分母:

p(ci)好求,用样本集中,ci的数量/总样本数即可
p(ω|ci)由于各个条件特征相互独立且地位相同,`p(ω|ci)=p(w0|ci)p(w1|ci)p(w2|ci)......p(wN|ci)`,可以分别求p(w0|ci),p(w1|ci),p(w2|ci),......,p(wN|ci),从而得到p(ω|ci)。
而求p(ωk|ci)也就变成了求在分类类别为ci的文档词汇表集合中,单个词项ωk出现的概率。
复制代码

测试分类函数

使用两个不同的样本来测试分类函数:


# 构造样本测试
def testingNB():listPosts, listClasses = loadDataSet()myVocabList = createVocabList(listPosts)trainMat = []for postinDoc in listPosts:trainMat.append(setOfWords2Vec(myVocabList, postinDoc))p0v, p1v, pAb = trainNB0(trainMat, listClasses)# print(p0v, p1v, pAb)testEntry = ['love']thisDoc = setOfWords2Vec(myVocabList, testEntry)print(testEntry, 'classified as', classifyNB(thisDoc, p0v, p1v, pAb))testEntry = ['stupid', 'garbage']thisDoc = (setOfWords2Vec(myVocabList, testEntry))print(testEntry, 'classified as:', classifyNB(thisDoc, p0v, p1v, pAb))if __name__ == '__main__':testingNB()
复制代码

观察结果,可以看到将两个文档正确的分类。 完整代码请查看:

github:naive_bayes

总结

  • 朴素贝叶斯分类
  • 条件概率
  • 贝叶斯定理
  • 特征条件独立性假设原则
  • 根据文档构建词向量
  • 词集模型和词袋模型
  • 概率为0,方便计算的改进和防止溢出的取对数改进

参考文章:
机器学习之朴素贝叶斯(NB)分类算法与Python实现

机器学习之贝叶斯分类(python实现)相关推荐

  1. 机器学习之用Python从零实现贝叶斯分类器

    机器学习之用Python从零实现贝叶斯分类器 2015/02/06 · 系列教程 · 13 评论 · 机器学习 分享到:27 本文由 伯乐在线 - Halal 翻译,toolate 校稿.未经许可,禁 ...

  2. 机器学习实战笔记(Python实现)-04-Logistic回归

    转自:机器学习实战笔记(Python实现)-04-Logistic回归 转自:简单多元线性回归(梯度下降算法与矩阵法) 转自:人工神经网络(从原理到代码) Step 01 感知器 梯度下降

  3. 机器学习算法与Python实践之(六)二分k均值聚类

    机器学习算法与Python实践这个系列主要是参考<机器学习实战>这本书.因为自己想学习Python,然后也想对一些机器学习算法加深下了解,所以就想通过Python来实现几个比较常用的机器学 ...

  4. 机器学习算法与Python实践之(五)k均值聚类(k-means)

    机器学习算法与Python实践这个系列主要是参考<机器学习实战>这本书.因为自己想学习Python,然后也想对一些机器学习算法加深下了解,所以就想通过Python来实现几个比较常用的机器学 ...

  5. 机器学习算法与Python实践之(三)支持向量机(SVM)进阶

    机器学习算法与Python实践这个系列主要是参考<机器学习实战>这本书.因为自己想学习Python,然后也想对一些机器学习算法加深下了解,所以就想通过Python来实现几个比较常用的机器学 ...

  6. 机器学习算法与Python实践之(二)支持向量机(SVM)初

    机器学习算法与Python实践这个系列主要是参考<机器学习实战>这本书.因为自己想学习Python,然后也想对一些机器学习算法加深下了解,所以就想通过Python来实现几个比较常用的机器学 ...

  7. 机器学习算法与Python实践之(二)支持向量机

    http://blog.csdn.net/zouxy09/article/details/17291543 机器学习算法与Python实践这个系列主要是参考<机器学习实战>这本书.因为自己 ...

  8. 机器学习算法与Python实践之(四)支持向量机(SVM)实现

    机器学习算法与Python实践之(四)支持向量机(SVM)实现 zouxy09@qq.com http://blog.csdn.net/zouxy09 机器学习算法与Python实践这个系列主要是参考 ...

  9. 机器学习算法与Python实践之(二)支持向量机(SVM)初级

    机器学习算法与Python实践之(二)支持向量机(SVM)初级 zouxy09@qq.com http://blog.csdn.net/zouxy09 机器学习算法与Python实践这个系列主要是参考 ...

最新文章

  1. python元素定位id和name_Python+Selenium自动化软件测试实战:Xpath,class,id,name定位和Iframe框架跳转...
  2. 【Pytorch神经网络理论篇】 14 过拟合问题的优化技巧(一):基本概念+正则化+数据增大
  3. android studio service directory path,Android Studio User目录缓存搬移到指定目录
  4. 基于PyTorch+YOLOv4的口罩佩戴检测,附数据集
  5. 《黑客大曝光:移动应用安全揭秘及防护措施》一3.5 小结
  6. 微擎修复去水印微信小程序源码
  7. bailian2705
  8. 什么是Python?Python简介
  9. Google Colab中把pyth3.7版本更换成python2.7
  10. 【沐风老师】3DMAX随机挤出插件2DExtruder使用教程
  11. 【转】感觉像绕口令般的英语组句
  12. 阿里云域名解析利用accesskey变动态域名DDNS,简易shell脚本型
  13. 迈动互联中标中国银河证券
  14. IE11不兼容array.from()解决方法
  15. 汇量科技蔡超:提高云使用率是云计算市场的下一个增长点
  16. 游戏美术行业的薪资待遇,人与人的差距真的在于努力,来看看数据吧
  17. 数据中台 画像标签_中台产品经理必懂(4):数据中台标签系统
  18. 中文自然语言处理--基于 textCNN 的电影推荐系统
  19. 医疗条码打印机行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
  20. 【算法】不用乘、除、取余操作实现除法

热门文章

  1. 关于某些域环境下Windows Hello无法使用的解决方法
  2. 查找 framework 文件中是否包含 WKWebView
  3. Arduino Yun的主要部件介绍选自Arduino Yun快速入门教程
  4. 文件打开不关闭程序会输出吗_干货!很多资深用户都不知道的10个BOOX阅读器使用技巧,很实用!...
  5. python迅雷远程下载页面_【教程】Chrome浏览器添加迅雷下载支持
  6. 如何让图像过渡更自然 python_如何过渡至 Python 3
  7. layui 导航收缩代码_pycharm的十个小技巧,让你写代码效率翻倍
  8. Nilearn教程系列(4)-脑部地图集绘制
  9. Draw Call未被批处理?在Unity 5.6中如何查找原因
  10. Hololens开发基础知识