Python:使用 SVD 实现 PCA
Python: Implement a PCA using SVD
我试图找出使用奇异值分解的 PCA 与使用特征向量分解的 PCA 之间的区别。
画出以下矩阵:
B = np.array([ [1, 2],
[3, 4],
[5, 6] ])
使用特征向量分解计算此矩阵 B 的 PCA 时,我们遵循以下步骤:
- 通过从每列中减去列均值来使数据(B 的条目)居中
- 计算协方差矩阵
C = Cov(B) = B^T * B / (m -1)
,其中 m = B 的 # 行
- 求出 C 的特征向量
PCs = X * eigen_vecs
当使用 SVD 计算矩阵 B 的 PCA 时,我们遵循以下步骤:
- 计算 B 的 SVD:
B = U * Sigma * V.T
PCs = U * Sigma
我已经为给定的矩阵完成了这两项工作。
使用特征向量分解得到这个结果:
[[-2.82842712 0. ]
[ 0. 0. ]
[ 2.82842712 0. ]]
使用 SVD 我得到了这个结果:
[[-2.18941839 0.45436451]
[-4.99846626 0.12383458]
[-7.80751414 -0.20669536]]
特征向量分解得到的结果是作为解给出的结果。那么,为什么用SVD得到的结果不一样呢?
我知道:C = Cov(B) = V * (Sigma^2)/(m-1)) * V.T
我觉得这可能与两个结果不同的原因有关。仍然。谁能帮助我更好地理解?
请在下面查看您的矩阵与 sklearn.decomposition.PCA 和 numpy.linalg.svd 的比较。您能否比较或 post 您是如何得出 SVD 结果的。
sklearn.decomposition.PCA的代码:
from sklearn.decomposition import PCA
import numpy as np
np.set_printoptions(precision=3)
B = np.array([[1.0,2], [3,4], [5,6]])
B1 = B.copy()
B1 -= np.mean(B1, axis=0)
n_samples = B1.shape[0]
print("B1 is B after centering:")
print(B1)
cov_mat = np.cov(B1.T)
pca = PCA(n_components=2)
X = pca.fit_transform(B1)
print("X")
print(X)
eigenvecmat = []
print("Eigenvectors:")
for eigenvector in pca.components_:
if eigenvecmat == []:
eigenvecmat = eigenvector
else:
eigenvecmat = np.vstack((eigenvecmat, eigenvector))
print(eigenvector)
print("eigenvector-matrix")
print(eigenvecmat)
print("CHECK FOR PCA:")
print("X * eigenvector-matrix (=B1)")
print(np.dot(PCs, eigenvecmat))
PCA 的输出:
B1 is B after centering:
[[-2. -2.]
[ 0. 0.]
[ 2. 2.]]
X
[[-2.828 0. ]
[ 0. 0. ]
[ 2.828 0. ]]
Eigenvectors:
[0.707 0.707]
[-0.707 0.707]
eigenvector-matrix
[[ 0.707 0.707]
[-0.707 0.707]]
CHECK FOR PCA:
X * eigenvector-matrix (=B1)
[[-2. -2.]
[ 0. 0.]
[ 2. 2.]]
numpy.linalg.svd:
print("B1 is B after centering:")
print(B1)
from numpy.linalg import svd
U, S, Vt = svd(X1, full_matrices=True)
print("U:")
print(U)
print("S used for building Sigma:")
print(S)
Sigma = np.zeros((3, 2), dtype=float)
Sigma[:2, :2] = np.diag(S)
print("Sigma:")
print(Sigma)
print("V already transposed:")
print(Vt)
print("CHECK FOR SVD:")
print("U * Sigma * Vt (=B1)")
print(np.dot(U, np.dot(Sigma, Vt)))
SVD 的输出:
B1 is B after centering:
[[-2. -2.]
[ 0. 0.]
[ 2. 2.]]
U:
[[-0.707 0. 0.707]
[ 0. 1. 0. ]
[ 0.707 0. 0.707]]
S used for building Sigma:
[4. 0.]
Sigma:
[[4. 0.]
[0. 0.]
[0. 0.]]
V already transposed:
[[ 0.707 0.707]
[-0.707 0.707]]
CHECK FOR SVD:
U * Sigma * Vt (=B1)
[[-2. -2.]
[ 0. 0.]
[ 2. 2.]]
我试图找出使用奇异值分解的 PCA 与使用特征向量分解的 PCA 之间的区别。
画出以下矩阵:
B = np.array([ [1, 2],
[3, 4],
[5, 6] ])
使用特征向量分解计算此矩阵 B 的 PCA 时,我们遵循以下步骤:
- 通过从每列中减去列均值来使数据(B 的条目)居中
- 计算协方差矩阵
C = Cov(B) = B^T * B / (m -1)
,其中 m = B 的 # 行 - 求出 C 的特征向量
PCs = X * eigen_vecs
当使用 SVD 计算矩阵 B 的 PCA 时,我们遵循以下步骤:
- 计算 B 的 SVD:
B = U * Sigma * V.T
PCs = U * Sigma
我已经为给定的矩阵完成了这两项工作。
使用特征向量分解得到这个结果:
[[-2.82842712 0. ]
[ 0. 0. ]
[ 2.82842712 0. ]]
使用 SVD 我得到了这个结果:
[[-2.18941839 0.45436451]
[-4.99846626 0.12383458]
[-7.80751414 -0.20669536]]
特征向量分解得到的结果是作为解给出的结果。那么,为什么用SVD得到的结果不一样呢?
我知道:C = Cov(B) = V * (Sigma^2)/(m-1)) * V.T
我觉得这可能与两个结果不同的原因有关。仍然。谁能帮助我更好地理解?
请在下面查看您的矩阵与 sklearn.decomposition.PCA 和 numpy.linalg.svd 的比较。您能否比较或 post 您是如何得出 SVD 结果的。
sklearn.decomposition.PCA的代码:
from sklearn.decomposition import PCA
import numpy as np
np.set_printoptions(precision=3)
B = np.array([[1.0,2], [3,4], [5,6]])
B1 = B.copy()
B1 -= np.mean(B1, axis=0)
n_samples = B1.shape[0]
print("B1 is B after centering:")
print(B1)
cov_mat = np.cov(B1.T)
pca = PCA(n_components=2)
X = pca.fit_transform(B1)
print("X")
print(X)
eigenvecmat = []
print("Eigenvectors:")
for eigenvector in pca.components_:
if eigenvecmat == []:
eigenvecmat = eigenvector
else:
eigenvecmat = np.vstack((eigenvecmat, eigenvector))
print(eigenvector)
print("eigenvector-matrix")
print(eigenvecmat)
print("CHECK FOR PCA:")
print("X * eigenvector-matrix (=B1)")
print(np.dot(PCs, eigenvecmat))
PCA 的输出:
B1 is B after centering:
[[-2. -2.]
[ 0. 0.]
[ 2. 2.]]
X
[[-2.828 0. ]
[ 0. 0. ]
[ 2.828 0. ]]
Eigenvectors:
[0.707 0.707]
[-0.707 0.707]
eigenvector-matrix
[[ 0.707 0.707]
[-0.707 0.707]]
CHECK FOR PCA:
X * eigenvector-matrix (=B1)
[[-2. -2.]
[ 0. 0.]
[ 2. 2.]]
numpy.linalg.svd:
print("B1 is B after centering:")
print(B1)
from numpy.linalg import svd
U, S, Vt = svd(X1, full_matrices=True)
print("U:")
print(U)
print("S used for building Sigma:")
print(S)
Sigma = np.zeros((3, 2), dtype=float)
Sigma[:2, :2] = np.diag(S)
print("Sigma:")
print(Sigma)
print("V already transposed:")
print(Vt)
print("CHECK FOR SVD:")
print("U * Sigma * Vt (=B1)")
print(np.dot(U, np.dot(Sigma, Vt)))
SVD 的输出:
B1 is B after centering:
[[-2. -2.]
[ 0. 0.]
[ 2. 2.]]
U:
[[-0.707 0. 0.707]
[ 0. 1. 0. ]
[ 0.707 0. 0.707]]
S used for building Sigma:
[4. 0.]
Sigma:
[[4. 0.]
[0. 0.]
[0. 0.]]
V already transposed:
[[ 0.707 0.707]
[-0.707 0.707]]
CHECK FOR SVD:
U * Sigma * Vt (=B1)
[[-2. -2.]
[ 0. 0.]
[ 2. 2.]]