04-0002 PCA算法

1.PCA算法简介

!!!插入代码的时候不要空行!!!

主成分分析(Principal Component Analysis,PCA), 是一种统计方法。通过正交变换将一组可能存在相关性的变量转换为一组线性不相关的变量,转换后的这组变量叫主成分。

在实际课题中,为了全面分析问题,往往提出很多与此有关的变量(或因素),因为每个变量都在不同程度上反映这个课题的某些信息。

主成分分析首先是由K.皮尔森(Karl Pearson)对非随机变量引入的,尔后H.霍特林将此方法推广到随机向量的情形。信息的大小通常用离差平方和或方差来衡量。

以上信息来自于百度,直接搬过来的,目的是为了有一个比较官方的解释,让整个文章看起来哄哄的~

2.PCA个人理解

!!!插入代码的时候不要空行!!!

此处是个人的理解:
关于PCA,是一种数据降维的方法,不如说是一种数据处理的方法,或者说是一种数据处理的思想,或者说是一个数据空间转换的函数···
一般而言,处理数据的时候,通常是一个m*n的矩阵,其中m是行,是样本的个数,n是列,是数据的维数,也就是说在当前的这个空间,每一个样本(每一条数据)中包含n个值,相当于一个n维坐标系,通过一个(x1,x2,···,xn)的坐标来表示一条数据。[这是对于原始数据的理解]
跳转一下,解释另一个东西。设想,在一个三维的直角坐标系里面有一个从原点出发的向量A。对于A,有着如下描述:A向量与x-y平面的夹角特别特别 特别 小。
上面这句话什么意思?就是说A向量在x轴y轴的分量都是不可以忽略的,在z轴的分量很小很小,以至于可以忽略不计。直观的说,我身为三维空间中的生物(我也不知道自己是几维的 ),直接观察到的A向量,与从z轴方向观察到的A向量很像,他们具有极高的拟合度。
显然,这个时候为了方便与我们处理数据,就会很自然的想到,舍弃z轴,因为那个轴上的分量很小,很不重要。此时,就能够用一个二维的坐标去表示一个三维的数据。
再想,倘若是A向量与z轴的夹角很小。也就是说在x轴y轴上的投影很小,那我们就可以直接把另外两轴丢弃,然后把z轴作为直角坐标轴,就可以近似的表示A向量。
也可以扩展一下想,倘若是更高维度的生物来看待这个问题,他们就能够从四维五维或者是更高维度,来观察这些数据。
所以,倘若我们的数据是可以在某未知维度的直角坐标系下表示出来,对于每一个样本,我们就知道它在哪个轴上的分量比较小,哪个轴可以去掉。
最终我们的目的:让这些数据可以表示出来,绘制在图中,一维的图,二维的图,或者是三维的图。我们可以画的也就这三个维度,物质决定意识,没有达到更高的维度很难画出高维度的图,所以对于这个有着n个维度的数据集,我们只能忽略掉很多维度(轴),取其中我们可以绘制的几个维度来对数据进行分析处理。
此时,舍弃维度的过程也就是降维。
预先假设了这种理想化的数据,称其为理想数据,理想数据是容易处理的,每个轴之间都互相不会干扰,相关性为零。
而原来的数据称其为原始数据,轴与轴之间存在一定的相关性,会互相影响,这种数据是不容易处理的。
协方差用来表示相关性,协方差矩阵是每两个维度之间相关性构成的矩阵。
所以说,理想数据就是最终的目的,而原始的数据是出发点,此时的数据处理转化成了寻找理想数据与原始数据之间关系的一个问题。也就是找到是的处理后的数据的协方差矩阵只有对角线上有值(只有自身跟自身有相关性),其他位置都是零(该维度与其他的维度之间没有相关性,不相关)。
好,这样的思路我很满意~

3.PCA算法推导

!!!插入代码的时候不要空行!!!

3.1逆向推导

设原始数据矩阵X的协方差矩阵为C,P是一组基按行组成的矩阵,设Y=PX,则Y为X对P做基变换后的数据。设Y的协方差矩阵为D,则可以进行如下推导:
在这里插入图片描述

观察式子右侧的结果,容易联想的是矩阵对角化的过程,但是也有一些不同,对角化的时候,C的左侧是转置,所以这个时候要试图寻找这个P与C对角化时 E T E^T ET之间有什么关系。

