朴素贝叶斯 - 概述(一)

194 阅读19分钟

根据菜菜的课程进行整理,方便记忆理解

代码位置如下:

概述

真正的概率分类器

在许多分类算法应用中,特征和标签之间的关系并非是决定性的。比如说,我们想预测一个人究竟是否会在泰坦尼克号海难中生存下来,那我们可以建一棵决策树来学习我们的训练集。在训练中,其中一个人的特征为:30岁,男,普通舱,他最后在泰坦尼克号海难中去世了。当我们测试的时候,我们发现有另一个人的特征也为:30岁,男,普通舱。基于在训练集中的学习,我们的决策树必然会给这个人打上标签:去世。然而这个人的真实情况一定是去世了吗?并非如此。

也许这个人是心脏病患者,得到了上救生艇的优先权。又有可能,这个人就是挤上了救生艇,活了下来。对分类算法来说,基于训练的经验,这个人“很有可能”是没有活下来,但算法永远也无法确定”这个人一定没有活下来“。即便这个人最后真的没有活下来,算法也无法确定基于训练数据给出的判断,是否真的解释了这个人没有存活下来的真实情况。这就是说,算法得出的结论,永远不是100%确定的,更多的是判断出了一种“样本的标签更可能是某类的可能性”,而非一种“确定”。我们通过某些规定,比如说,在决策树的叶子节点上占比较多的标签,就是叶子节点上所有样本的标签,来强行让算法为我们返回一个固定结果。但许多时候,我们也希望能够理解算法判断出的可能性本身。

每种算法使用不同的指标来衡量这种可能性。比如说,决策树使用的就是叶子节点上占比较多的标签所占的比例(接口predict_proba调用),逻辑回归使用的是sigmoid函数压缩后的似然(接口predict_proba调用),而SVM使用的是样本点到决策边界的距离(接口decision_function调用)。但这些指标的本质,其实都是一种“类概率”的表示,我们可以通过归一化或sigmoid函数将这些指标压缩到0~1之间,让他们表示我们的模型对预测的结果究竟有多大的把握(置信度)。但无论如何,我们都希望使用真正的概率来衡量可能性,因此就有了真正的概率算法:朴素贝叶斯

朴素贝叶斯是一种直接衡量标签和特征之间的概率关系的有监督学习算法,是一种专注分类的算法。朴素贝叶斯的算法根源就是基于概率论和数理统计的贝叶斯理论,因此它是根正苗红的概率模型。接下来,我们就来认识一下这个简单快速的概率算法。

朴素贝叶斯是如何工作的

朴素贝叶斯被认为是最简单的分类算法之一。首先,我们需要了解一些概率论的基本理论。假设有两个随机变量X和Y,他们分别可以取值为x和y。有这两个随机变量,我们可以定义两种概率:

联合概率与条件概率

联合概率:“X取值为x”和“Y取值为y”两个事件同时发生的概率,表示为P(X=x,Y=y)P(X = x,Y = y) 条件概率:在”X取值为x“的前提下,”Y取值为y“的概率,表示为P(Y=yX=x)P(Y = y|X = x)

举个例子,我们让X为"气温",Y为“七星瓢虫冬眠”,则X和Y可能的取值分为别x和y,其中x = {0,1},0表示没有下降到0度以下,1表示下降到了0度以下。y = {0,1},其中0表示否,1表示是。 两个事件分别发生的概率就为:

  • P(X=1)P(X = 1)= 50%,则是说明,气温下降到0度以下的可能性为50%,则 P(X=0)=1P(X=1)P(X = 0) = 1 - P(X = 1)= 50%。
  • P(Y=1)P(Y = 1)= 70%,则是说明,七星瓢虫会冬眠的可能性为70%,则 P(Y=0)=1P(Y=1)P(Y = 0) = 1 - P(Y = 1)= 30%。

则这两个事件的联合概率为P(X=1,Y=1)P(X = 1,Y = 1),这个概率代表了气温下降到0度以下和七星瓢虫去冬眠这两件事情同时独立发生的概率

