首页 > 技术知识 > 正文

  由于图像向量有100X100 维,维度相对比较高,所以为了提高分分类的效率和分类器的准确度 在分类前需要进行维度约减,   维度约减分为两种思路:直接删除贡献率很小的维度:或者将高纬向量映射降维到需要的维度空间。

一 特征选择

  找出对分类贡献大也就是能直接反应样本性质的维度的维度删去对分类结果产生负面影响的维度。由于问题是区别是否带口罩 而不是精确识别人脸,所以有冗余的维度。但是维度样本是提取剪裁过的面部特征是因此维度大部分需要保留,即便是特征选择也不会有超过50%的维度可以直接删除掉而不影响后续的分类器分类的正确性,所以我们在该问题中并没有使用这种思路进行降维。

二 特征变换

  另一种思路实现降维是通过适当的线性变换将D维的特征转化为d维度新特征,目的是减少特证间的相关性,其实就是将样本中的信息量重组,将对分类有用的信息量尽量集中在相对较少的特征上。从而使得分类器在接下来的分类中会有更好的效果,新空间中的样本距离间隔更大。由于缺乏该问题的先验概率我们在特征选择时也没有考虑K-L等监督模式的特征变换。而是直接使用PCA主成分分析。

PCA非监督的特征变换:

  主成分分析顾名思义,变换后的特征包含了原始样本的关键和主要信息。空间线性映射公式: (新特征是原始特征的线性组合) 但是需要在线性变换时保证新特征的尺度统一则需要组合系数的模为1。矩阵形式为: 特征变换的目的就是求最优A矩阵 为了使每个新特征维度之间的相关性最小,我们用方差衡量: 由于有约束条件,并求最大化方差,这就构成了带约束的拉格朗日函数极值问题。 最优解a1满足a1是协防差矩阵最大特征值对应的特征向量,称作第一主成分。求a2时,由于a1和a2要不相关 即 拉格朗日极值问题又多了一个约束条件。然后可以求得a2是协方差矩阵的第二大特征向值对应的特征向量。称作第二主成分…以此类推。由于变换后的方差之和等于变换前原始方差之和。可以进一步检测k个成分占了多少原始样本的信息量。我们至少保证变换后在新空间中的样本能至少保证原始样本信息量的90%才能不影响后续分类器的分类。

三 PCA的算法实现

1、导入数据并获取相关信息

%PCA主成分分析 clear load(dataset_processed.mat); tic % 因为PCA分析时不需要标签信息,所以我们可以使用所有数据进行PCA,提高分析性能 datas=[Training,Testing];%将所有数据整合到一起 [dim,num]=size(datas);%获取数据大小,dim为维度,num为数据数量

2、去均值化和计算协方差矩阵

% 去均值化 fprintf(去均值化\n); datas_mean=mean(datas,2); datas=datas-datas_mean; % 计算协方差阵 fprintf(计算协方差阵\n); c=datas*datas/num;

3、计算特征值和特征向量,并对特征值进行排序,确定阈值

% 计算特征值和特征向量 fprintf(计算特征值和特征向量\n); [u,lamda]=eig(c); lamda=ones(1,dim)*lamda;%eig函数生成的特征值转换成行向量 %将特征值和特征向量合成一个矩阵,第一列为特征值,从第二列开始为特征向量,特征向量按行排列 lamda_u=[lamda;u]; lamda_u=lamda_u; % 对特征向量按lamda大小进行降序排列,并确定K,阈值选0.9 thr=0.9; lamda_u=sortrows(lamda_u,1,descend);%对特征向量按lamda大小进行降序排列 lamda=lamda_u(:,1);%分离特征值 u=lamda_u(:,2:end);%分离特征向量

4、确定k值

%确定K值 fprintf(确定K值\n); for i=1:dim res=sum(lamda(1:i))/sum(lamda); if res>thr k=i; break end end u=u(1:k,:);

5、保存含有k个主成分的特征向量

