numpy.linalg.svd#
- linalg.svd(a, full_matrices=True, compute_uv=True, hermitian=False)[source]#
奇异值分解。
当 a 是一个二维数组,并且
full_matrices=False
时,它被分解为u @ np.diag(s) @ vh = (u * s) @ vh
,其中 u 和 vh 的厄米特转置是具有正交列的二维数组,而 s 是 a 的奇异值的 1D 数组。当 a 是高维数组时,如以下所述,SVD 将以堆叠模式应用。- 参数:
- a(…, M, N) array_like
一个实数或复数数组,其中
a.ndim >= 2
。- full_matricesbool, optional
如果为 True (默认值),则 u 和 vh 的形状分别为
(..., M, M)
和(..., N, N)
。否则,形状分别为(..., M, K)
和(..., K, N)
,其中K = min(M, N)
。- compute_uvbool, optional
是否除了 s 之外还要计算 u 和 vh。默认为 True。
- hermitianbool, optional
如果为 True,则假设 a 为厄米特矩阵(如果为实数值则为对称矩阵),从而可以使用更有效的方法查找奇异值。默认为 False。
- 返回:
- 当 compute_uv 为 True 时,结果是一个命名元组,包含以下
- 属性名称
- 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
计算矩阵的奇异值。
备注
分解使用 LAPACK 例程
_gesdd
执行。SVD 通常用于二维矩阵 \(A\) 的分解。高维情况将在下面讨论。在二维情况下,SVD 写成 \(A = U S V^H\),其中 \(A = a\),\(U= u\),\(S= \mathtt{np.diag}(s)\) 和 \(V^H = vh\)。一维数组 s 包含 a 的奇异值,u 和 vh 是酉矩阵。 vh 的行是 \(A^H A\) 的特征向量,u 的列是 \(A A^H\) 的特征向量。在这两种情况下,对应的(可能非零)特征值都由
s**2
给出。如果 a 的维数超过两维,则广播规则适用,如 Linear algebra on several matrices at once 中所述。这意味着 SVD 正在“堆叠”模式下工作:它迭代前
a.ndim - 2
维的所有索引,并且对于每种组合,SVD 都应用于最后两个索引。矩阵 a 可以使用(u * s[..., None, :]) @ vh
或u @ (s[..., None] * vh)
从分解中重建。(对于低于 3.5 的 python 版本,@
运算符可以用函数np.matmul
替换。)如果 a 是一个
matrix
对象(而不是ndarray
),则所有返回值也是如此。示例
>>> 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