而两个事件之间的条件概率为P(Y=1X=1)P(Y = 1|X = 1),这个概率代表了,当气温下降到0度以下这个条件被满足之后,七星瓢虫会去冬眠的概率。也就是说,气温下降到0度以下,一定程度上影响了七星瓢虫去冬眠这个事件。在概率论中,我们可以证明,两个事件的联合概率等于这两个事件任意条件概率 * 这个条件事件本身的概率

image.png

简单一些,则可以将上面的式子写成:

image.png

由上面的式子,我们可以得到贝叶斯理论等式:

image.png

而这个式子,就是我们一切贝叶斯算法的根源理论。我们可以把我们的特征X当成是我们的条件事件,而我们要求解的标签Y当成是我们被满足条件后会被影响的结果,而两者之间的概率关系就是P(YX)P(Y|X),这个概率在机器学习中,被我们称之为是标签的后验概率(posterior probability),即是说我们先知道了条件,再去求解结果。而标签Y在没有任何条件限制下取值为某个值的概率,被我们写作P(Y)P(Y),与后验概率相反,这是完全没有任何条件限制的,标签的先验概率(prior probability)。而我们的P(XY)P(X|Y)被称为“类的条件概率”,表示当Y的取值固定的时候,X为某个值的概率。那现在,有趣的事情就出现了

瓢虫冬眠:理解P(Y|X)

假设,我们依然让X是“气温”,这就是我们的特征,Y是“七星瓢虫冬眠”,就是我们的标签。现在,我们建模的目的是,预测七星瓢虫是否会冬眠。在许多教材和博客里,大家会非常自然地开始说,我们现在求的就是我们的P(YX)P(Y|X),然后根据贝叶斯理论等式开始做各种计算和分析。现在请问大家,我写作P(YX)P(Y|X)的这个概率,代表了什么呢?更具体一点,这个表达,可以代表多少种概率呢?

P(Y|X)代表了多少种情况的概率?

P(Y=1X=1)P(Y = 1|X = 1) 气温0度以下的条件下,七星瓢虫冬眠的概率 P(Y=1X=0)P(Y = 1|X = 0) 气温0度以上的条件下,七星瓢虫冬眠的概率 P(Y=0X=1)P(Y = 0|X = 1) 气温0度以下的条件下,七星瓢虫没有冬眠的概率 P(Y=0X=0)P(Y = 0|X = 0) 气温0度以上的条件下,七星瓢虫没有冬眠的概率

数学中的第一个步骤,也就是最重要的事情,就是定义清晰。其实在数学中,P(YX)P(Y|X) 还真的就代表了全部的可能性,而不是单一的概率本身。现在我们的Y有两种取值,而X也有两种取值,就让概率P(YX)P(Y|X)的定义变得很模糊,排列组合之后竟然有4种可能。在机器学习当中,一个特征X下取值可能远远不止两种,标签也可能是多分类的,还会有多个特征,排列组合以下,到底求解P(YX)P(Y|X)的是什么东西,是一个太让人感到混淆的点。同理, P(Y)P(Y)随着标签中分类的个数,可以有不同的取值。P(XY)P(X|Y)也是一样。在这里,我们来为大家澄清:

机器学习中的简写P(Y)P(Y),通常表示标签取到少数类的概率,少数类往往使用正样本表示,也就是P(Y=1)P(Y = 1),本质就是所有样本中标签为1的样本所占的比例。如果没有样本不均衡问题,则必须在求解的时候明确,你的Y的取值是什么。

P(YX)P(Y|X)是对于任意一个样本而言,如果这个样本的特征X的取值为1,则表示求解P(Y=1X=1)P(Y = 1|X = 1)。如果这个样本下的特征X取值为0,则表示求解P(Y=1X=0)P(Y = 1|X = 0)。也就是说, P(YX)P(Y|X)是具体到每一个样本上的,究竟求什么概率,由样本本身的特征的取值决定。每个样本的P(YX)P(Y|X)如果大于阈值0.5,则认为样本是少数类(正样本,1),如果这个样本的P(YX)P(Y|X)小于阈值0.5,则认为样本是多数类(负样本,0或者-1)。如果没有具体的样本,只是说明例子,则必须明确P(YX)P(Y|X)中X的取值。

