快捷方式

torch.linalg.svd

torch.linalg.svd(A, full_matrices=True, *, driver=None, out=None)

計算矩陣的奇異值分解 (SVD)。

K\mathbb{K}R\mathbb{R}C\mathbb{C},若 k = min(m,n),矩陣 AKm×nA \in \mathbb{K}^{m \times n} 的**完整 SVD** 定義為:

A=Udiag(S)VHUKm×m,SRk,VKn×nA = U \operatorname{diag}(S) V^{\text{H}} \mathrlap{\qquad U \in \mathbb{K}^{m \times m}, S \in \mathbb{R}^k, V \in \mathbb{K}^{n \times n}}

其中 diag(S)Km×n\operatorname{diag}(S) \in \mathbb{K}^{m \times n}, VHV^{\text{H}} 是共軛轉置,當 VV 是複數時;當 VV 是實數值時,則是轉置。矩陣 UU, VV (以及 VHV^{\text{H}}) 在實數情況下是正交的,而在複數情況下是么正的。

m > n (resp. m < n) 時,我們可以捨棄 U (resp. V) 最後的 m - n (resp. n - m) 行,以形成簡化奇異值分解 (reduced SVD)

A=Udiag(S)VHUKm×k,SRk,VKn×kA = U \operatorname{diag}(S) V^{\text{H}} \mathrlap{\qquad U \in \mathbb{K}^{m \times k}, S \in \mathbb{R}^k, V \in \mathbb{K}^{n \times k}}

其中 diag(S)Kk×k\operatorname{diag}(S) \in \mathbb{K}^{k \times k}。在這種情況下,UUVV 也具有正交列向量。

支援 float、double、cfloat 和 cdouble 等資料類型作為輸入。也支援矩陣批次,且如果 A 是一批矩陣,則輸出具有相同的批次維度。

返回的分解是一個名為 (U, S, Vh) 的具名元組,對應於上面的 UUSSVHV^{\text{H}}

奇異值會以遞減順序返回。

參數 full_matrices 選擇完整(預設)或簡化 SVD。

在 CUDA 中,driver kwarg 可與 cuSOLVER 後端一起使用,以選擇用於計算 SVD 的演算法。驅動程式的選擇是在準確性和速度之間取得平衡。

  • 如果 A 的條件良好(其 條件數 不太大),或者您不介意一些精度損失。

    • 對於一般矩陣:‘gesvdj’(Jacobi 方法)

    • 如果 A 是高或寬矩陣(m >> nm << n):‘gesvda’(近似方法)

  • 如果 A 的條件不好或精度很重要:‘gesvd’(基於 QR)

預設情況下(driver= None),我們會呼叫 ‘gesvdj’,如果失敗,我們會退回至 ‘gesvd’

numpy.linalg.svd 的差異

  • numpy.linalg.svd 不同,此函數總是返回一個包含三個張量的元組,且不支援 compute_uv 參數。請使用 torch.linalg.svdvals(),它僅計算奇異值,而不是 compute_uv=False

注意

full_matrices= True 時,關於 U[…, :, min(m, n):]Vh[…, min(m, n):, :] 的梯度將被忽略,因為這些向量可以是相應子空間的任意基底。

警告

返回的張量 UV 不是唯一的,也不會隨著 A 連續變化。由於缺乏唯一性,不同的硬體和軟體可能會計算出不同的奇異向量。

這種非唯一性是因為,在實數情況下,將任何一對奇異向量 uk,vku_k, v_k 乘以 -1,或者在複數情況下,乘以 eiϕ,ϕRe^{i \phi}, \phi \in \mathbb{R},會產生另外兩個有效的矩陣奇異向量。 因此,損失函數不應依賴於這個 eiϕe^{i \phi} 量,因為它沒有明確定義。 在計算此函數的梯度時,會檢查複數輸入。 因此,當輸入是複數並且位於 CUDA 裝置上時,此函數的梯度計算會將該裝置與 CPU 同步。

警告

當使用 UVh 計算梯度時,只有在 A 沒有重複的奇異值時,梯度才會是有限的。 如果 A 是矩陣,則零也不能是它的奇異值之一。 此外,如果任意兩個奇異值之間的距離接近於零,則梯度在數值上將是不穩定的,因為它取決於通過計算 σi\sigma_i 的奇異值 1minijσi2σj2\frac{1}{\min_{i \neq j} \sigma_i^2 - \sigma_j^2}。 在矩陣的情況下,當 A 具有小的奇異值時,梯度在數值上也會不穩定,因為它也取決於 1σi\frac{1}{\sigma_i} 的計算。

另請參閱

torch.linalg.svdvals() 僅計算奇異值。 與 torch.linalg.svd() 不同的是,svdvals() 的梯度始終在數值上是穩定的。

torch.linalg.eig() 用於計算矩陣的另一種譜分解的函數。 特徵分解僅適用於方陣。

torch.linalg.eigh() 用於計算 Hermitian 和對稱矩陣的特徵值分解(更快的)函數。

torch.linalg.qr() 用於另一種(快得多的)適用於通用矩陣的分解。

參數
  • A (Tensor) – 形狀為 (*, m, n) 的張量,其中 * 為零個或多個批次維度。

  • full_matrices (bool, optional) – 控制是否計算完整或簡化的SVD,並因此影響返回的張量 UVh 的形狀。預設值:True

關鍵字參數
  • driver (str, optional) – 要使用的cuSOLVER方法的名稱。此關鍵字參數僅適用於CUDA輸入。可用選項包括:Nonegesvdgesvdjgesvda。預設值:None

  • out (tuple, optional) – 三個張量的輸出元組。如果為 None,則忽略。

返回值

一個名為 (U, S, Vh) 的具名元組,對應於上面的 UUSSVHV^{\text{H}}

即使 A 是複數,S 也始終是實數值。它也會以降序排列。

UVh 將具有與 A 相同的 dtype。左/右奇異向量將分別由 U 的列和 Vh 的行給出。

範例

>>> A = torch.randn(5, 3)
>>> U, S, Vh = torch.linalg.svd(A, full_matrices=False)
>>> U.shape, S.shape, Vh.shape
(torch.Size([5, 3]), torch.Size([3]), torch.Size([3, 3]))
>>> torch.dist(A, U @ torch.diag(S) @ Vh)
tensor(1.0486e-06)

>>> U, S, Vh = torch.linalg.svd(A)
>>> U.shape, S.shape, Vh.shape
(torch.Size([5, 5]), torch.Size([3]), torch.Size([3, 3]))
>>> torch.dist(A, U[:, :3] @ torch.diag(S) @ Vh)
tensor(1.0486e-06)

>>> A = torch.randn(7, 5, 3)
>>> U, S, Vh = torch.linalg.svd(A, full_matrices=False)
>>> torch.dist(A, U @ torch.diag_embed(S) @ Vh)
tensor(3.0957e-06)

文件

訪問 PyTorch 的完整開發者文檔

查看文檔

教學

獲取初學者和高級開發人員的深入教學

查看教學

資源

尋找開發資源並獲得問題解答

查看資源