I recently learned about different methods of PCA. I decided to manually implement PCA in Python with Eigendecomposition of cov(X)
and the Singular Value Decomposition of X
and compare the results. I heard that the main difference is that SVD should give a more accurate result while taking longer to execute.
Here is my implementation:
import numpy as np
from scipy.linalg import svd,eig
SIZE=(3,3) #the data shape
def svd_(data):
mean=np.mean(data,axis=0)
centered=data-mean #center data using column means
print(f'{centered=}')
U, s, Vh=svd(centered)
print(f'{U=}\n{s=}\n,{Vh=}')
def eig_(data):
mean=np.mean(data,axis=0)
centered=data-mean #center data using column means
print(f'{centered=}')
cov=np.cov(centered.T)
eigen_values, eigen_vectors=eig(cov)
print(f'{eigen_values=}\n{eigen_vectors=}')
def main():
np.random.seed(42) #fixed seed
data=np.random.random(size=SIZE)
print(f'data is\n{data}')
svd_(data)
print()
eig_(data)
if __name__=='__main__':
main()
I get the following output:
data is
[[0.37454012 0.95071431 0.73199394]
[0.59865848 0.15601864 0.15599452]
[0.05808361 0.86617615 0.60111501]]
#svd_ below
centered=array([[ 0.03077938, 0.29307794, 0.23562612],
[ 0.25489775, -0.50161772, -0.3403733 ],
[-0.28567713, 0.20853978, 0.10474719]])
U=array([[ 0.41479721, 0.7032851 , 0.57735027],
[-0.81646137, 0.00758237, 0.57735027],
[ 0.40166416, -0.71086748, 0.57735027]])
s=array([8.05432409e-01, 2.49318619e-01, 2.61896384e-17])
,Vh=array([[-0.38500217, 0.76341895, 0.5186182 ],
[ 0.90910975, 0.21687009, 0.35564986],
[ 0.15903707, 0.60840683, -0.77752707]])
#eig_ below
centered=array([[ 0.03077938, 0.29307794, 0.23562612],
[ 0.25489775, -0.50161772, -0.3403733 ],
[-0.28567713, 0.20853978, 0.10474719]])
eigen_values=array([ 3.24360683e-01+0.j, 3.10798868e-02+0.j, -4.80648600e-18+0.j])
eigen_vectors=array([[ 0.38500217, -0.90910975, -0.15903707],
[-0.76341895, -0.21687009, -0.60840683],
[-0.5186182 , -0.35564986, 0.77752707]])
The main problem I have is that the values for Principal Components are too different between each method. I would expect U
and eigen_vectors
to be close to each other. Am I missing something?
TLDR. Assuming that U
, and eigen_vectors
represent principal components for the original matrix X
, why are they not equal?
eigenvectors
, which prompted my remark. If we take $X = USV^T$, one covariance eigen factorization is $\Sigma \propto X^TX=VS^2 V^T$. But if we expect the eigenvectors to be $U$, then something has gone wrong; perhaps we've transposed $X$. That's what I was trying to point out. (And likewise there's a similar discussion to be had about scaling factors...) This is why I suggest using a non-square $X$: you'll have the wrong number of vectors when you've transposed by mistake! $\endgroup$