首页 > 编程知识 正文

pca算法对数据的要求,图像pca降维原理

时间:2023-05-05 23:00:02 阅读:167245 作者:2478

1 .前言PCA :principal component analysis (主成分分析) )。

最近我发现我的关于PCA算法总结和个人理解的博客访问量很高。 正好现在再次学习了PCA (主成分分析)维数削减算法。 所以,我打算全面整理总结现在掌握的东西,对有需要的人有帮助。 看看自己写的关于PCA的博客,还很混乱,希望能在这里好好整理一下。 本文的所有总结都参考了Andrew Ng的PCA教程,感兴趣的人请自己学习。

上一个PCA博客: http://blog.csdn.net/Watkins ONG/article/details/8234766。 在这个博客里,我最开始在研究生院知道关于PCA的事情,但是不是很系统,然后出现了很多我总结的网络资料。

@copyright by watkins.song ^_^

2. PCA的应用范围PCA的应用范围如下。

1 .数据压缩

1.1数据压缩和数据降维首先可以减少内存和硬盘的使用,在内存不足或计算时出现内存溢出等问题时,需要使用PCA获取低维样本特征。

1.2其次,降低数据维度可以加快机器学习的速度。

2 .数据可视化

在许多情况下,可能需要看到样本的特征,但根本无法观察到高维特征。 此时,可以通过将样本的特征降维为2D或3D,即将样本的特征降维为两个特征或三个特征来采用可视化观察数据。

3. PCA原理介绍

3.1基础入门此处仅列出了需要使用PCA时需要了解的最基本的PCA原理。 了解这些原理后,正常使用就没有问题。 要深入理解PCA,需要学习矩阵分析的知识。 有关更详细的PCA算法,请参阅维基百科。

首先,定义样本和特征,假设有m个样本。 每个样品有n个特征,可以表示为:

从简单到难,我们先来看看从2D降维到1D的比较直观的显示:

在上图中,假设只有两个特征x1、x2。 然后,维度需要降低到1D。 此时,可以观察到中途用x表示的采样点大致分布在一条直线上。 然后,可以将[x1,x2]平面表示的所有坐标映射到图像绘制的直线z上。 上图中的黑色铅笔线表示了采样点映射的过程。

映射到直线z后,如果只用直线z表示样本的空间分布,则可以用一个坐标表示每个样本。 这样,可以将2D特征降维为1D特征。 类似地,当三维特征降低到二维时,具有三维特征的样本从一个三维空间映射到二维空间。

上图将所有二维特征的采样点映射到一维直线上。 这样,从上图可以看出在映射过程中存在映射误差。

在上图中,示例映射后的坐标位置用圆圈表示。 这些位置可以称为近似位置,今后将使用这些位置计算映射误差。

在降维映射过程中,由于存在映射误差,在降维高维特征之前,需要对所有特征进行归一化。 该正规化操作包括(1) feature scaling ) )使其具有与所有特征相似的尺度,否则一个特征特别小,一个特征特别影响降维效果) ) )。

在上图中,降维过程是找到一个或多个向量u1、u2、un,以便这些向量构成新的向量空间(需要学习矩阵分析哦),然后将需要降维的样本提取到这个新样本中

在2D - 1D降维过程中,找到一个向量u1就可以理解为。 u1表示一个方向,将所有采样映射到此方向。 其实,一个向量也可以表示一个样本空间。

对于3D - 2D降维过程,可以理解为找到两个向量u1,u2,(u1,u2 )定义新的特征空间,并将原始样本空间的样本映射到新的样本空间。

对于n-D - k-D降维过程,可以理解为找到k个向量u1,u2,uk,这k个向量定义了新的向量空间,并进行样本映射。

3.2既然cost function样本映射中存在误差,就需要计算每次映射的误差大小。 使用以下公式计算误差的大小:

x

-approx表示的是样本映射以后的新的坐标, 这个坐标如果位置如果用当前的样本空间表示, 维度和 样本X是一致的。

