所以我试图学习SVD如何在PCA(主成分分析)中使用它,但问题是它会得到错误的结果,我尝试使用np.linalg.svd
,这是我的代码:
A = np.array([[2, 2],
[1, 1]])
u, s, v = np.linalg.svd(A, full_matrices=False)
print(u)
print(s)
print(v)
这是我得到的结果:
[[-0.89442719 -0.4472136 ]
[-0.4472136 0.89442719]]
[3.16227766e+00 1.10062118e-17]
[[-0.70710678 -0.70710678]
[ 0.70710678 -0.70710678]]
我试着在WolframAlpha上进行SVD分解,得到了以下结果:
值的大小似乎是正确的,但符号是不正确的,即使我跟进了一个视频的教授在MIT OpenCourseWare on youtube和他给予这些结果:
同样大小的答案,但符号不同,那么可能出了什么问题呢?
1条答案
按热度按时间o7jaxewo1#
不同的约定
返回矩阵
v
的约定不同:从
numpy.linalg.svd
的文档(强调我的):奇异值分解
当a是一个2D数组,并且full_matrices=False时,则它被分解为**
u @ np.diag(s) @ vh = (u * s) @ vh
**,其中u
和vh
的Hermitian转置是具有正交列的2D数组,s是a的奇异值的1D数组。当a
是高维时,SVD以堆栈模式应用,如下所述。返回:
u{ (…, M, M), (…, M, K) }
array酉数组。前a.ndim - 2
维度的大小与输入a
的大小相同。后两个维度的大小取决于full_matrices的值。仅当compute_uv为True时返回。s(…, K)
array每个向量中的奇异值按降序排序。前a.ndim - 2
维度与输入a
维度的大小相同。vh
{ (…, N, N), (…, K, N) }
array酉数组。前a.ndim
- 2个维度的大小与输入a的大小相同。后两个维度的大小取决于full_matrices的值。仅当compute_uv为True时返回。总结一下:给定
x
,x = u @ np.diag(s) @ vh
的SVD分解,numpy.linalg.svd(x)
返回的矩阵是u
,s
和vh
,其中vh
是v
的厄米共轭。其他库和软件将返回v
,导致明显的不一致。很遗憾,不同的库有不同的约定,这也是我第一次处理这个问题时遇到的问题。
u
和v
的内在数学模糊性此外,数学的问题意味着the matrices
u
andv
are not uniquely determined。为了检查SVD是否正确,您需要检查矩阵
u
和v
是否确实是unitary以及x = u @ np.diag(s) @ vh
。如果两个条件都成立,则SVD是正确的,否则它不是。测试
numpy
库下面是一些简单的代码,可以检查SVD库在numpy中的实现是否正确(当然是正确的,可以将其视为教学练习):