numpy.linalg.svd#

linalg.svd(a, full_matrices=True, compute_uv=True, hermitian=False)[源代码]#

奇异值分解。

a 是一个二维数组,并且 full_matrices=False 时,它被分解为 u @ np.diag(s) @ vh = (u * s) @ vh,其中 uvh 的厄米共轭是具有正交列的二维数组,而 sa 的奇异值的一维数组。当 a 是高维的时,SVD 以堆叠模式应用,如下文所述。

参数:
a(..., M, N) array_like

一个实数或复数数组,其中 a.ndim >= 2

full_matricesbool, optional

如果为 True(默认值),则 uvh 的形状分别为 (..., M, M)(..., N, N)。否则,形状分别为 (..., M, K)(..., K, N),其中 K = min(M, N)

compute_uvbool, optional

除了 s 之外,是否计算 uvh。默认为 True。

hermitianbool, optional

如果为 True,则假定 a 是厄米(如果是实值则为对称),从而可以使用更有效的方法来查找奇异值。默认为 False。

返回:
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 时返回。

引发:
LinAlgError

如果 SVD 计算未收敛。

另请参阅

scipy.linalg.svd

SciPy 中的类似函数。

scipy.linalg.svdvals

计算矩阵的奇异值。

备注

compute_uv 为 True 时,结果是一个命名元组,包含以下属性名:USVh

分解使用 LAPACK 例程 _gesdd 进行。

SVD 通常被描述为二维矩阵 \(A\) 的分解。高维情况将在下面讨论。在二维情况下,SVD 被写成 \(A = U S V^H\),其中 \(A = a\)\(U= u\)\(S= \mathtt{np.diag}(s)\),而 \(V^H = vh\)s 的一维数组包含 a 的奇异值,而 uvh 是酉矩阵。 vh 的行是 \(A^H A\) 的特征向量,而 u 的列是 \(A A^H\) 的特征向量。在这两种情况下,相应的(可能非零的)特征值为 s**2

如果 a 的维度大于二维,则应用广播规则,如同时处理多个矩阵的线性代数中所述。这意味着 SVD 以“堆叠”模式工作:它遍历前 a.ndim - 2 个维度的所有索引,并对每个组合应用 SVD 到最后两个索引。矩阵 a 可以从分解中重构,使用 (u * s[..., None, :]) @ vhu @ (s[..., None] * vh)。(对于 3.5 版本以下的 Python,可以使用函数 np.matmul 替换 `@` 运算符。)

如果 a 是一个 matrix 对象(而不是 ndarray),则所有返回值也都是 matrix 对象。

示例

>>> import numpy as np
>>> rng = np.random.default_rng()
>>> a = rng.normal(size=(9, 6)) + 1j*rng.normal(size=(9, 6))
>>> b = rng.normal(size=(2, 7, 8, 3)) + 1j*rng.normal(size=(2, 7, 8, 3))

基于完整 SVD 的重构,二维情况

>>> U, S, Vh = np.linalg.svd(a, full_matrices=True)
>>> U.shape, S.shape, Vh.shape
((9, 9), (6,), (6, 6))
>>> np.allclose(a, np.dot(U[:, :6] * S, Vh))
True
>>> smat = np.zeros((9, 6), dtype=complex)
>>> smat[:6, :6] = np.diag(S)
>>> np.allclose(a, np.dot(U, np.dot(smat, Vh)))
True

基于缩减 SVD 的重构,二维情况

>>> U, S, Vh = np.linalg.svd(a, full_matrices=False)
>>> U.shape, S.shape, Vh.shape
((9, 6), (6,), (6, 6))
>>> np.allclose(a, np.dot(U * S, Vh))
True
>>> smat = np.diag(S)
>>> np.allclose(a, np.dot(U, np.dot(smat, Vh)))
True

基于完整 SVD 的重构,四维情况

>>> U, S, Vh = np.linalg.svd(b, full_matrices=True)
>>> U.shape, S.shape, Vh.shape
((2, 7, 8, 8), (2, 7, 3), (2, 7, 3, 3))
>>> np.allclose(b, np.matmul(U[..., :3] * S[..., None, :], Vh))
True
>>> np.allclose(b, np.matmul(U[..., :3], S[..., None] * Vh))
True

基于缩减 SVD 的重构,四维情况

>>> U, S, Vh = np.linalg.svd(b, full_matrices=False)
>>> U.shape, S.shape, Vh.shape
((2, 7, 8, 3), (2, 7, 3), (2, 7, 3, 3))
>>> np.allclose(b, np.matmul(U * S[..., None, :], Vh))
True
>>> np.allclose(b, np.matmul(U, S[..., None] * Vh))
True