在机器学习当中,对每一个样本,我们不可能只有一个特征\X,而是会存在着包含n个特征的取值的特征向量X\pmb{X}。因此机器学习中的后验概率,被写作P(YX)P(Y|\pmb{X}),其中X\pmb{X}中包含样本在n个特征Xi\pmb{X}_i上的分别的取值xix_i,由此可i以表示为X={X1=x1,X2=x2,,Xn=xn}\pmb{X} = \{X_1 = x_1,X_2 = x_2,……,X_n = x_n\}

因此,我们有:

image.png

虽然写法不同,但其实都包含折同样的含义。以此为基础,机器学习中,对每一个样本我们有:

image.png

对于分子而言,P(Y=1)P(Y = 1) 就是少数类占总样本量的比例, P(XY=1)P(\pmb{X}|Y = 1)则需要稍微复杂一点的过程来求解。假设我们只有两个特征X1X_1X2X_2 ,由联合概率公式,我们可以有如下证明

image.png

是一种若推广到n个XX上,则有:

image.png

这个式子证明,在Y=1的条件下,多个特征的取值被同时取到的概率,就等于Y=1的条件下,多个特征的取值被分别取到的概率相乘。其中,假设X1X_1X2X_2是有条件独立则可以让公式P(X1X2,Y=1)=P(X1Y=1)P(X_1|X_2,Y = 1) = P(X_1|Y = 1),这是在假设X2X_2是一个对X1X_1在某个条件下的取值完全无影响的变量。

比如说,温度(X1X_1)与观察到的瓢虫的数目(X2X_2)之间的关系。有人可能会说,温度在零下的时候,观察到的瓢虫数目往往很少。这种关系的存在可以通过一个中间因素:瓢虫会冬眠(Y)来解释。冬天瓢虫都冬眠了,自然观察不到很多瓢虫出来活动。也就是说,如果瓢虫冬眠的属性是固定的(Y=1Y = 1),那么观察到的温度和瓢虫出没数目之间关系就会消失,因此无论是否还存在着”观察到的瓢虫的数目“这样的因素,我们都可以判断这只瓢虫到底会不会冬眠。这种情况下,我们就说,温度与观察到的瓢虫的数目,是条件独立的。

假设特征之间是有条件独立的,可以解决众多问题,也简化了很多计算过程,这是朴素贝叶斯被称为朴素的理由。因此,贝叶斯在特征之间有较多相关性的数据集上表现不佳,而现实中的数据多多少少都会有一些相关性,所以贝叶斯的分类效力在分类算法中不算特别强大。同时,一些影响特征本身的相关性的降维算法,比如PCA和SVD,和贝叶斯连用效果也会不佳。但无论如何,有了这个式子,我们就可以求解出我们的分子了。

接下来,来看看我们贝叶斯理论等式的分母P(X)P(X)。我们可以使用全概率公式来求解P(X)P(X)

image.png

其中m代表标签的种类,也就是说,对于二分类而言我们有:

image.png

基于这个方程,我们可以来求解一个非常简单的例子下的后验概率

索引温度(X1X_1)瓢虫的年龄(X2X_2)瓢虫冬眠(Y)
0零下10天
1零下20天
2零上10天
3零下一个月
4零下20天
5零上两个月
6零下一个月
7零下两个月
8零上一个月
9零上10天
10零下20天

现在,我们希望预测零下的时候,年龄为20天的瓢虫,是否会冬眠。

image.png

对于分子我们可以求得:

image.png

对于分母我们可以求得:

image.png

所以我们的,温度为零下的时候, 生活了20天的瓢虫,会冬眠的概率为:

image.png

设定阈值为0.5,假设大于0.5的就被认为是会冬眠,小于0.5的就被认为是不会冬眠。根据我们的计算,我们认为一个在零下条件下,年龄为20天的瓢虫,是不会冬眠的。这就完成了一次预测。但是这样,有趣的地方又来了。刚才的预测过程是没有问题的。但我们总是好奇,这个过程如何对应sklearn当中的fit和predict呢?这个决策过程中,我们的训练集和我的测试集分别在哪里?以及,算法建模建模,我的模型在哪里呢?

贝叶斯的性质与最大后验估计