%保存K个含有主成分的特征向量 fprintf(正在保存\n); save(feature_PCA,u); toc

完整代码如下:

%PCA主成分分析 clear load(dataset_processed.mat); tic % 因为PCA分析时不需要标签信息,所以我们可以使用所有数据进行PCA,提高分析性能 datas=[Training,Testing];%将所有数据整合到一起 [dim,num]=size(datas);%获取数据大小,dim为维度,num为数据数量 % 去均值化 fprintf(去均值化\n); datas_mean=mean(datas,2); datas=datas-datas_mean; % 计算协方差阵 fprintf(计算协方差阵\n); c=datas*datas/num; % 计算特征值和特征向量 fprintf(计算特征值和特征向量\n); [u,lamda]=eig(c); lamda=ones(1,dim)*lamda;%eig函数生成的特征值转换成行向量 %将特征值和特征向量合成一个矩阵,第一列为特征值,从第二列开始为特征向量,特征向量按行排列 lamda_u=[lamda;u]; lamda_u=lamda_u; % 对特征向量按lamda大小进行降序排列,并确定K,阈值选0.9 thr=0.9; lamda_u=sortrows(lamda_u,1,descend);%对特征向量按lamda大小进行降序排列 lamda=lamda_u(:,1);%分离特征值 u=lamda_u(:,2:end);%分离特征向量 %确定K值 fprintf(确定K值\n); for i=1:dim res=sum(lamda(1:i))/sum(lamda); if res>thr k=i; break end end u=u(1:k,:); %保存K个含有主成分的特征向量 fprintf(正在保存\n); save(feature_PCA,u); toc
<

经过PCA主成分分析,最终保留90维的有用信息(含原始数据的90%),将含有90维主成分的特征向量保存到dataset_processed.mat)中

四、对所有数据进行降维

1、利用PCA分析得到的特征向量,对样本数据进行降维处理。

clear load(dataset_processed.mat); tic %训练数据去均值化 Training_mean=mean(Training,2); Training=Training-Training_mean; % 测试数据去均值化 Testing_mean=mean(Testing,2); Testing=Testing-Testing_mean; % 提取数据主成分 Training_b=u*Training; Testing_b=u*Testing;

2、绘制降维处理后的图像以及原始图像(正负类各一张)

figure(1) show=reshape(Training+Training_mean,100,100,[]); imageShow(uint8(show(:,:,1))); figure(2) show=reshape(u*Training_b+Training_mean,100,100,[]); imageShow(uint8(show(:,:,1))); figure(3) show=reshape(Training+Training_mean,100,100,[]); imageShow(uint8(show(:,:,10000))); figure(4) show=reshape(u*Training_b+Training_mean,100,100,[]); imageShow(uint8(show(:,:,10000)));

3、输出结果: 第一张图和第四张图分别是戴口罩和不戴口罩降维处理后的图像,可以看出,经过PCA分析以后,还是可以通过肉眼进行分类,但是PCA大大减少了图片的维度,这会大大地减少分类器所用的时间,提高分类效率。 4、保存数据

save(dataset_processed.mat,Training_b,Testing_b,-append);

完整代码如下:

clear load(dataset_processed.mat); tic %训练数据去均值化 Training_mean=mean(Training,2); Training=Training-Training_mean; % 测试数据去均值化 Testing_mean=mean(Testing,2); Testing=Testing-Testing_mean; % 提取数据主成分 Training_b=u*Training; Testing_b=u*Testing; figure(1) show=reshape(Training+Training_mean,100,100,[]); imageShow(uint8(show(:,:,1))); figure(2) show=reshape(u*Training_b+Training_mean,100,100,[]); imageShow(uint8(show(:,:,1))); figure(3) show=reshape(Training+Training_mean,100,100,[]); imageShow(uint8(show(:,:,10000))); figure(4) show=reshape(u*Training_b+Training_mean,100,100,[]); imageShow(uint8(show(:,:,10000))); save(dataset_processed.mat,Training_b,Testing_b,-append);
<

猜你喜欢