在天然界和人类活动中,发生的现象多种多言,有肯定性现象(例如偶数可以被2整除),也有不肯定的随机现象(例如新生婴儿是男孩仍是女孩)。几率论即是一门研究随机现象的统计规律性的数学学科。html
随机现象在一次试验中呈现不肯定的结果,而在大量重复试验中结果将呈现某种规律性,例如相对比较稳定的全国性别比例,这种规律性称为统计规律性。git
为了研究随机现象的统计规律性,就要对客观事物进行观察,观察的过程叫随机试验。github
随机试验有如下三个特色:web
随机试验的一切可能结果组成的集合称为样本空间,记为,其中w表示试验的每个可能的结果,又称为样本点。即样本空间为全体样本点的集合。算法
当咱们经过随机试验来研究随机现象时,每一次试验都只能出现中的某一个结果w,各个可能结果w是否在一次试验中出现是随机的。安全
在随机试验中,经常会关心其中某一些结果是否出现,例如抛一枚色子的结果是不是奇数。这些在一次试验中可能出现,也可能不出现的一类结果称为随机事件。app
笔者认为,在小数据下,随机事件是一类呈现出无规律结果的事件,可是在大数据下,随机事件每每会呈现出明显的统计规律,这也是大数据时代人工智能发展迅猛的缘由之一。框架
随机事件是一个抽象概念,经过引入集合论的理论框架,使得咱们能够经过集合的方式来考量随机事件间的关系以及对随机事件进行运算。函数
例如抛掷一枚均匀的色子,关心掷出的点数是不是偶数,定义,很显然,它是全体样本空间的一个子集。学习
因此,从集合的角度来看,样本空间的部分样本点组成的集合称为随机事件。
因为随机事件是一个集合,所以,事件之间的关系与事件之间的运算应该按照集合论中集合之间的关系与集合之间的运算来规定。
给定一个随机试验,Ω是它的样本空间,事件A,B,C与Ai(i = 1 ,2 , ... )都是Ω的子集。则随机事件间的关系有如下几种:
若是,那么,称事件B包含事件A。它的含义是:事件A发生一定致使事件B发生。
例如,事件A表示“灯泡寿命不超过200h”,事件B表示“灯泡寿命不超过 300h ”。因而。
若是且
,即A = B,那么称事件A与事件B相等。
若是A与B没有相同的样本点,则称事件A与事件B互补相容,或称为互斥。
事件A ∪ B = {ω:ω ∈ A 或 ω ∈ B},称为事件A与事件B的和事件(或并事件),它的含义是:当且仅当事件A与事件B中至少有1个发生时,事件A ∪ B发生。
事件A ∩ B = {ω:ω ∈ A 且 ω ∈ B},称为事件A与事件B的积事件(或交事件),它的含义是:当且仅当事件A与事件B同时发生时,事件A ∩ B发生,积事件也能够记做AB。
事件称为事件A与事件B的差事件,它的含义是 : 当且仅当事件A发生且事件B不发生时,事件A - B发生。
事件Ω-A称为事件A的对立事件(或逆事件,或余事件),记做,它的含义是:当且仅当事件A不发生时,事件
发生。因而
。
因为A也是的对立事件,所以称事件A与
互逆(或互余)。
A ∪ B = B ∪ A ,A ∩ B = B ∩ A
A ∪ (B ∪ C ) = (A ∪ B ) ∪ C ,
A ∩ (B ∩ C ) = (A ∩ B ) ∩ C ;
A ∪ (B ∩ C ) = (A ∪ B ) ∩ (A ∪ C ),
A ∩ (B ∪ C ) = (A ∩ B ) ∪ (A ∩ C );
Relevant Link:
《几率论与数理统计》同济大学数学系 第一章 - 第一节
几率是从频率学派发展而来的,咱们这里先定义频数和频率的概念。
在n次试验中若是事件A出现了na次,则称na为事件A的频数,称比值 na / n 为这n次试验中事件A出现的频率。
随着试验次数n的增大,频率值逐步”稳定“到一个实数,这个实数称为事件A发生的几率。
仔细看这个定义能够发现,几率的统计定义并非一个精确的数学定义,而更倾向于一个实验概括总结定理(Induction)。这里存在两个问题:
实际上,就像量子力学中的测不许原理同样,几率论并非一门研究肯定性的学科。在小数据下,随机事件呈现的是随机不肯定的结果,可是在大数据下,随机事件总体上处于一个特定统计规律的几率场中。关于大数定律的相关讨论,读者朋友能够参阅另外一篇文章。
1933年,柯尔莫哥洛夫(苏联)首次提出了几率的公理化定理。
设任一随机试验E,Ω为相应的样本空间,若对任意事件A,有惟一实数P(A)与之对应,且知足下面条件,则数P(A)称为事件A的几率:
Relevant Link:
《几率论与数理统计》同济大学数学系 第一章 - 第二节
在几率论发展的历史上,最早研究的,也最多见的的一类随机现象是等可能随机事件,在这类随机事件中,样本空间中的每一个基本事件发生的可能性都相等,这样的数学模型咱们称之为等可能摡型。
等可能摡型又能够主要分为两个主要方面:
通常地,称具备下列2个特征的随机试验的数学模型为古典概型:
在古典概型中,若是事件A中包含 na 个样本点,则事件A的几率为
用这种方法肯定的几率被称为古典几率。
值得特别注意的是,这里的 na 指的是样本点个数,样本点是几率论中的概念,不能直接等价于频率中的频数。咱们经过一批随机试验获得了事件A的统计频数,只有当随机试验的次数n很大时,大数定律才能起做用,这时候随机试验A的采样频数才能近似等于随机事件A的样本数(几率同分布假设),也即咱们才能用随机试验的统计结果近似做为几率统计的结果。
几何摡型是古典摡型的推广,保留每一个样本点发生的等可能性,但去掉了Ω中包含离散有限个样本点的限制,即容许试验可能的结果有连续无穷个。
通常地,几何概型的基本思路以下:
在几何概型中,咱们规定事件A的几率为:
其中,在一维情形下表示长度,在二维情形下表示面积,在三维情形下表示体积。
求几何概型的关键在于用图形正确地描述样本空间Ω和所求事件A,而后计算出相关图形的度量。
Relevant Link:
《几率论与数理统计》同济大学数学系 第一章 - 第三节
前三章咱们讨论了几率性的基本概念,随机事件,几率定义基本定义等内容,这章开始咱们来讨论几率论中一个很是重要的理论,条件几率以及事件的相互独立性。
能够这么说,正是由于这两个理论的发展,才有了后来的贝叶斯理论以及贝叶斯估计方法,以及再后来的朴素贝叶斯方法,甚至马尔科夫假设的发展也和它们有关系。
在大千世界中,事物是互相联系、互相影响的,这对随机事件也不例外。在同一试验中,一个事件发生与否对其余事件发生的可能性的大小到底是如何影响的?这即是条件几率理论要阐述和定义的内容。
笔者认为,条件几率是整个几率论体系基础中的基础,全部的随机事件间关系都可在条件几率的理论体系下解释,包括独立同分布事件,本质上也是条件几率的一个特例,即零依赖条件。
设E是随机试验,Ω是样本空间,A,B是随机试验E上的两个随机事件且P(B)>0,称
为在事件B发生的条件下,事件A发生的几率,称为条件几率。
能够验证,条件几率也知足几率的公理化定义的三条基本性质:
若是对条件几率定义式两端同乘P(A),可得以下定理:
几率的乘法公式:
设A,B为随机试验E上两个事件,且P(A)<0,则有。
在一个随机试验中,A,B是两个事件。若是它们之间是否发生是相互不影响的,这表现为 P(B | A) = P (B) 或 P(A | B) = P(A) 成立。
由条件几率延伸定理可得,这时,P(AB) = P(A)P(B)。
这说明无论事件A发生仍是不发生,都对事件B的发生的几率没有影响。咱们能够说事件A和事件B没有”关系“,或者称事件A与事件B相互独立。
设A,B为试验E的两个事件,若是知足等式,则称事件A,B相互独立,简称A,B独立。
同时,若事件A与事件B相互独立,则下列4个命题是等价的:
咱们将相互独立性推广到三个事件的状况,三个事件以上和三个本质上是相同的。
设A,B,C是试验E的三个事件,若是知足等式:
则称事件A,B,C两两相互独立。
设A,B,C是试验E的三个事件,若是知足等式:
则称事件A,B,C相互独立。
能够看到,在三元关系中,相互独立定义的要求比两两相互独立更加严格,知足两两相互独立的事件集合,未必必定就知足相互独立的定义。
举一个例子说明两两互相独立和相互独立的区别。
把一枚硬币相互独立的投掷2次,事件 Ai 表示”投掷第 i 次时出现正面“,i=1,2。事件 A3 表示”正、反面各出现一次“,因此有:
P(A1) = P(A2) = P(A3) = 1/2,P(A1 A2) = P(A1 A3) = P(A2 A3) = 1/4,因此 A1,A2,A3两两互相独立。
可是P(A1 A2 A3) = 0,因此 A1,A2,A3 不相互独立。
Relevant Link:
《几率论与数理统计》同济大学数学系 第一章 - 第四节
贝叶斯公式是几率论中最重要的知识点之一,该公式的意义在于开创了统计学的一个学派 - 贝叶斯学派,它和经典统计学派并列为现代统计学的两大分支。
贝叶斯公式是由英国学者贝叶斯(Thomas Bayes,1701-1761)为了解决二项分布的几率估计问题所提出的一种”逆几率“思想发展而来的。
”求几率这个问题的逆几率“和”求某问题的几率“是两个互为相反的过程:
贝叶斯的思想,之后后续学者对其思想的发展和理论的应用,最终发展成了贝叶斯统计理论,从而开辟了统计学发展中的一个新领域,对统计决策函数、统计推断、统计的估算等做出了巨大贡献。
贝叶斯学派与经典统计学派的差异在因而否使用先验信息,先验信息是指人们对一个事物的历史认知或主观判断。咱们知道,任何事物都是发展变化的,都会经过样本数据信息不断挖掘和发现新变化。经典统计学只使用样本数据信息,而贝叶斯分析则是把先验信息与样本数据结合起来进行推断。
全几率公式是几率论中一个很是重要的公式,一般咱们会遇到一些较为复杂的随机事件的几率计算问题,这时,若是将它分解成一些较为容易计算的状况分别进行考虑,能够化繁为简。
设E是随机试验,Ω是相应的样本空间,A1,A2,....,An为Ω的一个事件组,若知足条件:
则称事件组A1,A2,....,An为样本空间Ω的一个完备事件组,完备事件组完成了对样本空间的一个分割。
设A1,A2,....,An为样本空间Ω的一个完备事件组,且P(Ai) > 0(i=1,2,....,n),B为任一事件,则:
下面给出证实上述公式的一个几何表示:
因为,且
是两两互不相容的事件(即B与A1,A2,....,An中的任1个事件有且只有1个事件同时发生),所以
笔者认为,全几率公式能够这么理解:全几率公式表达了一个思想,致使某个结果B的缘由A能够分解为若干子状况,全部子状况累加起来共同致使告终果B,这是从缘由推结果的几率计算问题。
设A1,A2,....,An为样本空间Ω的一个完备事件组,且P(Ai) > 0(i=1,2,....,n),B为任一事件,当P(B) > 0时,有:
,i = 1,2,...,n
上面公式看着复杂,其实并不复杂,咱们将其和全几率公式进行对比。会发现如下几点:
笔者认为,贝叶斯公式能够这么理解:贝叶斯公式表达了一个思想,根据某个出现的结果B能够反推全部可能致使该结果的子缘由Ai,而具体根据结果B逆推出每一个子缘由的条件几率比重,则取决于这个子缘由和结果B的联合几率 ,这是从结果推缘由的逆几率计算问题。
从数学公式上来说,贝叶斯公式是全几率公式的逆运算,全几率公式和贝叶斯公式实际上表明了同一个事物的正反两面,有因就有果,有果就有因。
从映射的角度来看,贝叶斯和全几率公式能够理解为一个将”缘由“映射为”结果“的映射函数,也能够反过来解,将”结果“映射为”缘由“。
同时,这个因果的互相推导关系(映射)又不是固定不变的,它是随着随机试验的不断重复,不断调整”缘由-结果的映射比重“,这个所谓的比重就是先验几率,经过调整先验几率,因果之间的映射关系也随之改变,当达到大数统计的时候,这个映射关系会收敛到一个均值区间附近。
接下来最重要也最美妙的几个问题来了,那这个收敛均值区间和咱们先验是什么关系呢?咱们处于大数据的数据驱动时代,是应该相信数据仍是相信先验经验呢?笔者这里就本身在平常中的一些工做实践和思考给出个人一些观点:
这个小节,咱们用一个例子来讨论下,先验几率对最终贝叶斯后验估计结果的影响,先验使得咱们不单只看单次试验的结果,而同时还要结合对应事件是否发生的先验几率。
以医院检查某种疾病为例,某种疾病在全部人群中的感染率是0.1%(即在历史经验中这种病是一个很是罕见的病),医院现有的技术对于该疾病检测准确率为 99%(已知患病状况下, 99% 的可能性能够检查出阳性(患病);已知不患病下 99% 的可能性检查为阴性(正常))
设随机事件A为是否患病,随机事件B为是否被检测为阳性,则有:
经过贝叶斯公式,咱们可得”某我的被医院检测为阳性,同时又实际又真的患病(即真阳性)“的条件几率:
同理可得假阳性的条件几率为0.91。
能够看到,即便被医院检测为阳性,实际患病的几率其实还不到10%,有很大多是假阳性,须要确诊最终的结果,每每须要复检来肯定是否真的患病。
让咱们再来计算初检和复检结果都为阳性时(2次随机试验),患病的可能性。
假设两次检查的准确率相同,都是99%,这里令 B 为第一次检测结果为阳性,C 为第二次检测结果为阳性,A 为被检测者患病,则有:
计算”两次医院检测都是真阳性的几率“贝叶斯公式有:
可见复检结果大大提升了检测的可信度,可见复检的意义在于大幅减小假阳性的可能(0.91 -> 0.1),从而大大提升阳性检测的准确性。
这也必定程度上印证了上个小节的一个观点,当数据量足够大的时候,先验的做用会逐渐减弱,数据驱动的做用会占上峰,可是若是是小数据,先验对最终结果的影响就比较明显了。
生活中,若是体检中遇到了某种罕见病,不要慌张,赶忙再从新体检一次。
在这个小节中,笔者但愿经过一个具体的案例,向读者朋友展现贝叶斯统计推断的两个核心特色,即:
一袋中共装有10个球,分贝为红球和白球,可是每种颜色的球有几个不是很明确,若是按照完备事件组的定义,总有有11种可能(这是一个古典摡型),可是为了简化讨论,咱们假设完备集由下列三种可能组成:
在没有任何前置知识的状况下,咱们先设定一个先验,开始认为这三种可能的几率分别为:
试验的过程是每次从袋中有放回的拿一个球,接下来咱们来简要阐述下贝叶斯统计的过程。
第一轮的试验结果是,咱们取出的球是红色的。
咱们设”任取出一个球是红色“这个随机事件为B。试验的先验信息,P(A1) = 1/6,P(A2) = 1/3,P(A3) = 1/2。
根据全几率公式有:
又根据贝叶斯公式获得各个先验的后验几率估计:
因此,通过一次样本抽取试验后(引入了条件信息),结合历史先验信息,咱们获得了关于A1,A2,A3的后验几率。
在贝叶斯估计理论体系中,先验来自于历史,即包括先天的认知,也包括经过经验总结获得的历史经验认知(康德的理性与经验主义)。咱们在第一次试验中因为没有任何历史试验经验可总结,因此只能依据先天的认知假定了一个先验。可是通过了一次历史试验后,咱们已经有了一个后验几率估计,这时,咱们就能够将这个后验几率估计用做下一次试验的先验估计,即:
能够看到,相比于第一次的试验,A1和A2的先验都有微弱的提升,而A3的先验则微弱降低了。这是由于第一次的实验结果更倾向于强化A1和A2的发生可能,而弱化A3的发生可能。
能够想象,随着不断地试验,贝叶斯估计对事物的认识会不断加深和调整,对错误的先验会修正,对正确的先验会强化,最后收敛到真实附近。
Relevant Link:
《几率论与数理统计》同济大学数学系 第一章 - 第五节 https://zhuanlan.zhihu.com/p/22467549
在完成了对条件几率几率、全几率公式、贝叶斯公式的讨论以后,咱们接下来继续讨论一个基于理论的具体应用,本质上说,朴素贝叶斯法和贝叶斯理论之间的关系就至关于树枝和树根的关系,朴素贝叶斯法的理论依据来自于贝叶斯理论。
一言以蔽之,贝叶斯最优分类器是一种基于贝叶斯理论(全几率公式和贝叶斯公式)的生成式模型。
在贝叶斯最优分类理论中,对于给定的特征向量,咱们的目的是预测样本的标签
。
贝叶斯最优分类器的函数形式是:
接下来问题来了,根据全几率公式的分解,为了描述几率函数,咱们须要
个参数,这意味着,咱们所需的样本数量随特征个数呈现指数型增加(事件分解的越细,所需估计的参数数量就越多),很显然,这直接致使了维度爆炸问题。
独立同分布假设,是学者们提出的为了解决贝叶斯最优分类器运算量过大的一种方法。
咱们知道,在PAC可学习理论中,经过限制假设类能够缓解欠拟合问题,同时减少逼近偏差,虽然可能会引入估计偏差增大的问题。
在朴素贝叶斯方法中,咱们增长的一个假设是:对于给定的标签(目标值),各特征之间是彼此独立的。
有了这个假设,就能够由以下全几率公式:
也就是说,对于朴素贝叶斯生成式推测来讲,须要估计的参数个数只有 2d+1 个。这个独立假设显著减小了须要学习的参数数量。
注意,这里用的是”假设“这个词,也就是说这个假设并不必定是合理的(例如一段文本中不一样单词之间是存在语法依赖关系的),只是咱们为了简化运算而添加上的一个约束条件。
独立同分布假设其实也并非什么新的概念,文章前面提到的事件之间两两相互独立于事件之间互相独立的概念,就是这里所谓的独立同分布假设。
综上,朴素贝叶斯(naive Bayes)法是基于贝叶斯定理与特征条件独立假设的分类方法。
设输入空间为 n 维向量的集合,输出空间为类标记集合 Y = {C1,C2,...,Ck},输入特征向量
,输出类标记
,
是X和Y的联合几率分布,训练数据集
由
独立同分布产生。
朴素贝叶斯法的训练目标是,经过数据集学习联合几率分布。
但遗憾的是,联合几率不能直接产生(事实上它是未知的),咱们能够经过全几率公式计算获得联合几率。
先验几率分布:
条件几率分布:
先验几率和条件几率
累乘获得联合几率。
朴素贝叶斯预测的目的是”由果推因“,即根据n维输入向量x,反推全部可能的目标类几率值,并从中选择几率值最大的类做为最终预测值。
目标类几率值的计算公式以下:
朴素贝叶斯从全部目标类中选出后验几率最大的那一个类做为预测结果,最大后验几率估计的公式以下:
注意!上式中分母对全部分类Ck都是相同的,所以实际计算中,分母可约掉,最终最大后验几率估计公式以下:
朴素贝叶斯法预测时将实例分到后验几率最大的类中,这等价于指望风险最小化。
假设选择0-1损失函数做为损失的评估函数:
这时,指望风险是:。该式中指望是对联合分布P(X,Y)取得,而联合几率分布咱们是未知的,所以取等价的后验几率条件指望:
为了使指望风险最小化,只需对X = x逐个极小化,由此获得
等式推导的最后一步就是最后后验几率的意思,由此,根据指望风险最小化准则就推导出了等价的后验几率最大化准则:,这就是朴素贝叶斯法所采用的数学原理
Relevant Link:
https://www.google.com.hk/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=0ahUKEwj8m-mjmrvVAhUBzIMKHWiqCIoQFgglMAA&url=https%3a%2f%2fzh%2ewikipedia%2eorg%2fzh-cn%2f%25E6%259C%25B4%25E7%25B4%25A0%25E8%25B4%259D%25E5%258F%25B6%25E6%2596%25AF%25E5%2588%2586%25E7%25B1%25BB%25E5%2599%25A8&usg=AFQjCNGICcTloX_Ty9_xQ06UnWbSWHkcWw
咱们先计算先验几率:P(Y = 1) = 9 / 15;P(Y = -1) = 6 / 15
而后计算输入变量各个特征的条件几率:
= 2 / 9;
= 3 / 9;
= 4 / 9
= 1 / 9;
= 4 / 9;
= 4 / 9
= 3 / 6;
= 2 / 6;
= 1 / 6
= 3 / 6;
= 2 / 6;
= 1 / 6
根据最大后验几率公式,对于给定的
,计算其最大后验几率:
= 9 / 15 * 3 / 9 * 1 / 9 = 1 / 45
= 6 / 15 * 2 / 6 * 3 / 6 = 1 / 15
朴素贝叶斯法取后验几率最大的对应的类,因此 y = -1
这个小节咱们来讨论一种朴素贝叶斯估计的变种,平滑化的朴素贝叶斯估计。
原始的朴素贝叶斯估计是一种单纯从训练样本推导几率分布的算法,可是在实际工程实践中,可能遇到一个问题:在根据全几率公式计算分子中的条件几率时,可能由于数据分布不均匀致使结果出现零值等极端状况。
为何会有这个问题呢?咱们前面不是说先验分布是根据人的先天经验来设定的吗?这里怎么又说不许确不均匀呢?
实际上,在工程项目中,除了一些特定场景,大部分时候咱们不可能直接人工指定一个先验分布,而是须要根据训练样本集来获得先验分布以及先验条件几率的。
为了说明这个问题,咱们再来回顾一下朴素贝叶斯估计的公式:
公式中的分子是一个累乘式,试想若是有一个条件几率P(Xi | Yck) = 0,那整个分子的累乘结果就会等于0,分子为零,直接致使最终的贝叶斯后验几率估计也为零。
那接下来问题来了,这个等于意味着什么?合理吗?笔者的观点是,在海量均匀大数据下,可能合理,可是若是数据量不够或者分布不够均匀,这不合理,至关于便可老鼠屎坏了一锅汤,个别条件几率的0值,致使了总体的几率空洞,这显然是不合理的。
例如在文本分类任务中,咱们会对文本进行ngram分词并获得一个词表。以后在面对具体输入文本的时候,会逐一统计词表中的词在输入文本中的出现频率,那这个时候,就很容易出现某些特征在样本中出现次数为0的状况,这样就会致使这些词的条件几率为0,解决的方法也是进行平滑化,关于ngram平滑这个问题的讨论,笔者在另外一篇文章里有所涉及。
解决传统贝叶斯估计遇到0几率空洞问题的方法之一是加入平滑化因子,修改后的先验条件几率公式:
,式中λ>=0,等价于在随机变量各个取值的频数上赋予一个正数λ。
上面的公式,若是咱们对其进行对数化后能够看到,公式可分为两部分。
这代表对参数的估计再也不仅仅考虑样本的统计结果,还要考虑进先验分布,它如同一个惩罚项。也能够理解为经过平滑化因子,强行改变了经过统计方法获得的先验分布。
笔者这里多说一句,从原理上说,若是在具体应用中,算法开发者本身很是了解业务,例如笔者本身对安全攻防业务相对比较了解,是能够直接经过专家经验的方式,指定一个先验分布的,这么作的效果,有时候要比平滑化要好,缺点也很明显,比较费力,且对不一样数据的适应性会降低。
Relevant Link:
http://blog.csdn.net/juanjuan1314/article/details/78189527?locationNum=4&fps=1 http://www.cnblogs.com/liliu/archive/2010/11/24/1886110.html
咱们知道,咱们若是假设用于预测的全部词(例如15个词)互相之间都是有相关依存关系的,则朴素贝叶斯法的公式以下
可是了简便实现,咱们能够假设全部词之间是互相独立的,则计算过程会大大简化
下面咱们简述原理与预测过程
1. 输入全部邮件,而后获得邮件中每一个单词出如今垃圾邮件中的次数(条件几率 P(wordN | S) ),出如今正常邮件中的次数( P(wordN | H) ) 2. 设置默认几率,即若是在预测时遇到训练语料库中未见过的词,则赋值默认几率例如: 3.7e-4 3. 先验几率,设置Spam为0.2,Ham为0.8,即根据经验,100封邮件里有20封是垃圾邮件
有了这些参数,模型就训练出来了。朴素贝叶斯分类器的训练就是在计算条件几率
而后输入一封待处理邮件,找到里面全部出现的关键词
求出,A为一封邮件是垃圾邮件的事件,T为关键词出如今一封邮件中的事件。
是多个关键词。A和T是关联的事件。
每一个关键词根据朴素贝叶斯的假设,是相互独立的。
为
这些关键词同时出现的状况下A是垃圾邮件的几率。
表明了从待预测email中切出的词,A表明Spam或者Ham,上面公式要分别计算A = S和A = H时的独立联合条件几率。
这个计算在工程上也十分简单,就是把每一个词在语料库中出现的次数比例,累乘起来。分母可忽略不用计算,由于不影响分子的大小对比。
咱们用一个例子来讲明朴素贝叶斯是怎么应用在垃圾邮件分类中的
贝叶斯过滤器是一种统计学过滤器,创建在已有的统计结果之上。因此,咱们必须预先提供两组已经识别好的邮件,一组是正常邮件(ham),另外一组是垃圾邮件(spam)
咱们用这两组邮件,对过滤器进行"训练"。这两组邮件的规模越大,训练效果就越好。这里咱们假设正常邮件和垃圾邮件各4000封
"训练"过程很简单。首先,解析全部邮件,提取每个词(word)。而后,计算每一个词语在正常邮件和垃圾邮件中的出现频率。好比,咱们假定"sex"这个词,在4000封垃圾邮件中,有200封包含这个词,那么它的spam出现频率就是5%;而在4000封正常邮件中,只有2封包含这个词,那么ham出现频率就是0.05%。(若是某个词只出如今垃圾邮件中,就假定它在正常邮件的出现频率是1%,反之亦然。这样作是为了不几率为0。随着邮件数量的增长,计算结果会自动调整。)
有了这个初步的统计结果,过滤器就能够投入使用了
如今,咱们收到了一封新邮件。在未经统计分析以前,咱们假定它是垃圾邮件的几率为50%。(有研究代表,用户收到的电子邮件中,80%是垃圾邮件。可是,这里仍然假定垃圾邮件的"先验几率"为50%。)
咱们用S表示垃圾邮件(spam),H表示正常邮件(healthy)。所以,P(S)和P(H)的先验几率,都是50%
而后,对这封邮件进行解析,发现其中包含了sex这个词,请问这封邮件属于垃圾邮件的几率有多高?
咱们用W表示"sex"这个词,那么问题就变成了如何计算P(S|W)的值,即在某个词语(W)已经存在的条件下,垃圾邮件(S)的几率有多大。
根据条件几率公式,立刻能够写出
公式中,P(W|S)和P(W|H)的含义是,这个词语在垃圾邮件和正常邮件中,分别出现的几率。这两个值能够从历史资料库中获得,对sex这个词来讲,上文假定它们分别等于5%和0.05%。另外,P(S)和P(H)的值,前面说过都等于50%。因此,立刻能够计算P(S|W)的值:
所以,这封新邮件是垃圾邮件的几率等于99%。这说明,sex这个词的推断能力很强,将50%的"先验几率"一会儿提升到了99%的"后验几率"
在上面的例子中,基于一个词就推断一个email是不是垃圾邮件未免太过武断,在实际使用中很容易出现误报。由于在一封邮件里每每会包含不少词,为了能下降误报。更实际的作法是选出这封信中P(S|W)最高的15个词(对推断共享最高的15个词),计算它们的联合条件几率。若是有的词是第一次出现则初始化为0.4,由于垃圾邮件使用的每每是固定的语句,若是出现了训练库中从未出现的词,则有很大几率是正常的词
而所谓联合几率,就是指在多个事件发生的状况下,另外一个事件发生几率有多大。好比,已知W1和W2是两个不一样的词语,它们都出如今某封电子邮件之中,那么这封邮件是垃圾邮件的几率,就是联合几率。
在已知W1和W2的状况下,无非就是两种结果:垃圾邮件(事件E1)或正常邮件(事件E2)
其中,W一、W2和垃圾邮件的几率分别以下:
若是假定全部事件都是独立事件(这是一个强假设,可能会致使预测的准确性降低),那么就能够计算P(E1)和P(E2):
因为在W1和W2已经发生的状况下,垃圾邮件的几率等于下面的式子:
将上式带入即
将先验几率P(S)等于0.5代入,获得
将P(S|W1)记为P1,P(S|W2)记为P2,公式就变成
这就是联合几率的计算公式,将状况从二词扩展到15词,最终公式为
# -*- coding: utf-8 -*- # for tokenize import nltk from nltk.corpus import stopwords from nltk.tokenize import wordpunct_tokenize # for reading all the files from os import listdir from os.path import isfile, join # add path to NLTK file nltk.data.path = ['nltk_data'] # load stopwords stopwords = set(stopwords.words('english')) # path for all the training data sets # 用于训练模型的语料集 spam_path = 'data/spam/' easy_ham_path = 'data/easy_ham/' # change it to the type of mails you want to classify # path to the hard ham mails # 用于预测检验效果4个语料库 spam2_path = 'data/spam_2/' easy_ham2_path = 'data/easy_ham_2/' hard_ham2_path = 'data/hard_ham_2/' hard_ham_path = 'data/hard_ham/' # 分别测试模型在4种不一样类型的数据集中的分类效果 test_paths = [spam2_path, easy_ham2_path, hard_ham_path, hard_ham2_path] def get_words(message): """ Extracts all the words from the given mail and returns it as a set. """ # thanks http://slendermeans.org/ml4h-ch3.html # remove '=' symbols before tokenizing, since these # sometimes occur within words to indicate, e.g., line-wrapping # also remove newlines all_words = set(wordpunct_tokenize(message.replace('=\\n', '').lower())) # remove the stopwords msg_words = [word for word in all_words if word not in stopwords and len(word) > 2] return msg_words def get_mail_from_file(file_name): """ Returns the entire mail as a string from the given file. """ message = '' with open(file_name, 'r') as mail_file: for line in mail_file: # the contents of the actual mail start after the first newline # so find it, and then extract the words if line == '\n': # make a string out of the remaining lines for line in mail_file: message += line return message def make_training_set(path): """ Returns a dictionary of <term>: <occurrence> of all the terms in files contained in the directory specified by path. path is mainly directories to the training data for spam and ham folders. occurrence is the percentage of documents that have the 'term' in it. frequency is the total number of times the 'term' appears across all the documents in the path """ # initializations training_set = {} mails_in_dir = [mail_file for mail_file in listdir(path) if isfile(join(path, mail_file))] # count of cmds in the directory cmds_count = 0 # total number of files in the directory total_file_count = len(mails_in_dir) for mail_name in mails_in_dir: if mail_name == 'cmds': cmds_count += 1 continue # get the message in the mail message = get_mail_from_file(path + mail_name) # we have the message now # get the words in the message terms = get_words(message) # what we're doing is tabulating the number of files # that have the word in them # add these entries to the training set for term in terms: if term in training_set: training_set[term] = training_set[term] + 1 else: training_set[term] = 1 # reducing the count of cmds files from file count total_file_count -= cmds_count # calculating the occurrence for each term for term in training_set.keys(): training_set[term] = float(training_set[term]) / total_file_count return training_set # c is an experimentally obtained value # 贝叶斯估计P(S) = P(H) = 0.5 # 当一个新词出现时,咱们假定为3.7e-4 def classify(message, training_set, prior=0.5, c=3.7e-4): """ Returns the probability that the given message is of the given type of the training set. """ # 获取word token list msg_terms = get_words(message) msg_probability = 1 for term in msg_terms: if term in training_set: msg_probability *= training_set[term] else: msg_probability *= c return msg_probability * prior spam_training_set, ham_training_set = {}, {} def trainingProess(): global spam_training_set, ham_training_set print 'Loading training sets...', spam_training_set = make_training_set(spam_path) ham_training_set = make_training_set(easy_ham_path) print 'done.' def testProcess(): global spam_training_set, ham_training_set SPAM = 'spam' HAM = 'ham' for mail_path in test_paths: mails_in_dir = [mail_file for mail_file in listdir(mail_path) if isfile(join(mail_path, mail_file))] results = {} results[SPAM] = 0 results[HAM] = 0 print 'Running classifier on files in', mail_path[5:-1], '...' for mail_name in mails_in_dir: if mail_name == 'cmds': continue # 获取email的全文 mail_msg = get_mail_from_file(mail_path + mail_name) # 0.2 and 0.8 because the ratio of samples for spam and ham were the same # 贝叶斯估计P(S) = 0.2;P(H) = 0.8 # 当一个新词出现时,咱们假定为3.7e-4 spam_probability = classify(mail_msg, spam_training_set, 0.2) ham_probability = classify(mail_msg, ham_training_set, 0.8) # 计算获得独立联合条件几率: # P(T1|S) * P(T2|S) * ... * P(Tn|S) # P(T1|H) * P(T2|H) * ... * P(Tn|H) # 根据贝叶斯估计几率分别对S和H类的几率预测结果,断定属于垃圾邮件仍是正常邮件 if spam_probability > ham_probability: results[SPAM] += 1 else: results[HAM] += 1 total_files = results[SPAM] + results[HAM] spam_fraction = float(results[SPAM]) / total_files ham_fraction = 1 - spam_fraction print 'Fraction of spam messages =', spam_fraction print 'Fraction of ham messages =', ham_fraction print '' if __name__ == '__main__': # training process # 训练模型,获得训练集中每一个词的条件几率 trainingProess() # test process # 测试模型 testProcess() # 接收手工输入,并基于当前模型断定是不是恶意邮件 mail_msg = raw_input('Enter the message to be classified:') print '' ## 0.2 and 0.8 because the ratio of samples for spam and ham were the 0.2-0.8 spam_probability = classify(mail_msg, spam_training_set, 0.2) ham_probability = classify(mail_msg, ham_training_set, 0.8) if spam_probability > ham_probability: print 'Your mail has been classified as SPAM.' else: print 'Your mail has been classified as HAM.' print ''
Relevant Link:
http://www.ganecheng.tech/blog/53219332.html https://en.wikipedia.org/wiki/Naive_Bayes_spam_filtering https://github.com/aashishsatya/Bayesian-Spam-Filter/blob/master/ClassifierDemo.py http://www.ganecheng.tech/blog/53219332.html https://github.com/dwhitena/bayes-spam-filter http://www2.aueb.gr/users/ion/data/enron-spam/ http://www.ruanyifeng.com/blog/2011/08/bayesian_inference_part_two.html http://www.voidcn.com/blog/win_in_action/article/p-5800906.html