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- -*
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 中的各个项是否为侮辱性语言
# 表示不是侮辱性语言, 表示是
classVec = [,,,,,]
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 中单词相同处为 , 其余为
def setOfWords2Vec(vocabList, inputSet):
returnVec = []*len(vocabList)
for word in inputSet:
if word in vocabList:
returnVec[vocabList.index(word)] =
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[]) # 列数 # 因为 trainCategory 中为 的是侮辱性, 为 的不是, 所以求 sum 后就是侮辱性的个数
# 再除以总的集合数, 就行到侮辱性所占百分比
pAbusive = sum(trainCategory)/float(numTrainDocs) # p1Num/p0Num 为所有侮辱性/非侮辱性语句对应向量的和
# p1Denom/p0Denom 为所有侮辱性/非侮辱性语句中包含的单词数
p0Num = ones(numWords); p1Num = ones(numWords) # 全为 , 避免乘
p0Denom = 2.0; p1Denom = 2.0 # change to 2.0 for i in range(numTrainDocs):
if trainCategory[i] == :
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 还是 p0Vec
def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
# log 求加, 实际上就是贝叶斯公式分子中的求乘
# 因为 vec2Classify 对于出现的单词为 , 未出现的单词为
# 所以两者相乘实际上就是 P(w|Ci)
p1 = sum(vec2Classify * p1Vec) + log(pClass1) #element-wise mult
p0 = sum(vec2Classify * p0Vec) + log(1.0 - pClass1)
if p1 > p0:
return
else:
return # 另一种 inputSet 生成向量方法(与 setOfWords2Vec)
# 这里是每个单词出现一次, 就在相应位置 +
# setOfWords2Vec 是对于出现过的单词, 设置相应位置为
def bagOfWords2VecMN(vocabList, inputSet):
returnVec = []*len(vocabList)
for word in inputSet:
if word in vocabList:
returnVec[vocabList.index(word)] +=
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)) # 测试 , 结果应为 非侮辱
testEntry = ['love', 'my', 'dalmation']
thisDoc = array(setOfWords2Vec(myVocabList, testEntry))
print testEntry,'classified as: ',classifyNB(thisDoc,p0V,p1V,pAb) # 测试 , 结果应为 侮辱
testEntry = ['stupid', 'garbage']
thisDoc = array(setOfWords2Vec(myVocabList, testEntry))
print testEntry,'classified as: ',classifyNB(thisDoc,p0V,p1V,pAb) # 按空格拆分字符串, 只取长度大于 的单词
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) > ] if __name__ == "__main__":
testingNB()

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

好文参考
1.《算法杂货铺——分类算法之朴素贝叶斯分类(Naive Bayesian classification)

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

Naive Bayes 笔记的更多相关文章

  1. 学习笔记之Naive Bayes Classifier

    Naive Bayes classifier - Wikipedia https://en.wikipedia.org/wiki/Naive_Bayes_classifier In machine l ...

  2. 朴素贝叶斯算法(Naive Bayes)

    朴素贝叶斯算法(Naive Bayes) 阅读目录 一.病人分类的例子 二.朴素贝叶斯分类器的公式 三.账号分类的例子 四.性别分类的例子 生活中很多场合需要用到分类,比如新闻分类.病人分类等等. 本 ...

  3. [Scikit-learn] 1.9 Naive Bayes

    Ref: http://scikit-learn.org/stable/modules/naive_bayes.html 1.9.1. Gaussian Naive Bayes 原理可参考:统计学习笔 ...

  4. [Machine Learning & Algorithm] 朴素贝叶斯算法(Naive Bayes)

    生活中很多场合需要用到分类,比如新闻分类.病人分类等等. 本文介绍朴素贝叶斯分类器(Naive Bayes classifier),它是一种简单有效的常用分类算法. 一.病人分类的例子 让我从一个例子 ...

  5. Spark MLlib 之 Naive Bayes

    1.前言: Naive Bayes(朴素贝叶斯)是一个简单的多类分类算法,该算法的前提是假设各特征之间是相互独立的.Naive Bayes 训练主要是为每一个特征,在给定的标签的条件下,计算每个特征在 ...

  6. Microsoft Naive Bayes 算法——三国人物身份划分

    Microsoft朴素贝叶斯是SSAS中最简单的算法,通常用作理解数据基本分组的起点.这类处理的一般特征就是分类.这个算法之所以称为“朴素”,是因为所有属性的重要性是一样的,没有谁比谁更高.贝叶斯之名 ...

  7. Naive Bayes理论与实践

    Naive Bayes: 简单有效的常用分类算法,典型用途:垃圾邮件分类 假设:给定目标值时属性之间相互条件独立 同样,先验概率的贝叶斯估计是 优点: 1. 无监督学习的一种,实现简单,没有迭代,学习 ...

  8. [ML] Naive Bayes for Text Classification

    TF-IDF Algorithm From http://www.ruanyifeng.com/blog/2013/03/tf-idf.html Chapter 1, 知道了"词频" ...

  9. 朴素贝叶斯方法(Naive Bayes Method)

        朴素贝叶斯是一种很简单的分类方法,之所以称之为朴素,是因为它有着非常强的前提条件-其所有特征都是相互独立的,是一种典型的生成学习算法.所谓生成学习算法,是指由训练数据学习联合概率分布P(X,Y ...

随机推荐

  1. springboot添加fluent日志记录

    istio默认会进行日志的记录,但是仅仅记录到服务.以及服务之间调用的信息,不记录业务日志. 如: 所以需要添加业务日志记录. 1.引入依赖 <dependency>     <gr ...

  2. 公共的service接口

    package com.taotao.manager.service; import java.util.List; /** * @author Administrator * * @param &l ...

  3. VS2010下MFC的串口编程

    串口通信简介 一般来说,计算机都有一个或多个串行端口,这些串口提供了外部设备与PC进行数据传输和通信的通道,在CPU和外设之间充当解释器的角色.当字符数据从CPU发送给外设时,这些字符数据将被转换成串 ...

  4. filedisk.sys

    i386 amd http://blog.sina.com.cn/s/blog_4fcd1ea30100r19r.html

  5. Linux入门练习操作命令

    查看目录命令 1. 显示目录下所有文件 2.显示所有文件,包括隐藏文件 创建目录命令 1.在改目录下创建文件夹“practise” 切换目录 1.切换到指定的目录 2.切换到上一级目录 3.还在当前目 ...

  6. /bin/sh^M:bad interpreter:

    /bin/sh^M:bad interpreter: No such file or directory 这个错误发生在你在windows下编写文件上传到linux服务器去运行的时候. 错误原因:wi ...

  7. dfs序理解-hdu3887

    dfs序就是相当于把树转化成了一个区间,在区间上进行操作. void dfs(int u, int fa) { l[u]=++key; ; i=e[i].next) { int v=e[i].v; i ...

  8. 关于进行pdf的每页广告去除、转换word等方案。

    pdf转word经常使用的是 软件下载安装破解完成以后进行编辑pdf,可以导出word,效果比一般的word自带的转换效果要好. 在进行pdf的每页去除页脚或者页眉的广告时候,使用pdf的替换功能.这 ...

  9. day09作业—函数进阶

    # 2.写函数,接收n个数字,求这些参数数字的和.(动态传参) def func1(*args): sum = 0 for i in args: sum += i print(sum) func1(1 ...

  10. kbmmw 中的进程管理小工具

    kbmmw 5.6.20 发布了,本版本带来一个小功能,就是可以在kbmmw 应用里面建立和管理进程, 虽然你可以直接调用windows api 做类似的事情,但是kbmmw 里面简化了操作,也加强了 ...