보강 2. 수치선형대수 입문 An Introduction to Numerical Linear Algebra — 서술
이 책은 같은 경고를 다섯 번 했다.
L19에서 여인수 전개를 유도해 놓고 쓰지 말라고 했다. L20에서 크래머 공식을 유도해 놓고
또 쓰지 말라고 했다. L28에서 조르당 표준형은 수치적으로 존재하지 않는다고 했다.
L33에서 정규방정식을 손으로 쓰지 말라고 했다. 보강 1에서 공분산행렬을 만들지 말라고 했다.
다섯 번이면 우연이 아니다. 그런데 다섯이 정말 같은 이야기인가.
이번 글의 목표는 그것이다. 다섯을 한자리에 놓고 무엇이 같고 무엇이 다른지 가른 뒤,
그 뒤에 무엇이 있는지 본다. 새로 배우는 것은 거의 없다. 이미 가진 조각들을
다른 순서로 놓을 뿐이다.
계산이 틀리는 방식은 둘뿐이다.
너무 오래 걸리거나, 답이 틀리거나. 앞엣것은 알고리즘을 바꾸면 해결되고,
뒤엣것은 그렇지 않다. 뒤엣것에는 문제 자체의 성질 과 알고리즘의 잘못 이 섞여 있어서,
그 둘을 갈라내는 것이 이 글의 절반이다.
1. 다섯 번의 경고는 두 갈래였다 ¶ 한자리에 놓고 보자.
경고 무엇이 문제였나 L19 여인수 전개 항이 n ! n! n ! 개다 L20 크래머 공식 행렬식을 n + 1 n+1 n + 1 번 구해야 한다 L28 조르당 형 답이 ϵ \sqrt{\epsilon} ϵ 만큼 튄다 L33 정규방정식 조건수가 제곱된다 보강 1 공분산행렬 조건수가 제곱된다
위의 둘과 아래의 셋이 다른 이야기다.
위의 둘은 비용 이다. 답은 정확한데 살아 생전에 못 받는다. 셋을 나란히 적어 보자.
소거 : n 3 3 , 여인수 전개 : n ! , 크래머 : ( n + 1 ) n ! \text{소거} : \frac{n^3}{3},
\qquad
\text{여인수 전개} : n!,
\qquad
\text{크래머} : (n+1)\,n! 소거 : 3 n 3 , 여인수 전개 : n ! , 크래머 : ( n + 1 ) n ! (1) 의 세 값은 n n n 이 작을 때는 비슷하다. n = 5 n = 5 n = 5 에서 41번, 120번, 720번이라
스무 배 차이가 날 뿐이다. 그런데 n = 25 n = 25 n = 25 가 되면 5,208번과 4 × 1 0 26 4 \times 10^{26} 4 × 1 0 26 번이 된다.
1초에 10억 번씩 계산해도 1010 년, 곧 우주의 나이와 맞먹는다.
아래의 셋은 정확도 다. 계산은 순식간에 끝나는데 나온 숫자가 틀렸다.
그리고 이쪽이 훨씬 위험하다. 오래 걸리는 것은 눈에 보이지만 틀린 것은 안 보인다.
Figure 1: 왼쪽이 비용으로 무너지는 길, 오른쪽이 정확도로 무너지는 길이다.
왼쪽은 축이 n n n 이고 오른쪽은 축이 조건수다. 다른 것을 재고 있다.
Figure 1 의 오른쪽에서 세 선이 서로 다른 기울기로 올라간다.
ϵ κ \epsilon\kappa ϵ κ , ϵ κ 2 \epsilon\kappa^2 ϵ κ 2 , 그리고 평평한 ϵ \sqrt{\epsilon} ϵ .
이 세 기울기의 정체를 밝히는 것이 이 글의 나머지다.
2. 전방오차와 후방오차 ¶ 정확도 이야기를 하려면 말부터 정해야 한다. A x = b A\vv{x} = \vv{b} A x = b 를 풀어
x ^ \hat{\vv{x}} x ^ 를 얻었다고 하자. 얼마나 틀렸는가.
가장 자연스러운 답은 참값과 비교하는 것이다.
전방오차 = ∥ x ^ − x ∥ ∥ x ∥ \text{전방오차} = \frac{\lVert \hat{\vv{x}} - \vv{x} \rVert}{\lVert \vv{x} \rVert} 전방오차 = ∥ x ∥ ∥ x ^ − x ∥ 그런데 (2) 의 값은 잴 수가 없다. 참값 x \vv{x} x 를 모르니까 푸는 것이다.
그래서 질문을 뒤집는다 ¶ 수치해석의 요령이 여기 있다. "내 답이 얼마나 틀렸는가"를 묻는 대신
내 답이 어떤 문제의 정확한 답인가 를 묻는다.
( A + Δ A ) x ^ = b (A + \Delta A)\,\hat{\vv{x}} = \vv{b} ( A + Δ A ) x ^ = b (3) 의 식을 만족하는 Δ A \Delta A Δ A 중 가장 작은 것을 찾아 크기를 잰다.
후방오차 = ∥ Δ A ∥ ∥ A ∥ \text{후방오차} = \frac{\lVert \Delta A \rVert}{\lVert A \rVert} 후방오차 = ∥ A ∥ ∥ Δ A ∥ (4) 의 값은 잴 수 있다. 그리고 뜻이 분명하다. “내가 푼 것은
원래 문제가 아니라 이만큼 옆에 있는 문제였다.”
정말 잴 수 있는지 보이자. 잔차를 r = b − A x ^ \vv{r} = \vv{b} - A\hat{\vv{x}} r = b − A x ^ 라 두고
Δ A \Delta A Δ A 를 이렇게 잡아 보면 된다.
Δ A = r x ^ T ∥ x ^ ∥ 2 \Delta A = \frac{\vv{r}\,\hat{\vv{x}}^{\mathsf T}}{\lVert\hat{\vv{x}}\rVert^2} Δ A = ∥ x ^ ∥ 2 r x ^ T (5) 의 행렬을 (3) 에 넣어 보자. 랭크 1 행렬을
x ^ \hat{\vv{x}} x ^ 에 곱하는 것이라 계산이 한 줄로 끝난다.
( A + Δ A ) x ^ = A x ^ + r x ^ T x ^ ∥ x ^ ∥ 2 = A x ^ + r = b (A + \Delta A)\hat{\vv{x}}
= A\hat{\vv{x}} + \vv{r}\,\frac{\hat{\vv{x}}^{\mathsf T}\hat{\vv{x}}}{\lVert\hat{\vv{x}}\rVert^2}
= A\hat{\vv{x}} + \vv{r}
= \vv{b} ( A + Δ A ) x ^ = A x ^ + r ∥ x ^ ∥ 2 x ^ T x ^ = A x ^ + r = b (6) 의 마지막이 정확히 우리가 원한 것이다. 그리고 이 Δ A \Delta A Δ A 가
가장 작은 것 임도 알려져 있으므로, 후방오차를 잔차만으로 계산할 수 있다.
∥ Δ A ∥ ∥ A ∥ = ∥ r ∥ ∥ A ∥ ∥ x ^ ∥ \frac{\lVert\Delta A\rVert}{\lVert A\rVert}
= \frac{\lVert\vv{r}\rVert}{\lVert A\rVert\,\lVert\hat{\vv{x}}\rVert} ∥ A ∥ ∥ Δ A ∥ = ∥ A ∥ ∥ x ^ ∥ ∥ r ∥ (7) 의 오른쪽은 전부 손에 있는 값 이다. 참해를 몰라도 된다.
r = b − A x ^ \vv{r} = \vv{b} - A\hat{\vv{x}} r = b − A x ^ 는 거의 같은 두 수의 차 다.
x ^ \hat{\vv{x}} x ^ 가 정확할수록 두 항이 서로 가까워져 앞자리가 통째로 지워진다.
실습에서 정수 문제 400개로 재 보면, 잔차를 보통대로 계산했을 때
(10) 의 부등식이 38번 깨진 것처럼 보인다. 잔차를 유리수로 정확히
계산하면 0번 이고, 그때 전방오차가 한계의 최대 0.9928 배까지 올라간다.
부등식이 옳을 뿐 아니라 꽉 차 있다는 뜻이다.
반복 개선 (iterative refinement)이 잔차를 한 단계 높은 정밀도로 계산하는 이유가
이것이다. 같은 정밀도로 재면 고칠 것이 아예 안 보인다.
둘을 잇는 부등식 ¶ 이제 둘을 연결한다. (3) 에서 A x = b A\vv{x} = \vv{b} A x = b 를 빼면
A ( x ^ − x ) = − Δ A x ^ ⟹ x ^ − x = − A − 1 Δ A x ^ A(\hat{\vv{x}} - \vv{x}) = -\Delta A\,\hat{\vv{x}}
\qquad\Longrightarrow\qquad
\hat{\vv{x}} - \vv{x} = -A^{-1}\Delta A\,\hat{\vv{x}} A ( x ^ − x ) = − Δ A x ^ ⟹ x ^ − x = − A − 1 Δ A x ^ 이고, (8) 의 오른쪽에 노름을 씌우면
∥ x ^ − x ∥ ≤ ∥ A − 1 ∥ ∥ Δ A ∥ ∥ x ^ ∥ \lVert \hat{\vv{x}} - \vv{x} \rVert
\ \le\ \lVert A^{-1} \rVert\,\lVert \Delta A \rVert\,\lVert \hat{\vv{x}} \rVert ∥ x ^ − x ∥ ≤ ∥ A − 1 ∥ ∥ Δ A ∥ ∥ x ^ ∥ 이 된다. (9) 의 양변을 ∥ x ^ ∥ \lVert\hat{\vv{x}}\rVert ∥ x ^ ∥ 로 나누고
∥ A ∥ / ∥ A ∥ \lVert A\rVert/\lVert A\rVert ∥ A ∥ / ∥ A ∥ 를 끼워 넣으면 목표한 꼴이 나온다.
∥ x ^ − x ∥ ∥ x ^ ∥ ⏟ 전방오차 ≤ ∥ A ∥ ∥ A − 1 ∥ ⏟ κ ( A ) ⋅ ∥ Δ A ∥ ∥ A ∥ ⏟ 후방오차 \underbrace{\frac{\lVert \hat{\vv{x}} - \vv{x} \rVert}{\lVert \hat{\vv{x}} \rVert}}_{\text{전방오차}}
\ \le\
\underbrace{\lVert A \rVert\,\lVert A^{-1} \rVert}_{\kappa(A)}
\cdot
\underbrace{\frac{\lVert \Delta A \rVert}{\lVert A \rVert}}_{\text{후방오차}} 전방오차 ∥ x ^ ∥ ∥ x ^ − x ∥ ≤ κ ( A ) ∥ A ∥ ∥ A − 1 ∥ ⋅ 후방오차 ∥ A ∥ ∥ Δ A ∥ Figure 2: 왼쪽 화살표가 알고리즘이 책임지는 것이고 오른쪽 화살표가 우리가 원하는 것이다.
둘 사이의 환율이 조건수다.
(10) 의 부등식이 이 글에서 가장 중요한 한 줄이다.
전방오차 ≤ 조건수 × 후방오차 \text{전방오차} \ \le\ \text{조건수} \times \text{후방오차} 전방오차 ≤ 조건수 × 후방오차 (11) 의 두 인자는 성격이 완전히 다르다.
"이 답이 왜 이렇게 나빠요"에 대한 답이 늘 둘 중 하나다.
알고리즘이 나쁘거나, 문제가 원래 나쁘거나. 섞어서 말하면 안 된다.
다섯 경고를 다시 읽으면 ¶ 이제 Figure 1 의 세 기울기를 읽을 수 있다.
ϵ κ \epsilon\kappa ϵ κ — 후방안정한 알고리즘의 한계다. 후방오차가 ϵ \epsilon ϵ 이니
전방오차는 κ ϵ \kappa\epsilon κ ϵ 이다. 여기까지는 어쩔 수 없다.
ϵ κ 2 \epsilon\kappa^2 ϵ κ 2 — L33의 정규방정식과 보강 1의 공분산이 여기 있다.
A T A A^{\mathsf T}A A T A 를 만드는 순간 조건수가 제곱되니, 그 뒤에 아무리 좋은 알고리즘을 써도
ϵ κ 2 \epsilon\kappa^2 ϵ κ 2 을 넘지 못한다. 문제를 자기 손으로 나쁘게 만든 것이다.
ϵ \sqrt{\epsilon} ϵ — L28의 조르당 형이 여기 있다. 이것은 조건수 이야기가 아니라
문제 자체가 매끄럽지 않다 는 이야기인데, 5절에서 다시 본다.
3. 반복법 — 답을 향해 걸어간다 ¶ 소거는 유한 번에 끝난다. n 3 / 3 n^3/3 n 3 /3 번이면 답이 나온다. 그런데 n n n 이 백만이면
3 × 1 0 17 3 \times 10^{17} 3 × 1 0 17 번이라 그것도 못 쓴다.
이럴 때 쓰는 것이 반복법 이다. 정확한 답 대신 충분히 가까운 답 을 노린다.
쪼개고 되풀이한다 ¶ A A A 를 두 조각으로 나눈다. 하나는 풀기 쉬운 것, 하나는 나머지다.
A = M − N ⟹ M x = N x + b A = M - N
\qquad\Longrightarrow\qquad
M\vv{x} = N\vv{x} + \vv{b} A = M − N ⟹ M x = N x + b (12) 의 오른쪽 식은 여전히 x \vv{x} x 를 양쪽에 갖고 있어 풀 수 없다.
그런데 오른쪽에는 옛 답을 넣고 왼쪽에서 새 답을 뽑으면 되풀이가 된다.
x k + 1 = M − 1 ( N x k + b ) \vv{x}_{k+1} = M^{-1}\left(N\vv{x}_k + \vv{b}\right) x k + 1 = M − 1 ( N x k + b ) M M M 을 무엇으로 잡느냐가 방법을 정한다. A = D + L + U A = D + L + U A = D + L + U 로 대각·아래·위를 쪼개면
야코비 : M = D , 가우스-자이델 : M = D + L \text{야코비} : M = D,
\qquad
\text{가우스-자이델} : M = D + L 야코비 : M = D , 가우스 - 자이델 : M = D + L 이다. 성분으로 풀어 쓰면 왜 싼지가 보인다. 야코비는 이렇다.
x i ( k + 1 ) = 1 a i i ( b i − ∑ j ≠ i a i j x j ( k ) ) x_i^{(k+1)}
= \frac{1}{a_{ii}}\left( b_i - \sum_{j \neq i} a_{ij}\,x_j^{(k)} \right) x i ( k + 1 ) = a ii 1 ⎝ ⎛ b i − j = i ∑ a ij x j ( k ) ⎠ ⎞ (15) 의 오른쪽에는 옛 값만 들어간다. 그래서 n n n 개를 동시에
계산할 수 있고 병렬화가 쉽다. 가우스-자이델은 한 글자만 다르다.
x i ( k + 1 ) = 1 a i i ( b i − ∑ j < i a i j x j ( k + 1 ) − ∑ j > i a i j x j ( k ) ) x_i^{(k+1)}
= \frac{1}{a_{ii}}\left( b_i - \sum_{j < i} a_{ij}\,x_j^{(k+1)}
- \sum_{j > i} a_{ij}\,x_j^{(k)} \right) x i ( k + 1 ) = a ii 1 ( b i − j < i ∑ a ij x j ( k + 1 ) − j > i ∑ a ij x j ( k ) ) (16) 의 첫 합에 k + 1 k+1 k + 1 이 들어 있다. 방금 갱신한 값을 즉시 쓴다.
그래서 순서를 지켜야 하지만 정보가 더 새것이라 빠르다. 둘 다 한 번 도는 데
A A A 의 0이 아닌 성분 수만큼만 곱셈을 하므로, 성긴 행렬에서는 n 3 n^3 n 3 근처에도 안 간다.
수렴 조건은 L22가 이미 준다 ¶ 되풀이가 답으로 가는가. 오차 e k = x k − x \vv{e}_k = \vv{x}_k - \vv{x} e k = x k − x 를 보면 바로 나온다.
(13) 에서 참해도 같은 식을 만족하므로 빼면
e k + 1 = M − 1 N e k ⟹ e k = ( M − 1 N ) k e 0 \vv{e}_{k+1} = M^{-1}N\,\vv{e}_k
\qquad\Longrightarrow\qquad
\vv{e}_k = \left(M^{-1}N\right)^{k}\vv{e}_0 e k + 1 = M − 1 N e k ⟹ e k = ( M − 1 N ) k e 0 가 된다. (17) 의 오른쪽은 행렬의 거듭제곱 이고, 그것이 0으로 가는
조건은 L22에서 이미 배웠다. 모든 고윳값의 절댓값이 1보다 작아야 한다.
L22의 A k → 0 A^k \to 0 A k → 0 이 여기서 알고리즘의 수렴 판정이 된 셈이다.
앵커로 확인 ¶ 이 책에서 여러 번 쓴 삼중대각행렬을 쓰자.
T = tridiag ( − 1 , 2 , − 1 ) λ k ( T ) = 4 sin 2 k π 2 ( n + 1 ) T = \operatorname{tridiag}(-1,\ 2,\ -1)
\qquad
\lambda_k(T) = 4\sin^2\!\frac{k\pi}{2(n+1)} T = tridiag ( − 1 , 2 , − 1 ) λ k ( T ) = 4 sin 2 2 ( n + 1 ) kπ (18) 의 고윳값이 닫힌 꼴로 알려져 있어 모든 것을 손으로 확인할 수 있다.
n = 20 n = 20 n = 20 에서 조건수가 178.06 이고, 야코비의 스펙트럼 반지름은
ρ 야코비 = cos π n + 1 = 0.98883 \rho_{\text{야코비}} = \cos\frac{\pi}{n+1} = 0.98883 ρ 야코비 = cos n + 1 π = 0.98883 이다. (19) 의 값이 1에 아주 가깝다. 한 번 되풀이할 때마다 오차가
1.1%씩만 준다는 뜻이라 느리다. 가우스-자이델은 정확히 그 제곱인 0.97779 이라
두 배 빠르지만, 여전히 느리다.
켤레기울기 — 조건수에 제곱근이 붙는다 ¶ A A A 가 대칭 양의 정부호 이면(L27) 훨씬 좋은 방법이 있다.
L27에서 최급강하법을 보았다. 그때 수렴 인자가 κ − 1 κ + 1 \dfrac{\kappa-1}{\kappa+1} κ + 1 κ − 1 이었고,
조건수가 크면 1에 붙어 지그재그로 기어갔다. 켤레기울기법 은 같은 문제에서
최급강하 : κ − 1 κ + 1 vs 켤레기울기 : κ − 1 κ + 1 \text{최급강하} : \frac{\kappa - 1}{\kappa + 1}
\qquad\text{vs}\qquad
\text{켤레기울기} : \frac{\sqrt{\kappa} - 1}{\sqrt{\kappa} + 1} 최급강하 : κ + 1 κ − 1 vs 켤레기울기 : κ + 1 κ − 1 의 인자를 갖는다. (20) 의 차이는 제곱근 하나뿐 인데 그것이 전부를 바꾼다.
κ = 178 \kappa = 178 κ = 178 에서 왼쪽은 0.9888 이고 오른쪽은 0.8606 이다. 자릿수 하나를 더 얻는 데
왼쪽은 205번, 오른쪽은 15번이 든다.
그리고 하나 더 있다. 켤레기울기는 n n n 번 안에 정확히 끝난다. 매 단계마다
서로 A A A -직교인 방향을 하나씩 잡아 나가는데, n n n 개를 다 잡으면 공간을 다 덮기 때문이다.
Figure 3: 왼쪽에서 켤레기울기가 k = 20 k = 20 k = 20 에서 절벽처럼 떨어진다. 야코비와 가우스-자이델은
250번을 돌아도 10-3 근처다. 오른쪽은 세 감소 인자를 n n n 에 따라 그린 것이다.
4. 고윳값을 실제로 구하는 법 ¶ 이제 고윳값이다. L21에서 우리는 det ( A − λ I ) = 0 \det(A - \lambda I) = 0 det ( A − λ I ) = 0 을 풀어 고윳값을 구했다.
컴퓨터는 절대 그렇게 하지 않는다. 왜인지부터 보자.
특성다항식이라는 함정 ¶ 근이 1 , 2 , … , 20 1, 2, \dots, 20 1 , 2 , … , 20 인 다항식을 만들어 계수 하나를 아주 조금 흔들어 보자.
x 19 x^{19} x 19 의 계수는 -210 인데, 이것을 상대적으로 10-10 만큼 건드린다.
근 스무 개 중 열 개가 복소수가 된다. 가장 많이 움직인 근은 2.18 이나 옮겨 간다.
같은 크기로 행렬 쪽을 흔들면 어떻게 되는가. diag ( 1 , … , 20 ) \diag(1,\dots,20) diag ( 1 , … , 20 ) 의 성분을
같은 비율로 흔들면 고윳값은 4 × 1 0 − 9 4 \times 10^{-9} 4 × 1 0 − 9 만 움직인다.
다항식 계수를 흔들 때 : 2.18 vs 행렬을 흔들 때 : 4 × 1 0 − 9 \text{다항식 계수를 흔들 때} \ :\ 2.18
\qquad\text{vs}\qquad
\text{행렬을 흔들 때} \ :\ 4 \times 10^{-9} 다항식 계수를 흔들 때 : 2.18 vs 행렬을 흔들 때 : 4 × 1 0 − 9 (22) 의 두 값은 5 × 1 0 8 5 \times 10^8 5 × 1 0 8 배 차이가 난다.
Figure 4: 같은 크기의 상대 섭동이다. 왼쪽에서는 근이 복소평면으로 날아가고 오른쪽에서는
고윳값이 제자리를 지킨다.
이것은 L33·보강 1의 A T A A^{\mathsf T}A A T A 와 같은 종류의 실수다.
푸는 방법이 나쁜 것이 아니라 푸는 대상을 자기 손으로 나쁘게 만든 것 이다.
그래서 방향이 반대다. numpy.roots 는 다항식의 근을 구할 때
동반행렬을 만들어 그 고윳값을 구한다.
p ( x ) = x n + c n − 1 x n − 1 + ⋯ + c 0 ⟹ C = [ − c n − 1 − c n − 2 ⋯ − c 0 1 0 ⋯ 0 ⋱ ⋮ 1 0 ] p(x) = x^n + c_{n-1}x^{n-1} + \cdots + c_0
\quad\Longrightarrow\quad
C = \begin{bmatrix}
-c_{n-1} & -c_{n-2} & \cdots & -c_0 \\
1 & 0 & \cdots & 0 \\
& \ddots & & \vdots \\
& & 1 & 0
\end{bmatrix} p ( x ) = x n + c n − 1 x n − 1 + ⋯ + c 0 ⟹ C = ⎣ ⎡ − c n − 1 1 − c n − 2 0 ⋱ ⋯ ⋯ 1 − c 0 0 ⋮ 0 ⎦ ⎤ (23) 의 C C C 는 특성다항식이 정확히 p p p 인 행렬이다.
다항식에서 행렬로 가지, 그 반대로 가지 않는다.
거듭제곱법 — L22가 이미 증명해 두었다 ¶ 그러면 어떻게 구하는가. 가장 단순한 방법은 이미 배웠다.
L22의 3절에서 A k x A^k\vv{x} A k x 를 고유기저로 펼치고 λ 1 k \lambda_1^k λ 1 k 로 나눴다.
A k x λ 1 k = c 1 s 1 + c 2 ( λ 2 λ 1 ) k s 2 + ⋯ ⟶ c 1 s 1 \frac{A^k\vv{x}}{\lambda_1^k}
= c_1\vv{s}_1
+ c_2\!\left(\frac{\lambda_2}{\lambda_1}\right)^{k}\!\vv{s}_2
+ \cdots
\ \longrightarrow\ c_1\vv{s}_1 λ 1 k A k x = c 1 s 1 + c 2 ( λ 1 λ 2 ) k s 2 + ⋯ ⟶ c 1 s 1 (24) 의 식이 곧 알고리즘이다. A A A 를 자꾸 곱하고 길이를 1로 맞추면
지배 고유벡터가 나온다. L22는 이것을 "가장 큰 것만 살아남는다"고만 부르고
알고리즘이라 부르지 않았을 뿐이다.
수렴 속도도 그때 이미 나왔다. 가장 느리게 죽는 항이 λ 2 \lambda_2 λ 2 쪽이므로 인자가
∣ λ 2 / λ 1 ∣ \lvert\lambda_2/\lambda_1\rvert ∣ λ 2 / λ 1 ∣ 다.
고윳값은 레일리 몫 으로 뽑는다(보강 1에서 쓴 그것이다).
λ 1 ≈ v k T A v k ( ∥ v k ∥ = 1 ) \lambda_1 \approx \vv{v}_k^{\mathsf T}A\vv{v}_k
\qquad
(\lVert\vv{v}_k\rVert = 1) λ 1 ≈ v k T A v k (∥ v k ∥ = 1 ) (25) 의 값은 고유벡터보다 두 배 빨리 수렴한다. 왜 그런지 적어 두자.
A A A 가 대칭이라 하고 v = q 1 + δ w \vv{v} = \vv{q}_1 + \delta\vv{w} v = q 1 + δ w 로 두자.
여기서 w \vv{w} w 는 q 1 \vv{q}_1 q 1 에 수직인 단위벡터다. 분자를 펼치면
v T A v = λ 1 + 2 δ q 1 T A w + δ 2 w T A w \vv{v}^{\mathsf T}A\vv{v}
= \lambda_1 + 2\delta\,\vv{q}_1^{\mathsf T}A\vv{w} + \delta^2\,\vv{w}^{\mathsf T}A\vv{w} v T A v = λ 1 + 2 δ q 1 T A w + δ 2 w T A w 가 되는데, (26) 의 가운데 항이 사라진다.
A q 1 = λ 1 q 1 A\vv{q}_1 = \lambda_1\vv{q}_1 A q 1 = λ 1 q 1 이고 q 1 ⊥ w \vv{q}_1 \perp \vv{w} q 1 ⊥ w 이기 때문이다.
q 1 T A w = ( A q 1 ) T w = λ 1 q 1 T w = 0 \vv{q}_1^{\mathsf T}A\vv{w}
= (A\vv{q}_1)^{\mathsf T}\vv{w}
= \lambda_1\,\vv{q}_1^{\mathsf T}\vv{w}
= 0 q 1 T A w = ( A q 1 ) T w = λ 1 q 1 T w = 0 (27) 에서 A A A 가 대칭이라는 것을 썼다. 분모도 1 + δ 2 1 + \delta^2 1 + δ 2 이므로
결국 1차 항이 양쪽에서 다 사라진다.
v T A v / v T v = λ 1 + O ( δ 2 ) \vv{v}^{\mathsf T}A\vv{v} / \vv{v}^{\mathsf T}\vv{v}
= \lambda_1 + O(\delta^2) v T A v / v T v = λ 1 + O ( δ 2 ) (28) 의 결과가 두 배 빠른 이유의 전부다. 고유벡터가 δ \delta δ 만큼
틀렸어도 고윳값은 δ 2 \delta^2 δ 2 만큼만 틀린다. 대칭이 아니면 이 이득이 없다.
Figure 5: 왼쪽에서 파란 점이 회색 이론선 위에 정확히 앉는다. 오른쪽에서 주황(고윳값)의 기울기가
파랑(고유벡터)의 정확히 두 배다.
QR 알고리즘 — 유사변환을 되풀이한다 ¶ 거듭제곱법은 고윳값을 하나만 준다. 전부 구하려면 다른 것이 필요하다.
QR 알고리즘 은 놀랍도록 간단하다. 분해하고, 순서를 바꿔 다시 곱한다.
A k = Q k R k ⟹ A k + 1 = R k Q k A_k = Q_k R_k
\qquad\Longrightarrow\qquad
A_{k+1} = R_k Q_k A k = Q k R k ⟹ A k + 1 = R k Q k (29) 의 두 줄이 전부다. 그런데 왜 이것이 통하는가.
R k = Q k T A k R_k = Q_k^{\mathsf T}A_k R k = Q k T A k 를 대입해 보면 정체가 드러난다.
A k + 1 = R k Q k = Q k T A k Q k = Q k − 1 A k Q k A_{k+1} = R_k Q_k = Q_k^{\mathsf T}A_k Q_k = Q_k^{-1}A_k Q_k A k + 1 = R k Q k = Q k T A k Q k = Q k − 1 A k Q k (30) 의 마지막이 유사변환 이다(L28). 유사변환은 고윳값을
보존하므로 A k A_k A k 는 아무리 되풀이해도 처음과 같은 고윳값을 갖는다.
변하는 것은 비대각 성분뿐이고, 그것이 0으로 간다.
수렴 속도는 이웃한 고윳값의 비로 정해진다. 정확히는 ( i + 1 , i ) (i+1, i) ( i + 1 , i ) 성분이
∣ λ i + 1 / λ i ∣ k \lvert\lambda_{i+1}/\lambda_i\rvert^k ∣ λ i + 1 / λ i ∣ k 로 죽으므로, 전체가 0에 가는 속도는
max i ∣ λ i + 1 λ i ∣ \max_i \left\lvert \frac{\lambda_{i+1}}{\lambda_i} \right\rvert i max ∣ ∣ λ i λ i + 1 ∣ ∣ 이 정한다. (31) 의 값이 1에 가까우면, 곧 가까운 고윳값이 어딘가에
하나라도 있으면 전체가 느려진다.
∣ λ 2 / λ 1 ∣ \lvert\lambda_2/\lambda_1\rvert ∣ λ 2 / λ 1 ∣ 만 보면 안 된다. 예제 행렬의 고윳값이
7.049 , 2.643 , 2.308 7.049,\ 2.643,\ 2.308 7.049 , 2.643 , 2.308 인데 λ 2 / λ 1 = 0.375 \lambda_2/\lambda_1 = 0.375 λ 2 / λ 1 = 0.375 로 작지만
λ 3 / λ 2 = 0.873 \lambda_3/\lambda_2 = 0.873 λ 3 / λ 2 = 0.873 이라 느린 쪽이 전체를 붙잡는다.
실측 감소율이 0.873 이다.
시프트가 판을 바꾼다 ¶ 느린 것은 고칠 수 있다. μ \mu μ 를 하나 빼고 하고 다시 더하면 된다.
A k − μ I = Q k R k , A k + 1 = R k Q k + μ I A_k - \mu I = Q_k R_k,
\qquad
A_{k+1} = R_k Q_k + \mu I A k − μ I = Q k R k , A k + 1 = R k Q k + μ I (32) 의 변형도 여전히 유사변환이라 고윳값은 그대로다. 그런데 비가
∣ λ i + 1 − μ λ i − μ ∣ \left\lvert\dfrac{\lambda_{i+1}-\mu}{\lambda_i-\mu}\right\rvert ∣ ∣ λ i − μ λ i + 1 − μ ∣ ∣ 로 바뀌므로,
μ \mu μ 를 어느 고윳값 가까이 두면 그 비가 아주 작아진다.
μ = A k [ n , n ] \mu = A_k[n,n] μ = A k [ n , n ] 으로 두는 것이 가장 흔한 선택이다. 그 성분이 이미 고윳값에
가까워지고 있기 때문이다. 결과가 극적이다.
되풀이 시프트 없음 시프트 있음 1 1.2 1.2 3 0.9 3.4 × 1 0 − 1 3.4\times10^{-1} 3.4 × 1 0 − 1 4 3.7 × 1 0 − 3 3.7\times10^{-3} 3.7 × 1 0 − 3 5 4.4 × 1 0 − 9 4.4\times10^{-9} 4.4 × 1 0 − 9 6 6.5 × 1 0 − 27 6.5\times10^{-27} 6.5 × 1 0 − 27
자릿수가 매번 세 배로 늘어난다. 세제곱 수렴이다.
시프트 없이는 40번을 돌아도 10-12 에 못 간다.
Figure 6: 왼쪽에서 행렬이 대각으로 굳어 간다. 대각선의 세 수가 곧 고윳값이다.
오른쪽에서 시프트가 있는 쪽은 여섯 걸음 만에 바닥에 닿는다.
5. 조르당 형이 왜 위험한지, 정확한 언어로 ¶ L28에서 물었다. 조르당 형은 수학적으로 분명히 존재하는데 왜 컴퓨터가 못 잡는가.
그때는 ϵ \sqrt{\epsilon} ϵ 법칙을 관찰로만 보였다. 이제 이름을 붙일 수 있다.
고윳값에도 조건수가 있다 ¶ A A A 의 고윳값 λ \lambda λ 에 대해 오른쪽 고유벡터 x \vv{x} x 와 왼쪽 고유벡터
y \vv{y} y 가 있다. 왼쪽 고유벡터란 y T A = λ y T \vv{y}^{\mathsf T}A = \lambda\vv{y}^{\mathsf T} y T A = λ y T ,
곧 A T y = λ y A^{\mathsf T}\vv{y} = \lambda\vv{y} A T y = λ y 를 만족하는 것이다.
어디서 나오는지 유도해 보자. A A A 를 ε E \varepsilon E εE 만큼 흔들면 고윳값과 고유벡터가
함께 움직인다.
( A + ε E ) x ( ε ) = λ ( ε ) x ( ε ) (A + \varepsilon E)\,\vv{x}(\varepsilon) = \lambda(\varepsilon)\,\vv{x}(\varepsilon) ( A + εE ) x ( ε ) = λ ( ε ) x ( ε ) (33) 의 양변을 ε \varepsilon ε 으로 미분하고 ε = 0 \varepsilon = 0 ε = 0 을 넣으면
E x + A x ′ = λ ′ x + λ x ′ E\vv{x} + A\vv{x}' = \lambda'\vv{x} + \lambda\vv{x}' E x + A x ′ = λ ′ x + λ x ′ 이 된다. (34) 에는 모르는 것이 x ′ \vv{x}' x ′ 과 λ ′ \lambda' λ ′ 둘인데,
왼쪽 고유벡터를 곱하면 x ′ \vv{x}' x ′ 이 통째로 사라진다.
y T A = λ y T \vv{y}^{\mathsf T}A = \lambda\vv{y}^{\mathsf T} y T A = λ y T 이기 때문이다.
y T E x + y T A x ′ ⏟ = λ y T x ′ = λ ′ y T x + λ y T x ′ \vv{y}^{\mathsf T}E\vv{x} + \underbrace{\vv{y}^{\mathsf T}A\vv{x}'}_{=\ \lambda\vv{y}^{\mathsf T}\vv{x}'}
= \lambda'\,\vv{y}^{\mathsf T}\vv{x} + \lambda\,\vv{y}^{\mathsf T}\vv{x}' y T E x + = λ y T x ′ y T A x ′ = λ ′ y T x + λ y T x ′ (35) 의 양쪽에서 λ y T x ′ \lambda\vv{y}^{\mathsf T}\vv{x}' λ y T x ′ 이 지워지므로
λ ′ \lambda' λ ′ 이 곧바로 나온다.
λ ′ = y T E x y T x ⟹ ∣ δ λ ∣ ≤ ∥ E ∥ ∣ y T x ∣ ε \lambda' = \frac{\vv{y}^{\mathsf T}E\vv{x}}{\vv{y}^{\mathsf T}\vv{x}}
\qquad\Longrightarrow\qquad
\lvert \delta\lambda \rvert
\ \le\ \frac{\lVert E\rVert}{\lvert \vv{y}^{\mathsf T}\vv{x} \rvert}\,\varepsilon λ ′ = y T x y T E x ⟹ ∣ δ λ ∣ ≤ ∣ y T x ∣ ∥ E ∥ ε (36) 의 분모가 전부를 결정한다. 그래서 이렇게 이름을 붙인다.
κ ( λ ) = 1 ∣ y T x ∣ ( ∥ x ∥ = ∥ y ∥ = 1 ) \kappa(\lambda) = \frac{1}{\lvert \vv{y}^{\mathsf T}\vv{x} \rvert}
\qquad (\lVert\vv{x}\rVert = \lVert\vv{y}\rVert = 1) κ ( λ ) = ∣ y T x ∣ 1 (∥ x ∥ = ∥ y ∥ = 1 ) (37) 의 값이 그 고윳값의 조건수다. 좌우 고유벡터가 나란할수록 작고,
수직에 가까울수록 크다.
세 경우를 재 보자.
A A A κ ( λ 1 ) \kappa(\lambda_1) κ ( λ 1 ) 대칭 ( 4 1 1 3 ) \begin{pmatrix}4&1\\1&3\end{pmatrix} ( 4 1 1 3 ) 1 비대칭 ( 4 1 0 3 ) \begin{pmatrix}4&1\\0&3\end{pmatrix} ( 4 0 1 3 ) 1.414 거의 결함 ( 3 1 1 0 − 6 3 ) \begin{pmatrix}3&1\\10^{-6}&3\end{pmatrix} ( 3 1 0 − 6 1 3 ) 500
대칭행렬에서 1이다. 좌우 고유벡터가 같으니 y T x = 1 \vv{y}^{\mathsf T}\vv{x} = 1 y T x = 1 이다.
이것이 L25의 스펙트럼 정리가 주는 또 하나의 선물이다. 대칭행렬의 고윳값은
언제나 완벽하게 조건이 좋다.
결함이면 조건수가 무한대다 ¶ 결함 행렬로 가면 좌우 고유벡터가 수직에 가까워진다. 완전히 결함이면 정확히
수직이 되어 y T x = 0 \vv{y}^{\mathsf T}\vv{x} = 0 y T x = 0 이고, (37) 의 값이 무한대다.
조건수가 무한대라는 것은 (11) 의 부등식이 아무 말도 못 한다는 뜻이다.
그때는 1차 근사가 통하지 않고 다른 규칙이 나타난다. 조르당 블록 크기가 m m m 이면
∣ δ λ ∣ ∼ δ 1 / m \lvert \delta\lambda \rvert \ \sim\ \delta^{1/m} ∣ δ λ ∣ ∼ δ 1/ m 이다. (38) 에서 m = 2 m = 2 m = 2 이면 δ \sqrt{\delta} δ 이고,
δ = ϵ mach ≈ 1 0 − 16 \delta = \epsilon_{\text{mach}} \approx 10^{-16} δ = ϵ mach ≈ 1 0 − 16 이면 10-8 이다.
L28에서 측정한 기울기 0.5가 바로 이것이다.
조르당 형이 위험한 것은 알고리즘이 나빠서가 아니다.
결함 고윳값은 조건수가 무한대인 문제 이고, 그런 문제에서는 후방오차를
ϵ \epsilon ϵ 에 붙여 놓아도 전방오차가 ϵ \sqrt{\epsilon} ϵ 이 된다.
(11) 의 부등식으로 말하면, 오른쪽 인자가 아무리 작아도
왼쪽 인자가 무한대라 아무 보장이 없다. 알고리즘을 바꿔서 될 일이 아니다.
그래서 대안은 문제를 바꾸는 것 이다. 조르당 형 대신 슈어 분해
A = Q T Q H A = QTQ^{\mathsf H} A = QT Q H 를 쓴다. Q Q Q 가 직교라 조건수가 1이고, T T T 가 위삼각이라
대각선에 고윳값이 그대로 있다. 블록 구조는 못 얻지만 얻는 것은 믿을 수 있다.
6. 자주 하는 오해 ¶ ① 잔차가 작으면 답이 정확하다.
아니다. 잔차 ∥ A x ^ − b ∥ \lVert A\hat{\vv{x}} - \vv{b}\rVert ∥ A x ^ − b ∥ 가 작다는 것은 후방오차가 작다 는
뜻이지 전방오차가 작다는 뜻이 아니다. (11) 의 부등식에 조건수가 곱해져
있다. 조건수가 1012 이면 잔차가 10-16 이어도 답은 10-4 만큼 틀릴 수 있다.
② 조건수가 크면 알고리즘이 나쁜 것이다.
아니다. 조건수는 문제의 성질 이다. 세상에서 가장 좋은 알고리즘을 써도 줄지 않는다.
알고리즘이 책임지는 것은 후방오차 하나뿐이다.
③ 반복법이 소거보다 언제나 빠르다.
아니다. 반복법은 행렬이 크고 성기고 조건수가 나쁘지 않을 때 이긴다.
n n n 이 작거나 조건수가 크면 소거가 낫다. 그리고 Theorem 1 의 조건이
깨지면 반복법은 아예 발산한다. 소거는 적어도 답은 준다.
④ 켤레기울기는 n n n 번이면 끝나니 유한 알고리즘이다.
이론적으로는 그렇지만 실무에서는 아니다. 반올림 때문에 A A A -직교성이 무너져
n n n 번에 정확히 끝나지 않는다. 그리고 애초에 n n n 이 백만이면 n n n 번도 못 돈다.
κ \sqrt{\kappa} κ 로 정해지는 근사 수렴이 실제로 쓰는 성질이다.
⑤ 고윳값을 구하려면 특성다항식을 풀어야 한다.
정반대다. 4절이 답이다. 실무는 QR 알고리즘을 쓰고, 다항식의 근을 구할 때조차
동반행렬을 만들어 고윳값 쪽으로 간다.
⑥ 대칭행렬은 계산이 쉬우니 별 이득이 없다.
이득이 크다. 대칭이면 고윳값의 조건수가 정확히 1 이고, eigh 가 eig 보다
빠르며, 결함이 있을 수 없어 5절의 함정이 아예 없다. 대칭인지 먼저 확인하는 것이
L32의 흐름도가 그 자리에 있는 이유다.
마치며... ¶ 이번 글에서는 이 책이 다섯 번 한 경고를 하나로 묶었다.
실패하는 방식은 둘이다. 비용 과 정확도 . 여인수와 크래머는 앞엣것이고
조르당·정규방정식·공분산은 뒤엣것이다.
정확도 이야기는 전방오차 ≤ \le ≤ 조건수 × \times × 후방오차 한 줄로 정리된다.
후방오차는 알고리즘의 몫이고 조건수는 문제의 몫 이다.
반복법의 수렴은 스펙트럼 반지름 < 1 < 1 < 1 이 정한다. L22의 A k → 0 A^k \to 0 A k → 0 이
그대로 알고리즘의 판정 기준이 되었다.
켤레기울기가 특별한 것은 조건수에 제곱근이 붙기 때문이다.
고윳값은 특성다항식으로 구하지 않는다. 거듭제곱법은 L22에서 이미 증명해 두었고 ,
QR 알고리즘은 유사변환을 되풀이하는 것 (L28)이며, 시프트를 넣으면 세제곱으로 수렴한다.
그리고 조르당 형이 왜 위험한지 정확한 언어로 말할 수 있다.
결함 고윳값은 조건수가 무한대 다. 알고리즘을 바꿔서 될 일이 아니라
문제를 바꿔야 한다.
돌아보면 이 책의 후반부가 계속 같은 이야기를 하고 있었다.
존재하는 것과 손에 쥘 수 있는 것은 다르다. 그 차이를 재는 자가 조건수다.
다음은 보강 3 — 그래프 라플라시안과 스펙트럴 클러스터링 이다.
고윳값이 시간의 흐름을 예측하고(L23) 확률의 정착점을 알려주었는데(L24),
이번에는 그래프를 자르는 선 까지 알려준다.
이번 글의 내용을 파이썬으로 확인해 보려면 보강 2 실습 노트북 으로
넘어가면 된다. 세 반복법을 같은 문제에 걸어 감소 곡선을 겹쳐 보고, 거듭제곱법이
정말 ∣ λ 2 / λ 1 ∣ \lvert\lambda_2/\lambda_1\rvert ∣ λ 2 / λ 1 ∣ 로 수렴하는지 재고, 특성다항식과 행렬을
같은 크기로 흔들어 어느 쪽이 무너지는지 직접 볼 수 있다.