矩阵对角化时有如下的公式:
在这里插入图片描述

通过正交矩阵转置与逆相等的概念等,可以推知:
在这里插入图片描述

这样就能够解释,为什么我们要求原始数据协方差矩阵的特征值与特征向量,为什么我们可以直接拿着原始数据协方差矩阵的特征向量去乘原始数据,就能够得到理想数据。

3.2正向思维

关于这样讲解PCA的链接有好多,可以去度娘直接搜索。这种思路的目的是为了使得数据在某一个轴上的投影方差最大,问题的目的是求方差最大时数据之间的关系,手段是拉格朗日常数法(通过求偏导求解最值的一种方法)。
不求甚解,知道运算过程之后,总是会知道这样算是为什么,能够很容易的看懂推导的过程。上面你想思维也只是一部分,最后理想数据等于什么,两种方法得到的结果是一样的。

4.PCA算法流程

!!!插入代码的时候不要空行!!!

  1. 对原始数据A进行标准化(归一化)处理,得到矩阵B。[A、B都是m*n的]
  2. 求矩阵B的协方差矩阵Cov。[Cov是n*n的]
  3. 求协方差矩阵Cov的特征值e,特征向量v。[e是n1的,v是nn的]
  4. 将e排序,按照排好序的e,对v进行排序。[没有改变维度]
  5. 用归一化矩阵B乘上特征向量矩阵v,得到新的数据矩阵New。[New是mn的,mnnn得到m*n的矩阵]
  6. 取New的前n列进行绘制图表。[一般是取前两列或者三列,再多画不来]

说明一下即可,主要是算法过程中数据矩阵形式的变化,这也是代码实现时候的一大困扰。

5.PCA算法代码

!!!插入代码的时候不要空行!!!

clc;
oridata=load('iris.csv');
data=oridata(:,2:5);
coldata=oridata(:,1);
zdata=zscore(data);%数据标准化
data_cov=cov(zdata);%协方差矩阵
[data_v,data_d]=eig(data_cov);%特征值特征向量
d=diag(data_d);
eig1=sort(d,'descend');%按照特征值进行排序
v=fliplr(data_v);%根据排序后的特征值,得到一个特征向量的排序
new=zdata*v(:,1:2);%选取第一主成分以及第二主成分分别作为x,y轴
newdata=[coldata,new];
[a b]=size(newdata)
figure()
for i=1:a
    hold on
    if newdata(i,1)==0
        plot(newdata(i,2),newdata(i,3),'r.','markersize',15);
    elseif newdata(i,1)==1
        plot(newdata(i,2),newdata(i,3),'go','markersize',5);
    elseif newdata(i,1)==2
        plot(newdata(i,2),newdata(i,3),'b*','markersize',5);
    end
end

把下面数据保存成MATLAB可读取的文件,把上述代码保存为,m的文件,拿到MATLAB里直接运行即可。最后绘制的时候,一个点一个点的绘制,判断是第几类数据。

6.PCA算法数据

算法数据如下:
有150条,4个维度,第一列表示类别,不算在其中。
!!!插入代码的时候不要空行!!!

021433
1245631
1235131
021036
1205230
1195127
2134528
2164733
1174525
2144732
021631
1195025
011436
021332
2124026
1184927
2103323
021638
021630
1215628
041938
021430
2104127
2154529
021436
1195127
041534
1185531
2103324
021442
1155022
2143927
021429
2123927
1235732
2154230
1204928
1185825
2134423
2154925
2113025
1215431
1256136
2133629
1215530
011430
031738
2144430
041537
2175030
1225628
1155128
2154522
2144630
2113925
1235932
1235434
1255733
021335
2154532
1185130
1235332
2154530
1215733
021330
021632
1186032
1184930
021232
011130
2144431
021435
041634
2103526
1236130
2134226
011541
1184830
2134227
021531
041739
2164534
2103520
021332
2135429
021534
2105022
011531
021537
2124728
2134128
041339
1205132
2154931
2134025
031323
031538
2144828
021535
1256033
2154628
031434
2184832
2165127
1185530
051733
1226738
1216630
1135230
2134028
2113824
021434
1206438
061635
1206728
2124426
031430
021934
1145626
021240
1184828
2154530
021432
041544
1245634
1165830
1215930
1185629
2124230
1236926
2135629
021534
2103724
021531
1196128
031335
1186329
2154731
2134130
2134329
1225830
031435
2144729
1195327
021634
1205025
2134023
021734
1245128
021537