要特别注意, PCA降维和linear regression是不一样的, 虽然看上去很一致, 但是linear regression的cost function的计算是样本上线垂直的到拟合线的距离, 而PCA的cost function 是样本点到拟合线的垂直距离。 差别如下图所示:




3.3 PCA 计算过程
(A) Feature Normalization

首先要对训练样本的特征进行归一化, 特别强调的是, 归一化操作只能在训练样本中进行, 不能才CV集合或者测试集合中进行, 也就是说归一化操作计算的各个参数只能由训练样本得到, 然后测试样本根据这里得到的参数进行归一化, 而不能直接和训练样本放在一起进行归一化。  另外, 在训练PCA降维矩阵的过程中,也不能使用CV样本或者测试样本, 这样做是不对的。 有很多人在使用PCA训练降维矩阵的时候, 直接使用所有的样本进行训练, 这样实际上相当于作弊的, 这样的话降维矩阵是在包含训练样本和测试样本以及CV样本的情况下训练得到的, 在进行测试的时候, 测试样本会存在很大的优越性, 因为它已经知道了要降维到的空间情况。
特征归一化直接给出代码参考: function [X_norm, mu, sigma] = featureNormalize(X)%FEATURENORMALIZE Normalizes the features in X % FEATURENORMALIZE(X) returns a normalized version of X where% the mean value of each feature is 0 and the standard deviation% is 1. This is often a good preprocessing step to do when% working with learning algorithms.mu = mean(X);X_norm = bsxfun(@minus, X, mu);sigma = std(X_norm);X_norm = bsxfun(@rdivide, X_norm, sigma);% ============================================================end
注意: 这里的X是一个m * n 的矩阵, 有 m 个样本, 每个样本包含 n 个特征, 每一行表示一个样本。 X_norm是最终得到的特征, 首先计算了所有训练样本每个特征的均值, 然后减去均值, 然后除以标准差。 
(B) 计算降维矩阵
B1. 首先计算样本特征的协方差矩阵
如下图所示, 如果是每个样本单独计算, 则采用图中横线上的公式, 如果是采用矩阵化的计算, 则采用横线下的公式。


B2. 计算协方差矩阵的特征值和特征向量

采用奇异值分解的算法计算协方差矩阵的特征值和特征向量,  奇异值分解是个比较复杂的概念, 如果有兴趣可以查看wikipedia, 也可以直接使用matlab或者octave已经提供的奇异值分解的接口。


在上图中, U 则是计算得到的协方差矩阵的所有特征向量, 每一列都是一个特征向量, 并且特征向量是根据特征大小由大到小进行排序的, U 的维度为 n * n 。 U 也被称为降维矩阵。 利用U 可以将样本进行降维。 默认的U 是包含协方差矩阵的所有特征向量, 如果想要将样本降维到 k 维, 那么就可以选取 U 的前 k 列, Uk 则可以用来对样本降维到  k 维。 这样 Uk 的维度为 n * k
(C) 降维计算 获得降维矩阵后, 即可通过降维矩阵将样本映射到低维空间上。 降维公式如下图所示:

如果是对于矩阵X 进行降维, X 是 m * n的, 那么降维后就变为 m * k 的维度, 每一行表示一个样本的特征。
3.4  贡献率 (降维的k的值的选择) 在  http://blog.csdn.net/watkinsong/article/details/8234766 这篇文章中, 很多人问了关于贡献率的问题, 这就是相当于选择k的值的大小。 也就是选择降维矩阵 U 中的特征向量的个数。  k 越大, 也就是使用的U 中的特征向量越多, 那么导致的降维误差越小, 也就是更多的保留的原来的特征的特性。 反之亦然。
从信息论的角度来看, 如果选择的 k 越大, 也就是系统的熵越大, 那么就可以认为保留的原来样本特征的不确定性也就越大, 就更加接近真实的样本数据。 如果 k 比较小, 那么系统的熵较小, 保留的原来的样本特征的不确定性就越少, 导致降维后的数据不够真实。 (完全是我个人的观点)
关于 k 的选择, 可以参考如下公式: 

