PCA与SVD应用中负号问题


最近应用pca时遇到一个问题:自己写的pca过程和调用sklearn中的pca最后得到转换空间后的矩阵总有负号差异,后来通过读源码,常识,发现了问题原因:

简单说一下pca的实现,首先对于一个矩阵X,我们计算X·XT,显然这个一个半正定矩阵,可以做特征值分解,然后取出k个最大的特征值及其对应的特征向量就可以表达整个原矩阵。若X·XT=p-1Λp,因为p是单位矩阵,所以p-1=pT,即X·XT=p-1·Λ1/2·(p-1·Λ1/2)T,也就是降维的X后用来p-1·Λ1/2表示。其实从SVD的角度来理解也是一样的,若X=UΣVT,则X·XT=UΣ2UT,同样我们用来UΣ来表示原X。

当我看sklearn的文档时,文档并没有具体解释它的方法得到的结果在数学上的表示什么,钻研了半天,看了源码后才知道。

sklearn中的PCA分解时的方法是通过SVD来实现的。(自己写的PAC使用eig_val, eig_vec = np.linalg.eig(scatter_matrix),方法不同最后分解得到的值也就不同,svd的代码如下)发现方法用的这个不同后,自己又改成SVD的方法去做,结果就是还是相差负号,功夫不如有心人,还是发现了少了一步,在sklearn中的pAC中分解完后进行翻转特征向量符号以强制执行确定性输出操作(svd_flip,这才是相差负号的原因。我们看一下fit中的部分关键代码。

...
self.mean_ = np.mean(X, axis=0) X -= self.mean_ U, S, V = linalg.svd(X, full_matrices=False) U, V = svd_flip(U, V) components_ = V ... self.components_ = components_[:n_components] ...

 

经过了这个svd_flip函数处理后负号问题就解决了。应用sklearn中的PCA接口实现和我自己写的PAC得到的矩阵结果是完全一致的了

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM