贝叶斯定理概述及其python实现

发布于 2021-08-30  1664 次阅读


贝叶斯定理概述

朴素贝叶斯算法是统计学的一种分类方法,它利用概率统计知识进行分类。朴素贝叶斯以贝叶斯定理为基础,故称为贝叶斯分类。之所以有“朴素”两个字,是因为该算法假设特征之间互相独立,而这个假设看上去又有点“过头”(因为绝大多数实际问题不太可能存在完全的独立性),因此加上了朴素二字。

贝叶斯流派

在提出贝叶斯方法之前,人们认为一件事发生的概率 \theta 是未知但是个固定的,一件事只有发生或不发生两种可能,且不随观察结果的变化而变化。贝叶斯流派则不同,其认为一件事发生的概率是个不确定的值,概率是人的一个主观概念,代表了对某件事发生的相信程度。因此对频率流派来说,认为需要推断的参数 \theta 是一个固定的未知常数,即概率 \theta 虽然是未知的,但最起码是确定的一个值,同时,样本 X 是随机的,所以频率派研究的重点是样本空间,大部分的概率计算针对样本 X 的分布。贝叶斯派则相反,他们认为参数 \theta 是一个随机变量,样本$X$是固定的,研究的重点是参数 \theta 的分布。

贝叶斯定理

贝叶斯定理是18世纪英国数学家托马斯·贝叶斯提出的重要概率论理论,该定理是关于随机事件A和B的条件概率的计算公式。贝叶斯定理的具体公式如下:

P(A|B) = \frac{P(A|B)P(A)}{P(B)}

  • P(A)是A的先验概率,之所以称之为“先验”是应为他不考虑任何B方面的因素
  • P(B)是B的先验概率,也成为标准化常量(normalizing constant)
  • P(A|B)是已知B发生后A的条件概率,也由于得自B的取值而被称为A的后验概率
  • P(B|A)是已知A发生后B的条件概率,也由于得自A的取值而被称为B的后验概率

如上,贝叶斯定理可以解读为:在B出现的前提下事件A发生的概率,等于A出现的前提下事件B发生的概率,乘以事件A单独发生的概率,再除以事件B单独发生的概率。通常,事件A在事件B发生的条件下的概率,与事件B在事件A发生的条件下的概率是不一样的;然而,这两者之间是存在一定关系的,贝叶斯定理就是对于这种关系的描述。借助贝叶斯定理,我们就可以通过已知的三个概率来推测第四个概率。

朴素贝叶斯分类器概述

朴素贝叶斯分类器(Naive Bayes classifier,NBC)是一种常见且简单有效的贝叶斯分类算法。对已知类别,朴素贝叶斯分类器在估计类条件概率时假设特征之间条件独立。这样的假设,可以使得在有限的训练样本下,原本难以计算的联合概率 P(X_1,X_2,?,X_n|Y) 转化为每个类别条件概率的乘积。尤其是在特征很多时,就显得更加简便。条件独立假设可形式化地表述如下:

P(X|Y=y) = \prod_{i=1}^{n}P(X_i|Y=y)


其中每个特征集 X = {X_1,X_2,?,X_n} 包含n个特征。

条件独立性

给定X,Y条件独立,则有:

P(X,Y|Z) = P(X|Z)\ast P(Y|Z)

有了条件独立假设,就不必计算每一个组合的类条件概率,只需要对给定的Y,计算每一个X的条件概率。显然这种方法更实用,因为它不需要很大的训练集就能获得较好的概率估计,试想,如果没有这个条件,我们计算类条件概率就需要通过遍历计算所有不同的条件组合,需要大量样本的支持。

贝叶斯计算过程

假设某个体有n个特征,分别为 X_1,X_2,?,X_n 。现有m个类别,分别为 C_1,C_2,?,C_m
首先,朴素贝叶斯分类器计算每个类别的后验概率:

P(C_i|X_1 X_2 ? X_n) = \frac{P(X_1 X_2 ? X_n |C_i)\ast P(C_i)}{P(X_1 X_2 ? X_n)} = \frac{P(X_1|C_i)\ast P(X_2|C_i)\ast ?\ast P(X_n|C_i)}{P(X_1 X_2 ? X_n)} (i =1,2,?,m)

然后,比较独立特征的条件概率,将概率最大的那个类别,作为该样本的类别: P(C_k|X_1 X_2 ? X_n)

拉普拉斯修正Laplacian correction

