1 이 절이 다루는 것
§2.6까지 \(A = LU\) 분해를 완성했다. 이 절은 선형대수의 또 다른 핵심 연산인 전치(transpose)와, 그와 긴밀히 연결된 대칭 행렬, 치환 행렬을 다룬다. 마지막으로 행 교환이 필요할 때의 완전한 분해 \(PA = LU\) 를 다룬다.
§2.7의 핵심 질문
- 전치 행렬이란 무엇이고, 어떤 규칙이 성립하는가?
- \((AB)^T = B^T A^T\) 는 왜 역순인가?
- 대칭 행렬은 어떤 특별한 구조를 갖는가?
- \(R^T R\) 이 항상 대칭인 이유는 무엇인가?
- 치환 행렬 \(P\) 는 왜 \(P^T = P^{-1}\) 인가?
- 행 교환이 필요할 때 \(PA = LU\) 로 어떻게 처리하는가?
2 전치 행렬 (Transpose)
2.1 정의
\(A\) 가 \(m \times n\) 행렬일 때, 전치 행렬 \(A^T\)는 \(n \times m\) 행렬로 \(A\) 의 행과 열을 서로 교환한 것이다.
\[ (A^T)_{ij} = A_{ji} \]
직관: 행렬을 주대각선(\(i = j\))을 기준으로 “뒤집는다”. \((i, j)\) 위치의 원소가 \((j, i)\) 위치로 이동한다.
예시:
\[ A = \begin{bmatrix} 1 & 2 & 3 \\ 0 & 0 & 4 \end{bmatrix}_{2 \times 3} \implies A^T = \begin{bmatrix} 1 & 0 \\ 2 & 0 \\ 3 & 4 \end{bmatrix}_{3 \times 2} \]
- \(A\) 의 행 1 = \((1, 2, 3)\) → \(A^T\) 의 열 1
- \(A\) 의 행 2 = \((0, 0, 4)\) → \(A^T\) 의 열 2
2.2 기본 성질
\[ (A^T)^T = A \quad \text{(두 번 전치하면 원래로)} \]
\[ (cA)^T = cA^T \quad \text{(스칼라는 그대로)} \]
- 하삼각 행렬의 전치 = 상삼각 행렬
- 대각 행렬의 전치 = 자기 자신
3 전치의 연산 규칙
3.1 합의 전치
\[ (A + B)^T = A^T + B^T \]
원소별 덧셈이므로 자연스럽게 성립한다.
3.2 곱의 전치 — 역순이 되는 이유
\[ \boxed{(AB)^T = B^T A^T} \]
왜 역순인가? 먼저 벡터 버전 \((Ax)^T = x^T A^T\) 를 이해한다.
\(Ax\) 는 \(A\) 의 열들의 선형 결합(열 방법)이다. \(x^T A^T\) 는 \(A^T\) 의 행들의 선형 결합인데, \(A^T\) 의 행 = \(A\) 의 열이다. 따라서 같은 벡터들의 같은 선형 결합이 한쪽은 열벡터, 다른 쪽은 행벡터로 나타난다.
\[ (Ax)^T = x^T A^T \]
\(B = [x_1 \; x_2 \; \cdots]\) 의 여러 열에 이를 적용하면:
\[ AB = [Ax_1 \; Ax_2 \; \cdots] \implies (AB)^T = \begin{bmatrix} (Ax_1)^T \\ (Ax_2)^T \\ \vdots \end{bmatrix} = \begin{bmatrix} x_1^T A^T \\ x_2^T A^T \\ \vdots \end{bmatrix} = B^T A^T \]
수치 확인:
\[ AB = \begin{bmatrix} 1 & 0 \\ 1 & 1 \end{bmatrix} \begin{bmatrix} 5 & 0 \\ 4 & 1 \end{bmatrix} = \begin{bmatrix} 5 & 0 \\ 9 & 1 \end{bmatrix} \]
\[ B^T A^T = \begin{bmatrix} 5 & 4 \\ 0 & 1 \end{bmatrix} \begin{bmatrix} 1 & 1 \\ 0 & 1 \end{bmatrix} = \begin{bmatrix} 5 & 9 \\ 0 & 1 \end{bmatrix} = (AB)^T \checkmark \]
더 긴 곱: \((ABC)^T = C^T B^T A^T\) (역순). \(A = LDU\) 이면 \(A^T = U^T D^T L^T = U^T D L^T\).
3.3 역행렬의 전치
\[ (A^{-1})^T = (A^T)^{-1} \]
증명: \(A^{-1}A = I\) 양변을 전치하면 \(A^T (A^{-1})^T = I^T = I\). 따라서 \((A^{-1})^T\) 는 \(A^T\) 의 역행렬이다.
결론: 전치와 역행렬은 순서를 바꾸어도 된다. \(A^T\) 의 가역성은 \(A\) 의 가역성과 동치이다.
\((AB)^T = B^T A^T\) 를 외우는 법: 신발-양말 법칙과 같다. 신발을 벗으려면 먼저 신발을 벗고, 그다음 양말을 벗는다 — 신은 순서의 역순이다. 역행렬도 마찬가지: \((AB)^{-1} = B^{-1} A^{-1}\).
4 내적과 전치의 관계
4.1 내적의 행렬 표기
두 벡터 \(x, y\) 의 내적(dot product)을 행렬 표기로 쓰면:
\[ x \cdot y = x^T y \quad (1 \times n)(n \times 1) = 1 \times 1 \text{ (스칼라)} \]
\(T\) 가 안에 있으면 내적, 밖에 있으면 외적:
| 표현 | 크기 | 의미 |
|---|---|---|
| \(x^T y\) | \(1 \times 1\) | 내적 (스칼라) |
| \(x y^T\) | \(n \times n\) | 외적 (랭크 1 행렬) |
4.2 \((Ax)^T y = x^T (A^T y)\) 의 의미
\[ (Ax)^T y = x^T (A^T y) \quad \text{(모든 } x, y\text{에 대해 성립)} \]
이것이 전치를 정의하는 더 심층적인 방식이다. “\(Ax\) 와 \(y\) 의 내적” = “\(x\) 와 \(A^T y\) 의 내적”.
물리적 직관: 물리학에서 힘 \(f\) 와 변위 \(x\) 의 내적이 일(work)이다. \(A\) 가 좌표를 변환할 때, \(Ax\) 와의 내적을 \(x\) 와의 내적으로 바꿔주는 것이 \(A^T\) 이다. 이것이 전치의 본질이다.
미분에서의 유추: \(d/dt\) 의 “전치”는 무엇인가? 함수의 내적을 \(\int_{-\infty}^{\infty} x(t) y(t) \, dt\) 로 정의하면:
\[ \int_{-\infty}^{\infty} \frac{dx}{dt} y(t) \, dt = -\int_{-\infty}^{\infty} x(t) \frac{dy}{dt} \, dt \]
이것이 부분 적분(integration by parts)이다. 따라서 미분 연산자 \(d/dt\) 의 “전치”는 \(-d/dt\) 이다. 행렬에서 \(A^T = -A\) 인 반대칭 행렬(anti-symmetric matrix)과 같은 맥락이다.
5 대칭 행렬 (Symmetric Matrices)
5.1 정의
\[ A^T = A \quad \iff \quad a_{ji} = a_{ij} \text{ for all } i, j \]
대각선을 기준으로 좌우가 거울 대칭이다. 대각선 원소 \(a_{ii}\) 는 어떤 값이어도 된다.
\[ A = \begin{bmatrix} 1 & 2 \\ 2 & 5 \end{bmatrix} = A^T, \quad D = \begin{bmatrix} 1 & 0 \\ 0 & 10 \end{bmatrix} = D^T \]
대각 행렬은 모두 대칭이다 — 대각선 위아래의 원소들이 모두 0으로 같다.
5.2 대칭 행렬의 역행렬도 대칭
\(A\) 가 대칭(\(A^T = A\))이고 가역이면:
\[ (A^{-1})^T = (A^T)^{-1} = A^{-1} \]
대칭성이 역행렬에서도 보존된다.
5.3 \(A = LDL^T\) — 대칭 행렬의 특별한 분해
\(A\) 가 대칭 행렬이고 행 교환 없이 소거가 가능하면, §2.6의 \(A = LDU\) 가 특별한 형태를 취한다.
\[ A^T = A \implies U = L^T \]
왜인가? \(A = LDU\) 이면 \(A^T = U^T D^T L^T = U^T D L^T\). \(A^T = A\) 이므로 \(LDU = U^T D L^T\). 이 등식은 \(U = L^T\) 일 때만 성립한다.
\[ \boxed{A = LDL^T} \quad \text{(대칭 행렬의 분해)} \]
예시:
\[ A = \begin{bmatrix} 1 & 2 \\ 2 & 7 \end{bmatrix} = \underbrace{\begin{bmatrix} 1 & 0 \\ 2 & 1 \end{bmatrix}}_{L} \underbrace{\begin{bmatrix} 1 & 0 \\ 0 & 3 \end{bmatrix}}_{D} \underbrace{\begin{bmatrix} 1 & 2 \\ 0 & 1 \end{bmatrix}}_{L^T} \]
\(L\) 과 \(L^T\) 가 대칭적으로 배치된다. \(D\) 는 피벗을 담는 대각 행렬.
연산량 절감: 대칭 행렬은 절반만 저장하면 된다 (\(n(n+1)/2\) 개 원소). 소거도 절반 — \(n^3/3\) 에서 \(n^3/6\) 으로 줄어든다.
6 \(R^T R\) 과 \(RR^T\) — 자동으로 대칭인 행렬
6.1 핵심 사실
임의의 행렬 \(R\) (\(m \times n\))에 대해:
\[ (R^T R)^T = R^T (R^T)^T = R^T R \quad \checkmark \]
\(R^T R\) 은 항상 대칭이다.
같은 이유로 \(RR^T\) 도 항상 대칭이다.
원소로 확인: \((R^T R)_{ij}\) = \(R\) 의 \(i\) 번째 열과 \(j\) 번째 열의 내적 = \((R^T R)_{ji}\) (내적은 교환 가능). 대칭이다.
6.2 \(R^T R\) vs \(RR^T\)
| \(R^T R\) | \(RR^T\) | |
|---|---|---|
| 크기 | \(n \times n\) | \(m \times m\) |
| 대칭? | 예 | 예 |
| 같은가? | 일반적으로 아니다 |
예시: \(R = \begin{bmatrix} -1 & 1 & 0 \\ 0 & -1 & 1 \end{bmatrix}\)
\[ RR^T = \begin{bmatrix} 2 & -1 \\ -1 & 2 \end{bmatrix}, \quad R^T R = \begin{bmatrix} 1 & -1 & 0 \\ -1 & 2 & -1 \\ 0 & -1 & 1 \end{bmatrix} \]
두 행렬 모두 대칭이지만 크기도, 원소도 다르다.
6.3 왜 \(R^T R\) 이 중요한가
- 최소자승법: \(Rx = b\) 의 정규 방정식은 \(R^T Rx = R^T b\). \(R^T R\) 이 가역이면 최소자승 해를 직접 구할 수 있다.
- 공분산 행렬: 데이터 행렬 \(X\) 의 공분산은 \(\frac{1}{n}X^T X\) — 자동으로 대칭·반양정치이다.
- 그람 행렬(Gram matrix): \(K_{ij} = x_i^T x_j\) = \((X^T X)_{ij}\).
7 치환 행렬 (Permutation Matrices)
7.1 정의
치환 행렬 \(P\)는 단위 행렬 \(I\) 의 행들을 임의의 순서로 재배열한 행렬이다.
- 각 행에 정확히 하나의 1, 나머지 0.
- 각 열에 정확히 하나의 1, 나머지 0.
\(P\) 를 벡터에 곱하면 성분들의 순서를 재배열한다.
\(3 \times 3\) 치환 행렬은 6가지 (\(3! = 6\)). \(n \times n\) 은 \(n!\) 가지이다.
\[ P_{12} = \begin{bmatrix} 0 & 1 & 0 \\ 1 & 0 & 0 \\ 0 & 0 & 1 \end{bmatrix}, \quad P_{23} = \begin{bmatrix} 1 & 0 & 0 \\ 0 & 0 & 1 \\ 0 & 1 & 0 \end{bmatrix} \]
\[ P_{12} \begin{bmatrix} v_1 \\ v_2 \\ v_3 \end{bmatrix} = \begin{bmatrix} v_2 \\ v_1 \\ v_3 \end{bmatrix}, \quad P_{23} \begin{bmatrix} v_1 \\ v_2 \\ v_3 \end{bmatrix} = \begin{bmatrix} v_1 \\ v_3 \\ v_2 \end{bmatrix} \]
7.2 \(P^T = P^{-1}\) — 치환 행렬은 직교 행렬
\[ \boxed{P^T = P^{-1}, \quad \text{즉} \quad PP^T = P^T P = I} \]
직관 1 — 행 교환을 두 번 하면 원래로:
\(P\) 가 \(i\) 행과 \(j\) 행을 교환하면, \(P\) 를 다시 곱하면 다시 교환해 원래로 돌아온다.
\[ P_{ij} P_{ij} = I \implies P_{ij}^{-1} = P_{ij} \]
단순 행 교환은 \(P^T = P\) 이므로 \(P^{-1} = P^T\) 가 자연스럽게 성립한다.
직관 2 — 직교 행렬의 특성:
\(P\) 의 각 행은 단위 벡터 \(e_k\) 중 하나이다. 서로 다른 두 행은 직교하고, 각 행의 노름은 1이다. 즉 \(P\) 는 직교 행렬(orthogonal matrix)이다. 직교 행렬은 \(Q^T Q = I\) 를 만족한다.
직관 3 — 행과 열의 역할 반전:
\(P\) 의 1행이 “\(v\) 의 \(k\) 번째 성분을 1번째 위치로 가져오라”는 지시라면, \(P^T\) 의 1열은 “\(v\) 의 1번째 성분을 \(k\) 번째 위치로 돌려보내라”는 역지시이다. 전치가 자동으로 역연산이 된다.
7.3 치환의 부호 (Sign of Permutation)
치환 행렬 \(P\) 의 행렬식(determinant)은 \(+1\) 또는 \(-1\) 이다.
- 짝수 번의 행 교환으로 만들어진 \(P\): \(\det(P) = +1\) (우함수 치환, even permutation)
- 홀수 번의 행 교환: \(\det(P) = -1\) (기함수 치환, odd permutation)
\(n!\) 개의 치환 중 절반은 \(+1\), 절반은 \(-1\).
8 \(PA = LU\) — 행 교환을 포함한 완전한 분해
8.1 왜 필요한가
소거 중에 피벗 위치의 원소가 0이 되면 행을 교환해야 한다. 이 행 교환을 치환 행렬로 표현하면 \(A = LU\) 분해를 임의의 가역 행렬로 확장할 수 있다.
8.2 두 가지 관점
방법 1 — 소거 전에 미리 행 교환 (더 일반적):
\[ PA = LU \]
\(P\) 가 \(A\) 의 행들을 올바른 순서로 재배열한 뒤 소거를 진행하면 행 교환 없이 \(LU\) 분해가 된다.
방법 2 — 소거 중에 행 교환 (탐색식):
\[ A = L_1 P_1 U_1 \]
소거를 진행하다가 0 피벗을 만날 때마다 교환. 실제 수치 계산에서 더 자주 사용된다 (부분 피벗팅, partial pivoting).
8.3 \(PA = LU\) 예시
\[ A = \begin{bmatrix} 0 & 1 & 1 \\ 1 & 2 & 1 \\ 2 & 7 & 9 \end{bmatrix} \]
1행 1열의 피벗이 0이다. 1행과 2행을 교환한다.
\[ P = \begin{bmatrix} 0 & 1 & 0 \\ 1 & 0 & 0 \\ 0 & 0 & 1 \end{bmatrix},\quad PA = \begin{bmatrix} 1 & 2 & 1 \\ 0 & 1 & 1 \\ 2 & 7 & 9 \end{bmatrix} \]
이제 \(PA\) 에 소거를 적용한다.
\(E_{31}\) 적용 (\(\ell_{31} = 2\)):
\[ PA \to \begin{bmatrix} 1 & 2 & 1 \\ 0 & 1 & 1 \\ 0 & 3 & 7 \end{bmatrix} \]
\(E_{32}\) 적용 (\(\ell_{32} = 3\)):
\[ \to U = \begin{bmatrix} 1 & 2 & 1 \\ 0 & 1 & 1 \\ 0 & 0 & 4 \end{bmatrix} \]
\[ L = \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 2 & 3 & 1 \end{bmatrix} \]
\[ PA = LU = \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 2 & 3 & 1 \end{bmatrix} \begin{bmatrix} 1 & 2 & 1 \\ 0 & 1 & 1 \\ 0 & 0 & 4 \end{bmatrix} \checkmark \]
8.4 \(PA = LU\) 로 \(Ax = b\) 풀기
\[ Ax = b \implies PAx = Pb \implies LUx = Pb \]
- \(P\) 를 \(b\) 에 적용: \(\tilde{b} = Pb\) (행 순서 재배열)
- \(Lc = \tilde{b}\) 전방 대입
- \(Ux = c\) 후방 대입
8.5 부분 피벗팅 (Partial Pivoting)
실제 수치 계산에서는 0 피벗만 피하는 것이 아니라, 각 열에서 가장 큰 절댓값을 가진 원소를 피벗으로 선택한다.
왜인가? 작은 피벗으로 나누면 반올림 오차가 크게 증폭된다. 가장 큰 원소를 피벗으로 쓰면 나눗셈의 결과(승수 \(\ell_{ij}\))가 절댓값 1 이하가 되어 오차 증폭이 억제된다.
가역 행렬 \(A\) 에 대한 완전한 정리
임의의 가역 행렬 \(A\) 에 대해, 어떤 치환 행렬 \(P\) 가 존재하여
\[PA = LU\]
가 성립한다. \(L\) 은 하삼각, \(U\) 는 상삼각, \(P\) 는 치환 행렬이다.
9 직관 정리: 각 개념의 연결
전치 A^T
├── 내적: x^T y, (Ax)^T y = x^T(A^T y)
├── 대칭: A^T = A → A = LDL^T
│ └── R^T R 은 항상 대칭 (최소자승, 공분산)
└── 치환: P^T = P^{-1} (직교 행렬)
└── PA = LU (행 교환 포함한 완전한 분해)
10 Worked Examples
10.1 예시 1: \((AB)^T = B^T A^T\) 검증
\[ A = \begin{bmatrix} 1 & 2 \\ 0 & 3 \end{bmatrix},\quad B = \begin{bmatrix} 4 & 0 \\ 1 & 2 \end{bmatrix} \]
\[ AB = \begin{bmatrix} 6 & 4 \\ 3 & 6 \end{bmatrix},\quad (AB)^T = \begin{bmatrix} 6 & 3 \\ 4 & 6 \end{bmatrix} \]
\[ B^T A^T = \begin{bmatrix} 4 & 1 \\ 0 & 2 \end{bmatrix}\begin{bmatrix} 1 & 0 \\ 2 & 3 \end{bmatrix} = \begin{bmatrix} 6 & 3 \\ 4 & 6 \end{bmatrix} \checkmark \]
10.2 예시 2: \(A = LDL^T\) 대칭 분해
\[ A = \begin{bmatrix} 4 & 8 \\ 8 & 22 \end{bmatrix} \]
소거: \(\ell_{21} = 8/4 = 2\), 피벗 \(d_1 = 4\), \(d_2 = 22 - 2 \cdot 8 = 6\).
\[ L = \begin{bmatrix} 1 & 0 \\ 2 & 1 \end{bmatrix},\quad D = \begin{bmatrix} 4 & 0 \\ 0 & 6 \end{bmatrix},\quad L^T = \begin{bmatrix} 1 & 2 \\ 0 & 1 \end{bmatrix} \]
\[ LDL^T = \begin{bmatrix} 1 & 0 \\ 2 & 1 \end{bmatrix}\begin{bmatrix} 4 & 0 \\ 0 & 6 \end{bmatrix}\begin{bmatrix} 1 & 2 \\ 0 & 1 \end{bmatrix} = \begin{bmatrix} 4 & 8 \\ 8 & 22 \end{bmatrix} = A \checkmark \]
10.3 예시 3: 치환 행렬의 합성
\[ P_{32} = \begin{bmatrix} 1 & 0 & 0 \\ 0 & 0 & 1 \\ 0 & 1 & 0 \end{bmatrix},\quad P_{21} = \begin{bmatrix} 0 & 1 & 0 \\ 1 & 0 & 0 \\ 0 & 0 & 1 \end{bmatrix} \]
\[ P_{32}P_{21} = \begin{bmatrix} 0 & 1 & 0 \\ 0 & 0 & 1 \\ 1 & 0 & 0 \end{bmatrix} \quad \neq \quad P_{21}P_{32} = \begin{bmatrix} 0 & 0 & 1 \\ 1 & 0 & 0 \\ 0 & 1 & 0 \end{bmatrix} \]
치환 행렬도 일반적으로 교환 법칙이 성립하지 않는다.
역행렬 확인:
\[ (P_{32}P_{21})^{-1} = P_{21}^{-1}P_{32}^{-1} = P_{21}P_{32} = \begin{bmatrix} 0 & 0 & 1 \\ 1 & 0 & 0 \\ 0 & 1 & 0 \end{bmatrix} \]
\[ (P_{32}P_{21})(P_{21}P_{32}) = \begin{bmatrix} 0 & 1 & 0 \\ 0 & 0 & 1 \\ 1 & 0 & 0 \end{bmatrix} \begin{bmatrix} 0 & 0 & 1 \\ 1 & 0 & 0 \\ 0 & 1 & 0 \end{bmatrix} = I \checkmark \]
10.4 예시 4: 대칭 행렬의 행 교환이 대칭성에 미치는 영향
\[ P = \begin{bmatrix} 0 & 1 & 0 \\ 0 & 0 & 1 \\ 1 & 0 & 0 \end{bmatrix},\quad A = \begin{bmatrix} 1 & 4 & 5 \\ 4 & 2 & 6 \\ 5 & 6 & 3 \end{bmatrix} \]
\(PA\) 는 대칭이 아니다. 하지만 \(PAP^T = PAQ\) (\(Q = P^T\))는 다시 대칭이 된다.
왜인가? \((PAP^T)^T = (P^T)^T A^T P^T = PA P^T\). 즉 \(PAP^T\) 는 항상 대칭이다.
열에 \(P^T\) 를 곱하는 것은 행 교환과 같은 열 교환을 적용하는 것이다 — 행과 열을 동시에 같은 순서로 교환하면 대칭성이 유지된다.
11 ML/DL에서의 연결
11.1 그람 행렬과 커널 방법
\(X = [x_1 \; x_2 \; \cdots \; x_n]^\top\) (\(n \times d\) 데이터 행렬)에서:
\[ K = XX^\top, \quad K_{ij} = x_i^\top x_j \]
\(K\) 는 항상 대칭 반양정치 행렬이다. 커널 SVM, GP(Gaussian Process)에서 이 그람 행렬이 핵심이다.
11.2 어텐션의 대칭성
트랜스포머의 어텐션 스코어 행렬 \(S = QK^\top / \sqrt{d_k}\) 는 일반적으로 비대칭이다 (\(Q \neq K\)). 하지만 자기 어텐션(self-attention)에서 \(Q = K\) 이면 \(S = QQ^\top / \sqrt{d_k}\) 가 되어 대칭 행렬이다.
11.3 공분산과 \(R^T R\)
배치 데이터 \(X \in \mathbb{R}^{B \times d}\) (각 행이 샘플)의 경험적 공분산:
\[ \Sigma = \frac{1}{B} X^\top X \in \mathbb{R}^{d \times d} \]
\(R = X / \sqrt{B}\) 로 놓으면 \(\Sigma = R^\top R\) — 항상 대칭·양반정치 행렬이다. PCA의 고유벡터를 구하는 대상이 바로 이 행렬이다.
11.4 부분 피벗팅과 수치 안정성
딥러닝 프레임워크의 torch.linalg.solve, numpy.linalg.solve는 내부적으로 LAPACK의 dgesv를 호출한다. 이 루틴은 부분 피벗팅(\(PA = LU\))을 기본으로 사용한다 — 오차 증폭을 막기 위해.
12 코드로 확인하기
12.1 Step 1 — 전치 규칙 검증
import numpy as np
A = np.array([[1, 2], [3, 4], [5, 6]], dtype=float) # 3x2
B = np.array([[7, 8, 9], [0, 1, 2]], dtype=float) # 2x3
# (AB)^T = B^T A^T
AB = A @ B
print("(AB)^T:\n", AB.T)
print("B^T A^T:\n", B.T @ A.T)
print("같은가?", np.allclose(AB.T, B.T @ A.T))
# R^T R은 항상 대칭
R = np.random.randn(4, 3)
RtR = R.T @ R
print("\nR^T R 대칭?", np.allclose(RtR, RtR.T))12.2 Step 2 — \(A = LDL^T\) 분해 구현
import numpy as np
def ldlt_decomp(A):
"""
대칭 행렬 A의 LDL^T 분해.
행 교환 없는 경우 (모든 피벗 > 0 가정).
반환: L (하삼각, 대각 1), d (피벗 벡터)
"""
n = A.shape[0]
A = A.copy().astype(float)
L = np.eye(n)
d = np.zeros(n)
for k in range(n):
d[k] = A[k, k]
if abs(d[k]) < 1e-12:
raise ValueError(f"피벗 = 0: 열 {k}")
for i in range(k + 1, n):
L[i, k] = A[i, k] / d[k]
for j in range(k + 1, n):
A[i, j] -= L[i, k] * A[k, j]
return L, d
A = np.array([[4, 8, 4],
[8, 22, 10],
[4, 10, 7]], dtype=float)
L, d = ldlt_decomp(A)
D = np.diag(d)
print("L:\n", L)
print("d:", d)
print("LDL^T == A?", np.allclose(L @ D @ L.T, A))
print("A 대칭?", np.allclose(A, A.T))12.3 Step 3 — \(PA = LU\) 구현 및 검증
import numpy as np
def lu_with_pivot(A):
"""
부분 피벗팅을 이용한 PA = LU 분해.
반환: P (치환 행렬), L (하삼각), U (상삼각)
"""
n = A.shape[0]
A = A.copy().astype(float)
P = np.eye(n)
L = np.zeros((n, n))
for k in range(n):
# 부분 피벗팅: k열에서 k행 이하 중 최대 절댓값 행 선택
max_row = k + np.argmax(np.abs(A[k:, k]))
if max_row != k:
A[[k, max_row]] = A[[max_row, k]]
P[[k, max_row]] = P[[max_row, k]]
if k > 0:
L[[k, max_row], :k] = L[[max_row, k], :k]
L[k, k] = 1.0
for i in range(k + 1, n):
L[i, k] = A[i, k] / A[k, k]
A[i, k:] -= L[i, k] * A[k, k:]
U = np.triu(A)
return P, L, U
A = np.array([[0, 1, 1],
[1, 2, 1],
[2, 7, 9]], dtype=float)
P, L, U = lu_with_pivot(A)
print("P:\n", P)
print("L:\n", L)
print("U:\n", U)
print("PA == LU?", np.allclose(P @ A, L @ U))
# PA = LU로 Ax = b 풀기
b = np.array([3, 4, 5], dtype=float)
Pb = P @ b # Step 1: 우변에도 P 적용
# Step 2: Lc = Pb (전방 대입)
from scipy.linalg import solve_triangular
c = solve_triangular(L, Pb, lower=True)
# Step 3: Ux = c (후방 대입)
x = solve_triangular(U, c, lower=False)
print("\n해 x:", x)
print("검증 Ax:", A @ x, "== b:", b)13 핵심 요약
- 전치: \((A^T)_{ij} = A_{ji}\) — 주대각선 기준 뒤집기.
- 곱의 전치: \((AB)^T = B^T A^T\) — 역순. \(Ax\) 의 열 결합이 \(x^T A^T\) 의 행 결합과 같기 때문.
- \((Ax)^T y = x^T(A^T y)\): 전치의 본질 — “\(Ax\) 와 \(y\) 의 내적” = “\(x\) 와 \(A^T y\) 의 내적”.
- 대칭 행렬 \(A^T = A\): \(A = LDL^T\) 분해 — 연산량 절반으로 감소.
- \(R^T R\): 항상 대칭 — 최소자승, 공분산, 커널의 기본 구조.
- 치환 행렬 \(P\): \(P^T = P^{-1}\) — 직교 행렬, 행 교환 두 번 = 항등.
- \(PA = LU\): 임의의 가역 행렬에 대해 성립하는 완전한 분해.