我们学习的分类算法总是有一个特点:这些算法先从训练集中学习,获取某种信息来建立模型,然后用模型去对测试集进行预测。比如逻辑回归,我们要先从训练集中获取让损失函数最小的参数,然后用参数建立模型,再对测试集进行预测。在比如支持向量机,我们要先从训练集中获取让边际最大的决策边界,然后用决策边界对测试集进行预测。相同的流程在决策树,随机森林中也出现,我们在fit的时候必然已经构造好了能够让对测试集进行判断的模型。而朴素贝叶斯,似乎没有这个过程。

我给了大家一张有标签的表,然后提出说,我要预测零下的时候,年龄为20天的瓢虫,会冬眠的概率,然后我们就顺理成章地算了出来。没有利用训练集求解某个模型的过程,也没有训练完毕了我们来做测试的过程,而是直接对有标签的数据提出要求,就可以得到预测结果了。

这说明,朴素贝叶斯是一个不建模的算法。以往我们学的不建模算法,比如KMeans,比如PCA,都是无监督学习,而朴素贝叶斯是第一个有监督的,不建模的分类算法。在我们刚才举的例子中,有标签的表格就是我们的训练集,而我提出的要求“零下的时候,年龄为20天的瓢虫”就是没有标签的测试集。

我们认为,训练集和测试集都来自于同一个不可获得的大样本下,并且这个大样本下的各种属性所表现出来的规律应当是一致的,因此训练集上计算出来的各种概率,可以直接放到测试集上来使用。即便不建模,也可以完成分类。

但实际中,贝叶斯的决策过程并没有我们给出的例子这么简单。

image.png

对于这个式子来说,从训练集中求解P(Y=1)P(Y = 1)很容易,但P(X)P(X)P(xiY=1)P(x_i|Y = 1)这一部分就没有这么容易了。在我们的例子中,我们通过全概率公式来求解分母,两个特征就求解了四项概率。随着特征数目的逐渐变多,分母上的计算两会成指数级增长,而分子中的P(xiY=1)P(x_i|Y = 1)也越来越难计算。

不过幸运的是,对于同一个样本来说,在二分类状况下我们可以有:

image.png

在分类的时候,我们选择P(Y=1X)P(Y = 1|X)P(Y=0X)P(Y = 0|X)中较大的一个所对应的Y的取值,作为这个样本的分类。在比较两个类别的时候,两个概率计算的分母是一致的,因此我们可以不用计算分母,只考虑分子的大小。当我们分别计算出分子的大小之后,就可以通过让两个分子相加,来获得分母的值,以此来避免计算一个样本上所有特征下的概率P(X)P(X)。这个过程,被我们称为最大后验估计(MAP)。在最大后验估计中,我们只需要求解分子,主要是求解一个样本下每个特征取值下的概率P(xiY=yi)P(x-i|Y = y_i),再求连乘便能够获得相应的概率。

在现实中,要求解分子也会有各种各样的问题。比如说,测试集中出现的某种概率组合,是训练集中从未出现的状况,这种时候就会出现某一个概率为0的情况,贝叶斯概率的分子就会为0。还有,现实中的大多数标签还是连续型变量,要处理连续型变量的概率,就不是单纯的数样本个数的占比的问题了。接下来我们就来看看,如何对连续型特征求解概率。

汉堡称重:连续型变量的概率估计

要处理连续型变量,我们可以有两种方法。第一种是把连续型变量分成j个箱,把连续型强行变成分类型变量。我们分箱后,将每个箱中的均值xi^\hat{x_i}当作一个特征XiX_i上的取值,然后我们计算箱j中Y=1Y = 1所占的比例,就是我们的P(xiY=1)P(x_i|Y = 1)。这个过程的主要问题是,箱子不能太大也不能太小,如果箱子太大,就失去了分箱的基本意义,如果箱子太小,可能每个箱子里就没有足够的样本来帮助我们计算P(xiY)P(x_i|Y),因此我们必须要适当地衡量我们的分箱效果。