如果我们使用的实例数据量实在太小,缺少某种类型的样本,就会使该条件概率为0,进而导致该类别的后验概率直接为0,从而否定了其他特征对样本分类概率的估计,使得分类结果产生偏差。事实上,这种情况的出现,往往是由于我们的样本太少从而缺少概率较低事件的数据,并非这个事件从来不会发生。
为了解决0概率的问题,法国数学家皮埃尔·西蒙斯·拉普拉斯最早提出用加1的方法估计没有出现过的现象的概率,这就是拉普拉斯修正。当数据量很大时,每个分量的计数加1造成的估计概率的变化可以忽略不计,这样就可以方便有效地保证每一类中每个特征发生的概率是非0的。实际使用中,拉普拉斯修正增加的数值可以设置为任何一个值,通常加 \lambda (0<\lambda < 1) 来代替简单加1。同时如果对N个计数都加上 \lambda ,这时分母也要加上 N\ast \lambda 来保证所有类的概率加和为1。

数值型特征的处理

朴素贝叶斯算法需要计算概率,离散型变量采用频率来计算,连续性变量需要进行离散化处理才能进行计算。这样做的一个问题是,如果离散区间的数目过多,会因为每一个区间中记录太少而不能对特征条件概率做出可靠的估计。相反如果区间数目过少,有些区间就会含有来自不同类的记录,因此失去了正确的决策边界。
另一种连续型变量的处理方法是根据历史数据求得分布的参数,然后利用密度求得样本在该特征的条件概率。高斯分布通常被用来表示连续特征的类条件概率分布。例如,假设身高变量服从高斯分布,计算公式如下:

P(x,\eta,\sigma) = \frac{1}{\sqrt{2\pi}\sigma}e^{-\frac{(x-\eta)^2}{2\sigma^2}}

而在第 y_i 类中的均值和标准差分别为 \eta_{y_i}\sigma_{y_i} ,类条件概率为:

P(a_k|y_i) = p(a_k,\eta_{y_i},\sigma_{y_i})

因此,只要计算出训练样本中各个类别中此特征项划分的歌均值和标准差,带入上述公式即可得到需要的估计值。

优点

  • 分类效果稳健,特别适合于大规模数据集
  • 能够很方便地处理多分类任务
  • 对确实数据和噪声数据都不敏感

缺点

  • 特征之间相互独立的假设在实际应用中往往是不成立的,在特征个数比较多或者特征之间相关性较大时,分类效果一般
  • 需要知道先验概率,且先验概率很多时候取决于假设,假设的模型可以有很多种,因此在某些时候会由于假设的先验模型的原因导致预测效果不佳
  • 对输入数据的表达形式不敏感,应用在含有大量数值特征的数据集时并不理想

python实现

# 简单的二分类
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import GaussianNB
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from sklearn.metrics import accuracy_score

# 准备乳腺癌数据集
data = load_breast_cancer()
label_names = data['target_names']
labels = data['target']
feature_names = data['feature_names']
features = data['data']

# 分离训练集和验证集
train, test, train_labels, test_labels = train_test_split(features, labels, test_size=0.33, random_state=42)

# 创建朴素贝叶斯分类器,并拟合数据
gnb = GaussianNB()
model = gnb.fit(train, train_labels)

# 在验证集上进行预测,并输出accuracy score, 混淆矩阵和分类报告
preds = gnb.predict(test)
print('预测结果:')
print(preds)
print('\naccuracy score(准确率):')
print(accuracy_score(test_labels, preds))
print('\n混淆矩阵:')
print(confusion_matrix(test_labels,preds))
print('\n分类报告:')
print(classification_report(test_labels, preds))
预测结果:
[1 0 0 1 1 0 0 0 1 1 1 0 1 0 1 0 1 1 1 0 1 1 0 1 1 1 1 1 1 0 1 1 1 1 1 1 0
 1 0 1 1 0 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 0 0 1 1 0 0 1 1 1 0 0 1 1 0 0 1 0
 1 1 1 1 1 1 0 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 1 0 0 1 0 0 1 1 1 0 1 1 0
 1 1 0 0 0 1 1 1 0 0 1 1 0 1 0 0 1 1 0 0 0 1 1 1 0 1 1 0 0 1 0 1 1 0 1 0 0
 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 0 1 1 0 1 1 1 1 1 1 0 0
 0 1 1]

accuracy score(准确率):
0.9414893617021277

混淆矩阵:
[[ 61   6]
 [  5 116]]

分类报告:
              precision    recall  f1-score   support

           0       0.92      0.91      0.92        67
           1       0.95      0.96      0.95       121

    accuracy                           0.94       188
   macro avg       0.94      0.93      0.94       188
weighted avg       0.94      0.94      0.94       188