【博客的主要内容主要是自己的学习笔记,并结合个人的理解,供各位在学习过程中参考,若有疑问,欢迎提出;若有侵权,请告知博主删除,原创文章转载还请注明出处。】
机器学习主要任务是分类和回归。
之前通过《机器学习实战》学习了kNN和决策树两种分类算法,本次学习朴素贝叶斯。学习内容不局限与书本内容,结合网上文章进行学习。
1. 贝叶斯(Bayes)定理介绍
贝叶斯定理是由英国数学家贝叶斯在1763年首次提出的定理,它用来描述两个条件概率之间的关系。
在实际情况中,事件A和事件B是相互独立事件。可获得事件A的数据资料,希望通过对事件A的有关状态及概率分析推导出事件B的状态及发生概率。这里用贝叶斯定理,其数学表示:
2. 朴素贝叶斯分类(Naive Bayes Classifier)
朴素贝叶斯分类(Naive Bayes Classifier 或NBC)是基于贝叶斯定理与特征条件独立假设的分类方法。
2.1 分类的定义
1. 分类: 是将一个未知样本分到几个预先已知类的过程。
-
2. 数学角度对分类进行定义:
-
已知集合:
C=y1,y2,...,yn
和
I=x1,x2,...,xm
,确定映射规则y=f(x),使得任意
xi
属于
I
有且仅有一个
yj 属于C使得 yj=f(xi) 成立。
则 C 称为类别集合,每个元素即为类别; I 称为项集合;每个元素是一个待分类项, f 叫做分类器。分类算法主要任务即构造分类器 f 。
3. 贝叶斯分类器
-
以贝叶斯定理为基础的一类分类算法,它是一类利用概率统计知识进行分类的算法。
常见的算法:朴素贝叶斯算法、TAN算法(树增强型朴树贝叶斯算法)。
2.2 条件概率(conditional probability)
设A,B是两个事件,且A不是不可能事件,则称
(1)非负性;(2)规范性;(3)可列可加性。
2.3 贝叶斯定理描述
如果已知 P(A|B) ,要求得 P(B|A) ,那么可以得到:
2.4 贝叶斯定理的含义
贝叶斯分类原来是通过某对象的先验概率,利用贝叶斯公式计算出其后后验概率,即该对象属于某一类的概率,选在具有最大后验概率的类作为该对象所属的类。
把 P(A) 称为“先验概率(Prior probability)”,即在B事件发生之前,对A事件概率的一个判断;
P(A|B) 称为“后验概率(Posterior probability)”,即在B事件发生之后, 对A事件概率的重新评估;
“可能性函数(Likely hood)” P(B|A)P(B) 一个调整因子,使得预估概率更接近真实概率。
- 如果“可能函数” > 1 , 意味着“先验概率”被增强,事件A的发生的可能性变大;
- 如果“可能性函数” = 1,则事件无助于事件A的可能性;
- 如果“可能性函数” < 1,意味着“先验概率”被消弱,事件A的可能性变小。
3. 朴素贝叶斯分类推导
3.1 分类推导
朴素贝叶斯分类是基于贝叶斯定理的一种分类算法。根据数据特性分析由“离散型数据”和“连续性数据”,在先介绍两个基本概念:
1.离散型随机变量
如果一个随机变量X所有可能取到的值是有限个或者是可列无限多个,并且以确定的概率取这些不同的值,成为 离散型随机变量 例如X=1,2,3,……n
2.连续性随机变量
如果对于随机变量X的分布函数F(X)存在非负函数f(x)使得对于任意实数x有
F(x)=∫f(t)dt
,积分下限是负无穷,上限是x,则称X为 连续性随机变量
3.1.1 离散型随机数据推导
-
假设:现有训练数据集(X,Y)
-
每个样本
x
都包括
n 维特征, X={x1,x2,...,xn} -
类标记集合含有
k
中类别,
Y={y1,y2,...,yk}
现有新样本 x ,如何判断其所属类别?
分析
使用朴素贝叶斯算法进行分类,其主旨:选择具有最高概率的决策.
计算新样本x在类标记结合中的概率:
推导
1.朴素贝叶斯公式:
P(yk|x)=P(x|yk)P(yk)P(x)
2.根据 全概率公式 ,朴素贝叶斯公式演变为:
[全概率公式]
如果事件 B1、B2、B3…Bn 构成一个完备事件组,即它们两两互不相容,其和为全集;并且 P(Bi)>0 ,则对任一事件A有:
P(A)=P(A|B1)P(B1)+P(A|B2)P(B2)+...+P(A|Bn)P(Bn)=P(AB1)+P(AB2)+...+P(ABn)).
其中 A 与 Bn 的关系为交,即:
P(A)=∑i=1kP(x|yk)P(yk)
3.从推导公式可知,需要计算
P(yk)
和
P(x|yk)
。
P(yk)
通过数据计算可以获取;问题在于
P(x|yk)=P(x1,x2,...,xn|yk)
值?
若第i维特征
xi
可取值的个数有
si
个值,类别可取个数为
k
个,结果将以几何级数增加,其参数个数为
4.现在对数据事件做“独立性”假设,即假设
x1,x2,...,xn是相互独立
,此时公式:
P(x|yk)=P(x1,x2,...xn|yk)=∏ni=1P(xi|yk)
由统计学知,如果每个特征需要N个样本,那么对于10个特征将需要N^10个样本,对于包含1000个特征的数据将需要N^1000个样本。
如果特征之间相互独立,那么样本从N^1000减少到1000*N.
5.最终朴素贝叶斯公式:
P(yk|x)=P(yk)∏ni=1P(xi|yk)∑kP(yk)∏ni=1P(xi|yk)
即: f(x)=argmaxP(yk|x)=argmaxP(yk)∏ni=1P(xi|yk)∑kP(yk)∏ni=1P(xi|yk)
注意到上式对所有
yk
都是相同的,所以:
f(x)=argmaxkP(yk)∏ni=1P(xi|yk)
3.1.2 连续型随机数据推导
若数据特征属性为连续型值时,该值服从高斯分布(即正态分布)。数学公式:
而 P(ak|yi)=g(ak,ηyi,k,σyi,k)
ηyi,k
表示类别
yi
的样本中,第k维特征的均值
σyi,k
表示类别
yi
的样本中,第k维特征的方差
3.2 常用模型:高斯、多项式、伯努利
3.2.1 多项式
在特征为离散情况下,通过多项式模型对公式进行平滑处理。
多项式模型在计算先验概率
P(yk)
和 条件概率
P(xi|yk)
时:
N是总的样本个数,k是总的类别个数, Nyk 是类别为 yk 的样本个数, α 是平滑值。
Nyk 是类别为yk的样本个数,n是特征的维数, Nyk,xi 是类别为 yk 的样本中,第i维特征的值是 xi 的样本个数, α 是平滑值。
当
α=1
时,称作Laplace平滑;
当
0<α<1
时,称作Lidstone平滑;
当
α=0
时,不做平滑。
如果不做平滑,当某一维特征的值 xi 没在训练样本中出现过时,会导致 P(xi|yk)=0 ,从而导致后验概率为0.
3.2.2 高斯
当特征为连续变量时,每一维特征都服从于高斯分布(即正态分布)。示例:性别分类
3.2.3 伯努利
伯努利模型适用于离散特征的情况,伯努利模型中每个特征的取值只能是1和0.
伯努利模型中,条件概率
P(xi|yk)
的计算方式是:
当特征值
xi
= 1时,
P(xi|yk)=P(xi=1|yk)
;
当特征值
xi
= 0时,
P(xi|yk)=1−P(xi=1|yk)
;
3.3 案例分析
3.3.1 病人分析
1、问题:已收集6名病人职业、症状及诊断数据。现有一名打喷嚏建筑工人入院,判断其感冒概率?
序号 | 症状 | 职业 | 疾病 |
---|---|---|---|
01 | 打喷嚏 | 护士 | 感冒 |
02 | 打喷嚏 | 农夫 | 过敏 |
03 | 头痛 | 建筑工人 | 脑震荡 |
04 | 头痛 | 建筑工人 | 感冒 |
05 | 打喷嚏 | 教师 | 感冒 |
06 | 头痛 | 教师 | 脑震荡 |
07 | 打喷嚏 | 建筑工人 | ? |
2、计算:
a. 依据朴素贝叶斯公式:
可得: P(感冒|打喷嚏∗建筑工人)=P(打喷嚏∗建筑工人|感冒)∗P(感冒)P(打喷嚏∗建筑工人)
b. 假定“打喷嚏”和“建筑工人”两个特征是相互对立,则公式可以变成:
P(感冒|打喷嚏∗建筑工人)=P(打喷嚏|感冒)∗ P(建筑工人|感冒)∗P(感冒)P(打喷嚏)∗P(建筑工人)
c. 计算可得:
P(感冒|打喷嚏∗建筑工人)=0.66∗0.33∗0.50.5∗ 0.33=0.66
3.3.2 账号分类
1、描述:
现有SNS社区需对现有账户进行运营及监管,但其大量账户中存在”真实账户”和”虚假账户”两类。为提升运维效率及监管需对现有账户进行过滤分类。
2、分析过程:
假设
已有类别:A = {a0 表示真实账号,a1表示虚假账号}
待分特征属性: B = {b1,b2,b3}
根据贝叶斯公式:
P(A|B)=P(B|A)P(A)P(B)
推导过程
1、已分类集合:A={a0,a1} ;
待分类特征集合:B={b1,b2,b3}
2、依据朴素贝叶斯准则,则计算(在B条件下,A发生的概率):
P(a1|B),P(a2|B)
取
P(ai|B)=maxP(a1|B),P(a2|B)
3、根据贝叶斯公式,将计算转换为(在A条件下,B事件的概率):
P(B|ai)P(ai)=P(ai)∏ni=1P(B|ai)
在此详细推算过程
a、特征属性及划分
根据账号信息划分出“真实账号”和“虚假账号”的特征属性。
b1=日志数量/注册天数; b2=好友数量/注册天数; b3=是否使用真实头像
b1={b<=0.05,0.05<b<0.2,b>0.2}
b2={b<=0.1,0.1<b<0.8,b>=0.8}
b3={b=0,b=1}(b=0非真实头像,1真实头像)
b、获取1万条数据作为训练样本
真实账号:8900条;虚假账号:1100条
c、计算训练样本中每个类别的频率
P(a0)=890010000=0.89
P(a1)=110010000=0.11
d、计算每个类别条件下各特征属性划分的频率(在A条件下,B发生的概率)
P(b1<=0.05|a0)=0.3
P(0.05<b1<0.2|a0)=0.5
P(b1>=0.2|a0)=0.2
P(b1<=0.05|a1)=0.8
P(0.05<b1<0.2|a1)=0.1
P(b1>=0.2|a1)=0.1
P(b2<=0.1|a0)=0.1
P(0.1<b2<0.8|a0)=0.7
P(b2>=0.8|a0)=0.2
P(b2<=0.1|a1)=0.7
P(0.1<b2<0.8|a1)=0.2
P(b2>=0.8|a1)=0.1
P(b3=0|a0)=0.2
P(b3=1|a0)=0.8
P(b3=0|a1)=0.9
P(b3=1|a1)=0.1
e、使用分类器进行鉴别
现在鉴别一个账号,该账号b3=0,b2=0.2,b1=0.1,即:
P(a0)P(x|a0)=P(a0)P(0.05<b1<0.2|a0)P(0.1<b2<0.8|a0)P(b3|a0)
=0.89∗0.5∗0.7∗0.2=0.0623
P(a1)P(x|a1)=P(a1)P(0.05<b1<0.2|a1)P(0.1<b2<0.8|a1)P(b3|a1)
=0.11∗0.1∗0.2∗0.9=0.00198
由此可以看出该账号更趋向于真实账号。
3.3.3 性别分类
人类身体特征统计数据:
性别 | 身高(英尺) | 体重(磅) | 脚掌(英寸) |
---|---|---|---|
男 | 6 | 180 | 12 |
男 | 5.92 | 190 | 11 |
男 | 5.58 | 170 | 12 |
男 | 5.92 | 165 | 10 |
女 | 5 | 100 | 6 |
女 | 5.5 | 150 | 8 |
女 | 5.42 | 130 | 7 |
女 | 5.75 | 150 | 9 |
已知某人身高6英尺、体重130磅、脚掌8英寸,问是男是女?
1) 数据描述
类别:{男性,女性}
特征属性:{身高,体重,脚掌}
-
依据朴素贝叶斯推导,其最终需计算:
- P(身高|性别)∗P(体重|性别)∗P(脚掌|性别)∗P(性别)
由于身高、体重、脚掌都是连续变量,无法采用离散变量统计计算。在此假设身高、体重、脚掌都是正态分布,通过样本计算出均值和方差,从而获得正太分布的密度函数。
假设,男性升高的均值为5.855、方差0.035的正态分布,由此升高6英尺男性概率:
P(身高|性别)=12π√σe−(6−η)22σ2=1.5789
2) 计算分类
P(身高=6|男) * P(体重=130|男) * P(脚掌=8|男) * P(男) = 6.1984 *
e−9
P(身高=6|女) * P(体重=130|女) * P(脚掌=8|女) * P(女) = 5.3778 * e−4
可以得知,该人更倾向为女性。
4. 朴素贝叶斯算法分析
[机器学习实战:文本过滤器]
4.1 需求描述:
为维护在线社区留言板的正常次序,需屏蔽侮辱性的言论,需构建一个快速过滤器,如果某条留言使用了负面或侮辱性的言语,那么就将该留言标识为内容不当。
4.2 算法分析:【自问的过程】
1、拥有数据样本情况?
有若干条数据样本,其中每条“言论”均标识所属类别(即侮辱性言语或非侮辱性言语)
2、程序如何判断言语为侮辱性和非侮辱性?
1) 朴素贝叶斯
将使用朴素贝叶斯公式:
P(ci|w)=P(w|ci)P(ci)P(w)
c 表示分类类别即:侮辱性言语和非侮辱性言语
对每个类别分母都一样,即需计算
P(w|ci)
和
P(ci)
,在朴素贝叶斯中假设事件是相互独立的,故:
P(w|ci)=P(w0|ci)P(w1|ci)...P(wn|ci)
2) 需要计算什么?
P(w|ci)=P(w0|ci)∗P(w1|ci)∗...∗P(wn|ci)
以上用文字描述:计算每个类别下各个单词出现的概率。由此,需要统计内容:
a)每条言论下各个单词出现的次数;
b)每个类别的单词总数;
3) 数据分析:现有数据什么样?需要对数据如何处理?
a、对每条言语转换成向量数组;
b、制定“词典集合”,将每条言语做并集,去除重复单词;并将“词典集合”转换为向量数组;
4) 特殊情况分析:
a、由于 P(w|ci)=P(w0|ci)∗P(w1|ci)∗...∗P(wn|ci) 是做乘法运算,若其中一个单词概率为0,则该言语概率为0。
- [解决方法]将所有词出现数初始化为1,分母初始化为2。
b、太多很小数相乘,结果将趋近为0.
- [解决方法]对乘积取自然对数。在代数中有ln(a*b) = ln(a) + ln(b)。
4.3 算法实现
#1、将文本转换为数字向量
##a、建立不重复的词汇表
def createVocabList(dataSet):
vocabSet = set([])
for document in dataSet:
vocabSet = vocabSet | set(document)
return list(vocabSet)
#test
myVocabLists = createVocabList(postingLists)
##b、将每条言语转换为数字向量:建立与词汇表同等大小的言语向量,若言语中的词汇在词汇表中出现则标记为1,否则为0.
#vocabList:单词字典集合
#inputSet:单条文本
def 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
#test
wordsVec=[]
for postingList in postingLists:
wordsVec.append(setOfWords2Vec(myVocabLists,postingList))
#trainMainx - 输入文档矩阵
#trainCategory - 由每篇文档类别标签所构成的向量
def trainNB0(trainMatrix,trainCategory):
numTrainDocs = len(trainMatrix)
numWords = len(trainMatrix[0])
pAbusive = sum(trainCategory)/float(numTrainDocs)
#初始化概率
p0Num = ones(numWords)
p1Num = ones(numWords)
p0Denom = 2.0
p1Denom = 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)
p0Vect = log(p0Num / p0Denom)
return p0Vect,p1Vect,pAbusive
##test
p0Vect,p1Vect,pAbusive=trainNB0(wordsVec,classLists)