7.PCA算法应用

!!!插入代码的时候不要空行!!!

7.1PCA数据降维

上述即是数据降维PCA方法。

7.2PCA图像压缩

7.2.1理解

对于此处图像压缩的理解不是很深刻,自我感觉是将图片800800的,缩小成400400的进行保存,然后再将400400的图像打开,保存为800800的。这样做会变模糊,但是依旧能够从图片中获得主要信息。
图片压缩就是,利用PCA的方法提取出来图片中中的主成分(一个方块),然后再用这些方块去还原图片,主成分提取的多,图片丢失的信息就少,反正就会很模糊。

我记得有一个狗狗的表情包,有人把它分成好些小片,然后取一部分进行拼接,就可以得到好几个像素风格的相似表情包,当时只是觉得很搞笑,现在看来,那种思想就是PCA。

7.2.2代码

clc;
% 输入
In=imread('C:\Users\31386\Desktop\timg.jpg');
imR=In(:,:,1);
imG=In(:,:,2);
imB=In(:,:,3);
% In=rgb2gray(In);
% In=In(179:690,179:690);

% 输入参数
num_val = 10;                                 %取前num_val个特征值
size_block = 32;                                       %取size_block*size_block块

%调用函数
[outR]=PCA(imR,num_val,size_block);
[outG]=PCA(imG,num_val,size_block);
[outB]=PCA(imB,num_val,size_block);
Out(:,:,1)=outR(:,:);
Out(:,:,2)=outG(:,:);
Out(:,:,3)=outB(:,:);

% 显示图像
imshow(In),title('原图')
figure,imshow(Out),title('压缩后的图像')
% figure,imshow(Out2),title('差值的图像')
% figure,imshow(Out3),title('补充的图像')
imwrite(Out,'压缩后的图像.jpg')

%函数定义
% 将原图像矩阵分割成n*n的块,再转化为列矩阵,构成最终矩阵reIn
function [Out]=PCA(In,num_val,size_block)

In = im2double(In);
[row rol] = size(In);
m = 0;
Data = zeros(size_block*size_block,(row/size_block)*(rol/size_block));              % 数据矩阵
for i = 1:size_block:row
    for j = 1:size_block:rol
        m = m+1;
        block = In(i:i+size_block-1,j:j+size_block-1);
        Data(:,m) = block(:);
    end
end

% PCA处理
Data1 = Data - ones(size(Data,1),1)*mean(Data);             % 标准化处理
c = cov(Data1');                                     % 求矩阵协方差矩阵
[vec,val] = eig(c);                                      % 求特征值和特征向量

% 按特征值降序排列
val = diag(val);                                        % 从对角线拿出特征值
[val t] = sort(val,'descend');                             % 特征值降序排列
vec = vec(:,t);                                        % 特征向量也对应改变顺序

% 重构图像
vec_new = vec(:,1:num_val);                                    % 取前k个特征向量
    %计算所取特征值贡献率
    rata = val./sum(val);
    rata_sum = sum(rata(1:num_val));
    fprintf('选取%g个特征值的贡献率为:%g \n',num_val,rata_sum);   
    
y = vec_new'* Data;                                      % 映射 由公式:y=w'*x
Data2 = vec_new * y;                                    % 重构图像
Data2 = Data2 + ones(size(vec_new, 1), 1) * mean(Data);     % 加均值
m = 0;

for i = 1:size_block:row
    for j = 1:size_block:rol
        m = m + 1;
        block1 = reshape(Data2(:, m), size_block, size_block);        % 列向量块转化为方块
        Out(i:i+size_block-1, j:j+size_block-1) = block1; 
    end
end
end

插入代码的时候里面不能有空行,插入完可以在其中输入空行。我昨天已经写过一遍,5000多字,最后一位插入代码的时候,有空行,什么都没了。

改变自己菜的本质,从现在开始。虽然路途坎坷,但一直坚持便可。

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值