Python 使用 Numpy (np.linalg.svd) 进行奇异值分解

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24913232/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 05:27:46  来源:igfitidea点击:

Using Numpy (np.linalg.svd) for Singular Value Decomposition

pythonnumpypca

提问by dms_quant

Im reading Abdi & Williams (2010) "Principal Component Analysis", and I'm trying to redo the SVD to attain values for further PCA.

我正在阅读 Abdi & Williams (2010)“主成分分析”,我正在尝试重做 SVD 以获得进一步 PCA 的值。

The article states that following SVD:

文章指出以下SVD:

X = P D Q^t

X = PDQ^t

I load my data in a np.array X.

我将数据加载到 np.array X 中。

X = np.array(data)
P, D, Q = np.linalg.svd(X, full_matrices=False)
D = np.diag(D)

But i do not get the above equality when checking with

但是在检查时我没有得到上述相等性

X_a = np.dot(np.dot(P, D), Q.T)

X_a and X are the same dimensions, but the values are not the same. Am I missing something, or is the functionality of the np.linalg.svd function not compatible somehow with the equation in the paper?

X_a 和 X 是相同的维度,但值不相同。我是不是遗漏了什么,还是 np.linalg.svd 函数的功能与论文中的方程不兼容?

采纳答案by Frank M

TL;DR: numpy's SVD computes X = PDQ, so the Q is already transposed.

TL;DR:numpy 的 SVD 计算 X = PDQ,所以 Q 已经转置了。

SVD decomposes the matrix Xeffectively into rotations Pand Qand the diagonal matrix D. The version of linalg.svd()I have returns forward rotations for Pand Q. You don't want to transform Qwhen you calculate X_a.

SVD分解矩阵X有效成旋转PQ和对角矩阵Dlinalg.svd()I的版本为P和返回了向前旋转QQ计算时不想变换X_a

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))

I get: 1.02, 1.02, 1.8e-15, showing that X_avery accurately reconstructs X.

我得到:1.02, 1.02, 1.8e-15,表明X_a非常准确地重建X.

If you are using Python 3, the @operator implements matrix multiplication and makes the code easier to follow:

如果您使用的是 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())

回答by eewallace

From the scipy.linalg.svd docstring, where (M,N) is the shape of the input matrix, and K is the lesser of the two:

从 scipy.linalg.svd 文档字符串,其中 (M,N) 是输入矩阵的形状,K 是两者中的较小者:

Returns
-------
U : ndarray
    Unitary matrix having left singular vectors as columns.
    Of shape ``(M,M)`` or ``(M,K)``, depending on `full_matrices`.
s : ndarray
    The singular values, sorted in non-increasing order.
    Of shape (K,), with ``K = min(M, N)``.
Vh : ndarray
    Unitary matrix having right singular vectors as rows.
    Of shape ``(N,N)`` or ``(K,N)`` depending on `full_matrices`.

Vh, as described, is the transpose of the Q used in the Abdi and Williams paper. So just

如前所述,Vh 是 Abdi 和 Williams 论文中使用的 Q 的转置。所以就

X_a = P.dot(D).dot(Q)

should give you your answer.

应该给你答案。

回答by ?mer ?ayli

I think there are still some important points for those who use SVD in Python/linalg library. Firstly, https://docs.scipy.org/doc/numpy/reference/generated/numpy.linalg.svd.htmlis a good reference for SVD computation function.

我认为对于那些在 Python/linalg 库中使用 SVD 的人来说,仍然有一些重要的点。首先,https://docs.scipy.org/doc/numpy/reference/generated/numpy.linalg.svd.html是 SVD 计算函数的一个很好的参考。

Taking SVD computation as A= U D (V^T), For U, D, V = np.linalg.svd(A), this function returns V in V^T form already. Also D contains eigenvalues only, hence it has to be shaped into matrix form. Hence the reconstruction can be formed with

将 SVD 计算为 A=UD (V^T),对于 U,D,V = np.linalg.svd(A),该函数已经以 V^T 形式返回 V。此外,D 仅包含特征值,因此必须将其整形为矩阵形式。因此重建可以用

import numpy as np
U, D, V = np.linalg.svd(A)
A_reconstructed = U @ np.diag(D) @ V

The point is that, If A matrix is not a square but rectangular matrix, this won't work, you can use this instead

关键是,如果矩阵不是正方形而是矩形矩阵,这将不起作用,您可以改用它

import numpy as np
U, D, V = np.linalg.svd(A)
m, n = A.shape
A_reconstructed = U[:,:n] @ np.diag(D) @ V[:m,:]

or you may use 'full_matrices=False' option in the SVD function;

或者您可以在 SVD 函数中使用 'full_matrices=False' 选项;

import numpy as np
U, D, V = np.linalg.svd(A,full_matrices=False)
A_reconstructed = U @ np.diag(D) @ V