python朴素贝叶斯分类的手写数字识别_朴素贝叶斯分类器与手写数字分类的实现...

一、朴素贝叶斯分类器的原理

朴素贝叶斯方法是基于贝叶斯公式与特征条件独立的假设的分类方法。对于给定的训练数据集,基于特征条件独立的假设学习输入输出的联合概率分布,这样就学到了一个生成模型,然后基于该模型,对于给定的测试样本

,利用贝叶斯公式求出输出概率(或概率密度)最大的输出

。具体如下

在训练集中,给定了

个带标签的数据,记为

,其中

维(特征)向量(即实例点),通常在

中取值。

是该实例点的标签,表示该点的类别,在一个离散集合

取值(假设共有

个类别)。在贝叶斯分类器中有一个假设:存在一个联合分布

,训练数据

都是由该分布独立产生的。接下来,我们希望通过训练集中的数据估计该联合分布。由于

,所以我们先对

的分布进行估计。由于

只有有限个取值,在训练数据集中,我们通过频率来估计概率(这也是概率的最大似然估计):

这样就估计出了随机变量

的分布律。

接下来估计每一类中

的分布,即故意

。由于

维空间取值,我们对

的分布分两种简单情况进行讨论:

1、在每一类中,

的每一维

仅有有限个取值,即

是离散型随机变量,此时,用训练数据集估计

的分布为:

第二项较难估计,我们对它加上条件独立性假设,即在同一个类别中,

各个分量的取值是独立的。这样的假设极大的简化了问题的处理难度,但是会损失精度。这就是朴素贝叶斯的”朴素“名字的来源。这样上面公式就化为了

这样,该部分的计算就较为简单了,我们使用频率代替概率:

考虑到随机变量

的某一维的某些取值在训练样本中并没有出现,这样得到该维取到该值的所有样本的概率为0,可想而知这样的估计是不准确的。它在训练样本中未出现,说明它出现的概率很小,为了防止出现概率为0的情况,我们对上述估计引入拉普拉斯平滑,即引入一个正数

,将上述估计式改为

容易验证上式也是一种概率分布。当

时就是最大似然估计。

这样就估计出了联合分布

,对于测试集中的数据

,我们可以通过上面求到的分布函数,计算它属于每一类的概率大小,即

,将该样本预测为条件概率最大的类

。由于对于同一样本,上面各式的分母是相同的,所以只需要比较

的大小,并将该样本预测为条件概率最大的类

2、每一类中的

都是连续分布

我们要估计每一类的分布。根据数据估计分布是较为复杂的。简单起见,我们假设每一类的分布都是多元正态分布,那么对每一类的分布估计问题变成了多元正态分布的参数估计问题,对于每一类,我们分别用样本均值代替总体均值,用样本协方差代替总体协方差,这样就可以得到每一类的密度函数:

。对于

的估计与情况1同理。这样就得到了类概率密度的一个估计。对于测试集中的数据

,我们计算如下概率密度:

并将该样本归类到使得上式达到最大的类。同理,由于对于同个样本,上面

个式子的分母是一样的,所以我们只需要计算比较

的大小,并把该数据预测为使得上式达到最大的类。

二、用主成分分析+贝叶斯分类器实现手写数字的分类

这里仍然使用

数据集,该数据集的格式与导入,我们在上文《KNN与手写数字分类的实现》中有详细的介绍

由于这里的每个数据的维数(每张照片,对应训练数据矩阵与测试数据矩阵的每一列)为

,维度较高,直接应用贝叶斯分类器,计算复杂度较高,而这些数据具有较强的相关性,我们先使用主成分分析进行降维:将维度降低到

,然后假设每一类的分布都是多元正态分布,估计类条件概率密度。最后对测试集中的数据进行分类,源代码如下所示(这个代码写得非常垃圾,大量地方可以用矩阵之类的东西代替,可以降低时间复杂度的,但是今天不想动脑,就大量重复了代码片段,使用了大量循环,导致运行非常慢。以后有时间再来更新hhh)

读取训练数据与测试数据的代码

function images = loadMNISTImages(filename)

fp = fopen(filename, 'rb');

assert(fp ~= -1, ['Could not open ', filename, '']);

magic = fread(fp, 1, 'int32', 0, 'ieee-be');

assert(magic == 2051, ['Bad magic number in ', filename, '']);

numImages = fread(fp, 1, 'int32', 0, 'ieee-be');

numRows = fread(fp, 1, 'int32', 0, 'ieee-be');

numCols = fread(fp, 1, 'int32', 0, 'ieee-be');

