python 实现朴素贝叶斯算法
朴素贝叶斯算法的python 实现
⼀ 实验准备
实验介绍
在所有的机器学习分类算法中,朴素贝叶斯(Naive Bayesian Model,NBM)和其他绝⼤多数的分类算法都不同。对于⼤多数的分类算法,⽐如决策树,KNN,逻辑回归,⽀持向量机等,他们都是判别⽅法,也就是直接学习出特征输出Y和特征X之间的关系,要么是决策函数 = ( ) ,要么是条件分布  ( | ) 。但是朴素贝叶斯却是⽣成⽅法,也就是直接出特征输出Y和特征X的联合分布  ( , ) ,然后⽤  ( | )= ( , )/ ( ) 得出。
朴素贝叶斯分类的流程可以由下图表⽰(暂时不考虑验证):实验⽬的学习了解朴素贝叶斯的基本介绍学习掌握朴素贝叶斯算法相关的统计学知识(条件概率、全概率、以及贝叶斯公式推断)python实现朴素贝叶斯的代码详解(过滤⼴告、垃圾邮件)
sklearn中的朴素贝叶斯(⾼斯朴素贝叶斯、多项式朴素贝叶斯、伯努利朴素贝叶斯)三种⽅法的详解
实验准备
  服务器端:python3.6以上、Jupyter Notebook   客户端:Google Chrome浏览器
⼆ 实验步骤
2.1 朴素贝叶斯介绍
贝叶斯分类算法是统计学的⼀种概率分类⽅法,朴素贝叶斯分类是贝叶斯分类中最简单的⼀种,朴素贝叶斯法(Naive Bayes)是基于贝叶斯定理与特征条件独⽴假设的分类⽅法,其分类原理就是利⽤贝叶斯公式根据某特征的先验概率计算出其后验概率,然后选择具有最⼤后验概率的类作为该特征所属的类。之所以称之为“朴素”,是因为贝叶斯分类只做最原始、最简单的假设:所有的特征之间都是相互独⽴的。假设某样本有个属性,那么有。满⾜这样的公式就说明特征统计独⽴。
2.2 朴素贝叶斯相关的统计学知识
在了解朴素贝叶斯的算法之前,我们需要对相关必须的统计学知识做⼀个回顾。
贝叶斯学派很古⽼,但是从诞⽣到⼀百年前⼀直不是主流。主流是频率学派。频率学派的权威⽪尔逊和费歇尔都对贝叶斯学派不屑⼀顾,但是贝叶斯学派硬是凭借在现代特定领域的出⾊应⽤表现为⾃⼰赢得了半壁江⼭。
贝叶斯学派的思想可以概括为先验概率+数据=后验概率。也就是说我们在实际问题中需要得到的后验概率,可以通过先验概率和数据⼀起综合得到。数据⼤家好理解,被频率学派攻击的是先验概率,⼀般来说先验概率就是我们对于数据所在领域的历史经验,但是这个经验常常难以量化或者模型化,于是贝叶斯学派⼤胆的假设先验分布的模型,⽐如正态分布,beta分布等。这个假设⼀般没有特定的依据,因此⼀直被频率学派认为很荒谬。虽然难以从严密的数学逻辑⾥推出贝叶斯学派的逻辑,但是在很多实际应⽤中,贝叶斯理论很好⽤,⽐如垃圾邮件分类,⽂本分类。
2.2.1 条件概率公式
X a ,a ,…,a 12n P (X )=P (a ,a ,…,a )=12n P (a )∗1P (a )∗2P (a )n
条件概率公式(Condittional probability),是指在事件B发⽣的情况下,事件A发⽣的概率,⽤来表⽰。
  根据⽂⽒图可知:在事件B发⽣的情况下,事件A发⽣的概率就是除以。
  同理可得:
所以,
2.2.2 全概率公式
如果事件构成⼀个完备事件且都有正概率,那么对于任意⼀个事件B则有:
2.2.3 贝叶斯公式推断
根据条件概率和全概率公式,可以得到贝叶斯公式如下:
  转换为分类任务的表达式:
