2.10 贝叶斯分类器
文章目录
2.10.1 引入
参考内容:朴素贝叶斯 写作业还得看小明
-
某人开了一个邮箱接收粉丝邮件,一共收到 30 份邮件,他看了 29 封,发现里面有 16 封是
小黑子
寄的,13 封是真爱粉
寄的。还剩下 1 封,实现看不出来是哪边的,于是他想到了运用自己的概率论与数理统计的知识来分辨这一封信。 -
他挑选了四个关键词:
好帅
,哥哥
,坤坤
,太美
。统计了他们在信中出现的概率:小黑子/真爱粉 好帅 哥哥 坤坤 太美 小黑子 - 16 封 3 次 4 次 2 次 6 次 真爱粉 - 13 封 8 次 2 次 4 次 0 次 有如下一些表达式:
{P(小黑子)=2916P(真爱粉)=2913
其中,P(小黑子)=2916 表示已看过的 29 封信中,是小黑子
的概率为 2916。
⎩⎨⎧P(好帅∣小黑子)=3+4+2+63=153P(哥哥∣小黑子)=3+4+2+64=154P(坤坤∣小黑子)=3+4+2+62=152P(太美∣小黑子)=3+4+2+66=156⎩⎨⎧P(好帅∣真爱粉)=8+2+4+08=148P(哥哥∣真爱粉)=8+2+4+02=142P(坤坤∣真爱粉)=8+2+4+04=144P(太美∣真爱粉)=8+2+4+00=140
其中,P(好帅∣小黑子)=3+4+2+63=153 表示在小黑子
中,发送好帅
的概率为 153。 -
剩下的一封中,含有关键字:……
好帅
……坤坤
……-
如果猜测这是
小黑子
发送的,有:
P(小黑子)P(好帅∣小黑子)P(坤坤∣小黑子)=2916153152=0.0147 -
如果猜测这是
真爱粉
发送的,有:
P(真爱粉)P(好帅∣真爱粉)P(坤坤∣真爱粉)=2913148144=0.0732
-
-
由于 0.0147<0.0732,于是他由朴素贝叶斯的思想,认为这是由
真爱粉
发送的。
2.10.2 贝叶斯公式
-
贝叶斯定理由英国数学家贝叶斯 (Thomas Bayes) 发展,用来描述两个条件概率之间的关系,比如 P(A∣B) 和 P(B∣A)。
-
通常,事件 A 在事件 B(发生)的条件下的概率,与事件 B 在事件 A 的条件下的概率是不一样的;然而,这两者是有确定的关系,贝叶斯法则就是这种关系的陈述。
-
按照乘法法则,有:
P(A∩B)=P(A)∗P(B∣A)=P(B)∗P(A∣B)
或者:
P(A∣B)=P(B)P(B∣A)∗P(A) -
在贝叶斯法则中,每个名词都有约定俗成的名称:
- P(A) 是 A 的先验概率或边缘概率,之所以称为"先验"是因为它不考虑任何 B 方面的因素;
- P(A∣B) 是已知 B 发生后 A 的条件概率,也由于得自B的取值而被称作 A 的后验概率;
- P(B∣A) 是已知 A 发生后B的条件概率,也由于得自A的取值而被称作 B 的后验概率;
- P(B) 是 B 的先验概率或边缘概率,也作标准化常量(normalized constant)。
按这些术语,Bayes法则可表述为:
后验概率=标准化常量似然度∗先验概率
也就是说,后验概率与先验概率和似然度的乘积成正比。 -
另外,比例 P(B∣A)/P(B)也有时被称作标准似然度(standardised likelihood),Bayes法则可表述为:
后验概率=标准似然度∗先验概率 -
最核心的贝叶斯公式:
P(Ai∣B)=∑jP(B∣Aj)P(Aj)P(B∣Ai)
2.10.3 贝叶斯决策论
参考文献:《机器学习》周志华,P147
-
贝叶斯决策论是概率框架下实施决策的基本方法。对分类任务来说,在所有相关概率都已知的情况下,贝叶斯决策论考虑如何基于这些概率和误判损失来选择最优的类别标记。
-
以多分类任务为例:
-
假设有 N 种可能的标记:Y={c1,c2,…,cN}
-
将一个真实标记为 cj 的样本误分类为 ci 所产生的损失为:λij
-
基于后验概率 P(ci∣x) 可获得将样本 x 分类为 ci 所产生的期望损失,即在样本 x 上的“条件风险”:
R(ci∣x)=j=1∑NλijP(cj∣x) -
寻找判定准则 h:X→Y,以最小化总体风险:R(h)=Ex[R(h(x)∣x)]
-
贝叶斯判定准则(Bayes decision rule):为最小化总体风险,只需在每个样本上选择那个能使条件风险 R(c∣x) 最小的类别标记,即:
h∗(x)=c∈YargminR(c∣x)
此时,h∗ 称为贝叶斯最优分类器,与之对应的总体风险 R(h∗) 被称为贝叶斯风险。
-
-
若目标是最小化分类错误率,则误判损失 λij 可写为:
λij={01,if i=j;,otherwise
此时条件风险:
R(c∣x)=1−P(c∣x)
于是,最小化分类错误率的贝叶斯最优分类器为:
h∗(x)=c∈YargminP(c∣x)
即对每个样本 x,选择能使后验概率 P(c∣x) 最大的类别标记。 -
机器学习所要实现的是基于有限的训练样本集,尽可能准确地估计出后验概率 P(c∣x),有两种策略:
-
判别式模型(discriminative models):给定 x,通过直接建模 P(c∣x) 来预测 c;
- 决策树、BP 神经网络、支持向量机都属于此类。
-
生成式模型(generative models):先对联合概率分布 P(x,c) 建模,再由此获得 P(c∣x)。
-
必须考虑:
P(c∣x)=P(x)P(x,c) -
基于贝叶斯定理,P(c∣x) 可写为:
P(c∣x)=P(x)P(c)P(x,c)
其中,P(c) - 类“先验”概率;P(x∣c) - 样本 x 相对于类标记 c 的条件概率,或称为似然;P(x) 用于归一化的证据因子。 -
对于给定样本 x,证据因子 P(x) 与类标记 c 无关,因此估计 P(c∣x) 的问题就转化为如何基于训练数据 D 来估计先验概率 P(c) 和似然 P(x∣c)。
-
P(c) 可通过各类样本出现的频率来进行估计。
-
P(x∣c) 涉及关于 x 所有属性的联合概率,直接估计非常困难。
-
-
2.10.3 基本方法
2.10.3.1 极大似然估计(Maximum Likelihood Estimation)
参考内容:一文搞懂极大似然估计
- 对于函数 p(x∣θ),其有两个输入:x 表示某一个具体的数据,θ 表示模型的参数
- 如果 θ 是已知确定的, x 是变量,这个函数叫做概率函数(probability function),它描述对于不同的样本点 x ,其出现概率是多少。
- 如果 x 是已知确定的, θ 是变量,这个函数叫做似然函数(likelihood function), 它描述对于不同的模型参数,出现 x 这个样本点的概率是多少。
2.10.3.2 朴素贝叶斯分类器(Naive Bayes Classifier)
参考文献:《机器学习》周志华,P150
-
属性条件独立性假设:对已知类别,假设所有属性相互独立。
-
基于该假设,有:
P(c∣x)=P(x)P(c)P(x,c)=P(x)P(c)i=1∏dP(xi∣c)
其中,d 为属性数目,xi 为 x 在第 i 个属性上的取值。 -
基于贝叶斯判定准则,得朴素贝叶斯分类器:
hnb(x)=c∈YargmaxP(c)i=1∏dP(xi∣c)
显然,朴素贝叶斯分类器的训练过程就是基于训练集 D 来估计类先验概率 P(c),并为每个属性估计条件概率 P(xi∣c)。 -
估计类先验概率:
P(c)=∣D∣∣Dc∣
其中,Dc 表示训练集 D 种第 c 类样本组成的集合。对离散属性,条件概率 P(xi∣c) 可估计为:
P(xi∣c)=∣Dc∣∣Dc,xi∣
其中,Dc,xI 表示 Dc 在第 i 个属性上取值为 xi 的样本组成的集合。对连续属性,假定 p(xc∣c)∼N(μc,i,σc,i2),有:
p(xi∣c)=2πσc,i1exp(−2σc,i2(xi−μc,i)2) -
拉普拉斯修正:
-
某个属性在训练集中没有与某个类同时出现过,则会使连乘时得 0。
-
令 N 表示训练集 D 中可能的类别数,Ni 表示第 i 个属性可能得取值数,则:
P^(c)=∣D∣+N∣Dc∣+1P^(xi∣c)=∣Dc∣+Ni∣Dc,xi∣+1 -
拉普拉斯修正避免了因训练集样本不充分而导致概率估值为零的问题,并且在训练集变大时,修正过程所引入的先验的影响也会逐渐变得可忽略,使得估值逐渐趋向于实际概率。
-
2.10.3.3 半朴素贝叶斯分类器(Semi-Naive Bayes Classifier)
参考内容:贝叶斯算法小总结
-
特点:
- 属性条件独立性假设在现实中往往很难成立;
- 半朴素贝叶斯分类器适当考虑一部分属性间的相互依赖信息,即不需完全联合概率计算,又不至于彻底忽略了比较强的属性依赖关系;
- “独依赖估计(One-dependent Estimator, ODE)”是半朴素贝叶斯分类器最常采用的一种策略。
-
独依赖估计:
- 假设每个属性在类别之外最多仅依赖于一个其他属性,即:
P(c∣x)∝P(c)i=1∏dP(xi∣c,pai)
其中,pai 为属性 xi 所依赖的属性,称为 xi 的父属性。
- 假设每个属性在类别之外最多仅依赖于一个其他属性,即:
-
常见的半朴素贝叶斯算法
-
SPODE(Super-Parent ODE):假设所有属性都依赖于同一个属性;
-
TAN(Tree Augmented Naive Bayes):通过最大带权生成树算法确定属性之间的依赖关系,实际上仅保留了强相关属性之间的依赖性;
-
AODE(Averaged ODE):尝试将每个属性作为超父来构建 SPODE,然后将那些具有足够训练数据支撑的 SPODE 集成起来作为最终结果。
-
2.10.4 算法实例
python 版本 3.12.2,主要环境 scikit-learn, matplotlib。
-
使用鸢尾花数据集:
# 导入鸢尾花数据集 from sklearn.datasets import load_iris iris = load_iris() # 加载数据 print(iris.data) # 样本数据 print(iris.target) # 样本标签
- 包含150条记录;
- 4个属性:花萼长度,花萼宽度,花瓣长度,花瓣宽度;
- 1个标签:鸢尾花的类别(Setosa,Versicolour,Virginica三类)。
实验结果:
-
简单使用多种贝叶斯估计器进行训练与测试:
# 导入鸢尾花数据集 from sklearn import datasets iris = datasets.load_iris() # 导入各种贝叶斯估计器 from sklearn.naive_bayes import GaussianNB, MultinomialNB, ComplementNB, BernoulliNB, CategoricalNB # 导入数据集划分器 from sklearn.model_selection import train_test_split # 训练集的特征值 train_data,测试集的特征值 test_data; # 训练集的目标值 train_target,测试集的目标值 test_target; # 随机数种子22,指定测试集所占的比例为20% train_data, test_data, train_target, test_target = train_test_split(iris.data, iris.target, random_state=1,test_size=0.2) # 高斯朴素贝叶斯 clf = GaussianNB() clf = clf.fit(train_data, train_target) # 训练 y_pred=clf.predict(test_data) # 测试 print("高斯朴素贝叶斯,样本总数: %d 错误样本数 : %d" % (test_data.shape[0],(test_target != y_pred).sum())) # 多项分布朴素贝叶斯 clf = MultinomialNB() clf = clf.fit(train_data, train_target) # 训练 y_pred=clf.predict(test_data) # 测试 print("多项分布朴素贝叶斯,样本总数: %d 错误样本数 : %d" % (test_data.shape[0],(test_target != y_pred).sum())) # 补码朴素贝叶斯 clf = ComplementNB() clf = clf.fit(train_data, train_target) # 训练 y_pred=clf.predict(test_data) # 测试 print("补码朴素贝叶斯,样本总数: %d 错误样本数 : %d" % (test_data.shape[0],(test_target != y_pred).sum())) # 伯努利朴素贝叶斯 clf = BernoulliNB() clf = clf.fit(train_data, train_target) # 训练 y_pred=clf.predict(test_data) # 测试 print("伯努利朴素贝叶斯,样本总数: %d 错误样本数 : %d" % (test_data.shape[0],(test_target != y_pred).sum())) # 分类朴素贝叶斯 clf = CategoricalNB() clf = clf.fit(train_data, train_target) # 训练 y_pred=clf.predict(test_data) # 测试 print("分类朴素贝叶斯,样本总数: %d 错误样本数 : %d" % (test_data.shape[0],(test_target != y_pred).sum()))
实验结果:
-
利用不同分类器对不同类型的人造数据进行测试:
# 导入 numpy import numpy as np # 导入 matplot import matplotlib.pyplot as plt from matplotlib.colors import ListedColormap # 导入 scikit-learn from sklearn.model_selection import train_test_split # 训练集、验证集划分 from sklearn.preprocessing import StandardScaler # 标准化特征 from sklearn.preprocessing import MinMaxScaler # 特征映射到某一范围内 from sklearn.datasets import make_moons, make_circles, make_classification # 人工数据集生成器 from sklearn.naive_bayes import GaussianNB, MultinomialNB, BernoulliNB, ComplementNB, CategoricalNB # 贝叶斯分类器 # 创建模型集合 names = ["Multinomial", "Gaussian", "Bernoulli", "Complement", "Categorical"] # 模型的名字 classifiers = [MultinomialNB(), GaussianNB(), BernoulliNB(), ComplementNB(), CategoricalNB()] # 模型的对象 # 创建二分类数据集 N = 100 # 样本数 datasets = [make_classification(n_samples=N, n_features=2, n_redundant=0, n_informative=2,random_state=1, n_clusters_per_class=1), make_moons(n_samples=N,noise=0.3, random_state=0), make_circles(n_samples=N,noise=0.2, factor=0.5, random_state=1)] # 生成三类数据集 # 创建画布 figure = plt.figure(figsize=(9, 6)) # 创建宽度6英寸,高度9英寸的画布 # 选择贝叶斯模型 i = 1 # 0 - 多项,1 - 高斯,2 - 伯努利,3 - 补码,4 - 分类 # 处理并画图 for ds_index, ds in enumerate(datasets): # 数据集处理 X, y = ds # 取得数据集 X = StandardScaler().fit_transform(X) # 数据特征标准化 X = MinMaxScaler(feature_range=(0,1)).fit_transform(X) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.4, random_state=42) # 划分训练集与测试集 # 生成网格线 x1_min, x1_max = X[:, 0].min() - .5, X[:, 0].max() + .5 # 使轴1刚好能包含特征1的最小值和最大值 x2_min, x2_max = X[:, 1].min() - .5, X[:, 1].max() + .5 # 使轴2刚好能包含特征2的最小值和最大值 array1, array2 = np.meshgrid(np.arange(x1_min, x1_max, 0.2),np.arange(x2_min, x2_max, 0.2)) # 按0.2步长生成网格线 # 定义颜色映射 cm = plt.cm.RdBu # 红蓝渐变 cm_bright = ListedColormap(['#FF0000', '#0000FF']) # 选择左侧窗格,展现输入数据集 ax = plt.subplot(2, len(datasets), ds_index+1) # 设置标题 if ds_index == 0: ax.set_title("Input data: classification") elif ds_index == 1: ax.set_title("Input data: moons") elif ds_index == 2: ax.set_title("Input data: circles") # 绘制数据点 ax.scatter(X_train[:, 0], X_train[:, 1], c=y_train,cmap=cm_bright, edgecolors='k') ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test,cmap=cm_bright, alpha=0.6, edgecolors='k') ax.set_xlim(array1.min(), array1.max()) ax.set_ylim(array2.min(), array2.max()) ax.set_xticks(()) ax.set_yticks(()) # 选择右侧窗格,展现贝叶斯分类器结果 ax = plt.subplot(2, len(datasets), ds_index+4) # 贝叶斯分类 clf = classifiers[i].fit(X_train, y_train) # 训练分类器 score = clf.score(X_test, y_test) # 计算准确率 Z = clf.predict_proba(np.c_[array1.ravel(), array2.ravel()])[:, 1] # 预测,预测结果为 Z Z = Z.reshape(array1.shape) # 修改数据形状 # 绘制数据点 ax.contourf(array1, array2, Z, cmap=cm, alpha=.8) # 绘制等高线 ax.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap=cm_bright,edgecolors='k') ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test, cmap=cm_bright,edgecolors='k', alpha=0.6) ax.set_xlim(array1.min(), array1.max()) ax.set_ylim(array2.min(), array2.max()) ax.set_xticks(()) ax.set_yticks(()) ax.set_title(names[i]) ax.text(array1.max() - .3, array2.min() + .3, ('{:.1f}%'.format(score * 100)),size=15, horizontalalignment='right') plt.tight_layout() plt.show()
- 三类数据:
classification
,moons
,circles
; - 修改参数
i
选择不同贝叶斯模型; Categorical
贝叶斯在circles
数据上报错。
实验结果:
- 可见高斯贝叶斯不太擅长处理环型数据。
- 三类数据: