让你奶奶轻松搞懂Naive Bayes的理论与实践

stay simple,stay naive

hahaha,今天连文章的第一句话都改了。
不过,我标题党了... ...毕竟你奶奶可能连概率是什么都不知道,而我这里没有基础的教学。之所以取这个名字是因为,你只要顺着我的思路认真读下去,可以清楚地融会贯通Naive Bayes,搞懂它的原理。

朴素贝叶斯(Naive Bayes)是基于贝叶斯定理特征条件独立假设的分类方法。
换句话说,Naive Bayes的构造基础是贝叶斯定理,基本数学假设是:输入数据在各个维度上的特征被分类的条件概率之间是相互独立的。

本文将从朴素贝叶斯的算法出发,一点一点的剖析算法的原理,分析清楚朴素贝叶斯为什么要这样进行运算。
最后。上手实践。


朴素贝叶斯算法(naive Bayes algorithm)
输入:训练数据 T = {(x1,y1),(x2,y2),(x3,y3),···,(xN,yN)}
其中xi = (xi(1), xi(2), ..., xi(n))T,xi代表一条实例,这个数据集中每一条实例都由n个维度组成。
xi(j)是训练数据中第i个样本的第j维特征。
xi(j)∈{aj1, aj2, aj3, aj4, ..., ajS},说明j维可以在a这个集合中取值。
yi是xi这个实例对应的类别,有可能是c1,c2,c3,··· , cK
输出:实例x的分类

  1. 计算先验概率及条件概率
  2. 根据输入的数据xi = (xi(1), xi(2), ..., xi(n))T计算后验概率。
  3. 最大化后验概率,得到xi对应的类别。

我知道你没看懂。
因为上述算法只是一个引子,请认真阅读下边的内容,我会从头开始分析,讲清楚上边的算法为什么是这样,引导你真正懂得朴素贝叶斯。

注:
= = 经过之前有一篇文章受累不讨好地使用Latex手打公式,最后还出现了下图错误无法加载的情况,这次我决定手写,同学们就凑合看吧。O__O "…


教训

用通俗的话来讲,朴素贝叶斯,就是要学习一个X与Y的联合概率分布,这个联合概率分布就代表了X与某个Y之间的组合的可能性。这个联合概率分布学好了,就意味着朴素贝叶斯这个模型学好了。有了这个联合概率分布,再给一个输入值x,我想,学过概率的人都应该知道怎么计算在x的条件下的条件概率吧。这就是朴素贝叶斯的基本思路,非常简单,具体怎么计算,向下看。

在使用朴素贝叶斯分类时,有给定的输入x, 和训练得到的P(X, Y),就可以计算得到模型的后验概率分布P(Y = ck | X = x),也就是说得到了在X = x的条件下Y = ck的概率。最大化P(Y = ck | X = x),等同于Y = ck的概率最大时的那个ck,就是这个模型的输出,就是输入x的类别。最大化后验概率,这是后话。这里就来解释一下这个后验概率。

让你奶奶轻松搞懂Naive Bayes的理论与实践_第1张图片
公式推导

请看上图,公式(1)代表了条件独立性假设,说明X = x(n)相互之间是彼此独立的。
公式(2)就是我们所需要的后验概率,是我们要求的在输入x的条件下各种类别的概率,我们需要做的就是计算这个公式。为了让公式(1)可以在公式(2)中发挥作用,我们需要将公式(2)变形,变出含有公式(1)的样子,具体步骤见上图。
然后将公式(1)带入公式(2)。见公式(3),就是我们的目标函数,也就是本节题目所说的后验概率。

好了,后验概率已经出来了。
然后的问题是,我们为什么认为最大化后验概率就可以得到我们想要的结果呢。
来看下图告诉你为什么。
下图中最上边的公式大家应该认识,是0-1损失函数。在预测值和真实值相等的时候,函数为0;预测值和真实值不等的时候,函数为1。
看公式(5),是期望风险函数。接下来将这个风险期望变形。具体情况见下图,由公式(5)到公式(6)的转化。优化一个模型,我们需要最小化他的期望风险函数,也就是最小化公式(6)。具体情况见下图,推导地也很清楚。最后可以发现最小化使用0-1损失函数的风险函数就是最大化后验概率。

知道了为什么要最大化后验概率,后验概率也有了,进入到算法的最后一步,最大化这个后验概率。

看上图,看公式(4)。注意注意注意:在此纠正一下上图中的错误:公式(4)右边的那行字有误,并不是最大化ck,而是最大化这个后验概率从而得到使这个后验概率最大的ck
把公式(3)带入公式(4),观察公式(4)第2行中的分母,他用一个求和符号把每一个c求和,可知P(c1),P(c2),...,P(ck)的和为1。因此分母中的内容其实与ck无关。因为公式(4)被最大化是用来寻找ck的值,所以与ck无关的部分为了简化计算舍去。于是得到最终最大化后验概率的公式。

公式推导

到此为止!公式推导部分结束。你已经跟着我的思路得出了一个朴素贝叶斯的输出的最终公式。

y = argmaxckP(Y = ck) ∏jP(X(j) = x(j) | Y = ck)