P (A ∣B )P (A ∣B )P (B )P (A ∣B )=P (B )
P (A ∩B )
=>P (A ∩B )=P (A ∣B )P (B )
P (A ∩B )=P (B ∣A )P (A )
P (A ∣B )P (B )=P (B ∣A )P (A )
=>P (A ∣B )=
P (B )P (B ∣A )P (A )
A ,A ,A ,,A 123N P (
B )=P (BA )+P (BA )+…+P (BA )
12n =P (B ∣A )P (A )+P (B ∣A )P (A )+…+P (B ∣A )P (A )
1122n n P (B )=P (A )P (B ∣A )
i =1∑n i i P (A ∣B )=P (A )P (B )
P (B ∣A )
P (类别∣特征)=P (类别)P (特征)
P (特征∣类别)
P (A ∣B )=i P (A )i P (A )P (B ∣A )
∑i =1n
i i P (B ∣A )i
P(A)称为“先验概率”(Prior probability),即在B事件发⽣之前,我们对A事件概率的⼀个判断。
P(A|B)称为“后验概率”(Posterior probability),即在B事件发⽣之后,我们对A事件概率的重新评估。
P(B|A)/P(B)称为“可能性函数”(Likely hood),这是⼀个调整因⼦,使得预估概率更接近真是概率。
如果“可能性函数”>1,意味着“先验概率”被增强,事件A的发⽣的可能性变⼤;
如果“可能性函数”=1,意味着B事件⽆助于判断事件A的可能性;
如果“可能性函数”<1,意味着“先验概率”被削弱,事件A的发⽣的可能性变⼩;
所以条件概率可以理解为:后验概率=先验概率*调整因⼦
2.3 朴素贝叶斯的python实现
过滤⼴告、垃圾邮件
1、导⼊所需包
from numpy import *
from functools import reduce
2、加载数据集合及其对应的分类,从训练数据集中提取出属性矩阵和分类数据
# ⼴告、垃圾标识
adClass = 1
def loadDataSet():
wordsList = [['周六', '公司', '⼀起', '聚餐', '时间'],
['优惠', '返利', '打折', '优惠', '⾦融', '理财'],
['喜欢', '机器学习', '⼀起', '研究', '欢迎', '贝叶斯', '算法', '公式'],
['公司', '发票', '税点', '优惠', '增值税', '打折'],
['北京', '今天', '雾霾', '不宜', '外出', '时间', '在家', '讨论', '学习'],
['招聘', '兼职', '⽇薪', '保险', '返利']]
# 1 是, 0 否
classVec = [0, 1, 0, 1, 0, 1]
return wordsList, classVec
3、⽣成包含所有单词的list(此处⽣成的单词向量是不重复的)
从第⼀个和第⼆个集合开始进⾏并集操作,最后返回⼀个不重复的并集
def doc2VecList(docList):
a = list(reduce(lambda x, y: set(x) | set(y), docList))
return a
allWordsVec = doc2VecList(docList)
print(allWordsVec)
python中的 & | 是位运算符 and or 是逻辑运算符 当and的运算结果为true时候返回的并不是true⽽是运
算结果最后⼀位变量的值当and返回的结果是false时候,如果A AND B 返回的是第⼀个false的值,如果a为false 则返回a,如果a不是false,那么返回b 如果a or b 为true时候,返回的是第⼀个真的变量的值,如果a,b都为真时候那么返回a 如果a为假b为真那么返回b
a &
b a和b为两个set,返回结果取a和b的交集 a|b a和b为两个set,返回结果为两个集合的不重复并集
4、把单词转化为词向量,计算数据集中每⼀⾏每个单词出现的次数,如果此单词在数组中,数组的项值置1
```
def words2Vec(vecList, inputWords):
# 转化成以⼀维数组
resultVec = [0] * len(vecList)
for word in inputWords:
if word in vecList:
resultVec[vecList.index(word)] += 1  # 在单词出现的位置上的计数加1
else:
print('没有发现此单词')
return array(resultVec)
```
构建词向量矩阵,计算docList数据集中每⼀⾏每个单词出现的次数,其中返回的trainMat是⼀个数组的数组
```
trainMat = list(map(lambda x: words2Vec(allWordsVec, x), docList))
trainMat
```
<img src="attachment:image.png" width="400">
5、计算,⽣成每个词对于类别上的概率(其中概率是以ln进⾏计算的)
p0V:每个单词在⾮分类出现的概率,
p1V:每个单词在是分类出现的概率
pClass1为类别中是1的概率
def trainNB(trainMatrix, trainClass):
numTrainClass = len(trainClass)  # 类别⾏数
numWords = len(trainMatrix[0])      # 列数
# 全部都初始化为1,防⽌出现概率为0的情况出现,影响计算,因为在数量很⼤的情况下,在分⼦和分母同时+1的情况不会影响主要的数据        p0Num = ones(numWords)
p1Num = ones(numWords)
p0Words = 2.0      # 相应的单词初始化为2为了分⼦分母同时都加上某个数λ
p1Words = 2.0
统计每个分类的词的总数,训练数据集的⾏数作为遍历的条件,从1开始python新手能做啥兼职
如果当前类别为1,那么p1Num会加上当前单词矩阵⾏数据,依次遍历
如果当前类别为0,那么p0Num会加上当前单词矩阵⾏数据,依次遍历
同时统计当前类别下单词的个数和p1Words和p0Words
for i in range(numTrainClass):
if trainClass[i] == 1:
# 数组在对应的位置上相加
p1Num += trainMatrix[i]
p1Words += sum(trainMatrix[i])
else:
p0Num += trainMatrix[i]
p0Words += sum(trainMatrix[i])
* 计算每种类型⾥⾯,每个单词出现的概率
* 朴素贝叶斯分类中,y=x是单调递增函数,y=ln(x)也是单调的递增的
* 如果x1>x2 那么ln(x1)>ln(x2)
* 在计算过程中,由于概率的值较⼩,所以我们就取对数进⾏⽐较,根据对数的特性 * ln(MN) = ln(M)+ln(N)
* ln(M/N) = ln(M)-ln(N)
* ln(M**n)= nln(M)
* 注:其中ln可替换为log的任意对数底
```
p0Vec = log(p0Num / p0Words)
p1Vec = log(p1Num / p1Words)
# 计算在类别中1出现的概率,0出现的概率可通过1-p得到
pClass1 = sum(trainClass) / float(numTrainClass)
return p0Vec, p1Vec, pClass1
```
训练计算每个词在分类上的概率
p0V, p1V, pClass1 = trainNB(trainMat, classVec)
pClass1

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。