コンテンツにスキップ

対称固有値問題と特異値分解の計算:三重対角化・Sturm 列・Jacobi 法・精度の保証

対象読者: 本テーマの QR 法の章と行列ノルム・条件数の章を学び、特異値分解の定義を知っている人。固有値摂動に関する Weyl の不等式は章の中で証明します。

前提となる記事:固有値の計算 II:QR 法の収束・Hessenberg 化・陰的 Q の定理とシフト、行列のノルムと線形方程式の条件数:誘導ノルム・後退誤差・特異行列までの距離

生 Markdown

対称な行列の固有値(行列の「伸び縮みの大きさ」)や、一般の行列の特異値(行列がどれだけ空間をゆがめるかを表す数)を、コンピュータはどう計算し、その答えはどこまで信用できるのか。この章はその 2 つの問いに答えます。まず行列を扱いやすい形(帯状の形)に直し、その形に合った計算法で固有値を求めます。そのうえで、丸め誤差があっても答えの誤差がどのくらいに収まるかを、証明と数値実験で確かめます。読み終えると、eigh や svd の結果がなぜ信頼できるのか、固有ベクトルだけは信頼できない場合があるのはなぜか、を説明できるようになります。

  • 実対称行列は Householder 鏡映を使った変換で対称な三重対角行列(対角とそのすぐ隣にしか成分がない行列)に直せます(演算量 4n3/34n^3/3)。三重対角行列の固有値は、QR 法(1 回 O(n)O(n))、Sturm 列(固有値が xx より小さいものの個数を数える漸化式)による二分法(kk 番目の固有値を指定して求められる)、分割統治法・MRRR(どちらも §7 で紹介する、全固有ベクトルを速く求める方法)などで求めます。
  • Jacobi 法は、2 行 2 列の回転で非対角成分を 1 つずつ消していく算法です。1 回の回転で非対角成分の 2 乗和はちょうど 2apq22a_{pq}^2 減り、最大の成分を選ぶ古典的 Jacobi 法は off(Ak+1)2≤(1−2/(n(n−1))) off(Ak)2\mathrm{off}(A_{k+1})^2 \le (1 - 2/(n(n-1)))\,\mathrm{off}(A_k)^2 で収束します。
  • 対称行列の固有値計算が後退安定(出てきた答えが、元の行列を少しだけ動かした行列の厳密な答えになっていること。つまり計算した固有値が ∥E∥2≤cnu∥A∥2\|E\|_2 \le cnu\|A\|_2 の A+EA + E の厳密な固有値)なら、Weyl の不等式により各固有値の絶対誤差は cnu∥A∥2cnu\|A\|_2 以下です。固有ベクトルの誤差は固有値の隔たり δ\delta で割った ∥r∥/δ\|\boldsymbol{r}\|/\delta で抑えられ(sin θ 評価)、近い固有値の固有ベクトルは不安定です。
  • 特異値は Jordan–Wielandt 行列 (OAATO)\begin{pmatrix} O & A \\ A^{\mathsf{T}} & O \end{pmatrix} の固有値 ±σi\pm\sigma_i として対称固有値問題に帰着し、∣σi(A+E)−σi(A)∣≤∥E∥2|\sigma_i(A + E) - \sigma_i(A)| \le \|E\|_2 が成り立ちます。ATAA^{\mathsf{T}}A の固有値から計算すると、小さい特異値は桁を失います。
  • SVD の計算は、Householder 変換による二重対角化 A=U(BO)VTA = U\begin{pmatrix} B \\ O \end{pmatrix}V^{\mathsf{T}} と、二重対角行列 BB を対角が 00 の対称三重対角行列(Golub–Kahan の行列)の固有値問題に読み替えることで行います。

研究で最も多く呼ばれる固有値の関数は、対称(Hermite 行列)行列の eigh・eigvalsh と、特異値分解の svd です。対称行列の固有値問題は、一般の行列より 3 つの点で恵まれています。固有値は実数で、固有ベクトルは直交にとれ(定理 4.2[スペクトル定理])、固有値の摂動は行列の摂動のノルムで抑えられる(条件数 1)ことです。

本章では、QR 法の章 の算法を対称行列に特化し、さらに対称行列だけで使える算法(Sturm 列の二分法、Jacobi 法)を加えます。そのうえで「計算した固有値・固有ベクトルはどこまで正しいか」を、行列のノルムと条件数の章 の Weyl の不等式の系と、残差による固有ベクトルの評価で答えます。最後に特異値分解の計算を対称固有値問題に帰着させます。

大規模な疎行列の一部の固有値を求める Lanczos 法は、Krylov 部分空間法 I の章 で扱います。本章は密行列の全固有値を対象にします。

この章では行列は実とし、uu は単位丸め、ノルムは 2 ノルム ∥⋅∥2\|\cdot\|_2 と Frobenius ノルム ∥⋅∥F\|\cdot\|_F です。対称行列の固有値は、断らない限り大きい順に λ1(⋅)≥⋯≥λn(⋅)\lambda_1(\cdot) \ge \cdots \ge \lambda_n(\cdot) と並べます。

定理 2.1(Householder 変換による三重対角化)✓

実対称行列 A∈Rn×nA \in \mathbb{R}^{n\times n}(n≥3n \ge 3)について、n−2n - 2 個の Householder 鏡映(または単位行列)の積である直交行列 QQ があって、T=QTAQT = Q^{\mathsf{T}}AQ は対称な三重対角行列になる。対称性を使うと演算量は約 4n3/34n^3/3 である。

この定理のねらいは、固有値を求める前に、成分の多くが 00 の扱いやすい形へ固有値を変えずに直しておくことです。証明の前半は一般の場合の Hessenberg 化の結果を使い、後半は、鏡映を両側から掛けた結果が「階数 1 の行列 2 つの和」の形に整理できることを示して手間を数えます。

証明(定理 2.1)

存在は、Hessenberg 化(定理 4.1[固有値の計算 II])を対称行列に使えば、対称な Hessenberg 行列として三重対角行列が得られることから従います。

演算量: 第 kk 段で右下の m×mm\times m の対称ブロック A′A'(m=n−km = n - k)に鏡映 P=I−βvvTP = I - \beta\boldsymbol{v}\boldsymbol{v}^{\mathsf{T}} を両側から掛けます。p=βA′v\boldsymbol{p} = \beta A'\boldsymbol{v}、w=p−β2(vTp)v\boldsymbol{w} = \boldsymbol{p} - \tfrac{\beta}{2}(\boldsymbol{v}^{\mathsf{T}}\boldsymbol{p})\boldsymbol{v} とおくと、展開して