但其实,我们没有必要这样做,因为我们可以直接通过概率论中来计算连续型变量的概率分布。在分类型变量的情况中,比如掷骰子的情况,我们有且仅有六种可能的结果1~6,并且每种结果的可能性为1/6。此时每个基本的随机事件发生的概率都是相等的,所以我们可以使用1N\frac{1}{N}来表示有N个基本随机事件可以发生的情况。

基于此,我们来思考一个简单的问题:汉堡王向客户承诺说他们的汉堡至少是100g一个,但如果我们去汉堡王买个汉堡,我们可以预料到它肯定不是标准的100g。设我们的汉堡重量为特征XiX_i,100g就是我们的取值xix_i,那我买到一个汉堡是100g的概率是P(100g|Y)多少呢?如果我们买n个汉堡,很可能n个汉堡都不一样重,只要我们称重足够精确,100.000001g和100.00002g就可以是不一致的。这种情况下我们可以买无限个汉堡,可能得到无限个重量,可以有无限个基本随机事件的发生,所以我们有:

image.png

即买到的汉堡刚好是100g概率为0。当一个特征下有无数种可能发生的事件时,这个特征的取值就是连续型的,比如我们现在的特征“汉堡的重量”。从上面的例子可以看得出,当特征为连续型时,随机取到某一个事件发生的概率就为0

那换一个问题,我们随机买一个汉堡,汉堡的重量在98g ~ 102g之间的概率是多少?即是说,我们现在求解概率P(98g<x<102g)P(98g < x < 102g)。那我们现在随机购买100个汉堡,称重后记下所有重量在98g ~ 102g之间的汉堡个数,假设为m,则就有:

image.png

如果我们基于100个汉堡绘制直方图,并规定每4g为一个区间,横坐标为汉堡的重量的分布,纵坐标为这个区间上汉堡的个数。

image.png

那我们可以看到最左边的图。m就是中间的浅绿色区间中所对应的纵坐标轴。则对于我们的概率,我们可以变换为:

image.png

如果我们购买一万个汉堡并绘制直方图(如中间的图),将直方图上的区间缩小,P(98g<x<102g)P(98g < x < 102g) 依然是所有浅绿色区域的面积除以所有柱状图的面积,可以看见现在我们的直方图变得更加平滑,看起来更像一座山了。那假设我们购买10W个,或者无限个汉堡,则我们可以想象我们的直方图最终会变成仿佛一条曲线,而我们的汉堡重量的概率P(98g<x<102g)P(98g < x < 102g)依然是所有浅绿色柱子的面积除以曲线下所有柱状图的总面积。当购买无数个汉堡的时候形成的则条曲线就叫做概率密度曲线(probability density function,PDF)。

一条曲线下的面积,就是这条曲线所代表的函数的积分。如果我们定义曲线可以用函数f(x)f(x)来表示的话,我们整条曲线下的面积就是:

image.png

其中dxdxf(x) f(x)在x上的微分。在某些特定的f(x)f(x)下,我们可以证明,上述积分等于1。总面积是1,这说明一个连续型特征XX的取值取到某个区间[xix_i,xi+x_i + \in ]之内的概率就为这个区间上概率密度曲线下的面积,所以我们的特征XiX_i在区间[xix_i, xi+x_i + \in]中取值的概率可以表示为:

image.png

非常幸运的是,在我们后验概率的计算过程中,我们可以将常量\in抵消掉,然后我们就可以利用f(xi)f(x_i)的某种变化来估计我们的P(xiY) P(x_i|Y)了。现在,我们就将求解连续型变量下某个点取值的概率问题,转化成了求解一个函数f(x)f(x)在点xix_i上的取值的问题。那接下来只要找到我们的f(x)f(x),我们就可以求解出不同的条件概率了。

在现实中,我们往往假设我们的f(x)f(x)是满足某种统计学中的分布的,最常见的就是高斯分布(正太分布,像我们购买汉堡的例子),常用的还有伯努利分布,多项式分布。这些分布对应着不同的贝叶斯算法,其实他们的本质都是相同的,只不过他们计算之中的f(x)f(x)不同。每个都对应着一系列需要我们去估计的参数,因此在贝叶斯中,我们的fit过程其实是在估计对应分布的参数,predict过程是在该参数下的分布中去进行概率预测。