上面这个公式 要求 <= 0.01, 也就是说保留了系统的99%的不确定性。  需要计算的就是, 找到一个最小的 k 使得上面的公式成立, 但是如果计算上面公式, 计算量太大, 并且对于每一个  k  取值都需要重新计算降维矩阵。  可以采用下面的公式计算 k 的取值, 因为在 对协方差矩阵进行奇异值分解的时候返回了 S , S 为协方差矩阵的特征值, 并且 S 是对角矩阵, 维度为  n * n, 计算 k 的取值如下:

3.5  重构 (reconstruction, 根据降维后数据重构原数据), 数据还原 获得降维后的数据, 可以根据降维后的数据还原原始数据。 还原原始数据的过程也就是获得样本点映射以后在原空间中的估计位置的过程, 即计算 X-approx的过程。


使用降维用的降维矩阵 Uk, 然后将 降维后的样本 z 还原回原始特征, 就可以用上图所示的公式。

4. PCA的应用示例 貌似本页已经写的太多了, 所以这里示例另外给出。  请狂点: http://blog.csdn.net/watkinsong/article/details/38539289
由于篇幅问题, 这里只给出代码, 关于代码的解释和插图, 请访问上面链接
%% Initializationclear ; close all; clcfprintf('this code will load 12 images and do PCA for each face.n');fprintf('10 images are used to train PCA and the other 2 images are used to test PCA.n');m = 4000; % number of samplestrainset = zeros(m, 32 * 32); % image size is : 32 * 32for i = 1 : mimg = imread(strcat('./img/', int2str(i), '.bmp'));img = double(img);trainset(i, :) = img(:);end%% before training PCA, do feature normalizationmu = mean(trainset);trainset_norm = bsxfun(@minus, trainset, mu);sigma = std(trainset_norm);trainset_norm = bsxfun(@rdivide, trainset_norm, sigma);%% we could save the mean face mu to take a look the mean faceimwrite(uint8(reshape(mu, 32, 32)), 'meanface.bmp');fprintf('mean face saved. pausedn');pause;%% compute reduce matrixX = trainset_norm; % just for convience[m, n] = size(X);U = zeros(n);S = zeros(n);Cov = 1 / m * X' * X;[U, S, V] = svd(Cov);fprintf('compute cov done.n');%% save eigen facefor i = 1:10ef = U(:, i)';img = ef;minVal = min(img);img = img - minVal;max_val = max(abs(img));img = img / max_val;img = reshape(img, 32, 32);imwrite(img, strcat('eigenface', int2str(i), '.bmp'));endfprintf('eigen face saved, paused.n');pause;%% dimension reductionk = 100; % reduce to 100 dimensiontest = zeros(10, 32 * 32);for i = 4001:4010img = imread(strcat('./img/', int2str(i), '.bmp'));img = double(img);test(i - 4000, :) = img(:);end% test set need to do normalizationtest = bsxfun(@minus, test, mu);% reductionUk = U(:, 1:k);Z = test * Uk;fprintf('reduce done.n');%% reconstruction%% for the test set images, we only minus the mean face,% so in the reconstruct process, we need add the mean face backXp = Z * Uk';% show reconstructed facefor i = 1:5face = Xp(i, :) + mu;face = reshape((face), 32, 32);imwrite(uint8(face), strcat('./reconstruct/', int2str(4000 + i), '.bmp'));end%% for the train set reconstruction, we minus the mean face and divide by standard deviation during the train% so in the reconstruction process, we need to multiby standard deviation first, % and then add the mean face backtrainset_re = trainset_norm * Uk; % reductiontrainset_re = trainset_re * Uk'; % reconstructionfor i = 1:5train = trainset_re(i, :);train = train .* sigma;train = train + mu;train = reshape(train, 32, 32);imwrite(uint8(train), strcat('./reconstruct/', int2str(i), 'train.bmp'));endfprintf('job done.n');

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。