1 朴素贝叶斯法的学习与分类
朴素贝叶斯的思想是:对于给定的一个训练数据集,首先基于特征条件独立假设学习输入输出的联合概率分布;然后基于此模型,对给定的输入 ,利用贝叶斯定理求出后验概率最大的输出 。由于朴素贝叶斯实际上是学习生成数据的机制,因此属于生成模型。
1.1 基本方法
设输入空间 ,输出空间为类标记集合 。输入为特征向量 , 输出为类标记 。 是定义在输入空间 上的随机向量, 是定义在输出空间 上的随机变量。 是 和 的联合概率分布。训练数据集由 独立同分布生成。
先验概率分布 条件概率分布由于朴素贝叶斯对条件概率分布做了条件相互独立的假设。因此有
后验概率计算根据贝叶斯定理进行 (具体过程可参考李航《统计学习方法(第二版)):
对于条件相互独立的假设太强,有半朴素贝叶斯之类的算法通过考虑部分关联性适度改进,例如为了计算量不至于太大,我们假定每个属性只依赖另外的一个属性。解决特征之间的相关性,我们还可以使用主成分分析(PCA)的方法,去除特征相关性,再进行朴素贝叶斯计算。
1.2 后验概率最大化的含义
朴素贝叶斯将实例分到后验概率最大的类中等价于经验风险最小化。选则 0-1 损失函数:其中 是分类决策函数。结合联合分布的条件期望,故经验风险函数为为使经验风险最小化,只需对 逐个极小化,由此可得:这样一来,根据期望风险最小化准则就得到了后验概率最大化准则:即朴素贝叶斯采用的原理
1.3 对看到的一个有关朴素贝叶斯假设分析的思考
看到一篇文章说朴素贝叶斯的假设有两条:
1、自变量之间独立
2、连续型自变量关于因变量服从正态分布
关键在于第二条,这说明了朴素贝叶斯对自变量不服从正态分布的数据集拟合效果极差。
但是在我学习以及推导过程中并未发现该要求,于是我就尝试复刻了他的分析过程,代码是用数学软件 matlab 编写的:
(1)生成数据集并绘制散点图
% 随机生成一个 [0,1] x [0,1] 上的 xy<0.25 类别为 1;yx>0.25 类别为 2 的数据集
x = (randi(101,500,1)-1)./100;
y = (randi(101,500,1)-1)./100;
z = zeros(500,1);
for i = 1:500
if y(i)>0.2*sin(20*x(i))+0.5
z(i) = 1;
else
z(i) = 2;
end
end
% 绘制原数据散点图 标签为1为红色 标签为2为蓝色
figure
hold on
ezplot('y=0.2*sin(20*x)+0.5');
title('{y}={0.2}{\times}{sin}({20}{\times}{x})+{0.5}')
set(gca,'Xlim',[-0.05,1.05]);
set(gca,'Ylim',[-0.05,1.05]);
gscatter(x,y,z,'br','o');
hold off
(2)采用朴素贝叶斯法分类
nbGau = fitcnb([x,y], z);
nbGauResubErr = resubLoss(nbGau);
cp = cvpartition(z,'KFold',10);
nbGauCV = crossval(nbGau, 'CVPartition',cp);
nbGauCVErr = kfoldLoss(nbGauCV)
figure
hold on
ezplot('y=0.2*sin(20*x)+0.5');
title('{y}={0.2}{\times}{sin}({20}{\times}{x})+{0.5}')
set(gca,'Xlim',[-0.05,1.05]);
set(gca,'Ylim',[-0.05,1.05]);
labels = predict(nbGau, [x y]);
gscatter(x,y,labels,'br','o');
可以看出和原文说的一样分类效果确实不是很好,但是在编写的过程中我已经发现问题了:这里的朴素贝叶斯是采用的先验为高斯分布(正态分布)的朴素贝叶斯,这样自然的对自变量不服从正态分布的数据集拟合效果会不好!
那既然发现问题了,有没有办法解决呢?那当然是有的!常见的朴素贝叶斯有以下几种:
1. GaussianNB
先验为高斯分布(正态分布)的朴素贝叶斯,适用于样本特征的分布大部分为连续性,其假定各个特征 在各个类别 下服从正态分布。
2. MutinomiaINB
先验为多项式分布的朴素贝叶斯。描述各类样本出现的次数或者出现次数的比例,常用于文本分类,特征表示的是次数。适用于样本分布为多元离散值。
3. BernuoliNB
先验为伯努利分布的朴素贝叶斯。假设特征为先验概率为二元伯努利分布。适用于样本特征是二元离散值或者稀疏的多元离散值。
不难发现,我们其实可以尝试使用先验为多项式分布的 MutinomiaINB 来进行学习,代码也只需设置 fitcnb
函数的先验分布参数:
nbGau = fitcnb([x,y], z,'DistributionNames','mvmn'); %修改先验分布参数为 'mvmn'
nbGauResubErr = resubLoss(nbGau);
cp = cvpartition(z,'KFold',10);
nbGauCV = crossval(nbGau, 'CVPartition',cp);
nbGauCVErr = kfoldLoss(nbGauCV)
figure
hold on
ezplot('y=0.2*sin(20*x)+0.5');
title('{y}={0.2}{\times}{sin}({20}{\times}{x})+{0.5}')
set(gca,'Xlim',[-0.05,1.05]);
set(gca,'Ylim',[-0.05,1.05]);
labels = predict(nbGau, [x y]);
gscatter(x,y,labels,'br','o');
可以看到学习结果比之前明显好了不少!这提醒我们,在使用朴素贝叶斯模型进行学习的时候要考虑特征向量符合什么样的先验分布,这样才能具有更好的分类效果。这一点不仅仅可以运用在朴素贝叶斯上,对于其他的模型也是同理,只有考虑好了特征的分布性质,才能采用更加适合的模型进行学习!
2 朴素贝叶斯的参数估计以及算法
在朴素贝叶斯法中,学习意味着估计先验概率 以及条件概率 。可以应用极大似然估计法或者贝叶斯估计法估计相应的概率。贝叶斯估计相较于极大似然估计的区别在于贝叶斯估计在随机变量各个取值的频数上赋予一个正数 ,当 时即为极大似然估计。
下面给出朴素贝叶斯的学习与分类算法。
算法 4.1 (朴素贝叶斯算法)
输入:训练数据集 ,其中 ,; 是第 个样本的第 个特征,,, 是第 个特征可能取的第 个值,,;实例 ;
输出:对实例 的分类;
(1) 计算先验概率以及条件概率
(2) 对于给定的实例 ,计算
(3) 确定实例 的类
其中,去掉标红的符号后的算法即为采用极大似然估计,保留标红符号后的算法则为采用贝叶斯估计。
贝叶斯估计是为了解决极大似然估计中要估计的概率值为 0 的情况。常取 ,这时称为拉普拉斯平滑。