假设有一个矩阵B
,其大小为500*1000 double
(此处,500
代表观察数量,1000
代表要素数量)。
sigma
是B
的协方差矩阵,D
是对角矩阵,其对角元素是sigma
的特征值。假设A
是协方差矩阵sigma
的特征向量。
我有以下问题:
我需要选择对应于具有最大幅度的特征值的第一个k = 800
特征向量来对所选特征进行排名。最终矩阵名为Aq
。我怎么能在MATLAB中做到这一点?
这些选定的特征向量是什么意思?
一旦我计算Aq
,最终矩阵1000*800 double
的大小似乎为Aq
。 500
的时间点/观测信息已消失。对于最终矩阵Aq
,矩阵1000
中的值Aq
现在代表什么?此外,矩阵800
中的值Aq
现在代表什么?
答案 0 :(得分:18)
我假设您确定了eig
函数中的特征向量。我将来推荐的是使用eigs
功能。这不仅可以为您计算特征值和特征向量,还可以为您计算k
最大特征值及其关联的特征向量。这可以节省计算开销,因为您不需要计算矩阵的所有特征值和相关的特征向量,因为您只需要一个子集。您只需将数据的协方差矩阵提供给eigs
,它就会为您返回k
个最大特征值和特征向量。
现在,回到你的问题,你所描述的最终是Principal Component Analysis。这背后的机制是计算数据的协方差矩阵,并找到计算结果的特征值和特征向量。众所周知,由于计算大矩阵的特征值和特征向量的数值不稳定性,不推荐这样做。现在最常规的做法是通过Singular Value Decomposition。具体地说,V
矩阵的列给出了协方差矩阵或主成分的特征向量,相关的特征值是矩阵S
对角线中产生的奇异值的平方根。
请参阅有关Cross的信息性帖子验证为何首选:
https://stats.stackexchange.com/questions/79043/why-pca-of-data-by-means-of-svd-of-the-data
我还会引入另一个链接,讨论为什么在主成分分析中使用奇异值分解的原理:
现在让我们一次回答你的问题。
MATLAB以未排序的方式生成特征值和特征向量的相应排序。如果您希望在k
(在您的示例中为800)的输出中选择最大的eig
特征值和关联的特征向量,则您需要排序特征值按降序排列,然后重新排列从eig
生成的特征向量矩阵的列,然后选择第一个k
值。
我还应该注意,使用eigs
并不能保证排序顺序,所以当它归结为它时你也必须明确排序。
在MATLAB中,做我们上面描述的内容会是这样的:
sigma = cov(B);
[A,D] = eig(sigma);
vals = diag(D);
[~,ind] = sort(abs(vals), 'descend');
Asort = A(:,ind);
注意你对特征值的绝对值进行排序是一件好事,因为缩放的特征值本身也是特征值。这些量表还包括否定词。这意味着如果我们有一个特征值为-10000的组件,这是一个非常好的迹象,表明该组件对您的数据有一些重要意义,如果我们纯粹根据数字本身进行排序,则会将其置于较低等级附近。
第一行代码找到了B
的协方差矩阵,即使您已将其表示已存储在sigma
中,但让我们重现这一点。接下来,我们找到协方差矩阵的特征值和相关的特征向量。请注意,特征向量矩阵A
的每一列代表一个特征向量。具体而言,A
的i th 列/特征向量对应于D
中所见的i th 特征值。
然而,特征值在对角矩阵中,因此我们使用diag
命令提取对角线,对它们进行排序并找出它们的顺序,然后重新排列A
以遵守此顺序。我使用sort
的第二个输出,因为它告诉您未排序结果中每个值在排序结果中出现的位置。这是重新排列特征向量矩阵A
的列所需的排序。您必须选择'descend'
作为标志,以便最大特征值和相关的特征向量首先出现,就像我们之前谈到的那样。
然后,您可以通过以下方式获取第一个k
最大的向量和值
k = 800;
Aq = Asort(:,1:k);
众所周知,协方差矩阵的特征向量等于主成分。具体而言,第一个主成分(即最大特征向量和相关的最大特征值)为您提供数据中最大可变性的方向。之后的每个主要组成部分都为您提供了降低性质的可变性。值得注意的是,每个主要成分彼此正交。
这是来自维基百科的二维数据的一个很好的例子:
我从维基百科关于主成分分析的文章中提取了上述图像,我将其链接到上面。这是根据以(1,3)
为中心的双变量高斯分布分布的样本的散点图,其标准偏差在大致(0.878, 0.478)
方向上为3,在正交方向上为1。标准偏差为3的组件是第一主成分,而正交的组件是第二主成分。显示的向量是由相应特征值的平方根缩放的协方差矩阵的特征向量,并且移位使得它们的尾部处于平均值。
现在让我们回到你的问题。我们查看k
最大特征值的原因是执行dimensionality reduction的一种方式。从本质上讲,您将执行数据压缩,您可以在其中获取更高维度的数据并将其投影到较低维度的空间。投影中包含的主要组件越多,它就越像原始数据。它实际上开始逐渐减少,但前几个主要组件允许您忠实地重建您的数据。
我在过去偶然发现的这篇伟大的Quora帖子中发现了一个表演PCA(或SVD)和数据重建的伟大视觉示例。
您可以使用此矩阵将较高维度的数据重新投影到较低维度的空间。行数为1000仍然存在,这意味着数据集中最初有1000个要素。 800就是数据的维数降低了。将该矩阵视为从特征(1000)的原始维度到其减少维度(800)的转换。
然后,您可以将此矩阵与重建原始数据结合使用。具体而言,这将为您提供原始数据与最小错误量相似的近似值。在这种情况下,您不需要使用所有主要组件(即只有k
最大向量),您可以使用比以前更少的信息创建数据的近似值。
如何重建数据非常简单。让我们先谈谈完整数据的正向和反向操作。正向操作是获取原始数据并重新投影,但不是低维度,我们将使用所有组件。您首先需要获取原始数据,但减去平均值:
Bm = bsxfun(@minus, B, mean(B,1));
Bm
将生成一个矩阵,其中每个样本的每个特征均被减去。 bsxfun
允许以不等维度减去两个矩阵,前提是您可以广播维度,以便它们都可以匹配。具体而言,在这种情况下会发生的是,将计算B
的每个列/特征的平均值,并生成与B
一样大的临时复制矩阵。当您使用此复制矩阵减去原始数据时,效果将使用各自的特征平均值减去每个数据点,从而分散数据,使每个要素的平均值为0.
完成此操作后,项目操作就是:
Bproject = Bm*Asort;
上述操作非常简单。您正在做的是将每个样本的特征表示为主要组件的线性组合。例如,给定分散数据的第一个样本或第一行,投影域中的第一个样本特征是与整个样本有关的行向量和作为列的第一个主成分的点积。第一个样本在投影域中的第二个特征是整个样本和第二个分量的加权和。您将对所有样本和所有主要组件重复此操作。实际上,您正在重新投影数据,使其与主成分相关 - 主成分是将数据从一个表示转换为另一个表示的正交基矢量。
可以在此处找到我刚才谈到的更好的描述。看看Amro的回答:
Matlab Principal Component Analysis (eigenvalues order)
现在要倒退,你只需要进行逆运算,但是具有特征向量矩阵的特殊属性是,如果你转置它,你得到逆。要恢复原始数据,请撤消上述操作并将问题添加回问题:
out = bsxfun(@plus, Bproject*Asort.', mean(B, 1));
您希望恢复原始数据,因此您针对之前的操作解决了Bm
问题。但是,Asort
的倒数只是这里的转置。执行此操作后发生的事情是您正在获取原始数据,但数据仍然是分散的。要恢复原始数据,必须将每个要素的均值添加回数据矩阵以获得最终结果。这就是我们在此处使用其他bsxfun
调用的原因,以便您可以针对每个示例的功能值执行此操作。
您应该能够使用以上两行代码在原始域和投影域中来回切换。现在降维(或原始数据的近似)发挥作用的是相反的操作。首先需要做的是将数据投影到主要组件的基础上(即正向操作),但现在回到我们尝试使用减少数量的主成分重建数据的原始域,只需使用Asort
替换上述代码中的Aq
,并减少您在Bproject
中使用的功能数量。具体地:
out = bsxfun(@plus, Bproject(:,1:k)*Aq.', mean(B, 1));
执行Bproject(:,1:k)
选择数据投影域中的k
个功能,对应k
个最大特征向量。有趣的是,如果您只想要关于降低维度的数据表示,您可以使用Bproject(:,1:k)
,这就足够了。但是,如果您想继续前进并计算原始数据的近似值,我们需要计算相反的步骤。上面的代码就像我们之前使用的数据的完整维度一样,但我们使用Aq
以及选择k
中的Bproject
功能。这将为您提供由矩阵中k
个最大特征向量/特征值表示的原始数据。
如果你想看一个很棒的例子,我会模仿我链接到你但使用另一张图片的Quora帖子。考虑使用灰度图像进行此操作,其中每行是"样本"每列都是一个功能。我们将摄影师图像作为图像处理工具箱的一部分:
im = imread('camerman.tif');
imshow(im); %// Using the image processing toolbox
我们得到这张图片:
这是一个256 x 256的图像,这意味着我们有256个数据点,每个点有256个特征。我要做的是将图像转换为double
,以便在计算协方差矩阵时获得精确度。现在我要做的是重复上面的代码,但每次从3,11,15,25,45,65和125逐步增加k
。因此,对于每个{{1}我们正在引入更多主成分,我们应该慢慢开始重建数据。
这里有一些可运行的代码说明了我的观点:
k
如您所见,大部分代码与我们所看到的相同。不同的是,我循环遍历%%%%%%%// Pre-processing stage
clear all;
close all;
%// Read in image - make sure we cast to double
B = double(imread('cameraman.tif'));
%// Calculate covariance matrix
sigma = cov(B);
%// Find eigenvalues and eigenvectors of the covariance matrix
[A,D] = eig(sigma);
vals = diag(D);
%// Sort their eigenvalues
[~,ind] = sort(abs(vals), 'descend');
%// Rearrange eigenvectors
Asort = A(:,ind);
%// Find mean subtracted data
Bm = bsxfun(@minus, B, mean(B,1));
%// Reproject data onto principal components
Bproject = Bm*Asort;
%%%%%%%// Begin reconstruction logic
figure;
counter = 1;
for k = [3 11 15 25 45 65 125 155]
%// Extract out highest k eigenvectors
Aq = Asort(:,1:k);
%// Project back onto original domain
out = bsxfun(@plus, Bproject(:,1:k)*Aq.', mean(B, 1));
%// Place projection onto right slot and show the image
subplot(4, 2, counter);
counter = counter + 1;
imshow(out,[]);
title(['k = ' num2str(k)]);
end
的所有值,使用k
最高特征向量投射回原始空间(即计算近似值),然后显示图像。
我们得到了这个好身材:
正如您所看到的,从k
开始并没有给我们带来任何好处......我们可以看到一些一般结构,但添加更多内容并不会有什么坏处。正如我们所做的那样。开始增加组件数量,我们开始更清楚地了解原始数据的样子。在k=3
,我们实际上可以看到摄像师看起来完美的样子,我们不需要26件及以后的部件来看看发生了什么。这就是我在谈论数据压缩时所说的,你不需要处理所有主要组件,以便清楚地了解正在进行的工作。
我想通过向您介绍Chris Taylor关于主成分分析主题的精彩阐述来结束本文,其中包含代码,图表和一个很好的解释!这是我开始使用PCA的地方,但Quora帖子巩固了我的知识。
Matlab - PCA analysis and reconstruction of multi dimensional data