个人觉得
PCA数学原理
这篇文章是学习PCA最好的博文,通俗易懂~~~
本文简单的记录自己学习PCA时候遇到的一些小问题,好记性不如烂笔头~~~~
1. 数据格式问题
2. cov函数的问题
3. eig、eigs、princomp
开始之前,说明一些变量:
X:表示数据集,C:表示协方差矩阵。
**********************************************************************************************************************************
针对以下两种数据存储格式,分别介绍。
(1)
X: n*d
说明:n表示样本数目,d表示每个样本的特征纬度。
即:
每行代表一个样本
。
X = X -repmat(mean(X,1),size(X,1),1); % 去均值:依然是n*d
C = X'*X./(size(X,1)-1); % 协方差:变为d*d,因为计算的是每个纬度之间的关系,不是每个样本之间的相关性。这点务必理解。
这两行代码与下面一行代码是等价的:选其中一种就可以了
C = cov(X);
然后我们来看一下eig、eigs两者的问题:
eig:给出矩阵的所有特征向量和特征值
[F1, V] = eig(C); % V:每一列是一个特征值,F1:每一列就是与特征值对应的特征向量。
[V1, order] =sort(diag(V),'descend'); % 因为得到的特征值和特征向量没有排序,所以要排序。
F = F1(:,order);
eigs:通过迭代给出
指定数量(默认为6)的
矩阵的特征向量和特征值
[F, V] = eigs(double(C),k); % k:指定返回的特征值和特征向量的数量。
而且默认是降序排序,不需要重新sort了。
那么最终降维后的结果就是:
Y = X*F % 维度变化:n*d*d*k=n*k,实现了PCA降维
**********************************************************************************************************************************
(2)
X: d*n
说明:n表示样本数目,d表示每个样本的特征纬度。
即:
每列代表一个样本
。
X = X -repmat(mean(X,2),1,size(X,2)); % 去均值:依然是d*n
C = X*X'./(size(X,2)-1); % 协方差:变为d*d,注意与第一种情况的区别。
这两行代码与下面一行代码是等价的:
C = cov(X'); <span style="font-family: Arial, Helvetica, sans-serif;">% 注意与第一种情况的区别。</span>
然后我们来看一下eig、eigs两者的问题:
eig: 同上
[F1, V] = eig(C); % V:每一列是一个特征值,F1:每一列就是与特征值对应的特征向量。
[V1, order] =sort(diag(V),'descend'); % 因为得到的特征值和特征向量没有排序,所以要排序。
F = F1(:,order);
eigs:同上
[F, V] = eigs(double(C),k); % k:指定返回的特征值和特征向量的数量。
而且默认是降序排序,不需要重新sort了。
那么最终降维后的结果就是:
Y = F'*X % 维度变化:[d*k]'*d*n=k*n,实现了PCA降维
**********************************************************************************************************************************
matlab自带的PCA函数了:princomp
常用格式:
[coef, score, latent, T2] = princomp(X);
% 注意:X是n*d,即每一行是一个样本
% coef: 特征向量矩阵(投影/映射矩阵),和排序后的eig()/eigs()返回的 F 是一样的,按列存放。 维度:d*d
% score:得分矩阵,就是在新的基空间中的坐标,就是投影后的坐标。 维度:n*d
% latent:特征向量,默认已经降序排列。 维度:d*1
score = bsxfun(@minus,X,mean(X,1)*coef);
X = bsxfun(@plus,score*inv(coef),mean(X,1)).
**********************************************************************************************************************************
最关心的部分来啦,三者到底什么关系?
(前提:X:n*d)
(1)参数是X
[coef, score, latent, T2] = princomp(X);
(2)参数是C
C = cov(X);
[F1, V] = eig(C); % V:每一列是一个特征值,F1:每一列就是与特征值对应的特征向量。
[V1, order] =sort(diag(V),'descend'); % 因为得到的特征值和特征向量没有排序,所以要排序。
F = F1(:,order);
(3)
参数是C,k
C = cov(X);
[F, V] = eigs(double(C),k);
答案:代码片段1中的coef,代码片段2和3中的F,计算结果是一模一样的啦。
**********************************************************************************************************************************
princomp(zscore(x))是做什么的?
zscore()函数是标注化,目的:使得X均值为0,标准差为1。原理:去均值,再除以标准差。
即:zscore(x) = (x-mean(x))./std(x)
需要注意的是,std(x)有两种:(图片来自互联网,感谢原作者)
zscore(x)=zscore(x,0) std部分使用的是公式1;
zscore(x,1) std部分使用的是公式2.
********************************************************************************************************************************
MATLAB中cov(x)与cov(x,1)的区别?
matlab中计算协方差是首先加了n项,然后除以n或n-1,cov(x)呢是除以n-1,cov(x,1)呢是除以n。
cov(x)是无偏估计,
cov(x,1)是最大似然估计。
cov(x,1)=cov(x)*(n-1)/n;