对的,前边说了什么基本理论,什么公式推导,你可以暂时忘掉,因为到了这一步,我们的任务仅仅是计算上边这个公式的值,这个公式的值就是朴素贝叶斯的输出值。

我们要计算什么,相信你此时已经非常了解了。然后,算。
这就来到了文章开头的算法的第一个步骤:

计算先验概率及条件概率

y = argmaxckP(Y = ck) ∏jP(X(j) = x(j) | Y = ck) 这个公式就是由Y的先验概率和条件概率相乘得到的,所以为了计算这个公式,我们要在这里计算先验概率及条件概率。
这里提供两种方式来估计这两种概率:

  • 极大似然估计
  • 贝叶斯估计
1. 极大似然估计
先验概率P(Y = c~k~) 的极大似然估计
条件概率P(X^(j)^ = x^(j)^ | Y = c~k~) 的极大似然估计
2. 贝叶斯估计

然而用极大似然估计可能会出现所要估计的概率值为0的情况,0就会影响后验概率的计算结果,使分类产生偏差。因此我们在极大似然估计的分子和分母部分分别加上一个小尾巴,防止0的出现。改进之后的估计方法叫做贝叶斯估计。

先验概率P(Y = c~k~) 的贝叶斯估计
条件概率P(X^^(j)^ = x^(j)^ | Y = c~k~) 的贝叶斯估计
根据输入的数据xi = (xi(1), xi(2), ..., xi(n))T计算P(Y = ck) ∏jP(X(j) = x(j) | Y = ck)

上一步骤中已经有了条件概率的计算公式,在这一步骤中根据输入的x通过公式计算出我们需要的条件概率。

最大化后验概率,得到xi对应的类别

到了这一步,整个朴素贝叶斯的计算就完成了。
理论结合实践,下边一道例题让你对上边所讲的理论部分有更深入的理解。

例题

根据下表中的训练数据来训练一个贝叶斯分类器,来确定输入值x = (2, S)的类别。
下表中X1,X2为输入值的2个维度,Y为输出值,可以看出是一个分类问题,分为1和-1两类。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
X1 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3
X2 S M M S S S M M L L L M M L L
Y -1 -1 1 1 -1 -1 -1 1 1 1 1 1 1 1 -1

上图的解题过程清晰易懂,模拟了前文讲解的朴素贝叶斯的过程.


到了代码实现的时间。
这次使用的是20类新闻文本作为数据集。

# coding=utf-8
# import 与这个数据集相关的包
from sklearn.datasets import fetch_20newsgroups
# 与鸢尾不同的是,这个数据集无法直接加载,而是需要从网络下载数据,不过基本套路与上一篇的knn差不多
news = fetch_20newsgroups(subset='all')

print len(news.data)
print news.data[0]

展示数据集样例:可以看出有18846条数据,下边的内容为其中的第1条。

18846
From: Mamatha Devineni Ratnam 
Subject: Pens fans reactions
Organization: Post Office, Carnegie Mellon, Pittsburgh, PA
Lines: 12
NNTP-Posting-Host: po4.andrew.cmu.edu



I am sure some bashers of Pens fans are pretty confused about the lack
of any kind of posts about the recent Pens massacre of the Devils. Actually,
I am  bit puzzled too and a bit relieved. However, I am going to put an end
to non-PIttsburghers' relief with a bit of praise for the Pens. Man, they
are killing those Devils worse than I thought. Jagr just showed you why
he is much better than his regular season stats. He is also a lot
fo fun to watch in the playoffs. Bowman should let JAgr have a lot of
fun in the next couple of games since the Pens are going to beat the pulp out of Jersey anyway. I was very disappointed not to see the Islanders lose the final
regular season game.          PENS RULE!!!

然后,还是熟悉的操作,分割测试集和训练集。分割结果就不向上贴了。

from sklearn.cross_validation import train_test_split

X_train, X_test, Y_train, Y_test = train_test_split(news.data, news.target, test_size=0.25, random_state=33)

然后,就是要导入模型开始训练了。
等等,是不是发现了有一些什么不一样?上次的鸢尾数据是什么样的?这次呢?机器认识这次的自然语言吗?
所以在这里需要有一个步骤是将数据中的文本转化为特征向量。

# 文本与特征向量转化的模块
from sklearn.feature_extraction.text import CountVectorizer
# 这里的操作就像上一次的数据标准化
w2v = CountVectorizer()
X_train = w2v.fit_transform(X_train)
X_test = w2v.transform(X_test)

现在就可以导入模型了。

from sklearn.naive_bayes import MultinomialNB

NB = MultinomialNB()
# 训练
NB.fit(X_train, Y_train)
# 测试
predict = NB.predict(X_test)

print NB.score(X_test, Y_test)
0.839770797963

ok,大功告成。
炎炎夏日去喝杯冰饮吧。


参考文献:
统计学方法 | python机器学习及实践

如果你也喜欢机器学习,并且也像我一样在ML之路上努力,请关注我,我会进行不定期更新,总有一些可以帮到你。

文中公式推导为我个人理解,不保证理解完全正确,望指正
部分图片来自网络,部分本人手写
最后,字丑勿怪,但是人帅呀

你可能感兴趣的:(让你奶奶轻松搞懂Naive Bayes的理论与实践)