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 的厄米特转置是具有正交列的二维数组,`s` 是 a 的奇异值的一维数组.当 a 是更高维时,SVD 以堆叠模式应用,如下所述.

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

一个具有 a.ndim >= 2 的实数或复数数组.

full_matricesbool, 可选

如果为 True(默认),`u` 和 vh 的形状分别为 (..., M, M)(..., N, N).否则,形状分别为 (..., M, K)(..., K, N),其中 K = min(M, N).

compute_uvbool, 可选

是否在计算 s 的同时计算 uvh.默认为 True.

hermitianbool, 可选

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

在 1.17.0 版本加入.

返回:
compute_uv 为 True 时,结果是一个命名元组,包含以下内容
属性名称:
U{ (…, M, M), (…, M, K) } 数组

单一数组.前 a.ndim - 2 维的大小与输入 a 的那些维相同.最后两维的大小取决于 full_matrices 的值.仅当 compute_uv 为 True 时返回.

S(…, K) 数组

包含奇异值的向量(s),每个向量中的奇异值按降序排列.前 a.ndim - 2 维的大小与输入 a 的相应维大小相同.

Vh{ (…, N, N), (…, K, N) } 数组

单一数组.前 a.ndim - 2 维的大小与输入 a 的那些维相同.最后两维的大小取决于 full_matrices 的值.仅当 compute_uv 为 True 时返回.

引发:
LinAlgError

如果SVD计算不收敛.

参见

scipy.linalg.svd

SciPy 中的类似功能.

scipy.linalg.svdvals

计算矩阵的奇异值.

备注

在 1.8.0 版本发生变更: 广播规则适用,详情请参见 numpy.linalg 文档.

分解是通过使用 LAPACK 例程 _gesdd 执行的.

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

如果 a 有超过两个维度,那么广播规则适用,如在 同时对多个矩阵进行线性代数运算 中所解释的.这意味着 SVD 在”堆叠”模式下工作:它遍历前 a.ndim - 2 维度的所有索引,并对每个组合应用 SVD 到最后两个索引.矩阵 a 可以用分解来重建,使用 (u * s[..., None, :]) @ vhu @ (s[..., None] * vh).(@ 运算符可以用函数 np.matmul 替换,适用于 3.5 以下版本的 python.)

如果 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的重构,2D情况:

>>> 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的重构,4D情况:

>>> 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的重构,4D情况:

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