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
,其中 u 和 vh 的 Hermitian 轉置是具有正交列的 2D 陣列,而 s 是 a 的奇異值的 1D 陣列。當 a 是更高維度時,SVD 會以堆疊模式應用,如下所述。- 參數:
- a(…, M, N) 類陣列
具有
a.ndim >= 2
的實數或複數陣列。- full_matricesbool,可選
如果為 True (預設值),則 u 和 vh 的形狀分別為
(..., M, M)
和(..., N, N)
。否則,形狀分別為(..., M, K)
和(..., K, N)
,其中K = min(M, N)
。- compute_uvbool,可選
是否除了 s 之外還計算 u 和 vh。預設為 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 的奇異值,而 u 和 vh 是么正的。vh 的列是 \(A^H A\) 的特徵向量,而 u 的行是 \(A A^H\) 的特徵向量。在這兩種情況下,對應的 (可能非零) 特徵值由
s**2
給出。如果 a 具有兩個以上的維度,則會套用廣播規則,如 一次對多個矩陣進行線性代數運算 中所述。這表示 SVD 以「堆疊」模式運作:它迭代前
a.ndim - 2
個維度的所有索引,並且對於每個組合,SVD 都會應用於最後兩個索引。矩陣 a 可以從分解中重建,使用(u * s[..., None, @ vh
或u @ (s[..., None] * vh)
。(對於 Python 3.5 以下的版本,@
運算子可以用函數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 的重建,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