sklearn学习03——Bayes
- 前言
- 一、朴素贝叶斯
- 1.1、贝叶斯分类器的理论框架
- 1.2、朴素贝叶斯分类器
- 1.3、朴素贝叶斯的代码实现
- 总结
前言
本篇首先介绍朴素贝叶斯分类器的原理(参考西瓜书),最后使用 sklearn 简单实现它。
一、朴素贝叶斯
1.1、贝叶斯分类器的理论框架
贝叶斯分类器的理论框架基于贝叶斯决策论(Bayesian decision theory),而贝叶斯决策论是概率框架下实施决策的基本方法。对分类任务来说,在所有相关概率都已知的理想情形下,贝叶斯决策论考虑如何基于这些概率和误判损失来选择最优的类别标记。
具体来说,若目标是最小化分类错误率,则我们要找的就是:对于每个样本 x,选择能使后验概率 P(C | x)最大的类别标记。 即如下公式:
其中 h*(x)为贝叶斯最优分类器。然而在现实任务中,后验概率 P(C | x)通常难以直接获得,从这个角度来看,机
器学习所要实现的是基于有限的训练样本集尽可能准确地估计出后验概率P(C | x)。所以贝叶斯分类器使用的策略是: 生成式模型,先对联合概率分布 P(x,C)建模,然后再由此获得 P(C | x)。基于条件概率的定义,有:
再根据贝叶斯定理,可将后验概率转化为:
由以上公式可知,最终贝叶斯分类器将 求解后验概率的问题 转化为了 求先验概率P(C)和 类条件概率P(x | C)的问题。
1.2、朴素贝叶斯分类器
由 1.1 节最终的后验概率公式(贝叶斯公式)可知,估计后验概率的最大困难在于:类条件概率P(x | C)是 x样本上所有属性上的联合概率,这很难从有限的训练样本直接估计得到。原因有以下两点:
- 基于有限训练样本直接估计联合概率,在计算上斗争会遭遇纽合爆炸问题;
- 在数据上将会遭遇样本稀疏问题,属性数越多,问题越严重。
西瓜书上的一个举例:假设样本的 d 个属性都是二值的,则样本空间将有 2^d 种可能的取值,在现实应用中,这个值往往远大于训练样本数 m ,也就是说,很多样本取值在训练集中根本没有出现,直接使用频率来估计 P(x | C) 显然不可行,因为 “未被观测到” 与 “出现概率为零” 通常是不同的。
所以,为了避开这个障碍,朴素贝叶斯分类器采用了 “属性条件独立性假设”:对已知类别,假设所有属性相互独立。换言之,假设每个属性独立地对分类结果发生影响。则基于此假设,后验概率计算公式可变为如下:
因为最终计算的是,在样本 x这个样本确定的条件下,看它属于哪一类的概率高,即后验概率高的那一类作为最终类别,分母均为 P(x),所以分母不需要求了,朴素贝叶斯分类器最终的目标就是:
在实际计算中,上面的公式会做如下略微改动:
- 由于某些特征属性的值P(xi | Ci)可能很小,多个特征的 P 值连乘后可能约等于0。可以公式两边取 log 然后变乘法为加法,避免类乘问题。
- P(Ci) 和P(xi | Ci)一般不直接使用样本的频率计算出来,一般会使用拉普拉斯平滑。如下公式:
其中,Dc 为该类别的频数(属于该类别的有多少个样本),N 表示所有类别的可能数(有多少类别)。
其中,Dc,xi 为该特征对应属性的频数,Dc 为该类别的频数,Ni表示该特征的可能的属性数。
1.3、朴素贝叶斯的代码实现
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns; sns.set()
from sklearn.datasets import make_blobs
# make_blobs:为聚类产生数据集
# n_samples:样本点数,n_features:数据的维度,centers:产生数据的中心点,默认值3
# cluster_std:数据集的标准差,浮点数或者浮点数序列,默认值1.0,random_state:随机种子
X, y = make_blobs(n_samples = 100, n_features=2, centers=2, random_state=2, cluster_std=1.5)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='RdBu')
plt.show()
from sklearn.naive_bayes import GaussianNB
model = GaussianNB()
model.fit(X, y)
rng = np.random.RandomState(0)
X_test = [-6, -14] + [14, 18] * rng.rand(2000, 2)
y_pred = model.predict(X_test)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='RdBu')
lim = plt.axis()
plt.scatter(X_test[:, 0], X_test[:, 1], c=y_pred, s=20, cmap='RdBu', alpha=0.1)
plt.axis(lim)
plt.show()
yprob = model.predict_proba(X_test)
yprob[-8:].round(2)
总结
- 贝叶斯是一种生成式模型,不是直接拟合分类结果,而是拟合出后验概率公式计算对应分类的概率。
- 对于小规模数据集,表现良好。
- 朴素贝叶斯分类器是建立在特征相互独立的假设上的。
- 拉普拉斯修正较好地解决了先验概率、类条件概率中某一项为 0 ,最后得到 0 值的问题。