学习内容概括
朴素贝叶斯算法(Naive Bayes, NB) 是应用最为广泛的分类算法之一,朴素贝叶斯算法一般应用在文本分类,垃圾邮件的分类,信用评估,钓鱼网站检测等。学习内容包括掌握朴素贝叶斯公式,结合两个实例了解朴素贝叶斯的参数估计以及掌握朴素贝叶斯估计。具体学习内容
Part 1. 莺尾花数据集–贝叶斯分类
Step1: 库函数导入
import warnings
warnings.filterwarnings('ignore')
import numpy as np
# 加载莺尾花数据集
from sklearn import datasets
# 导入高斯朴素贝叶斯分类器
from sklearn.naive_bayes import GaussianNB
from sklearn.model_selection import train_test_split
Step2: 数据导入&分析
X, y = datasets.load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
我们需要计算两个概率分别是:条件概率: P ( X ( i ) = x ( i ) ∣ Y = c k ) P(X^{(i)}=x^{(i)}|Y=c_k) P(X(i)=x(i)∣Y=ck)和类目 c k c_k ck的先验概率: P ( Y = c k ) P(Y=c_k) P(Y=ck)。
通过分析发现训练数据是数值类型的数据,这里假设每个特征服从高斯分布,因此我们选择高斯朴素贝叶斯来进行分类计算。
Step3: 模型训练
# 使用高斯朴素贝叶斯进行计算
clf = GaussianNB(var_smoothing=1e-8)
clf.fit(X_train, y_train)
Step4: 模型预测
# 评估
y_pred = clf.predict(X_test)
acc = np.sum(y_test == y_pred) / X_test.shape[0]
print("Test Acc : %.3f" % acc)
# 预测
y_proba = clf.predict_proba(X_test[:1])
print(clf.predict(X_test[:1]))
print("预计的概率值:", y_proba)
OUT:
Test Acc : 0.967
[2]
预计的概率值: [[1.63542393e-232 2.18880483e-006 9.99997811e-001]]
计算预测准确性这里,计算预测值与验证集的标签相等的数量比上所有验证集包含的记录数,得到的就是准确率acc
Step5: 原理简析。
高斯朴素贝叶斯假设每个特征都服从高斯分布,我们把一个随机变量X服从数学期望为μ,方差为
σ
2
σ^2
σ2的数据分布称为高斯分布。对于每个特征我们一般使用平均值来估计μ和使用所有特征的方差估计
σ
2
σ^2
σ2
P
(
X
(
i
)
=
x
(
i
)
∣
Y
=
c
k
)
=
1
2
π
σ
y
2
exp
(
−
(
x
(
i
)
−
μ
c
k
)
2
2
σ
c
k
2
)
P(X^{(i)}=x^{(i)}|Y=c_k) = \frac{1}{\sqrt{2\pi\sigma^2_y}} \exp\left(-\frac{(x^{(i)} - \mu_{c_k})^2}{2\sigma^2_{c_k}}\right)
P(X(i)=x(i)∣Y=ck)=2πσy21exp(−2σck2(x(i)−μck)2)
从上述例子中的预测结果中,我们可以看到类别2对应的后验概率值最大,所以我们认为类目2是最优的结果。
Part 2. 模拟离散数据集–贝叶斯分类
Step1: 库函数导入
import random
import numpy as np
# 使用基于类目特征的朴素贝叶斯
from sklearn.naive_bayes import CategoricalNB
from sklearn.model_selection import train_test_split
Step2: 数据导入&分析
这里是随机生成了600*100的数组
# 模拟数据
rng = np.random.RandomState(1)
# 随机生成600个100维的数据,每一维的特征都是[0, 4]之前的整数
X = rng.randint(5, size=(600, 100))
y = np.array([1, 2, 3, 4, 5, 6] * 100)
data = np.c_[X, y]
# X和y进行整体打散
random.shuffle(data)
X = data[:,:-1]
y = data[:, -1]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
Step3: 模型训练&可视化
clf = CategoricalNB(alpha=1)
clf.fit(X_train,y_train)
acc = clf.score(X_test,y_test)
acc
# 随机数据测试,分析预测结果,贝叶斯会选择概率最大的预测结果
# 比如这里的预测结果是6,6对应的概率最大,由于我们是随机数据
# 读者运行的时候,可能会出现不一样的结果。
x = rng.randint(5, size=(1, 100))
print(clf.predict_proba(x))
print(clf.predict(x))
Step4: 原理简析
alpha=1这个参数表示什么?
我们知道贝叶斯法一定要计算两个概率:条件概率:
P
(
X
(
i
)
=
x
(
i
)
∣
Y
=
c
k
)
P(X^{(i)}=x^{(i)}|Y=c_k)
P(X(i)=x(i)∣Y=ck)和类目
c
k
c_k
ck的先验概率:
P
(
Y
=
c
k
)
P(Y=c_k)
P(Y=ck)。
对于离散特征:
P
(
X
(
j
)
=
x
(
j
)
∣
Y
=
c
k
)
=
∑
i
=
1
N
I
(
x
i
j
=
a
j
l
,
y
i
=
c
k
)
+
α
∑
i
=
1
N
I
(
y
i
=
c
k
)
+
S
j
α
P(X^{(j)}=x^{(j)}|Y=c_k)=\frac{\sum_{i=1}^{N}I(x_i^j=a_{jl},y_i=c_k)+\alpha}{\sum_{i=1}^{N}I(y_i=c_k)+S_j\alpha}
P(X(j)=x(j)∣Y=ck)=∑i=1NI(yi=ck)+Sjα∑i=1NI(xij=ajl,yi=ck)+α
我们可以看出就是对每一个变量的多加了一个频数alpha。当alphaλ=0时,就是极大似然估计。通常取值alpha=1,这就是拉普拉斯平滑(Laplace smoothing),这有叫做贝叶斯估计,主要是因为如果使用极大似然估计,如果某个特征值在训练数据中没有出现,这时候会出现概率为0的情况,导致整个估计都为0,因为引入贝叶斯估计。
其中:
S
j
S_j
Sj:表示第j个特征的个数。
x
i
j
x_i^j
xij:表示第i个样本的第j维元素。
y
i
y_i
yi:第i个样本的label。
问题记录
sklearn版本问题,因为sklearn版本导致了出现以下两个问题:
1.低版本sklearn的高斯朴素贝叶斯GaussianNB没有var_smoothing参数
2.低版本sklearn没有CategoricalNB函数
显然解决办法就是升级sklearn包。但是在排查的时候首先想到的不是版本问题。为何呢?因为阿里云的DSW平台很强大,它的类notebook工具支持pip命令,当我使用如下命令,系统返回的是0.23.2,是很新的版本。于是我认为此版本sklearn的GaussianNB函数本身就没有var_smoothing参数。于是我去除此参数,可正常使用,但是实际上,是我弄错了,后面我再使用sklearn.__version__命令得出sklearn的版本是0.19.1,那我到底在使用的是哪一个版本呢。通过查sklearn官方文档,明确了0.23.2版本包含CategoricalNB函数,0.19.1版本没有此函数,显然我需要升级sklearn包
请教了训练营的老师,推荐我用如下命令进行更新,这是在DSW平台的类jupyter notebook上敲命令直接安装
!pip install --ignore-installed scikit-learn
ps:在为确定是sklearn版本问题之前,我也排查了另一个方向,确认自己的python文件是否与导入的包重名了,导致引入路径错乱。
import os
path = '/'
s = 'CategoricalNB'
for filewalks in os.walk(path):
for files in filewalks[2]:
#print('true files',files)
if s in files:
print(s,' is in',os.path.join(filewalks[0],files))
没有找到重名文件。
学习总结
优点: 朴素贝叶斯算法主要基于经典的贝叶斯公式进行推倒,具有很好的数学原理。而且在数据量很小的时候表现良好,数据量很大的时候也可以进行增量计算。由于朴素贝叶斯使用先验概率估计后验概率具有很好的模型的可解释性。
缺点: 朴素贝叶斯模型与其他分类方法相比具有最小的理论误差率。但是实际上并非总是如此,这是因为朴素贝叶斯模型给定输出类别的情况下,假设属性之间相互独立,这个假设在实际应用中往往是不成立的,在属性个数比较多或者属性之间相关性较大时,分类效果不好。而在属性相关性较小时,朴素贝叶斯性能最为良好。对于这一点,有半朴素贝叶斯之类的算法通过考虑部分关联性适度改进,例如为了计算量不至于太大,我们假定每个属性只依赖另外的一个。解决特征之间的相关性,我们还可以使用数据降维(PCA)的方法,去除特征相关性,再进行朴素贝叶斯计算。