贝叶斯是一种直接衡量标签和特征之间概率关系的有监督机器学习,是一种专注分类的算法,算法根源就是基于概率论和数理统计的贝叶斯理论。
朴素贝叶斯要根据不同的算法选择不同的数据结构,比如多项式朴素贝叶斯要训练前对连续性数据做分箱处理变成多分类的数据结构,伯努利分布要将数据变成二分类的数据结构。
1.联合概率和条件概率
这里的P(Y)通常是指正例样本的概 率。
因为
所以得到贝叶斯理论公式
分子求解方式:
我们假设特征之间相互独立,可以解决众多问题,也简化了很多计算过程,这也是朴素贝叶斯被称为”朴素“的原因。所以朴素贝叶斯在特征有较多关联性的数据集上往往表现不是很好。朴素贝叶斯假设特征之间相互独立,所以PCA等降维方式不能和朴素贝叶斯理论一起用。
分母求解方式
分母可以用全概率公式进行求解
公式可以理解为
举例:
计算过程
拉普拉斯平滑
如果词频列表里面有很多次数是0,有可能计算结果为0,拉普拉斯平滑解决分类后某一概率为0的问题。
加上拉普拉斯平滑系数后结果就不会变成0
sklearn中的朴素贝叶斯
高斯朴素贝叶斯
高斯朴素贝叶斯假设P(xi, Y)是服从高斯分布(也就是正态分布)来估计每个特征下类别的概率,对于每个特征下的取值服从正态分布概率密度函数
高斯朴素贝叶斯对月亮型,环形,线性数据集都可以做分类,但是这里前提是特征之间相互独立,所以现实中并不准确。所以现实中我们要做线性的数据还是先用逻辑回归,非线性的还是先用SVM。
高斯朴素贝叶斯不接受稀疏矩阵。
我们在使用高斯朴素贝叶斯这个类的时候,我们通常不填写参数(全部保留默认值)。太过简单也意味着没有参数可调很容易达到极限。
from sklearn.naive_bayes import GaussianNB # 高斯朴素贝叶斯
data = load_digits() # 这是个多分类数据,类别是10个,可以通过np.unique(Y_train)去重查看
X = data.data
y = data.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25)
gnb = GaussianNB()
gnb.fit(X_train, y_train)
print(gnb.score(X_test, y_test)) # 返回预测的精确性accuracy
# 分数0.8688888888888889
y_predict = gnb.predict(X_test) # 返回所有样本预测的类别
prob = gnb.predict_proba(X_test) # 查看预测概率结果,每一个样本在每个类别下的概率加和等于1
通过混淆矩阵的方式查看预测结果准确率
from sklearn.metrics import confusion_matrix # 混淆矩阵
CM(y_test, y_predict)
如果判断正确,大部分数据应该都集中在对角线上。从混淆矩阵上看,我们的预测结果是不错的
[[39 0 0 0 1 1 0 0 0 0]
[ 0 38 1 0 1 0 0 1 4 3]
[ 0 3 21 0 0 0 1 0 15 0]
[ 0 1 0 31 0 2 0 4 7 0]
[ 1 0 2 0 41 0 0 1 0 0]
[ 0 0 0 0 0 40 0 0 1 0]
[ 0 0 0 0 0 0 46 0 0 0]
[ 0 0 0 0 0 0 0 47 0 0]
[ 0 3 0 0 0 3 0 1 44 0]
[ 0 0 0 0 1 1 0 4 7 33]]
多项式朴素贝叶斯
假设数据服从简单的多项式分布,多项式分布擅长分类型变量
sklearn中多项式朴素贝叶斯不接受负值的输入,经常被用于文本分类。
α是人为的加上噪音防止出现0的情况,所以α越大,准确率也越低
一般朴素贝叶斯所有参数都保持默认。(不加参数)
from sklearn.datasets import fetch_20newsgroups
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
def naviebayes():
"""
朴素贝叶斯进行文本分类
:return:
"""
news = fetch_20newsgroups(subset='all')
X = news.data
y = news.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25)
# 对数据进行特征抽取
news_tf = TfidfVectorizer()
# 以训练集当中的词的列表进行每篇文章重要性统计
X_train = news_tf.fit_transform(X_train)
print(news_tf.get_feature_names())
X_test = news_tf.transform(X_test)
# 进行朴素贝叶斯算法的预测
mlt = MultinomialNB(alpha=1.0)
mlt.fit(X_train, y_train)
y_predict = mlt.predict(X_test)
print("预测得到的分类是:", y_predict)
print("准确率是:",mlt.score(X_test, y_test))
# 查看预测的概率结果
prob = gnb.predict_proba(X_test)
return None
if __name__ == "__main__":
naviebayes()
新闻数据集一共二十个类别。
伯努利朴素贝叶斯
伯努利朴素贝叶斯主要处理二项分布的贝叶斯。这个类要求将样本转换成二分类的特征向量。
binarize:将特征转成二值化,设置一个阈值,如果是None,那么伯努利分布类就默认已经二分类完毕了,但是我们一般不用这个参数,这个参数会将所有特征全部二值化。
from sklearn.naive_bayes import BernoulliNB
补集朴素贝叶斯ComplementNB:样本不均衡问题
分类特征中,一些特征样本数量特别大,一些特征样本数量相对又特别少
改进朴素贝叶斯:补集朴素贝叶斯ComplementNB(也比较擅长分类数据)
分类的时候更倾向于使用补集朴素贝叶斯。效果比伯努利朴素贝叶斯好。
from sklearn.naive_bayes import ComplementNB
用补集朴素贝叶斯召回率相较于多项式分布贝叶斯会大大提升
朴素贝叶斯优缺点
优点:
(1)朴素贝叶斯模型发源于古典数学理论,有稳定的分类效率。
(2)对缺失值不太敏感,算法比较简单,常用于文本分类。
(3)分类准确度高,速度快。
缺点:
由于使用了样本属性独立性假设,所以样本属性有关联性时效果不好。
对于文本分类,神经网络要比朴素贝叶斯效果更好。
布里尔分数
是衡量预测概率与真实结果差异的一种方式,Pi为朴素贝叶斯预测出的概率, Oi是样本所对应的真实结果。只能取到0到1,分数越高,预测结果越差劲,越接近于0越好
sklearn中,pos_label与prob中的索引要一致,就可以查看这个类别下的布里尔分数
from sklearn.metrics import brier_score_loss
brier_score_loss(y_test, y_predict[:8], pos_label=8)
新版的sklearn只能计算2分类了。所以标签只能是二分类的数值。
布里尔分数每次只能用于一个类别。
对数似然函数
from sklearn.metrics import log_loss
# 第二个参数返回的是概率,返回的数值越小越好
print(log_loss(y_test, prob))
混淆矩阵
from sklearn.metrics import confusion_matrix as CM
CM(Ytest,Y_pred)