朴素贝叶斯(下)
2.2 概率类模型的评估指标
混淆矩阵和精确性可以帮助我们了解贝叶斯的分类结果。然而,我们选择贝叶斯进行分类,大多数时候都不是为了单单追求效果,而是希望看到预测的相关概率。这种概率给出预测的可信度,所以对于概率类模型,我们希望能够由其他的模型评估指标来帮助我们判断,模型在“概率预测”这项工作上,完成得如何。接下来,我们就来看看概率模型独有的评估指标。
2.2.1 布里尔分数Brier Score
概率预测的准确程度被称为“校准程度”,是衡量算法预测出的概率和真实结果的差异的一种方式。一种比较常用的指标叫做布里尔分数,它被计算为是概率预测相对于测试样本的均方误差,表示为:
其中N是样本数量, 为朴素贝叶斯预测出的概率, 是样本所对应的真实结果,只能取到0或者1,如果事件发生则为1,如果不发生则为0。这个指标衡量了我们的概率距离真实标签结果的差异,其实看起来非常像是均方误差。布里尔分数的范围是从0到1,分数越高则预测结果越差劲,校准程度越差,因此布里尔分数越接近0越好。由于它的本质也是在衡量一种损失,所以在sklearn当中,布里尔得分被命名为brier_score_loss。我们可以从模块metrics中导入这个分数来衡量我们的模型评估结果。
布里尔分数可以用于任何可以使用predict_proba接口调用概率的模型,我们来探索一下在我们的手写数字数据集上,逻辑回归,SVC和我们的高斯朴素贝叶斯的效果如何:
可以观察到,逻辑回归的布里尔分数有着压倒性优势,SVC的效果明显弱于贝叶斯和逻辑回归(如同我们之前在SVC的讲解中说明过的一样,SVC是强行利用sigmoid函数来压缩概率,因此SVC产出的概率结果并不那么可靠)。贝叶斯位于逻辑回归和SVC之间,效果也不错,但比起逻辑回归,还是不够精确和稳定。
2.2.2 对数似然函数Log Loss
另一种常用的概率损失衡量是对数损失(log_loss),又叫做对数似然,逻辑损失或者交叉熵损失,它是多元逻辑回归以及一些拓展算法,比如神经网络中使用的损失函数。它被定义为,对于一个给定的概率分类器,在预测概率为条件的情况下,真实概率发生的可能性的负对数(如何得到这个损失函数的证明过程和推导过程在逻辑回归的章节中有完整得呈现)。由于是损失,因此对数似然函数的取值越小,则证明概率估计越准确,模型越理想。值得注意得是,对数损失只能用于评估分类型模型。
第一个参数是真实标签,第二个参数是我们预测的概率。如果我们使用shift tab来查看log_loss的参数,会发现第二
个参数写着y_pred,这会让人误解为这是我们的预测标签。由于log_loss是专门用于产出概率的算法的,因此它假设
我们预测出的y就是以概率形式呈现,但在sklearn当中,我们的y_pred往往是已经根据概率归类后的类别{0,1,
2},真正的概率必须要以接口predict_proba来调用,千万避免混淆。
注意到,我们用log_loss得出的结论和我们使用布里尔分数得出的结论不一致:当使用布里尔分数作为评判标准的时
候,SVC的估计效果是最差的,逻辑回归和贝叶斯的结果相接近。而使用对数似然的时候,虽然依然是逻辑回归最强
大,但贝叶斯却没有SVC的效果好。为什么会有这样的不同呢?
因为逻辑回归和SVC都是以最优化为目的来求解模型,然后进行分类的算法。而朴素贝叶斯中,却没有最优化的过
程。对数似然函数直接指向模型最优化的方向,甚至就是逻辑回归的损失函数本身,因此在逻辑回归和SVC上表现得
更好。
那什么时候使用对数似然,什么时候使用布里尔分数?
在现实应用中,对数似然函数是概率类模型评估的黄金指标,往往是我们评估概率类模型的优先选择。但是它也有一些缺点,首先它没有界,不像布里尔分数有上限,可以作为模型效果的参考。其次,它的解释性不如布里尔分数,很难与非技术人员去交流对数似然存在的可靠性和必要性。第三,它在以最优化为目标的模型上明显表现更好。而且,它还有一些数学上的问题,比如不能接受为0或1的概率,否则的话对数似然就会取到极限值(考虑以 为底的自然对数在取到0或1的时候的情况)。所以因此通常来说,我们有以下使用规则:
回到我们的贝叶斯来看,如果贝叶斯的模型效果不如其他模型,而我们又不想更换模型,那怎么办呢?如果以精确度为指标来调整参数,贝叶斯估计是无法拯救了——不同于SVC和逻辑回归,贝叶斯的原理简单,根本没有什么可用的参数。但是产出概率的算法有自己的调节方式,就是调节概率的校准程度。校准程度越高,模型对概率的预测越准确,算法在做判断时就越有自信,模型就会更稳定。如果我们追求模型在概率预测上必须尽量贴近真实概率,那我们就可以使用可靠性曲线来调节概率的校准程度。
2.2.3 可靠性曲线Reliability Curve
可靠性曲线(reliability curve),又叫做概率校准曲线(probability calibration curve),可靠性图(reliabilitydiagrams),这是一条以预测概率为横坐标,真实标签为纵坐标的曲线。我们希望预测概率和真实值越接近越好,最好两者相等,因此一个模型/算法的概率校准曲线越靠近对角线越好。校准曲线因此也是我们的模型评估指标之一。和布里尔分数相似,概率校准曲线是对于标签的某一类来说的,因此一类标签就会有一条曲线,或者我们可以使用一个多类标签下的平均来表示一整个模型的概率校准曲线。但通常来说,曲线用于二分类的情况最多,大家如果感兴趣可以自行探索多分类的情况。
根据这个思路,我们来绘制一条曲线试试看。
-
导入需要的库和模块
-
创建数据集
-
建立模型,绘制图像
-
使用可靠性曲线的类在贝叶斯上绘制一条校准曲线
-
不同的n_bins取值下曲线如何改变?
-
建立更多模型
-
建立循环,绘制多个模型的概率校准曲线
2.2.4 预测概率的直方图
我们可以通过绘制直方图来查看模型的预测概率的分布。直方图是以样本的预测概率分箱后的结果为横坐标,每个箱中的样本数量为纵坐标的一个图像。注意,这里的分箱和我们在可靠性曲线中的分箱不同,这里的分箱是将预测概率均匀分为一个个的区间,与之前可靠性曲线中为了平滑的分箱完全是两码事。我们来绘制一下我们的直方图:
2.2.5 校准可靠性曲线
base_estimator
需要校准其输出决策功能的分类器,必须存在predict_proba或decision_function接口。 如果参数cv = prefit,分类器必须已经拟合数据完毕。
cv
整数,确定交叉验证的策略。可能输入是:
None,表示使用默认的3折交叉验证
任意整数,指定折数对于输入整数和None的情况下来说,如果时二分类,则自动使用类sklearn.model_selection.StratifiedKFold进行折数分割。如果y是连续型变量,则使用sklearn.model_selection.KFold进行分割。已经使用其他类建好的交叉验证模式或生成器cv
可迭代的,已经分割完毕的测试集和训练集索引数组输入"prefit",则假设已经在分类器上拟合完毕数据。在这种模式下,使用者必须手动确定用来拟合分类器的数据与即将倍校准的数据没有交集
method
进行概率校准的方法,可输入"sigmoid"或者"isotonic"输入’sigmoid’,使用基于Platt的Sigmoid模型来进行校准输入’isotonic’,使用等渗回归来进行校准当校准的样本量太少(比如,小于等于1000个测试样本)的时候,不建议使用等渗回归,因为它倾向于过拟合。样本量过少时请使用sigmoids,即Platt校准。我们依然来使用之前建立的数据集。
-
包装函数
-
设实例化模型,设定模型的名字
-
基于函数进行绘图
-
基于校准结果查看精确性的变化
-
试试看对于SVC,哪种校准更有效呢?
2.3 多项式朴素贝叶斯以及其变化
2.3.1 多项式朴素贝叶斯MultinomialNB
-
导入需要的模块和库
-
建立数据集
-
归一化,确保输入的矩阵不带有负数
-
建立一个多项式朴素贝叶斯分类器吧
-
那分类器的效果如何呢?
-
效果不太理想,思考一下多项式贝叶斯的性质,我们能够做点什么呢?
2.3.2 伯努利朴素贝叶斯BernoulliNB
多项式朴素贝叶斯可同时处理二项分布(抛硬币)和多项分布(掷骰子),其中二项分布又叫做伯努利分布,它是一种现实中常见,并且拥有很多优越数学性质的分布。因此,既然有着多项式朴素贝叶斯,我们自然也就又专门用来处理二项分布的朴素贝叶斯:伯努利朴素贝叶斯。伯努利贝叶斯类BernoulliN假设数据服从多元伯努利分布,并在此基础上应用朴素贝叶斯的训练和分类过程。多元伯努利分布简单来说,就是数据集中可以存在多个特征,但每个特征都是二分类的,可以以布尔变量表示,也可以表示为{0,1}或者{-1,1}等任意二分类组合。因此,这个类要求将样本转换为二分类特征向量,如果数据本身不是二分类的,那可以使用类中专门用来二值化的参数binarize来改变数据。
在sklearn中,伯努利朴素贝叶斯的实现也非常简单:
2.3.3 探索贝叶斯:贝叶斯的样本不均衡问题
接下来,我们来探讨一个分类算法永远都逃不过的核心问题:样本不平衡。贝叶斯由于分类效力不算太好,因此对样本不平衡极为敏感,我们接下来就来看一看样本不平衡如何影响了贝叶斯。
-
导入需要的模块,建立样本不平衡的数据集
-
查看所有贝叶斯在样本不平衡数据集上的表现
2.3.4 改进多项式朴素贝叶斯:补集朴素贝叶斯ComplementNB
补集朴素贝叶斯(complement naive Bayes,CNB)算法是标准多项式朴素贝叶斯算法的改进。CNB的发明小组创造出CNB的初衷是为了解决贝叶斯中的“朴素”假设带来的各种问题,他们希望能够创造出数学方法以逃避朴素贝叶斯中的朴素假设,让算法能够不去关心所有特征之间是否是条件独立的。以此为基础,他们创造出了能够解决样本不平衡问题,并且能够一定程度上忽略朴素假设的补集朴素贝叶斯。在实验中,CNB的参数估计已经被证明比普通多项式朴素贝叶斯更稳定,并且它特别适合于样本不平衡的数据集。有时候,CNB在文本分类任务上的表现有时能够优于多项式朴素贝叶斯,因此现在补集朴素贝叶斯也开始逐渐流行。
那来看看,补集朴素贝叶斯在不平衡样本上的表现吧,同时我们来计算一下每种贝叶斯的计算速度:
3 案例:贝叶斯分类器做文本分类
文本分类是现代机器学习应用中的一大模块,更是自然语言处理的基础之一。我们可以通过将文字数据处理成数字数据,然后使用贝叶斯来帮助我们判断一段话,或者一篇文章中的主题分类,感情倾向,甚至文章体裁。现在,绝大多数社交媒体数据的自动化采集,都是依靠首先将文本编码成数字,然后按分类结果采集需要的信息。虽然现在自然语言处理领域大部分由深度学习所控制,贝叶斯分类器依然是文本分类中的一颗明珠。现在,我们就来学习一下,贝叶斯分类器是怎样实现文本分类的。
3.1 文本编码技术简介
3.1.1 单词计数向量
在开始分类之前,我们必须先将文本编码成数字。一种常用的方法是单词计数向量。在这种技术中,一个样本可以包含一段话或一篇文章,这个样本中如果出现了10个单词,就会有10个特征(n=10),每个特征 代表一个单词,特征的取值 表示这个单词在这个样本中总共出现了几次,是一个离散的,代表次数的,正整数。 在sklearn当中,单词计数向量计数可以通过feature_extraction.text模块中的CountVectorizer类实现,来看一个简单的例子
3.1.2 TF-IDF
TF-IDF全称term frequency-inverse document frequency,词频逆文档频率,是通过单词在文档中出现的频率来衡量其权重,也就是说,IDF的大小与一个词的常见程度成反比,这个词越常见,编码后为它设置的权重会倾向于越小,以此来压制频繁出现的一些无意义的词。在sklearn当中,我们使用feature_extraction.text中类TfidfVectorizer来执行这种编码。
3.2 探索文本数据
在现实中,文本数据的处理是十分耗时耗力的,尤其是不规则的长文本的处理方式,绝对不是一两句话能够说明白的,因此在这里我们将使用的数据集是sklearn中自带的文本数据集fetch_20newsgroup。这个数据集是20个网络新闻组的语料库,其中包含约2万篇新闻,全部以英文显示,如果大家希望使用中文则处理过程会更加困难,会需要自己加载中文的语料库。在这个例子中,主要目的是为大家展示贝叶斯的用法和效果,因此我们就使用英文的语料库。
现在我们就可以直接通过参数来提取我们希望得到的数据集了。
3.3 使用TF-IDF将文本数据编码
3.4 在贝叶斯上分别建模,查看结果