教程地址:http://deeplearning.stanford.edu/wiki/index.php/UFLDL%E6%95%99%E7%A8%8B
练习地址1:http://deeplearning.stanford.edu/wiki/index.php/Exercise:PCA_in_2D
练习地址2: http://deeplearning.stanford.edu/wiki/index.php/Exercise:PCA_and_Whitening
1.习惯性啰嗦几句
(1)通过svd来避免求高维度数据的协方差矩阵
PCA的推导有挺多版本的,ng的CS229中PCA那章讲过,还介绍了通过svd来避免求高维度数据的协方差矩阵(高维度协方差矩阵计算量很大),所以这次PCA_in_2D练习中我写了两个版本:
一个是pca_2d.m是按教程写的标准答案(但是我觉得教程绕了几个弯子,也可能是另有深意,我没理解到)。
一个是another_pca_2d.m,这是我按照我自己的理解,使用svd绕开求协方差矩阵这一步来计算pca:
建议先看看矩阵分析课本上关于奇异值分解(svd)的推导过程。
首先说说[u,s,v]=svd(x),s对角线上为x的奇异值,也是矩阵xx'特征值的平方根;u为矩阵xx'的特征向量。我们用Sigma代表数据x的协方差矩阵。
若X为n*m矩阵,n维特征,m个样本。m表示样本数,(xx')/m其实就是Sigma(实际上应该是Sigma的样本估计,样本多就可认为就是Sigma),也就是说可以直接通过s求得Sigma的特征值(把s对角线元素平方再除以m即可),这样计算,过程中并没有算Sigma具体是多少。
此外,PCA得出的最佳投影方向为Sigma的特征向量方向,xx'与(xx')/m特征向量一样,所以u就是旋转矩阵。
而在教程中,有代码:
sigma = x * x' / size(x, 2)
[U,S,V] = svd(sigma);
U为sigma*sigma’的特征向量矩阵,S对角线为sigma的奇异值(也等于sigma*sigma‘的特征值开平方根)。
注意:先计算了协方差矩阵sigma,再用svd计算sigma的奇异值(S的对角线元素),sigma奇异值就等于sigma的特征值。理由:根据矩阵分析中svd的推导过程,会先计算sigma*sigma‘的特征值,再开平方根,就得到了S(的对角线元素);而由于sigma是实对称矩阵,sigma=sigma’,其实求得是sigma^2的特征值,再开根,其实就是sigma的特征值。此外,根据svd推导过程,U为sigma*sigma‘(也就是sigma^2)的特征向量组成的矩阵,那U同时也是sigma的特征向量矩阵,所以u和U中各向量其实是一样的(符号可能相反)。(矩阵A与A^2的特征向量都相同,特征值后者是前者的平方)。
综上:教程中使用svd是为了求sigma的特征值和特征向量(用eig函数也可以,只是svd数值计算上更稳定),而实际上,根据CS229-PCA那章,svd可以直接绕过求sigma这步&#