PA′P=A′−βvvTA′−βA′vvT+β2(vTA′v)vvT=A′−vwT−wvTPA'P = A' - \beta\boldsymbol{v}\boldsymbol{v}^{\mathsf{T}}A' - \beta A'\boldsymbol{v}\boldsymbol{v}^{\mathsf{T}} + \beta^2(\boldsymbol{v}^{\mathsf{T}}A'\boldsymbol{v})\boldsymbol{v}\boldsymbol{v}^{\mathsf{T}} = A' - \boldsymbol{v}\boldsymbol{w}^{\mathsf{T}} - \boldsymbol{w}\boldsymbol{v}^{\mathsf{T}}

です(vpT+pvT−β(vTp)vvT=vwT+wvT\boldsymbol{v}\boldsymbol{p}^{\mathsf{T}} + \boldsymbol{p}\boldsymbol{v}^{\mathsf{T}} - \beta(\boldsymbol{v}^{\mathsf{T}}\boldsymbol{p})\boldsymbol{v}\boldsymbol{v}^{\mathsf{T}} = \boldsymbol{v}\boldsymbol{w}^{\mathsf{T}} + \boldsymbol{w}\boldsymbol{v}^{\mathsf{T}})。対称な行列とベクトルの積 A′vA'\boldsymbol{v} が約 2m22m^2、対称な階数 2 の更新が下三角だけで約 2m22m^2 なので、1 段は約 4m24m^2、合計 ∑m4m2≈4n3/3\sum_m 4m^2 \approx 4n^3/3 です。

一般の Hessenberg 化の 10n3/310n^3/3 に比べ、対称性で手間が半分以下になります。固有ベクトルも要るときは QQ を累積する手間(約 4n3/34n^3/3)が加わります。

対称な三重対角行列 TT の対角を α1,…,αn\alpha_1, \ldots, \alpha_n、副対角を β1,…,βn−1\beta_1, \ldots, \beta_{n-1} とし、N(x)N(x) を「xx より小さい TT の固有値の個数(重複度込み)」とします。計算機援用証明の章の Sturm 列の定理(定理 5.1[行列計算の認証と最適化の証明書])により、漸化式

d1(x)=α1−x,dk(x)=αk−x−βk−12dk−1(x)d_1(x) = \alpha_1 - x,\qquad d_k(x) = \alpha_k - x - \frac{\beta_{k-1}^2}{d_{k-1}(x)}

の値がすべて定義されて 00 でない xx では、N(x)=#{k:dk(x)<0}N(x) = \#\{k : d_k(x) < 0\} が O(n)O(n) の演算で求まります。

次の命題の考え方は、数当てゲームの「半分に絞る」方法と同じです。「xx より小さい固有値は何個か」が安く数えられるので、xx を動かして個数が k−1k - 1 個から kk 個に変わる場所を挟み、区間を半分ずつ狭めて kk 番目の固有値に近づけます。

命題 3.1(Sturm 列による二分法)✓

TT の固有値を小さい順に μ1≤⋯≤μn\mu_1 \le \cdots \le \mu_n とし、1≤k≤n1 \le k \le n を固定する。a0<b0a_0 < b_0 が N(a0)≤k−1N(a_0) \le k - 1、N(b0)≥kN(b_0) \ge k を満たすとする(たとえば Gershgorin の円板 定理 2.2[行列の固有値評価と不等式] から a0=min⁡i(αi−∣βi−1∣−∣βi∣)a_0 = \min_i(\alpha_i - |\beta_{i-1}| - |\beta_i|) とし、b0b_0 をその最大より大きくとる。β0=βn=0\beta_0 = \beta_n = 0)。j=0,1,…j = 0, 1, \ldots について cj=(aj+bj)/2c_j = (a_j + b_j)/2 とし、N(cj)≥kN(c_j) \ge k なら (aj+1,bj+1)=(aj,cj)(a_{j+1}, b_{j+1}) = (a_j, c_j)、そうでなければ (aj+1,bj+1)=(cj,bj)(a_{j+1}, b_{j+1}) = (c_j, b_j) とする(各 cjc_j で Sturm 列は定義されているとする)。このとき

  1. すべての jj で aj≤μk<bja_j \le \mu_k < b_j、bj−aj=(b0−a0)/2jb_j - a_j = (b_0 - a_0)/2^j であり、∣cj−μk∣≤(b0−a0)/2j+1|c_j - \mu_k| \le (b_0 - a_0)/2^{j+1}。
  2. 幅を τ>0\tau > 0 以下にするのに要する反復は ⌈log⁡2((b0−a0)/τ)⌉\lceil\log_2((b_0 - a_0)/\tau)\rceil 回で、全体の演算量は O(nlog⁡2((b0−a0)/τ))O(n\log_2((b_0 - a_0)/\tau)) である。
証明(命題 3.1)

N(x)≤k−1N(x) \le k - 1 は「xx より小さい固有値は k−1k - 1 個以下」なので μk≥x\mu_k \ge x と同値で、N(x)≥kN(x) \ge k は μk<x\mu_k < x と同値です。初期条件から a0≤μk<b0a_0 \le \mu_k < b_0 で、更新の規則は N(aj)≤k−1N(a_j) \le k - 1 と N(bj)≥kN(b_j) \ge k を保つので、帰納法で aj≤μk<bja_j \le \mu_k < b_j です。区間は毎回半分になるので幅は (b0−a0)/2j(b_0 - a_0)/2^j で、中点 cjc_j と区間内の点 μk\mu_k の距離は幅の半分以下です。2 は (b0−a0)/2j≤τ(b_0 - a_0)/2^j \le \tau を解いたもので、1 回の N(cj)N(c_j) の計算は Sturm 列の定理(定理 5.1[行列計算の認証と最適化の証明書])により漸化式 d1,…,dnd_1, \ldots, d_n の O(n)O(n) の演算です。Gershgorin の円板の定理からすべての固有値は [a0,max⁡i(αi+∣βi−1∣+∣βi∣)][a_0, \max_i(\alpha_i + |\beta_{i-1}| + |\beta_i|)] に入るので、例の a0a_0, b0b_0 は初期条件を満たします(a0a_0 の左に固有値はなく、b0b_0 の左にすべての固有値がある)。

二分法の利点は、kk を指定して「下から kk 番目の固有値」だけを求められること、区間の中の固有値だけを求められること、そして互いに独立なので並列に計算できることです。固有値が求まった後の固有ベクトルは、冪乗法・逆反復の章 の逆反復で 1〜2 回の反復で求まります。SciPy では scipy.linalg.eigh_tridiagonal(..., lapack_driver="stebz") がこの方法(LAPACK の stebz)です。

Jacobi 法の発想は単純で、行列の「対角以外の成分」が全部 00 なら固有値は対角成分そのものなので、対角以外を回転で少しずつ 00 に近づけていく、というものです。次の定義と補題は、回転の形と、1 回の回転で対角以外の成分の 2 乗和がどれだけ減るかを調べます。

定義 4.1(非対角部分のノルムと Jacobi 回転)↗

正方行列 AA について off(A)=(∑i≠jaij2)1/2\mathrm{off}(A) = \bigl(\sum_{i\ne j}a_{ij}^2\bigr)^{1/2} とする。p<qp < q と c=cos⁡ϕc = \cos\phi, s=sin⁡ϕs = \sin\phi について、単位行列の (p,p),(p,q),(q,p),(q,q)(p,p), (p,q), (q,p), (q,q) 成分を c,s,−s,cc, s, -s, c に置き換えた直交行列 J=J(p,q,ϕ)J = J(p, q, \phi) を Jacobi 回転という。

補題 4.2(1 回の回転で減る量)✓

AA を実対称行列、p<qp < q、apq≠0a_{pq} \ne 0 とする。ϕ\phi を

(cos⁡2ϕ, sin⁡2ϕ)=(app−aqq, −2apq)(app−aqq)2+4apq2(\cos2\phi,\ \sin2\phi) = \frac{(a_{pp} - a_{qq},\ -2a_{pq})}{\sqrt{(a_{pp} - a_{qq})^2 + 4a_{pq}^2}}

と選ぶと、B=JTAJB = J^{\mathsf{T}}AJ(J=J(p,q,ϕ)J = J(p, q, \phi))は対称で bpq=0b_{pq} = 0 であり、

off(B)2=off(A)2−2apq2\mathrm{off}(B)^2 = \mathrm{off}(A)^2 - 2a_{pq}^2

が成り立つ。

証明(補題 4.2)

AJAJ の第 pp 列は c ap−s aqc\,\boldsymbol{a}_p - s\,\boldsymbol{a}_q、第 qq 列は s ap+c aqs\,\boldsymbol{a}_p + c\,\boldsymbol{a}_q(aj\boldsymbol{a}_j は AA の第 jj 列)で、JTJ^{\mathsf{T}} の第 pp 行は第 pp 成分 cc・第 qq 成分 −s-s だけをもちます。よって

bpq=c(sapp+capq)−s(saqp+caqq)=(c2−s2)apq+cs(app−aqq)=apqcos⁡2ϕ+12(app−aqq)sin⁡2ϕb_{pq} = c(sa_{pp} + ca_{pq}) - s(sa_{qp} + ca_{qq}) = (c^2 - s^2)a_{pq} + cs(a_{pp} - a_{qq}) = a_{pq}\cos2\phi + \tfrac12(a_{pp} - a_{qq})\sin2\phi

で、ϕ\phi の選び方を代入すると apq(app−aqq)−apq(app−aqq)a_{pq}(a_{pp} - a_{qq}) - a_{pq}(a_{pp} - a_{qq}) に正の定数を掛けたもので 00 です。

直交行列を掛けても Frobenius ノルムは変わらないので ∥B∥F=∥A∥F\|B\|_F = \|A\|_F です。JJ は第 pp, qq 行・列しか混ぜないので、BB の対角成分のうち変わるのは bppb_{pp}, bqqb_{qq} だけです。さらに、{p,q}\{p, q\} の 2 行 2 列の部分行列について (bppbpqbqpbqq)=RT(appapqaqpaqq)R\begin{pmatrix} b_{pp} & b_{pq} \\ b_{qp} & b_{qq} \end{pmatrix} = R^{\mathsf{T}}\begin{pmatrix} a_{pp} & a_{pq} \\ a_{qp} & a_{qq} \end{pmatrix}R(R=(cs−sc)R = \begin{pmatrix} c & s \\ -s & c \end{pmatrix} は直交)なので、この部分の Frobenius ノルムも等しく、bpq=bqp=0b_{pq} = b_{qp} = 0 から bpp2+bqq2=app2+aqq2+2apq2b_{pp}^2 + b_{qq}^2 = a_{pp}^2 + a_{qq}^2 + 2a_{pq}^2 です。対角成分の 2 乗和は 2apq22a_{pq}^2 増え、全体の 2 乗和は変わらないので、非対角の 2 乗和は 2apq22a_{pq}^2 減ります。

定理 4.3(古典的 Jacobi 法の収束)✓

A0=AA_0 = A を nn 次実対称行列(n≥2n \ge 2)とし、AkA_k の非対角成分のうち絶対値最大の (p,q)(p, q)(p<qp < q)を選んで 補題 4.2 の回転で Ak+1=JkTAkJkA_{k+1} = J_k^{\mathsf{T}}A_kJ_k とする(off(Ak)=0\mathrm{off}(A_k) = 0 なら止める)。このとき

off(Ak+1)2≤(1−2n(n−1))off(Ak)2\mathrm{off}(A_{k+1})^2 \le \Bigl(1 - \frac{2}{n(n-1)}\Bigr)\mathrm{off}(A_k)^2

であり、AkA_k の対角成分を大きい順に並べた d1(k)≥⋯≥dn(k)d_1^{(k)} \ge \cdots \ge d_n^{(k)} は ∣di(k)−λi(A)∣≤off(Ak)|d_i^{(k)} - \lambda_i(A)| \le \mathrm{off}(A_k) を満たす。とくに対角成分は固有値に収束する。

証明(定理 4.3)

off(Ak)2\mathrm{off}(A_k)^2 は n(n−1)n(n-1) 個の非対角成分の 2 乗和で、選んだ apq2a_{pq}^2 はその最大なので apq2≥off(Ak)2/(n(n−1))a_{pq}^2 \ge \mathrm{off}(A_k)^2/(n(n-1)) です。補題 4.2 から off(Ak+1)2=off(Ak)2−2apq2\mathrm{off}(A_{k+1})^2 = \mathrm{off}(A_k)^2 - 2a_{pq}^2 で、評価を得ます。

AkA_k は AA と直交相似なので固有値が等しく(積の定理 定理 6.1[行列式とその性質] から特性多項式が等しい)、DkD_k を AkA_k の対角部分とすると Ak=Dk+(Ak−Dk)A_k = D_k + (A_k - D_k) です。対称行列 Ak−DkA_k - D_k の 2 ノルムは Frobenius ノルム off(Ak)\mathrm{off}(A_k) 以下なので、エルミート行列の固有値の摂動(系 8.1[行列のノルムと線形方程式の条件数])から、DkD_k の固有値(=対角成分を大きい順に並べたもの)と AkA_k の固有値の差は off(Ak)\mathrm{off}(A_k) 以下です。

1 掃引(n(n−1)/2n(n-1)/2 回の回転)あたりの縮小率は評価からは (1−2/(n(n−1)))n(n−1)/4≈e−1/2(1 - 2/(n(n-1)))^{n(n-1)/4} \approx e^{-1/2} にすぎませんが、実際には掃引を重ねると収束は 2 次になります(注意 4.4)。最大の成分を探す手間を省き、(p,q)(p, q) を決まった順に回る巡回 Jacobi 法が実用の形です。

# Python 3.12.10 / NumPy 2.5.2(x86-64)/乱数種 20261006
import numpy as np
rng = np.random.default_rng(20261006)
n = 8
G = rng.standard_normal((n, n))
A = (G + G.T) / 2
ref = np.linalg.eigvalsh(A)
def offd(B): # 非対角部分
return B - np.diag(np.diag(B))
N = n * (n - 1) // 2 # 1 掃引 = N 回の回転
print("掃引 off(A) 比 評価の比 (1-2/(n(n-1)))^(N/2)")
B, prev = A.copy(), np.linalg.norm(offd(A))
print(f" 0 {prev:.1e}")
for sweep in range(1, 4):
for _ in range(N):
p, q = np.unravel_index(np.argmax(abs(offd(B))), B.shape)
th = 0.5 * np.arctan2(-2 * B[p, q], B[p, p] - B[q, q])
J = np.eye(n)
J[p, p] = J[q, q] = np.cos(th)
J[p, q], J[q, p] = np.sin(th), -np.sin(th)
B = J.T @ B @ J
o = np.linalg.norm(offd(B))
print(f"{sweep:3d} {o:.1e} {o / prev:.1e}"
f" {(1 - 2 / (n * (n - 1))) ** (N / 2):.2f}")
prev = o
d = np.sort(np.diag(B))
print("固有値の誤差 < 1e-13:", np.abs(d - ref).max() < 1e-13)
掃引 off(A) 比 評価の比 (1-2/(n(n-1)))^(N/2)
0 5.8e+00
1 2.8e-01 4.8e-02 0.60
2 1.5e-03 5.5e-03 0.60
3 4.2e-09 2.8e-06 0.60
固有値の誤差 < 1e-13: True

検算. (a) 3 掃引後の対角成分は numpy.linalg.eigvalsh の固有値と 10−1310^{-13} 以内で一致します。定理 4.3 の保証は off(A3)≈4×10−9\mathrm{off}(A_3) \approx 4\times10^{-9} までですが、実際の誤差はずっと小さく、これは対称行列の固有値の誤差が非対角部分の 2 次で効くためです(補題 3.4[固有値の計算 I] と同じ現象)。(b) 回転はコードの arctan2 で 補題 4.2 の ϕ\phi をそのまま実装しています。(c) 1 掃引ごとの比は評価の 0.600.60 をはるかに下回り、off\mathrm{off} は 5.8→0.28→1.5×10−3→4.2×10−95.8 \to 0.28 \to 1.5\times10^{-3} \to 4.2\times10^{-9} と減り、off(A0)\mathrm{off}(A_0) に対する比で見ると 4.8×10−2→2.6×10−4→7.3×10−104.8\times10^{-2} \to 2.6\times10^{-4} \to 7.3\times10^{-10} と、1 掃引で桁数が 2 倍以上になっています(漸近 2 次収束)。

注意 4.4(Jacobi 法の 2 次収束と高い相対精度)

巡回 Jacobi 法は、固有値が相異なれば漸近的に 2 次収束することが知られています(掃引の順序に関する精密な解析が要る)。また、Jacobi 法は小さい固有値も相対誤差で正確に求められる場合があり(たとえば A=DHDA = DHD、DD が対角で HH がよい条件の正定値行列のとき)、QR 法にはない利点です。いずれも本章では使いません。Golub–Van Loan『Matrix Computations』4th ed. §8.5、J. Demmel, K. Veselić, “Jacobi’s method is more accurate than QR”, SIAM J. Matrix Anal. Appl. 13 (1992) を参照してください。

5. 計算した固有値・固有ベクトルの精度

Section titled “5. 計算した固有値・固有ベクトルの精度”

系 5.1(後退安定な固有値計算の精度)✓

AA を実対称行列とし、計算した値 λ^1≥⋯≥λ^n\hat{\lambda}_1 \ge \cdots \ge \hat{\lambda}_n が、ある対称行列 EE(∥E∥2≤η∥A∥2\|E\|_2 \le \eta\|A\|_2)について A+EA + E の厳密な固有値であるとする。このとき ∣λ^i−λi(A)∣≤η∥A∥2|\hat{\lambda}_i - \lambda_i(A)| \le \eta\|A\|_2(すべての ii)である。

証明(系 5.1)

λ^i=λi(A+E)\hat{\lambda}_i = \lambda_i(A + E) なので、エルミート行列の固有値の摂動(系 8.1[行列のノルムと線形方程式の条件数])から ∣λ^i−λi(A)∣≤∥E∥2≤η∥A∥2|\hat{\lambda}_i - \lambda_i(A)| \le \|E\|_2 \le \eta\|A\|_2 です。

三重対角化・対称 QR 法・Jacobi 法はいずれも直交変換を積み重ねる算法で、後退誤差は η=cnu\eta = cnu(cc は小さな定数)の程度です(QR 分解の章 の Householder 変換の後退安定性と同じ議論。デフレーションの誤差は 命題 5.4[固有値の計算 II])。したがってどの固有値も絶対誤差 cnu∥A∥2cnu\|A\|_2 の程度で求まります。ただし相対誤差ではないので、∣λi∣≪∥A∥2|\lambda_i| \ll \|A\|_2 の小さい固有値は桁を失いえます。

固有ベクトルは事情が違います。次の評価が示すように、誤差は固有値の隔たりに反比例します。

次の定理の記号は、V\mathcal{V} が固有値 λ\lambda の固有空間(その固有値の固有ベクトル全体が作る 部分空間)、δ\delta が θ\theta から見て最も近い「別の固有値」までの距離、r\boldsymbol{r} が「x\boldsymbol{x} が固有ベクトルからどれだけずれているか」を測る残差です。言いたいことは、残差が小さくても、別の固有値が近いと角度は大きくずれうる、ということです。

定理 5.2(残差による固有ベクトルの評価(sin θ 評価))✓

AA を Hermite 行列、x\boldsymbol{x} を単位ベクトル、θ=x∗Ax\theta = \boldsymbol{x}^{*}A\boldsymbol{x}、r=Ax−θx\boldsymbol{r} = A\boldsymbol{x} - \theta\boldsymbol{x} とする。λ\lambda を AA の固有値、V\mathcal{V} をその固有空間とし、

δ=min⁡{∣λ′−θ∣:λ′ は λ と異なる A の固有値}>0\delta = \min\{|\lambda' - \theta| : \lambda' \text{ は } \lambda \text{ と異なる } A \text{ の固有値}\} > 0

とする。このとき sin⁡∠(x,V)≤∥r∥2/δ\sin\angle(\boldsymbol{x}, \mathcal{V}) \le \|\boldsymbol{r}\|_2/\delta である。とくに λ\lambda が単純で v\boldsymbol{v} がその固有ベクトルなら sin⁡∠(x,v)≤∥r∥2/δ\sin\angle(\boldsymbol{x}, \boldsymbol{v}) \le \|\boldsymbol{r}\|_2/\delta。

証明(定理 5.2)

正規直交な固有ベクトル u1,…,un\boldsymbol{u}_1, \ldots, \boldsymbol{u}_n(固有値 λj\lambda_j)で x=∑jcjuj\boldsymbol{x} = \sum_jc_j\boldsymbol{u}_j と展開します(定理 4.2[スペクトル定理])。V\mathcal{V} は λj=λ\lambda_j = \lambda となる uj\boldsymbol{u}_j で張られるので(V\mathcal{V} の元を展開すると、λj≠λ\lambda_j \ne \lambda の成分は 00)、V\mathcal{V} への直交射影は ∑λj=λcjuj\sum_{\lambda_j=\lambda}c_j\boldsymbol{u}_j で、

sin⁡2∠(x,V)=∑λj≠λ∣cj∣2\sin^2\angle(\boldsymbol{x}, \mathcal{V}) = \sum_{\lambda_j\ne\lambda}|c_j|^2

です(定義 2.1[固有値の計算 I])。一方 r=∑j(λj−θ)cjuj\boldsymbol{r} = \sum_j(\lambda_j - \theta)c_j\boldsymbol{u}_j なので

∥r∥22=∑j(λj−θ)2∣cj∣2≥∑λj≠λ(λj−θ)2∣cj∣2≥δ2sin⁡2∠(x,V)\|\boldsymbol{r}\|_2^2 = \sum_j(\lambda_j - \theta)^2|c_j|^2 \ge \sum_{\lambda_j\ne\lambda}(\lambda_j - \theta)^2|c_j|^2 \ge \delta^2\sin^2\angle(\boldsymbol{x}, \mathcal{V})

です。単純な場合は V=span⁡{v}\mathcal{V} = \operatorname{span}\{\boldsymbol{v}\} です。

これは Davis–Kahan の sin θ 定理の 1 次元の場合です。計算した固有ベクトル x^\hat{\boldsymbol{x}} が A+EA + E の厳密な固有ベクトルなら、Ax^−θ^x^A\hat{\boldsymbol{x}} - \hat\theta\hat{\boldsymbol{x}} の大きさは ∥E∥2\|E\|_2 の程度(命題 7.1[固有値の計算 I] から ∥r∥2≤∥(A−λ^I)x^∥2=∥Ex^∥2\|\boldsymbol{r}\|_2 \le \|(A - \hat\lambda I)\hat{\boldsymbol{x}}\|_2 = \|E\hat{\boldsymbol{x}}\|_2)なので、固有ベクトルの角の誤差はおよそ ∥E∥2/δ\|E\|_2/\delta です。固有値が近い(δ\delta が小さい)と、固有ベクトルは大きく動きえます。

例 5.3(近い固有値では固有ベクトルだけが大きく動く)

ε>0\varepsilon > 0 として A=(1+ε001−ε)A = \begin{pmatrix} 1 + \varepsilon & 0 \\ 0 & 1 - \varepsilon \end{pmatrix}、E=(0εε0)E = \begin{pmatrix} 0 & \varepsilon \\ \varepsilon & 0 \end{pmatrix} とします。A+E=I+ε(111−1)A + E = I + \varepsilon\begin{pmatrix} 1 & 1 \\ 1 & -1 \end{pmatrix} の固有値は 1±2ε1 \pm \sqrt{2}\varepsilon で、AA の固有値 1±ε1 \pm \varepsilon からの変化は (2−1)ε≤∥E∥2=ε(\sqrt{2} - 1)\varepsilon \le \|E\|_2 = \varepsilon と小さいままです。ところが A+EA + E の固有ベクトルは (cos⁡(π/8),sin⁡(π/8))(\cos(\pi/8), \sin(\pi/8)) などで、AA の固有ベクトル e1\boldsymbol{e}_1, e2\boldsymbol{e}_2 から ε\varepsilon によらず 22.5°22.5° 回転しています。固有値の隔たり 2ε2\varepsilon と摂動の大きさ ε\varepsilon が同じ程度なので、sin θ 評価は sin⁡∠≤O(1)\sin\angle \le O(1) しか保証せず、実際に O(1)O(1) の回転が起きています。固有値が重なると固有ベクトルは一意でなくなるので、近い固有値の固有ベクトルを個別に求めるのではなく、それらが張る部分空間を求めるのが正しい問題設定です(定理 5.2 の V\mathcal{V} を固有値の塊の不変部分空間に替えた評価が Davis–Kahan の定理です)。

次の 2 つのコードで確かめます。1 つ目は scipy.linalg.eigh の 3 つの駆動ルーチン(後の表)の残差と直交性、2 つ目は固有値の間隔 gg を変えたときの固有ベクトルの誤差です。

# Python 3.12.10 / NumPy 2.5.2 / SciPy 1.18.1(x86-64, OpenBLAS)/乱数種 20261006
import numpy as np
from scipy.linalg import eigh
rng = np.random.default_rng(20261006)
u = 2.0**-53
def band(x): # 末尾の桁は BLAS で変わるので桁の帯で示す
return "< 1" if x < 1 else "< 100" if x < 100 else ">= 100"
print(" n driver 残差/(n u) 直交性/(n u)")
for n in (100, 400):
G = rng.standard_normal((n, n))
A = (G + G.T) / 2
nA = np.linalg.norm(A, 2)
for drv in ("ev", "evd", "evr"):
w, V = eigh(A, driver=drv)
res = np.linalg.norm(A @ V - V * w, 2) / nA
orth = np.linalg.norm(V.T @ V - np.eye(n), 2)
print(f"{n:4d} {drv:4s} {band(res / (n * u)):>9s}"
f" {band(orth / (n * u)):>9s}")
n = 400 # 三重対角 Toeplitz(2, -1)
T = 2 * np.eye(n) - np.eye(n, k=1) - np.eye(n, k=-1)
k = np.arange(1, n + 1)
exact = np.sort(4 * np.sin(k * np.pi / (2 * (n + 1))) ** 2)
err = np.abs(eigh(T, eigvals_only=True) - exact).max()
print("Toeplitz: 最大誤差/(n u ||T||) < 1:", err / (n * u * 4) < 1)
n driver 残差/(n u) 直交性/(n u)
100 ev < 1 < 1
100 evd < 1 < 1
100 evr < 1 < 100
400 ev < 1 < 1
400 evd < 1 < 1
400 evr < 1 < 100
Toeplitz: 最大誤差/(n u ||T||) < 1: True

検算. (a) 三重対角 Toeplitz 行列の固有値は閉じた形 4sin⁡2(kπ/(2(n+1)))4\sin^2(k\pi/(2(n+1)))(ノルムの章 の三重対角 Toeplitz 行列の補題)で、誤差は nu∥T∥2nu\|T\|_2 未満(∥T∥2<4\|T\|_2 < 4)と 系 5.1 の予言の範囲にあります。(b) 3 つの駆動ルーチンはいずれも残差 ∥AV−VΛ∥2/∥A∥2\|AV - V\Lambda\|_2/\|A\|_2 が nunu 未満で、後退安定です。直交性は ev・evd が nunu 未満、evr(MRRR)は nunu の数倍〜十数倍で、MRRR が直交性を固有ベクトルの計算の精度で確保する算法であることの反映です(注意 7.2)。(c) nn を 4 倍にしても nunu で割った値は同じ帯に入り、誤差が nun u に比例する程度の評価と整合します。値の末尾は BLAS のスレッド数で変わるので、帯で示しました。

# Python 3.12.10 / NumPy 2.5.2(x86-64, OpenBLAS)/乱数種 20261006
import numpy as np
rng = np.random.default_rng(20261006)
n = 50
Q, _ = np.linalg.qr(rng.standard_normal((n, n)))
G = rng.standard_normal((n, n))
E = (G + G.T) / 2
E *= 1e-8 / np.linalg.norm(E, 2) # ||E||_2 = 1e-8
print(" 間隔 g sin(角) ||r||/delta ||E||/g")
for g in (1e-2, 1e-4, 1e-6, 1e-7):
lam = np.concatenate(([1.0, 1.0 + g], np.linspace(2, 3, n - 2)))
A = (Q * lam) @ Q.T
w, W = np.linalg.eigh(A + E)
x = W[:, 0] # A + E の最小の固有ベクトル
v = Q[:, 0] # A の最小の固有ベクトル
s = np.linalg.norm(x - (v @ x) * v)
th = x @ A @ x
r = np.linalg.norm(A @ x - th * x)
delta = np.min(np.abs(lam[1:] - th)) # 他の固有値との隔たり
print(f" {g:.0e} {s:.1e} {r / delta:.1e} {1e-8 / g:.0e}")
間隔 g sin(角) ||r||/delta ||E||/g
1e-02 2.0e-08 5.4e-07 1e-06
1e-04 1.9e-06 5.4e-05 1e-04
1e-06 1.9e-04 5.4e-03 1e-02
1e-07 1.9e-03 5.4e-02 1e-01

検算. (a) AA の固有値と固有ベクトルは構成に使った値で、角はその固有ベクトルとの間で測っています。(b) どの行でも sin⁡∠≤∥r∥2/δ\sin\angle \le \|\boldsymbol{r}\|_2/\delta が成り立ち、定理 5.2 の評価の内側にあります(∥r∥2/δ\|\boldsymbol{r}\|_2/\delta は ∥E∥2/g\|E\|_2/g と同じ程度)。(c) 間隔 gg を 100 分の 1 にすると、角の誤差も評価もちょうど 100 倍になり、1/g1/g に比例します。摂動 ∥E∥2=10−8\|E\|_2 = 10^{-8} は一定なので、固有値の誤差は 10−810^{-8} 以下のまま、固有ベクトルの誤差だけが隔たりに反比例して増えています。

ここまでは対称行列の話でした。特異値は一般の長方形の行列にも定まりますが、AA とその転置を右上と左下に置いた対称な大きい行列を作れば、対称行列の固有値の話に持ち込めます。次の定理は、その大きい行列の固有値が特異値とその符号違い(と、m>nm > n のときの余りの 00)であることを示します。

定理 6.1(Jordan–Wielandt の拡大行列)✓

A∈Cm×nA \in \mathbb{C}^{m\times n}(m≥nm \ge n)の特異値を σ1≥⋯≥σn≥0\sigma_1 \ge \cdots \ge \sigma_n \ge 0(rank⁡A\operatorname{rank}A より先は 00 とする)とする。(m+n)(m+n) 次の Hermite 行列

C(A)=(OAA∗O)C(A) = \begin{pmatrix} O & A \\ A^{*} & O \end{pmatrix}

の固有値は σ1,…,σn,−σ1,…,−σn\sigma_1, \ldots, \sigma_n, -\sigma_1, \ldots, -\sigma_n と m−nm - n 個の 00 である。とくに大きい順に λi(C(A))=σi\lambda_i(C(A)) = \sigma_i(i≤ni \le n)である。

証明(定理 6.1)

特異値分解 A=UΣV∗A = U\Sigma V^{*}(定理 4.1[行列の分解と標準形])の UU の列を u1,…,um\boldsymbol{u}_1, \ldots, \boldsymbol{u}_m、VV の列を v1,…,vn\boldsymbol{v}_1, \ldots, \boldsymbol{v}_n とします。AV=UΣAV = U\Sigma、A∗U=VΣTA^{*}U = V\Sigma^{\mathsf{T}} から、i≤ni \le n で Avi=σiuiA\boldsymbol{v}_i = \sigma_i\boldsymbol{u}_i、A∗ui=σiviA^{*}\boldsymbol{u}_i = \sigma_i\boldsymbol{v}_i、i>ni > n で A∗ui=0A^{*}\boldsymbol{u}_i = \boldsymbol{0} です(ΣT\Sigma^{\mathsf{T}} の第 ii 列は i>ni > n で 00)。よって i≤ni \le n について

C(A)(ui±vi)=(±AviA∗ui)=±σi(ui±vi)C(A)\begin{pmatrix} \boldsymbol{u}_i \\ \pm\boldsymbol{v}_i \end{pmatrix} = \begin{pmatrix} \pm A\boldsymbol{v}_i \\ A^{*}\boldsymbol{u}_i \end{pmatrix} = \pm\sigma_i\begin{pmatrix} \boldsymbol{u}_i \\ \pm\boldsymbol{v}_i \end{pmatrix}

(複号同順)で、i>ni > n では C(A)(ui;0)=0C(A)(\boldsymbol{u}_i; \boldsymbol{0}) = \boldsymbol{0} です。これら 2n+(m−n)=m+n2n + (m - n) = m + n 個のベクトルを 2\sqrt{2} や 11 で正規化すると、ui\boldsymbol{u}_i たちと vi\boldsymbol{v}_i たちがそれぞれ正規直交であることから互いに正規直交です(たとえば (ui;vi)(\boldsymbol{u}_i; \boldsymbol{v}_i) と (ui;−vi)(\boldsymbol{u}_i; -\boldsymbol{v}_i) の内積は 1−1=01 - 1 = 0)。m+nm + n 次元の正規直交な固有ベクトルの基底が得られたので、固有値は上のもので尽きます。σn≥0\sigma_n \ge 0 なので、大きい順の先頭 nn 個は σ1,…,σn\sigma_1, \ldots, \sigma_n です。

系 6.2(特異値の摂動)✓

A,E∈Cm×nA, E \in \mathbb{C}^{m\times n}(m≥nm \ge n)について、すべての i≤ni \le n で ∣σi(A+E)−σi(A)∣≤∥E∥2|\sigma_i(A + E) - \sigma_i(A)| \le \|E\|_2 である。

証明(系 6.2)

C(A+E)=C(A)+C(E)C(A + E) = C(A) + C(E) です。Hermite 行列 HH の 2 ノルムは固有値の絶対値の最大です(固有ベクトルの正規直交基底で展開すると ∥Hx∥22=∑jλj2∣cj∣2\|H\boldsymbol{x}\|_2^2 = \sum_j\lambda_j^2|c_j|^2)。定理 6.1 から C(E)C(E) の固有値の絶対値の最大は σ1(E)\sigma_1(E) で、これは ∥E∥2\|E\|_2 に等しい(命題 4.2[行列のノルムと線形方程式の条件数] の 3)ので ∥C(E)∥2=∥E∥2\|C(E)\|_2 = \|E\|_2 です。定理 6.1 の後半とエルミート行列の固有値の摂動(系 8.1[行列のノルムと線形方程式の条件数])から ∣σi(A+E)−σi(A)∣=∣λi(C(A+E))−λi(C(A))∣≤∥C(E)∥2=∥E∥2|\sigma_i(A + E) - \sigma_i(A)| = |\lambda_i(C(A + E)) - \lambda_i(C(A))| \le \|C(E)\|_2 = \|E\|_2 です。

特異値も固有値と同じく条件数 1 の問題で、後退安定な算法なら各特異値の絶対誤差は cnu∥A∥2=cnu σ1cnu\|A\|_2 = cnu\,\sigma_1 の程度です。ところが「ATAA^{\mathsf{T}}A の固有値の平方根」として計算すると、こうはなりません。

例 6.3(ATAA^T A を経由すると小さい特異値が失われる)

ATAA^{\mathsf{T}}A を浮動小数で作って固有値を計算すると、系 5.1 の誤差は ∥ATA∥2=σ12\|A^{\mathsf{T}}A\|_2 = \sigma_1^2 に対して uu の程度、つまり固有値 σi2\sigma_i^2 の絶対誤差が uσ12u\sigma_1^2 の程度です。σi\sigma_i に戻すと誤差は約 uσ12/(2σi)u\sigma_1^2/(2\sigma_i) で、σi≲u σ1≈10−8σ1\sigma_i \lesssim \sqrt{u}\,\sigma_1 \approx 10^{-8}\sigma_1 の特異値は 1 桁も正しくありません。直接 SVD を計算すれば誤差は uσ1u\sigma_1 の程度なので、σi≫uσ1\sigma_i \gg u\sigma_1 である限り何桁かは正しく求まります。

# Python 3.12.10 / NumPy 2.5.2(x86-64, OpenBLAS)/乱数種 20261006
import numpy as np
rng = np.random.default_rng(20261006)
m, n = 60, 13
sig = 10.0 ** -np.arange(n) # 1, 1e-1, ..., 1e-12
U, _ = np.linalg.qr(rng.standard_normal((m, n)))
V, _ = np.linalg.qr(rng.standard_normal((n, n)))
A = (U * sig) @ V.T
s1 = np.linalg.svd(A, compute_uv=False)
ev = np.linalg.eigvalsh(A.T @ A)[::-1]
s2 = np.sqrt(np.maximum(ev, 0.0))
print(" sigma svd の相対誤差 sqrt(eig(A^T A)) の相対誤差")
for i in (0, 3, 6, 8, 10, 12):
e1 = abs(s1[i] - sig[i]) / sig[i]
e2 = abs(s2[i] - sig[i]) / sig[i]
t1 = "< 1e-6" if e1 < 1e-6 else f"{e1:.0e}"
t2 = "< 1e-6" if e2 < 1e-6 else f"{e2:.0e}"
print(f" 1e-{i:<2d} {t1:>8s} {t2:>8s}")
sigma svd の相対誤差 sqrt(eig(A^T A)) の相対誤差
1e-0 < 1e-6 < 1e-6
1e-3 < 1e-6 < 1e-6
1e-6 < 1e-6 < 1e-6
1e-8 < 1e-6 7e-04
1e-10 < 1e-6 2e+01
1e-12 2e-06 1e+00

検算. (a) 参照値は構成に使った特異値 10−i10^{-i} です(格納した AA 自体が丸めで uσ1u\sigma_1 程度ずれるので、10−1210^{-12} では SVD でも相対誤差 10−610^{-6} の程度が残ります。これは 系 6.2 の ∥E∥2≈u\|E\|_2 \approx u による u/σi≈10−4u/\sigma_i \approx 10^{-4} 以下という予言の範囲です)。(b) 同じ行列について、SVD(gesdd)と ATAA^{\mathsf{T}}A の固有値という 2 つの方法を比べています。(c) ATAA^{\mathsf{T}}A 経由の誤差は σ=10−8≈u\sigma = 10^{-8} \approx \sqrt{u} で目に見えるようになり、それより小さい特異値では 11 以上(桁が残らない)になります。例 6.3 の uσ12/σi2u\sigma_1^2/\sigma_i^2 の相対誤差の見積もりは上界で、実際の値はそれ以下です。

6.1. 二重対角化と Golub–Kahan の三重対角行列

Section titled “6.1. 二重対角化と Golub–Kahan の三重対角行列”

SVD の計算は、ATAA^{\mathsf{T}}A を作らずに、AA に左右から別々の直交変換を掛けて行います。

定理 6.4(Householder 変換による二重対角化)✓

A∈Rm×nA \in \mathbb{R}^{m\times n}(m≥n≥2m \ge n \ge 2)について、Householder 鏡映(または単位行列)の積である直交行列 U∈Rm×mU \in \mathbb{R}^{m\times m}、V∈Rn×nV \in \mathbb{R}^{n\times n} があって

UTAV=(BO),B=(d1e1d2⋱⋱en−1dn)U^{\mathsf{T}}AV = \begin{pmatrix} B \\ O \end{pmatrix},\qquad B = \begin{pmatrix} d_1 & e_1 & & \\ & d_2 & \ddots & \\ & & \ddots & e_{n-1} \\ & & & d_n \end{pmatrix}

(BB は上二重対角)となる。AA と BB の特異値は等しい。演算量は約 4mn2−4n3/34mn^2 - 4n^3/3 である。

証明(定理 6.4)

k=1,…,nk = 1, \ldots, n の順に、左から鏡映 UkU_k を掛けて第 kk 列の第 k+1k+1 行以下を 00 にし、k≤n−2k \le n - 2 なら右から鏡映 VkV_k を掛けて第 kk 行の第 k+2k+2 列以降を 00 にします。Uk=diag⁡(Ik−1,U~k)U_k = \operatorname{diag}(I_{k-1}, \tilde{U}_k) は第 kk 列の第 kk 行以下のベクトルの Householder 鏡映(命題 3.2[QR 分解]。ベクトルが 0\boldsymbol{0} なら単位行列)、Vk=diag⁡(Ik,V~k)V_k = \operatorname{diag}(I_k, \tilde{V}_k) は第 kk 行の第 k+1k+1 列以降のベクトル(の転置)の Householder 鏡映です。

UkU_k は第 kk 行以下だけを混ぜるので、すでに作った第 1,…,k−11, \ldots, k-1 行(第 k−1k-1 行は第 k−1k-1, kk 列以外が 00)と、第 1,…,k−11, \ldots, k-1 列の第 kk 行以下の 00 を壊しません。VkV_k は第 k+1k+1 列以降だけを混ぜるので、第 1,…,k1, \ldots, k 列(とくに今作った第 kk 列の 00)を壊しません。帰納法で、最後に得られる行列は上二重対角の BB の下に OO を置いた形です。U=U1⋯UnU = U_1\cdots U_n、V=V1⋯Vn−2V = V_1\cdots V_{n-2} とします。

特異値が等しいのは、A=U(BO)VTA = U\begin{pmatrix} B \\ O \end{pmatrix}V^{\mathsf{T}} に BB の特異値分解 B=UBΣBVBTB = U_B\Sigma_BV_B^{\mathsf{T}} を代入すると、A=(Udiag⁡(UB,I))(ΣBO)(VVB)TA = \bigl(U\operatorname{diag}(U_B, I)\bigr)\begin{pmatrix} \Sigma_B \\ O \end{pmatrix}(VV_B)^{\mathsf{T}} が AA の特異値分解になり、Σ\Sigma の対角は特異値分解で一意に定まる(ATAA^{\mathsf{T}}A の固有値の平方根、定理 4.1[行列の分解と標準形])からです。演算量は、p=m−kp = m - k, q=n−kq = n - k として左の鏡映が約 4pq4pq、右の鏡映が約 4pq4pq で、∑k8(m−k)(n−k)≈8(mn2/2−n3/6)=4mn2−4n3/3\sum_k 8(m - k)(n - k) \approx 8(mn^2/2 - n^3/6) = 4mn^2 - 4n^3/3 です。

m≫nm \gg n のときは、先に QR 分解 A=QRA = QR をして nn 次の RR を二重対角化する方が速くなります(R-二重対角化)。

命題 6.5(Golub–Kahan の三重対角行列)✓

BB を 定理 6.4 の nn 次上二重対角行列とする。2n2n 次の対称三重対角行列

TGK=(0d1d10e1e10d2d20⋱⋱⋱dndn0)T_{\mathrm{GK}} = \begin{pmatrix} 0 & d_1 & & & & \\ d_1 & 0 & e_1 & & & \\ & e_1 & 0 & d_2 & & \\ & & d_2 & 0 & \ddots & \\ & & & \ddots & \ddots & d_n \\ & & & & d_n & 0 \end{pmatrix}

(対角は 00、副対角は d1,e1,d2,e2,…,en−1,dnd_1, e_1, d_2, e_2, \ldots, e_{n-1}, d_n)は、Jordan–Wielandt 行列 C(B)C(B) を置換行列で並べ替えたもので、その固有値は ±σ1(B),…,±σn(B)\pm\sigma_1(B), \ldots, \pm\sigma_n(B) である。

証明(命題 6.5)

C(B)(xy)=(ByBTx)C(B)\begin{pmatrix} \boldsymbol{x} \\ \boldsymbol{y} \end{pmatrix} = \begin{pmatrix} B\boldsymbol{y} \\ B^{\mathsf{T}}\boldsymbol{x} \end{pmatrix} の成分は

(By)i=diyi+eiyi+1,(BTx)j=ej−1xj−1+djxj(B\boldsymbol{y})_i = d_iy_i + e_iy_{i+1},\qquad (B^{\mathsf{T}}\boldsymbol{x})_j = e_{j-1}x_{j-1} + d_jx_j

です(e0=en=0e_0 = e_n = 0)。未知数を z=(y1,x1,y2,x2,…,yn,xn)\boldsymbol{z} = (y_1, x_1, y_2, x_2, \ldots, y_n, x_n) の順に並べ替える置換行列を PP とすると、yjy_j(第 2j−12j - 1 位置)の式は xj−1x_{j-1}(第 2j−22j - 2 位置)と xjx_j(第 2j2j 位置)だけを係数 ej−1e_{j-1}, djd_j で含み、xix_i(第 2i2i 位置)の式は yiy_i(第 2i−12i - 1 位置)と yi+1y_{i+1}(第 2i+12i + 1 位置)だけを係数 did_i, eie_i で含みます。よって PTC(B)P=TGKP^{\mathsf{T}}C(B)P = T_{\mathrm{GK}} です。置換行列は直交なので固有値は C(B)C(B) と同じで、m=nm = n の 定理 6.1 から ±σi(B)\pm\sigma_i(B) です。

したがって、二重対角行列の特異値は、対角が 00 の対称三重対角行列の固有値問題として、§3 の二分法でも、QR 法の章 のシフトつき QR 法でも求められます。実際の実装(Golub–Kahan–Reinsch の算法)は TGKT_{\mathrm{GK}} を作らず、BB に左右から Givens 回転を掛ける「暗黙のシフトつき QR 法」を BB の上で直接行います。これは BTBB^{\mathsf{T}}B に対するシフトつき QR 法と同値で、陰的 Q の定理(定理 4.3[固有値の計算 II])により正当化されます。

関数LAPACK の駆動ルーチン算法
numpy.linalg.eigh・eigvalshsyevd(heevd)三重対角化+分割統治法
scipy.linalg.eigh(..., driver="ev")syev三重対角化+暗黙のシフトつき QR 法
scipy.linalg.eigh(..., driver="evd")syevd三重対角化+分割統治法
scipy.linalg.eigh(..., driver="evr")(標準問題の既定)syevr三重対角化+MRRR(固有値の一部も指定可)
scipy.linalg.eigh(..., driver="evx")syevx三重対角化+二分法と逆反復(固有値の一部)
scipy.linalg.eigh_tridiagonal(..., lapack_driver="stebz")stebzSturm 列の二分法(§3)
numpy.linalg.svd、scipy.linalg.svd(既定)gesdd二重対角化+分割統治法
scipy.linalg.svd(..., lapack_driver="gesvd")gesvd二重対角化+暗黙のシフトつき QR 法

どの駆動ルーチンも三重対角化(二重対角化)で後退安定なので、固有値・特異値の絶対誤差は nu∥A∥2nu\|A\|_2 の程度で、違いは速さと固有ベクトルの直交性の細部です。全部の固有ベクトルが要る大きな問題では分割統治法・MRRR が速く、少数の固有値だけなら evr・evx が手間を省けます。大きな疎行列の一部の固有値には、Krylov 部分空間法の章の scipy.sparse.linalg.eigsh を使います。

注意 7.1(対称三重対角 QR 法のシフト)

syev の QR 法は Wilkinson シフト(QR 法の章 の注意)を使い、すべての対称三重対角行列で大域的に収束します。その証明は Parlett『The Symmetric Eigenvalue Problem』第 8 章にあり、本章では使いません。局所的な 3 次収束は 系 5.3[固有値の計算 II] で示しました。

注意 7.2(分割統治法と MRRR)

分割統治法(Cuppen)は、三重対角行列を 2 つに分けて階数 1 の修正で結び、修正後の固有値を「永年方程式」1+ρ∑izi2/(di−λ)=01 + \rho\sum_i z_i^2/(d_i - \lambda) = 0 の根として求めます。固有ベクトルの直交性を保つ工夫(Gu–Eisenstat)を含めて、全固有ベクトルを最も速く求める方法の 1 つです。MRRR(多重相対的にロバストな表現、Dhillon–Parlett)は、シフトした LDLTLDL^{\mathsf{T}} 分解の表現の上で各固有値を高い相対精度で求め、逆反復の変種で固有ベクトルを互いに独立に O(n)O(n) ずつ計算して、全体を O(n2)O(n^2) で行います。どちらも本章の定理には使いません。J. J. M. Cuppen, “A divide and conquer method for the symmetric tridiagonal eigenproblem”, Numer. Math. 36 (1981)、I. S. Dhillon, B. N. Parlett, “Multiple representations to compute orthogonal eigenvectors of symmetric tridiagonal matrices”, Linear Algebra Appl. 387 (2004) を参照してください。

注意 7.3(乱択特異値分解)

大きな行列の上位 kk 個の特異値だけが要るとき、ガウス乱数の行列 Ω\Omega(n×(k+p)n\times(k + p))を掛けた Y=AΩY = A\Omega の列空間の正規直交基底 QQ を作り、小さな行列 QTAQ^{\mathsf{T}}A の SVD から近似する乱択 SVD がよく使われます。その誤差が最良の階数 kk 近似の誤差の小さな定数倍に収まることは確率論の評価(ガウス行列の擬似逆のモーメント)で示され、本章の範囲を超えます。N. Halko, P. G. Martinsson, J. A. Tropp, “Finding structure with randomness”, SIAM Review 53 (2011) を参照してください。

演習 8.1易

n=1000n = 1000 次の対称三重対角行列の固有値がすべて [−4,4][-4, 4] にあるとき、命題 3.1 で 1 つの固有値を幅 10−1210^{-12} の区間に閉じ込めるのに要する反復回数と、おおよその演算量(Sturm 列 1 回を 3n3n 回の演算とする)を求めよ。全固有値を求める場合はどうか。

解答

⌈log⁡2(8/10−12)⌉=⌈log⁡28+12log⁡210⌉=⌈3+39.86⌉=43\lceil\log_2(8/10^{-12})\rceil = \lceil\log_2 8 + 12\log_2 10\rceil = \lceil 3 + 39.86\rceil = 43 回です。1 回が約 30003000 演算なので、固有値 1 つあたり約 1.3×1051.3\times10^{5}、全固有値で約 1.3×1081.3\times10^{8} 演算です(区間の分割を共有すると減らせます)。三重対角化の約 4n3/3≈1.3×1094n^3/3 \approx 1.3\times10^{9} よりは小さく、固有値だけなら主な手間は三重対角化です。

演習 8.2標準

A=(2112)A = \begin{pmatrix} 2 & 1 \\ 1 & 2 \end{pmatrix} に 補題 4.2 の回転を 1 回施し、ϕ\phi と B=JTAJB = J^{\mathsf{T}}AJ を求めよ。off(B)2=off(A)2−2a122\mathrm{off}(B)^2 = \mathrm{off}(A)^2 - 2a_{12}^2 を確かめよ。

解答

a11−a22=0a_{11} - a_{22} = 0、−2a12=−2-2a_{12} = -2 なので (cos⁡2ϕ,sin⁡2ϕ)=(0,−1)(\cos2\phi, \sin2\phi) = (0, -1)、ϕ=−π/4\phi = -\pi/4、c=1/2c = 1/\sqrt{2}、s=−1/2s = -1/\sqrt{2} です。J=12(1−111)J = \frac{1}{\sqrt{2}}\begin{pmatrix} 1 & -1 \\ 1 & 1 \end{pmatrix} で、

AJ=12(3−131),B=JTAJ=12(11−11)(3−131)=(3001)AJ = \frac{1}{\sqrt{2}}\begin{pmatrix} 3 & -1 \\ 3 & 1 \end{pmatrix},\qquad B = J^{\mathsf{T}}AJ = \frac12\begin{pmatrix} 1 & 1 \\ -1 & 1 \end{pmatrix}\begin{pmatrix} 3 & -1 \\ 3 & 1 \end{pmatrix} = \begin{pmatrix} 3 & 0 \\ 0 & 1 \end{pmatrix}

です。off(A)2=2\mathrm{off}(A)^2 = 2、off(B)2=0=2−2⋅12\mathrm{off}(B)^2 = 0 = 2 - 2\cdot1^2 で成り立ちます。対角成分の 2 乗和は 88 から 1010 に 2a122=22a_{12}^2 = 2 増えています。

演習 8.3標準

σ1=1\sigma_1 = 1、σn=10−6\sigma_n = 10^{-6} の行列について、後退誤差 ∥E∥2≤10u\|E\|_2 \le 10u の SVD と、ATAA^{\mathsf{T}}A の固有値(後退誤差 ∥E′∥2≤10u∥ATA∥2\|E'\|_2 \le 10u\|A^{\mathsf{T}}A\|_2)の平方根で求めた σn\sigma_n の相対誤差の上界を、系 6.2 と 系 5.1 から見積もれ(u≈1.1×10−16u \approx 1.1\times10^{-16})。

解答

SVD: ∣σ^n−σn∣≤10u≈1.1×10−15|\hat{\sigma}_n - \sigma_n| \le 10u \approx 1.1\times10^{-15} で、相対誤差は 1.1×10−91.1\times10^{-9} 以下です。ATAA^{\mathsf{T}}A: 固有値 σn2=10−12\sigma_n^2 = 10^{-12} の絶対誤差は 10u⋅1≈1.1×10−1510u\cdot1 \approx 1.1\times10^{-15} 以下で、相対誤差は 1.1×10−31.1\times10^{-3} 以下、平方根をとると相対誤差は約半分の 5.5×10−45.5\times10^{-4} 以下です。SVD は約 9 桁、ATAA^{\mathsf{T}}A 経由は約 3 桁しか保証されません。

  • B. N. Parlett『The Symmetric Eigenvalue Problem』SIAM, 1998 — 第 3 章(Sturm 列)、第 7 章(三重対角化)、第 8 章(QR 法)、第 9 章(Jacobi 法)、第 10・11 章(固有値・固有ベクトルの誤差評価)。
  • G. H. Golub, C. F. Van Loan『Matrix Computations』4th ed., Johns Hopkins University Press, 2013 — §8.1(対称固有値問題の摂動)、§8.3〜8.5(対称 QR 法・分割統治・Jacobi 法)、§8.6(SVD の計算)。
  • J. W. Demmel『Applied Numerical Linear Algebra』SIAM, 1997 — 第 5 章(対称固有値問題と SVD)。
  • G. H. Golub, W. Kahan, “Calculating the singular values and pseudo-inverse of a matrix”, SIAM J. Numer. Anal. 2 (1965), 205–224.
  • E. Anderson ほか『LAPACK Users’ Guide』3rd ed., SIAM, 1999 — 駆動ルーチンの一覧。

このテーマの 100 本ノック(100 問)

執筆: Claude Code(Opus 5.5)、Claude Code(Sonnet 5.5)・監査 2 回(Claude Code)・最終 2026-10-12

この記事の誤りを報告する ・運営: 夢現技研合同会社 ・料金 ・利用条件 ・特定商取引法に基づく表記

© 2026 夢現技研合同会社 ・コード例は MIT ライセンスです。