numpy.linalg.svd#

linalg.svd(a, full_matrices=True, compute_uv=True, hermitian=False)[原始碼]#

奇異值分解。

a 是 2D 陣列,且 full_matrices=False 時,它會被分解為 u @ np.diag(s) @ vh = (u * s) @ vh,其中 uvh 的 Hermitian 轉置是具有正交列的 2D 陣列,而 sa 的奇異值的 1D 陣列。當 a 是更高維度時,SVD 會以堆疊模式應用,如下所述。

參數:
a(…, M, N) 類陣列

具有 a.ndim >= 2 的實數或複數陣列。

full_matricesbool,可選

如果為 True (預設值),則 uvh 的形狀分別為 (..., M, M)(..., N, N)。否則,形狀分別為 (..., M, K)(..., K, N),其中 K = min(M, N)

compute_uvbool,可選

是否除了 s 之外還計算 uvh。預設為 True。

hermitianbool,可選

如果為 True,則假定 a 為 Hermitian (如果是實數值則為對稱),從而可以使用更有效的方法來尋找奇異值。預設為 False。

返回:
compute_uv 為 True 時,結果是一個具名元組,具有以下
屬性名稱
U{ (…, M, M), (…, M, K) } 陣列

么正陣列。前 a.ndim - 2 個維度的大小與輸入 a 的大小相同。最後兩個維度的大小取決於 full_matrices 的值。僅在 compute_uv 為 True 時返回。

S(…, K) 陣列

包含奇異值的向量,每個向量內以遞減順序排序。前 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

計算矩陣的奇異值。

註解

分解是使用 LAPACK 常式 _gesdd 執行的。

SVD 通常用於描述 2D 矩陣 \(A\) 的分解。更高維度的情況將在下面討論。在 2D 情況下,SVD 寫為 \(A = U S V^H\),其中 \(A = a\)\(U= u\)\(S= \mathtt{np.diag}(s)\)\(V^H = vh\)。1D 陣列 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)。(對於 Python 3.5 以下的版本,@ 運算子可以用函數 np.matmul 替換。)

如果 amatrix 物件 (而不是 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 的重建,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 的重建,2D 情況

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