1.导读
朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法;之所以为朴素,就是假设特征条件独立,使得计算简单;如果没有假设特征条件独立,则应该考虑各特征条件之间的关系,从而形成贝叶斯网络;本次博客主要从基础公式,朴素贝叶斯法的学习与分类、参数估计、高斯朴素贝叶斯等方面介绍朴素贝叶斯法。
2.原始数学公式
无论是在高中数学还是概率论中,我们都会学到条件概率公式,条件概率公式如下:
.
.
也可以写成
.
.
当事件A和B互不相关时,有
.
.
全概率公式有
.
.
贝叶斯定理为:
.
.
看到了这里,不禁想问,这些个公式对我们有什么帮助呢?首先,我们先有这么一个模型的前提:对于给定的训练数据集,首先基于特征条件独立假设学习输入/输出的联合概率分布,然后基于这个模型,对给定的输入x,利用此定理(公式5)求出后验概率最大的输出y。我们把公式5中的符合都换成模型描述中常用的x与y可得:
.
.
3.朴素贝叶斯分类器
上文提到,朴素贝叶斯法之所以为朴素,是因为假设特征条件独立;我们的输入数据X有着多种特征,将他们假设为独立,就好像公式(3)中那样,各个特征的概率累乘,就可得最后的结果,下面公式给出:
.
.
将(7)代入到(6)中可得
.
.
于是可得,朴素贝叶斯分类器为:
.
.
可见,分母对所有的 c k \ c_k ck都是相同的,所以公式9可写为:
.
.
为什么要取最大值呢?因为后验概率最大等价于期望风险最小化,换个角度来看,就是希望通过这样的方法所取得的结果的损失是最小的;有如下推导:
1.选择0-1损失函数: L ( Y , f ( X ) ) = { 1 Y / = f ( X ) 0 Y = f ( X ) \ L(Y,f(X))=\begin{cases} 1&\text{} Y \mathrlap{\,/}{=}f(X) \\ 0&\text{} Y=f(X) \\ \end{cases} L(Y,f(X))={10Y/=f(X)Y=f(X)
2.根据联合分布可取得条件期望为: E X ∑ k = 1 K L ( c k , f ( X ) ) P ( c k ∣ X ) \ E_X \displaystyle\sum_{k=1}^{K}L(c_k,f(X))P(c_k|X) EXk=1∑KL(ck,f(X))P(ck∣X)
3.使期望风险最小化,对各个x最小化有
.
.
4.推导完成,得到 a r g max c k P ( y = c k ∣ X = x ) \ arg \displaystyle\max_{c_k}P(y=c_k|X=x) argckmaxP(y=ck∣X=x)
4.朴素贝叶斯法的参数估计
看到了这,我们还不知道怎么去让模型“学习”,在此,学习意味着估计
P
(
Y
=
c
k
)
\ P(Y=c_k)
P(Y=ck)和
P
(
X
(
j
)
=
x
(
j
)
∣
Y
=
c
k
)
\ P(X^{(j)}=x^{(j)}|Y=c_k)
P(X(j)=x(j)∣Y=ck);在此使用极大似然估计有:
.
.
.
.
但是,使用极大似然估计有时候会出现为0的情况,会影响到后续的计算结果,那么我们可以采用贝叶斯估计,如下:
.
.
.
.
常取 λ = 1 \ \lambda=1 λ=1,这时称为拉普拉斯平滑。
上面考虑的情况为分散的,如果特征值为连续的呢?我们又应该怎么做?我们可以假设在 c k \ c_k ck的条件下,x服从高斯分布(正态分布)。根据正态分布的概率密度函数即可计算出 P ( X = x ∣ Y = c k ) \ P(X=x|Y=c_k) P(X=x∣Y=ck),公式如下:
.
.
注意:在代码实现的时候最好先按类别分好X,然后再进行操作。在多特征值的时候,将其累乘即可。
5.优缺点分析
由于特征条件独立这一假设为一个较强的假设,模型所包含的条件概率大大减小,使得模型的学习与预测大为简化,因此高效而又易实现;但是缺陷在于分类的性能不高。
6.代码实现
class NaiveBayes:
def __init__(self):
self.model = None
def mean(X):
return sum(X) / float(len(X))
# 标准差(方差)
def stdev(self, X):
avg = self.mean(X)
return math.sqrt(sum([pow(x-avg, 2) for x in X]) / float(len(X)))
# 概率密度函数
def gaussian_probability(self, x, mean, stdev):
exponent = math.exp(-(math.pow(x-mean,2)/(2*math.pow(stdev,2))))
return (1 / (math.sqrt(2*math.pi) * stdev)) * exponent
# 处理X_train
def summarize(self, train_data):
summaries = [(self.mean(i), self.stdev(i)) for i in zip(*train_data)]
return summaries
# 分类别求出数学期望和标准差
def fit(self, X, y):
labels = list(set(y))
data = {label:[] for label in labels}
for f, label in zip(X, y):
data[label].append(f)
self.model = {label: self.summarize(value) for label, value in data.items()}
return 'gaussianNB train done!'
# 计算概率
def calculate_probabilities(self, input_data):
probabilities = {}
for label, value in self.model.items():
probabilities[label] = 1
for i in range(len(value)):
mean, stdev = value[i]
probabilities[label] *= self.gaussian_probability(input_data[i], mean, stdev)
return probabilities
# 类别
def predict(self, X_test):
label = sorted(self.calculate_probabilities(X_test).items(), key=lambda x: x[-1])[-1][0]
return label
def score(self, X_test, y_test):
right = 0
for X, y in zip(X_test, y_test):
label = self.predict(X)
if label == y:
right += 1
return right / float(len(X_test))
7.总结
因为这次属于复习一遍概念,所以代码没有码,从电脑里不知道什么时候从github下的代码贴了上来,大家参考一下就好~最近报夏令营什么的真的头晕脑胀辽,下一个写决策树;这次的朴素贝叶斯总体上来说还是比较简单的,公式的推导也比较简单,毕竟这一“特征条件独立”的假设太强了,剩下的就是之前学过的公式的应用了,主要要关注在期望风险最小化的推导以及高斯那里,其他的问题都不大。(手动狗头)水了水了,看不懂公式的去补一下概率论 知识就好,简单的很。