朴素贝叶斯算法简洁

http://blog.csdn.net/xlinsist/article/details/51236454

引言


先前曾经看了一篇文章,一个老外程序员写了一些很牛的Shell脚本,包括晚下班自动给老婆发短信啊,自动冲Coffee啊,自动扫描一个DBA发来的邮件啊, 等等。于是我也想用自己所学来做一点有趣的事情。我的想法如下:


首先我写个scrapy脚本来抓取某个网站上的笑话

之后写个Shell脚本每天早上6点自动抓取最新的笑话

然后用朴素贝叶斯模型来判断当前的笑话是否属于成人笑话

如果是成人笑话,用脚本把它自动发给好兄弟的邮箱

如果不是成人笑话,用脚本把它自动发给女朋友的邮箱

在这个系列的文章中,你会学到:


朴素贝叶斯背后的数学原理

算法具体的工作过程(结合实例)

scikit-learn快速实现算法

这个系列的文章还会涉及到scrapy,pandas,numpy的一些知识,遇到这些知识的时候我会具体解释的。这个系列的文章我会主要详细的介绍上面的第3步实现过程,其余的我会将源码放在github上供大家参考。下面,就让我们享受这个奇妙之旅吧。


朴素贝叶斯概述


众所周知,朴素贝叶斯是一种简单但是非常强大的线性分类器。它在垃圾邮件分类,疾病诊断中都取得了很大的成功。它只所以称为朴素,是因为它假设特征之间是相互独立的,但是在现实生活中,这种假设基本上是不成立的。那么即使是在假设不成立的条件下,它依然表现的很好,尤其是在小规模样本的情况下。但是,如果每个特征之间有很强的关联性和非线性的分类问题会导致朴素贝叶斯模型有很差的分类效果。


朴素贝叶斯背后的数学原理


后验概率(Posterior Probabilities)


为了更好地了解朴素贝叶斯分类器是怎么工作的,了解贝叶斯法则是很必要的。它可以被简单地描述成下面的公式:



后验概率=条件概率先验概率现象概率

我们可以用一个关于老天是否下雨的例子来解释上面的公式。



P(给定天上有乌云,下雨的概率)=P(给定天上下雨,有乌云的概率)P(下雨的概率)P(有乌云的概率)

我们可以看到,如果我们想要在给定现象下,预测某种结果的概率,我们必须知道:1、在给定这种结果下,出现这种现象的概率。2、出现这种结果的概率。3、出现这种现象的概率。


在实际应用中,我们的现象不可能只有一个,比如,在垃圾邮件分类中,甚至可能有几千个词的特征向量。下面,我将引入一些数学上的记号来统一后面的表达:


ωj表示属于哪个类别,j∈{1,2,3,…,m}

xi表示特征向量中的第i个特征,i∈{1,2,3,…,n}

朴素贝叶斯的目标就是分别求得P(ωj|给定现象)j∈{1,2,3,…,m},选出最大的概率。


下面我将分别解释上面的三个概率。


条件概率(Conditional Probabilities)


随机变量的独立性意味着我告诉你一个变量的出现,并不影响你相信另一个出现的可能。最简单的一个例子就是抛硬币,也就是第一次的反正面并不会影响你再一次抛出现反正面的概率(也就是0.5)。


朴素贝叶斯模型中,特征之间不仅仅是独立的,而且是加条件的独立的。比如说:我的特征向量x中,有n个特征,那么我可以把概率写成下面的形式:



P(x|ωj)=P(x1|ωj)P(x2|ωj)P(x3|ωj)P(xn|ωj)=∏k=1nP(xk|ωj)

P(x|ωj)的概率我们可以理解成:在给定属于某个类别的条件下,观察到出现现象x的概率。在特征向量中的每个特点的概率我们都可以通过极大似然估计(maximum-likelihood estimate)来求得,也就是简单地求某个特征在某个类别中的频率,公式如下:



P(xi|ωj)=Nxi|ωjNωj(i=(1,…,n))

Nxi|ωj:在所有属于类别ωj的训练样本中,特征xi出现的次数

Nωj:在所有属于类别ωj的训练样本中,所有特征出现的次数

现在,我要用一个简单的分类垃圾邮件的例子来阐明上面的概念。比如我有4封邮件,其中2封为垃圾邮件,特征向量中有4个特征。具体如下表:


样本序号 love buy deal cat 是否为垃圾邮件

1 1 0 0 1 不是

2 0 1 1 0

3 0 1 0 1

4 1 0 1 1 不是

现在我要求P(buy,deal|spam)这个概率,通过条件的独立性和极大似然估计,我们可以求出这个概率:



P(buy,deal|spam)=P(buy|spam)P(deal|spam)=1+11+1+1+111+1+1+1=18

先验概率(Prior Probabilities)


先验概率道理其实很简单,在上面的那个垃圾邮件的例子中,我们可以用极大似然估计来求得:24,通式如下:



p(ωj)=NωjNc

Nωj:属于类ωj的样本数

Nc:所有的样本数

通过上面后验概率的公式,我们可知:如果先验概率服从均匀分布,那么后验概率将完全取决于条件概率和现象概率,然而现象概率是常量,所以后验概率就完全取决于条件概率了。


注意:我认为在某些分类应用中,先验概率应该去咨询应用领域的专家,你不能单凭样本中出现的概率来求得先验概率。比如:如果我的训练集中,下雨天的样本要比晴天的样本多,你不能说现实生活中下雨天的概率要比晴天的时候大。因此,对于某些应用,先验概率应该去咨询应用领域的专家。


现象概率(Evidence Probabilities)


现象概率是独立于类别的。比如上面那个垃圾邮件的例子,我想知道P(deal)这个现象发生的概率,我只需要找出我所有的样本中出现deal这个特征的概率,与属于哪个类别没有任何关系。


其实我们完全没有必要算出这个概率,因为我们要求属于哪个类别的概率最大,而在这个过程中,它对于每次计算类别的概率中(也就是P(ωj|xi))都是常量,所以它不会影响到最终的决策。


加上平滑(Additive Smoothing)


还是上面那个邮件的例子,假设我们要求P(love|spam),我们会发现,在垃圾邮件中并没有出现love这个词,因此概率为0,如果这个条件概率为0,那么整个后验概率就为0。为了避免0概率的发生,我们可以加上平滑项。把上面条件概率的公式改为下面的形式:



P(xi|ωj)=Nxi|ωj+αNωj+αn(i=(1,…,n))

Nxi|ωj:在所有属于类别ωj的训练样本中,特征xi出现的次数

Nωj:在所有属于类别ωj的训练样本中,所有特征出现的次数

α:附加的平滑项参数。α<1叫做Lidstone smoothing ;α=1叫做Laplace smoothing

n:特征数

一个PHP版本的朴素贝叶斯

http://blog.csdn.net/u012543061/article/details/53005029