評價此頁

torch.linalg.eigh#

torch.linalg.eigh(A, UPLO='L', *, out=None)#

計算複共軛厄米特矩陣或實對稱矩陣的特徵值分解。

K\mathbb{K}R\mathbb{R}C\mathbb{C},複共軛厄米特矩陣或實對稱矩陣 AKn×nA \in \mathbb{K}^{n \times n} 的**特徵值分解**定義為

A=Qdiag(Λ)QHQKn×n,ΛRnA = Q \operatorname{diag}(\Lambda) Q^{\text{H}}\mathrlap{\qquad Q \in \mathbb{K}^{n \times n}, \Lambda \in \mathbb{R}^n}

其中,當 QQ 是複數時,QHQ^{\text{H}} 是共軛轉置;當 QQ 是實數時,QHQ^{\text{H}} 是轉置。QQ 在實數情況下是正交的,在複數情況下是酉的。

支援浮點 (float)、雙精度浮點 (double)、複數浮點 (cfloat) 和複數雙精度浮點 (cdouble) 資料型別。還支援矩陣批處理,如果 `A` 是一個矩陣批處理,則輸出具有相同的批處理維度。

假定 A 是厄米特(或對稱)的,但內部不進行檢查,而是

  • 如果 UPLO= ‘L’(預設),則計算中僅使用矩陣的下三角部分。

  • 如果 UPLO= ‘U’,則僅使用矩陣的上三角部分。

特徵值按升序返回。

注意

當輸入在 CUDA 裝置上時,此函式會使該裝置與 CPU 同步。

注意

實對稱或複共軛厄米特矩陣的特徵值始終是實數。

警告

對稱矩陣的特徵向量不是唯一的,也不是相對於 A 連續的。由於這種不唯一性,不同的硬體和軟體可能會計算出不同的特徵向量。

這種不唯一性是由以下事實引起的:在實數情況下將特徵向量乘以 -1,或在複數情況下乘以 eiϕ,ϕRe^{i \phi}, \phi \in \mathbb{R} 會產生另一組有效的矩陣特徵向量。因此,損失函式不應依賴於特徵向量的相位,因為該量沒有明確定義。在計算此函式的梯度時,會對複數輸入進行檢查。因此,當輸入為複數且位於 CUDA 裝置上時,此函式的梯度計算會將該裝置與 CPU 同步。

警告

使用 eigenvectors 張量計算的梯度僅在 A 具有不同特徵值時才是有限的。此外,如果任何兩個特徵值之間的距離接近零,梯度將變得數值不穩定,因為它取決於透過 1minijλiλj\frac{1}{\min_{i \neq j} \lambda_i - \lambda_j} 的計算 λi\lambda_i 得到的。

警告

使用者可能會遇到 PyTorch 在使用 CUDA 版本早於 12.1 Update 1 的 CUDA 裝置上處理大型病態輸入矩陣時崩潰。更多詳細資訊請參閱 線性代數數值穩定性。如果發生這種情況,使用者可以(1)調整輸入矩陣使其病態程度降低,或者(2)使用 torch.backends.cuda.preferred_linalg_library() 來嘗試其他支援的後端。

另請參閱

torch.linalg.eigvalsh() 僅計算厄米特矩陣的特徵值。與 torch.linalg.eigh() 不同,eigvalsh() 的梯度始終是數值穩定的。

torch.linalg.cholesky() 用於厄米特矩陣的不同分解。Cholesky 分解比特徵值分解提供的資訊少,但計算速度快得多。

torch.linalg.eig() 用於(較慢的)計算非厄米特方陣特徵值分解的函式。

torch.linalg.svd() 用於(較慢的)計算任意形狀矩陣的更一般的 SVD 分解的函式。

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

引數
  • A (Tensor) – 形狀為 (*, n, n) 的張量,其中 * 是零個或多個批次維度,由對稱或埃爾米特矩陣組成。

  • UPLO (‘L’, ‘U’, optional) – 控制在計算中是使用 A 的上三角部分還是下三角部分。預設值:‘L’

關鍵字引數

out (tuple, optional) – 包含兩個張量的輸出元組。如果為 None 則忽略。預設為 None

返回

一個命名元組 (eigenvalues, eigenvectors),對應於上面的 Λ\LambdaQQ

eigenvalues 始終是實數值,即使 A 是複數。它們也將按升序排列。

eigenvectorsAdtype 相同,並且將包含作為其列的特徵向量。

示例:
>>> A = torch.randn(2, 2, dtype=torch.complex128)
>>> A = A + A.T.conj()  # creates a Hermitian matrix
>>> A
tensor([[2.9228+0.0000j, 0.2029-0.0862j],
        [0.2029+0.0862j, 0.3464+0.0000j]], dtype=torch.complex128)
>>> L, Q = torch.linalg.eigh(A)
>>> L
tensor([0.3277, 2.9415], dtype=torch.float64)
>>> Q
tensor([[-0.0846+-0.0000j, -0.9964+0.0000j],
        [ 0.9170+0.3898j, -0.0779-0.0331j]], dtype=torch.complex128)
>>> torch.dist(Q @ torch.diag(L.cdouble()) @ Q.T.conj(), A)
tensor(6.1062e-16, dtype=torch.float64)
>>> A = torch.randn(3, 2, 2, dtype=torch.float64)
>>> A = A + A.mT  # creates a batch of symmetric matrices
>>> L, Q = torch.linalg.eigh(A)
>>> torch.dist(Q @ torch.diag_embed(L) @ Q.mH, A)
tensor(1.5423e-15, dtype=torch.float64)