我正在阅读 Abdi & Williams (2010)“主成分分析”,我正在尝试重做 SVD 以获得进一步 PCA 的值。
文章指出以下 SVD:
X = P D Q^t
我将数据加载到 np.array X 中。
X = np.array(data)
P, D, Q = np.linalg.svd(X, full_matrices=False)
D = np.diag(D)
但是我在检查时没有得到上面的相等性
X_a = np.dot(np.dot(P, D), Q.T)
X_a 和 X 是相同的维度,但是值不一样。我是否遗漏了什么,或者 np.linalg.svd 函数的功能是否与论文中的方程不兼容?
最佳答案
TL;DR:numpy 的 SVD 计算 X = PDQ,因此 Q 已经转置。
SVD 将矩阵 X
有效地分解为旋转 P
和 Q
以及对角矩阵 D
。我为 P
和 Q
返回正向旋转的 linalg.svd()
版本。您不想在计算 X_a
时转换 Q
。
import numpy as np
X = np.random.normal(size=[20,18])
P, D, Q = np.linalg.svd(X, full_matrices=False)
X_a = np.matmul(np.matmul(P, np.diag(D)), Q)
print(np.std(X), np.std(X_a), np.std(X - X_a))
我得到:1.02、1.02、1.8e-15,表明 X_a
非常准确地重构了 X
。
如果您使用的是 Python 3,@
运算符可实现矩阵乘法并使代码更易于理解:
import numpy as np
X = np.random.normal(size=[20,18])
P, D, Q = np.linalg.svd(X, full_matrices=False)
X_a = P @ diag(D) @ Q
print(np.std(X), np.std(X_a), np.std(X - X_a))
print('Is X close to X_a?', np.isclose(X, X_a).all())
关于python - 使用 Numpy (np.linalg.svd) 进行奇异值分解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24913232/