images = fread(fp, inf, 'unsigned char');

images = reshape(images, numCols, numRows, numImages);

images = permute(images,[2 1 3]);

fclose(fp);

% Reshape to #pixels x #examples

images = reshape(images, size(images, 1) * size(images, 2), size(images, 3));

% Convert to double and rescale to [0,1]

images = double(images) / 255;

end

读取标签的代码

function labels = loadMNISTLabels(filename)

fp = fopen(filename, 'rb');

assert(fp ~= -1, ['Could not open ', filename, '']);

magic = fread(fp, 1, 'int32', 0, 'ieee-be');

assert(magic == 2049, ['Bad magic number in ', filename, '']);

numLabels = fread(fp, 1, 'int32', 0, 'ieee-be');

labels = fread(fp, inf, 'unsigned char');

assert(size(labels,1) == numLabels, 'Mismatch in label count');

fclose(fp);

end

分类源代码

%调用自定义函数,读取60000张照片,记为Train

Train=loadMNISTImages('train-images.idx3-ubyte');

%读入标签,对60000张训练图片进行分类

Trainlabels=loadMNISTLabels('train-labels.idx1-ubyte');

%调用自定义函数,读取10000张测试照片,记为Test

Test=loadMNISTImages('t10k-images.idx3-ubyte');

%读取测试集标签

Testlabel=loadMNISTLabels('t10k-labels.idx1-ubyte');

[m1,n1]=size(Train);

[m2,n2]=size(Test);

%求总体协方差矩阵COV(X,Y)=E{(X-u)(X-u)'}

u=sum(Train,2)/n1;

COV=(Train-u*ones(1,n1))*(Train-u*ones(1,n1))'/n1;

%求前50个主成分方向

[eigenvactor,eigenvalue]=eig(COV);

P=(eigenvactor(:,m1-50+1:m1))';

%投影得到每个照片的50个新特征

newfeature=P*Train;

%将用PCA降维之后的数据按标签分成10类,分别为M{1,1}...M{1,10}

count=ones(1,10);

for i=1:60000

M{1,Trainlabels(i,1)+1}(:,count(1,Trainlabels(i,1)+1))=newfeature(:,i);

count(1,Trainlabels(i,1)+1)=count(1,Trainlabels(i,1)+1)+1;

end

%计算每一类的均值向量,第i类的均值向量为矩阵u1的第i列

for i=1:10

[SIZE(i,1),SIZE(i,2)]=size(M{1,i});

u1(:,i)=(sum(M{1,i},2))/SIZE(i,2);

end

%计算每一类的协方差矩阵,记为COV1{1,1}...COV1{1,10}

for i=1:10

COV1{1,i}=(M{1,i}-u1(:,i)*ones(1,SIZE(i,2)))*(M{1,i}-u1(:,i)*ones(1,SIZE(i,2)))'/SIZE(i,2);

end

%计算每一类的先验概率,pr的第i行为第i类的先验概率

pr=SIZE(:,2)/n1;

%测试集投影到50个主方向

X=P*Test;

%计算测试集中的每个照片属于每类的后验概率,并通过最大值进行分类

for i=1:10000;

for j=1:10;

Q(1,j)=-(X(:,i)-u1(:,j))'*(inv(COV1{1,j}))*(X(:,i)-u1(:,j))-2*log(det(COV1{1,j}))+2*log(pr(j,1));

end

[m,n]=max(Q);

k=n-1;

NL(i,1)=k;

end

T=NL(:,1);

%统计分类正确的照片个数,记为s

s=0;

for i=1:10000

if Testlabel(i,1)==T(i,1)

s=s+1;

end

end

%输出准确率

accuracy=s/n2;

分类的准确率为

,在我电脑上运行时间10s左右。

在上文中,我用主成分分析将

维数据降低成

维。下面讨论降低到的维数

与准确率的关系,可得到如图所示的数据

与准确率的关系拟合拟合出来,如下所示

从实验结果可以看出,随着

的增加,准确率先增大,后几乎维持不变。一开始准确率随

增大而增大,因为m过小,不足以包含原数据大部分信息,所以随着 m 增大,原数据保留的有用信息越来越多, 所以准确率越来越高。当

充分大时,原数据有用的信息几乎被全部利用了,再增大

,反而会引入大量冗余信息,准确率不会继续提高。由于在实验原理中做了大量理想化假设,而且该实验方法是基于数理统计的,即使不压缩准确率也不可能达到百分之百,这是由统计学习方法本身所决定的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值