Chapter 03

행렬은 변환이다

행렬을 "숫자를 네모나게 늘어놓은 표"로 배웠다면, 이 장에서 그 생각을 버립니다. 행렬은 공간 전체를 한 번에 휘고 늘이고 돌리는 기계이고, 칸에 적힌 숫자는 그 기계의 설계도입니다. 이렇게 보면 행렬 곱은 "변환을 이어 붙이기", 역행렬은 "되돌리기", 행렬식은 "넓이가 몇 배 되나", 고유벡터는 "방향이 안 바뀌는 축"이라는 그림이 됩니다. 그리고 그 그림 하나하나가 카메라의 색, 건물의 흔들림, 이미지 압축이라는 공학 문제를 풀어 줍니다.

이 수식이 없었다면스마트폰 카메라의 "맞는 색"

스마트폰 이미지 센서의 R·G·B 컬러 필터는 사람 눈의 세 원뿔세포와 분광 감도가 다릅니다. 필터끼리 겹치는 모양도, 봉우리 위치도 다르지요. 그래서 센서가 읽은 숫자를 그대로 화면에 보내면 하늘은 탁하고 피부는 누렇고 초록은 빛이 바랩니다. 픽셀마다 "이 색이면 이렇게 고쳐라"를 표로 만들기에는 색의 조합이 너무 많습니다.

해법은 놀랍도록 작습니다. 3×3 행렬 하나, 숫자 아홉 개가 모든 픽셀의 (R, G, B)를 표준 색공간의 (R, G, B)로 옮깁니다. 행렬은 색 하나하나가 아니라 색공간 전체를 한 번에 변환하기 때문입니다. 이것이 색 보정 행렬(CCM)이고, 지금 이 순간에도 세계의 모든 카메라 파이프라인에서 초당 수억 번 곱해지고 있습니다.

센서 RGB ≠ 눈의 RGB→색마다 보정표? 불가능→3×3 선형 변환→매 픽셀 9번 곱셈

행렬은 기저벡터가 어디로 가는지의 기록

사진 한 장을 기울이려면 공식이 몇 개 필요할까

사진 편집 앱에서 사진을 15° 돌리고, 옆으로 살짝 비스듬하게 밀고, 가로로 1.2배 늘린다고 합시다. 1,200만 화소 각각의 새 좌표를 계산해야 합니다. 회전 공식, 전단 공식, 확대 공식을 따로 만들어 차례로 적용해야 할까요? 변환이 수백 종류라면 공식도 수백 개일까요?

막힌 곳을 뚫는 관찰은 이것입니다. 위의 변환들은 모두 선형 변환(linear transformation)입니다. 원점은 제자리에 있고, 직선은 직선으로, 평행하고 등간격인 격자선은 여전히 평행하고 등간격인 격자선으로 갑니다. 식으로 쓰면 \(T(a\mathbf{u}+b\mathbf{v}) = aT(\mathbf{u}) + bT(\mathbf{v})\)입니다.

이 성질 하나로 놀라운 일이 생깁니다. 평면의 모든 벡터는 \(\mathbf{v} = x\,\hat{\imath} + y\,\hat{\jmath}\)처럼 두 기저벡터의 조합으로 쓸 수 있으니, 선형성에 의해

$$T(\mathbf{v}) = x\,T(\hat{\imath}) + y\,T(\hat{\jmath}) = x\begin{bmatrix}a\\c\end{bmatrix} + y\begin{bmatrix}b\\d\end{bmatrix} = \begin{bmatrix}a & b\\ c & d\end{bmatrix}\begin{bmatrix}x\\y\end{bmatrix}$$
\(\hat{\imath}=(1,0)\)이 가는 곳 \((a,c)\)가 1열, \(\hat{\jmath}=(0,1)\)이 가는 곳 \((b,d)\)가 2열. 행렬–벡터 곱은 "열들을 x개, y개씩 더하라"는 지시다.

즉 두 벡터(숫자 네 개)만 알면 평면 전체가 어디로 가는지 다 안다는 뜻입니다. 행렬은 바로 그 네 숫자를 적어 둔 기록입니다. 1,200만 화소든 무한히 많은 점이든, 공식은 \(A\mathbf{v}\) 하나입니다. 회전이냐 전단이냐는 공식의 종류가 아니라 칸에 적힌 숫자의 차이일 뿐입니다.

변환 전: 표준 격자변환 후: A = [1 −0.5; 0.5 1]îĵv = 2î + 1ĵAî = (1, 0.5)Aĵ = (−0.5, 1)Av = 2(Aî) + 1(Aĵ)= (1.5, 2)
그림 3-1. 왼쪽의 v = 2î + 1ĵ는 "î로 두 칸, ĵ로 한 칸"이라는 지시다. 변환 뒤에도 그 지시는 그대로이고, 다만 î와 ĵ가 각각 Aî, Aĵ(행렬의 두 열)로 바뀌었을 뿐이다. 그래서 Av = 2(Aî) + 1(Aĵ). 격자선은 기울어져도 평행·등간격을 유지한다.

아래 시뮬레이터가 이 장의 대표 데모입니다. 초록 점(î가 가는 곳)과 빨강 점(ĵ가 가는 곳)을 끌면 격자 전체가 따라 휩니다. 숫자를 직접 넣어도 됩니다.

SIMULATOR

격자를 휘는 기계: 2×2 행렬

î′, ĵ′ 끝점을 끌어 보세요
행렬 A (열 = î′, ĵ′)
행렬식 det A = ad − bc—
넓이 배율—
방향—
계수 (rank)—
해볼 것: ① 빨강 점(ĵ′)을 초록 점 왼쪽 아래로 넘겨 보세요. 평행사변형이 빨갛게 바뀌고 F가 거울상이 됩니다(det < 0). ② 두 점을 원점을 지나는 한 직선 위에 놓으면 평면 전체가 선으로 납작해집니다(det = 0). ③ '전단'과 '비균일 확대'는 모양을 크게 바꾸지만 넓이 배율은 1입니다. 모델: 원점을 고정하는 2차원 선형 변환만 다룹니다(평행이동은 3절 심화 참고). 끈 점은 0.1 단위로 맞춰집니다.
변환행렬î가 가는 곳det쓰이는 곳
회전 θ\(\begin{bmatrix}\cos\theta & -\sin\theta\\ \sin\theta & \cos\theta\end{bmatrix}\)\((\cos\theta, \sin\theta)\)1사진 수평 보정, 자이로 자세 계산
전단\(\begin{bmatrix}1 & k\\ 0 & 1\end{bmatrix}\)\((1,0)\) 그대로1이탤릭체, 롤링 셔터 왜곡 근사
확대\(\begin{bmatrix}s_x & 0\\ 0 & s_y\end{bmatrix}\)\((s_x, 0)\)\(s_x s_y\)리사이즈, 화이트 밸런스 이득(3×3 대각)
반사\(\begin{bmatrix}-1 & 0\\ 0 & 1\end{bmatrix}\)\((-1,0)\)−1셀피 좌우 반전
투영\(\begin{bmatrix}1 & 0\\ 0 & 0\end{bmatrix}\)\((1,0)\)0그림자, 3D→2D 정사영, 최소제곱
읽는 습관 하나 행렬을 보면 먼저 열을 세로로 읽으세요. "1열은 î가 가는 곳, 2열은 ĵ가 가는 곳." 이 습관 하나로 \(\begin{bmatrix}0 & -1\\ 1 & 0\end{bmatrix}\)이 90° 회전이라는 것이 계산 없이 보입니다. î는 위로, ĵ는 왼쪽으로 갔으니까요.

행렬식은 넓이 배율이다

변환 뒤 픽셀 하나는 몇 배 넓어지나

사진을 변환하면 원래 한 화소였던 영역이 변환 뒤에는 몇 화소를 덮을까요? 빛의 세기(단위 넓이당 에너지)를 보존하려면 이 비율로 밝기를 나눠야 합니다. 확률 밀도를 좌표 변환할 때도, 적분 변수를 바꿀 때도 똑같은 질문이 나옵니다. "이 변환은 넓이를 몇 배로 만드는가?"

선형 변환은 격자를 평행·등간격으로 유지하므로 모든 칸이 똑같은 비율로 넓어지거나 줄어듭니다. 그러니 단위 정사각형 하나가 몇 배가 되는지만 보면 됩니다. 단위 정사각형은 두 열벡터 \((a,c)\), \((b,d)\)가 만드는 평행사변형으로 가고, 그 넓이가 행렬식(determinant)입니다.

ac/2bcbd/2ac/2bcbd/2ad − bc(a, c) = (3, 1), (b, d) = (1, 2): 12 − 2·1 − 2·1.5 − 2·1 = 5 = 3·2 − 1·1넓이 = 큰 직사각형 − 바깥 조각det > 0방향 유지det < 0뒤집힘(거울상)det = 0선으로 납작
그림 3-2. 왼쪽: 두 열 (a, c), (b, d)가 만드는 평행사변형의 넓이는 감싸는 직사각형 (a+b)(c+d)에서 바깥의 직사각형 2개와 삼각형 4개를 뺀 값, 즉 ad − bc. 오른쪽: 부호는 방향을 말한다. det > 0이면 F가 그대로 읽히고, det < 0이면 거울상, det = 0이면 평면이 선으로 납작해진다.
$$\det\begin{bmatrix}a & b\\ c & d\end{bmatrix} = ad - bc, \qquad \det(AB) = \det A\cdot\det B, \qquad \det(A^{-1}) = \frac{1}{\det A}$$
두 번째 식은 그림으로 당연하다. 넓이를 \(\det B\)배 한 뒤 다시 \(\det A\)배 하면 \(\det A\det B\)배다. 3×3에서는 세 열이 만드는 평행육면체의 부피 배율이고, 일반적으로 n차원 부피 배율이다.

부호까지 보면 정보가 하나 더 있습니다. det < 0인 변환은 공간을 뒤집습니다. 오른손 좌표계를 왼손 좌표계로 바꾸고, 시계 방향을 반시계 방향으로 바꿉니다. 3D 그래픽에서 det < 0인 변환을 메시에 걸면 삼각형의 앞뒤 판정(정점 순서로 정함)이 뒤집혀 면이 사라지는 버그가 생기는 이유가 이것입니다.

야코비안 비선형 변환도 아주 작은 영역에서는 선형처럼 보입니다(1장의 "확대하면 직선"). 그 국소 선형 변환의 행렬이 야코비 행렬 \(J\)이고, \(|\det J|\)가 그 점에서의 넓이 배율입니다. 극좌표 적분의 \(dx\,dy = r\,dr\,d\theta\), 확률 밀도의 변수 변환 \(p_Y(y) = p_X(x)/|\det J|\)가 모두 이 한 줄에서 나옵니다.

행렬 곱은 변환을 이어 붙이기, 순서가 중요하다

변환 열 개를 매 픽셀에 열 번 적용해야 할까

카메라 파이프라인이든 게임 엔진이든 변환은 줄줄이 이어집니다. 물체를 돌리고, 기울이고, 카메라 좌표로 옮기고, 화면에 투영합니다. 정점 백만 개마다 행렬 열 개를 차례로 곱하면 계산이 열 배입니다. 미리 하나로 합칠 수는 없을까요? 합친다면 어떤 순서로?

먼저 \(B\)를 하고 그다음 \(A\)를 하는 합성 변환 \(\mathbf{v}\mapsto A(B\mathbf{v})\)도 선형입니다. 선형이면 행렬 하나로 쓸 수 있고, 그 행렬의 열은 역시 "î와 ĵ가 최종적으로 가는 곳"입니다. î는 \(B\)에 의해 \(B\)의 1열 \(\mathbf{b}_1\)로 가고, 그것이 다시 \(A\mathbf{b}_1\)로 갑니다. 그래서

$$AB = \Big[\,A\mathbf{b}_1 \;\; A\mathbf{b}_2\,\Big], \qquad (AB)\mathbf{v} = A(B\mathbf{v})$$
행렬 곱의 "행 곱하기 열" 규칙은 외워야 할 규칙이 아니라 이 정의를 계산한 결과다. 오른쪽에 있는 행렬이 먼저 적용된다(함수 합성 \(f\circ g\)와 같은 순서).

한 번 곱해 두면 픽셀마다 행렬 하나만 곱하면 됩니다. 하지만 순서를 바꾸면 결과가 달라집니다. 30° 회전 \(R\)과 가로 전단 \(S\)로 직접 계산해 보면

$$SR = \begin{bmatrix}1.366 & -0.366\\ 0.5 & 0.866\end{bmatrix} \;\neq\; RS = \begin{bmatrix}0.866 & 0.366\\ 0.5 & 1.366\end{bmatrix}$$
\(SR\): 먼저 회전, 다음 전단. \(RS\): 먼저 전단, 다음 회전. 두 행렬 모두 det = 1(넓이는 같다)이지만 모양은 다르다.
SIMULATOR

순서를 바꾸면 결과가 바뀐다: BA vs AB

왼쪽: 먼저 A(회전) → 다음 B = BA
오른쪽: 먼저 B → 다음 A(회전) = AB
BA (먼저 A)—
AB (먼저 B)—
차이 ‖AB − BA‖—
해볼 것: ① 기본값(30° 회전, 전단 k = 1)에서 재생을 눌러 두 F가 다른 곳에 도착하는 것을 보세요. 점선은 반대편 패널의 최종 결과입니다. ② B를 '균일 확대'로 바꾸면 차이가 0이 됩니다. 균일 확대는 어떤 변환과도 교환됩니다. ③ θ = 180°에서는 '가로로만 늘이기'도 교환됩니다. 왜일까요? 모델: 중간 단계는 회전은 각도를, 나머지는 행렬 원소를 선형 보간해 그렸습니다(거울 반사는 중간에 납작해져 보입니다).
평행이동은 선형이 아니다 → 동차 좌표 "오른쪽으로 3칸 옮기기"는 원점을 움직이므로 2×2 행렬로는 쓸 수 없습니다. 컴퓨터 그래픽스는 점 \((x,y)\)를 \((x,y,1)\)로 한 차원 올려 3×3 행렬(3D는 4×4)의 마지막 열에 이동량을 넣습니다. 그러면 회전·확대·이동이 모두 행렬 곱 하나로 합쳐집니다. GPU가 4×4 행렬 곱셈에 특화된 이유입니다.

카메라에서도 순서는 실제 문제입니다. 뒤에서 볼 CCM은 화이트 밸런스를 먼저 적용한 뒤의 센서 값을 기준으로 맞춘 행렬입니다. 대각 행렬(화이트 밸런스)과 CCM은 일반적으로 교환되지 않으므로, 순서를 바꾸면 같은 숫자로도 색이 틀어집니다.

연립방정식은 "어떤 입력이 이 출력으로 가나"

섞여 버린 두 픽셀을 되돌리기

이미지 센서의 이웃한 두 픽셀은 빛과 전하가 서로 조금씩 새어 들어갑니다(crosstalk). 픽셀 1에 들어온 진짜 신호 \(x_1\) 중 비율 \(\alpha\)가 픽셀 2로 새고, 반대도 마찬가지라면 측정값은 \(b_1 = (1-\alpha)x_1 + \alpha x_2\), \(b_2 = \alpha x_1 + (1-\alpha)x_2\)입니다. 측정값 \(\mathbf{b}\)에서 진짜 \(\mathbf{x}\)를 되찾을 수 있을까요? \(\alpha\)가 0.5에 가까우면?

이것은 \(A\mathbf{x} = \mathbf{b}\) 꼴의 연립방정식입니다. 변환의 언어로 바꾸면 질문이 선명해집니다. "\(A\)라는 기계에 무엇을 넣어야 \(\mathbf{b}\)가 나오는가?" 즉 변환을 거꾸로 돌리는 것, 역변환 \(A^{-1}\)입니다. 같은 방정식을 두 가지로 그릴 수 있습니다.

(x, y) = (2, 3)2x − y = 1x + y = 5행 그림: 두 직선의 교점a₁ = (2, 1)a₂ = (−1, 1)2a₁b = (1, 5) = 2a₁ + 3a₂열 그림: 열벡터를 몇 개씩 더하나
그림 3-3. 같은 연립방정식 2x − y = 1, x + y = 5. 왼쪽(행 그림): 방정식 하나가 직선 하나, 해는 교점. 오른쪽(열 그림): 행렬의 열 a₁ = (2, 1), a₂ = (−1, 1)을 각각 몇 개씩 더해야 b = (1, 5)에 닿는가. 답은 2개와 3개다. 열 그림이 "변환" 관점이다.
$$A^{-1} = \frac{1}{ad-bc}\begin{bmatrix}d & -b\\ -c & a\end{bmatrix}, \qquad \mathbf{x} = A^{-1}\mathbf{b}$$
\(\det A\)로 나누는 것이 보인다. 넓이를 \(\det A\)배 한 변환을 되돌리려면 \(1/\det A\)배 해야 하니 당연하다. 그리고 \(\det A = 0\)이면 되돌릴 수 없다.

det = 0이면 평면 전체가 직선 하나(또는 점 하나)로 납작해집니다. 서로 다른 무수한 입력이 같은 출력으로 뭉개졌으니 정보가 사라진 것입니다. 그러면 두 경우뿐입니다. \(\mathbf{b}\)가 그 직선 밖에 있으면 해가 없고(어떤 입력도 거기로 가지 않음), 직선 위에 있으면 해가 무수히 많습니다(여러 입력이 거기로 감). 크로스토크 문제에서 \(\alpha = 0.5\)는 두 픽셀이 완전히 반씩 섞인 경우로, 어떤 수학으로도 원래 두 값을 분리할 수 없습니다. 합만 알 수 있지요.

SIMULATOR

열 그림으로 연립방정식 풀기와 조건수

a₁, a₂, b를 끌 수 있습니다
예시
—
해 x = (x₁, x₂)—
det A—
조건수 κ = σ₁/σ₂—
잡음 때문에 틀어진 x—
해볼 것: ① 크로스토크 α를 0에서 0.5로 천천히 올리세요. 격자 칸이 점점 납작해지고, 잡음을 켜면 x의 오차가 폭발합니다(참값은 x = (1.2, 0.5)). ② '특이: 해 무수히'에서 b를 직선 밖으로 살짝 빼 보세요. 해가 무수히 많다가 갑자기 하나도 없어집니다. ③ 두 열의 길이를 모두 절반으로 줄이면 det는 1/4이 되지만 κ는 그대로입니다. 모델: 2×2 실수 행렬. 기울어진 격자는 a₁, a₂의 정수 배 조합(=입력 격자의 상)이고, b가 놓인 칸을 세면 x₁, x₂를 눈으로 읽을 수 있습니다. |det| / (|a₁||a₂|) < 0.005이면 특이로 취급합니다.

시뮬레이터에서 보았듯이 "det = 0이냐 아니냐"는 실무에서 충분한 질문이 아닙니다. det가 0이 아니어도 두 열이 거의 평행하면 \(\mathbf{b}\)의 작은 오차가 \(\mathbf{x}\)의 큰 오차로 부풀어 오릅니다. 그 증폭률의 상한이 조건수(condition number)입니다.

$$\frac{\|\Delta\mathbf{x}\|}{\|\mathbf{x}\|} \;\le\; \kappa(A)\,\frac{\|\Delta\mathbf{b}\|}{\|\mathbf{b}\|}, \qquad \kappa(A) = \frac{\sigma_{\max}}{\sigma_{\min}}$$
\(\sigma\)는 7절의 특이값(단위원이 변환되어 생긴 타원의 반지름들). 크로스토크 행렬의 경우 \(\kappa = 1/(1-2\alpha)\)이므로 α = 0.2면 1.67배, α = 0.45면 10배, α = 0.49면 50배 증폭된다.
det가 작다 ≠ 풀기 어렵다 \(0.1I\)(모든 것을 1/10로 줄이기)는 det = 0.01로 작지만 κ = 1이라 완벽하게 되돌릴 수 있습니다. 반대로 det = 1이라도 κ가 10⁶인 행렬이 있습니다. 수치적으로 위험한지 판단할 때는 det가 아니라 조건수를 보세요. 이 문제는 10장에서 부동소수점 오차와 함께 다시 만납니다.

색 보정 행렬: 센서 RGB를 사람의 RGB로

센서는 사람과 다른 눈으로 세상을 본다

사람의 L·M·S 원뿔세포, 그리고 센서의 R·G·B 필터는 둘 다 "빛의 스펙트럼을 세 숫자로 요약하는 장치"입니다. 그런데 요약하는 방식(분광 감도 곡선)이 다릅니다. 특히 사람의 L과 M 원뿔은 봉우리가 30 nm 정도밖에 떨어져 있지 않아 크게 겹치는데, 센서 필터의 곡선은 제조 공정과 염료가 정합니다. 같은 장면에서 두 장치가 내놓는 세 숫자는 다를 수밖에 없습니다. 어떻게 맞출까요?

400500600700파장 (nm)사람 눈 원뿔세포SML400500600700파장 (nm)스마트폰 센서 컬러 필터BGR
그림 3-4. 분광 감도의 개략도(가우스 곡선으로 단순화, 실제 곡선과 높이는 다르다). 원뿔세포 L·M은 크게 겹치고, 센서 필터는 봉우리 위치와 겹침 모양이 다르다. 센서 R 필터 오른쪽이 급히 떨어지는 것은 적외선 차단 필터 때문이다.

만약 센서의 세 감도 곡선이 사람 눈(정확히는 CIE 등색 함수)의 세 곡선의 선형 결합이라면, 센서의 (R, G, B)와 사람이 느끼는 색 사이의 관계는 정확히 3×3 행렬 하나입니다. 이 조건을 루터–아이브스 조건(Luther–Ives condition)이라 합니다. 실제 센서는 이 조건을 완벽히 만족하지 못하지만 근처에는 있으므로, 표준 색 차트(24색 등)를 찍어서 "센서 값 → 목표 sRGB 값"의 오차가 가장 작은 3×3 행렬을 최소제곱으로 구합니다(9장). 이것이 색 보정 행렬(CCM, Color Correction Matrix)입니다.

센서 rawR, G, B 필터 화이트 밸런스diag(g_R, g_G, g_B) CCM3×3, 행 합 = 1 감마 인코딩sRGB 전달 함수 화면·JPEGsRGB 8비트 회색을 회색으로 (대각 행렬) 색 섞임 되돌리기 (선형) 비선형 · 여기부터 선형 아님
그림 3-5. 단순화한 카메라 색 처리 순서(디모자이크, 노이즈 제거, 톤 매핑 등은 생략). CCM은 선형 광량 영역에서 적용해야 한다. 감마 인코딩 뒤의 값에 행렬을 곱하면 선형성이 깨져 밝기에 따라 색이 달라진다.

전형적인 CCM은 이런 모양입니다(이 장의 시뮬레이터에서 쓰는 예시 값이며, 실제 값은 센서마다 다릅니다).

$$\begin{bmatrix}R\\G\\B\end{bmatrix}_{\text{sRGB}} = \begin{bmatrix}1.70 & -0.55 & -0.15\\ -0.25 & 1.55 & -0.30\\ -0.05 & -0.60 & 1.65\end{bmatrix}\begin{bmatrix}R\\G\\B\end{bmatrix}_{\text{센서}}$$
대각 원소가 1보다 크고 비대각 원소가 음수다. 센서 필터가 겹쳐서 "빨강 채널에도 초록 빛이 섞여 들어온" 만큼을 빼 주는 것이다. 즉 CCM은 색 섞임 행렬의 역행렬에 가깝고, 그 결과 채도가 올라간다. 각 행의 합은 1이다.

행 합 = 1은 우연이 아닙니다. 화이트 밸런스를 거친 회색은 센서에서 \((g, g, g)\)입니다. CCM을 곱한 결과의 R 성분은 \(g\times(\text{1행의 합})\)이므로 행 합이 모두 1이면 회색이 그대로 회색으로 나옵니다. 행렬 언어로는 "\((1,1,1)\)이 고윳값 1인 고유벡터"라는 조건입니다(5절). 행 합이 깨지면 흰 벽에 색이 낍니다.

그런데 공짜가 아닙니다. 센서의 각 채널에는 독립적인 잡음이 있습니다. R 출력은 \(1.70R - 0.55G - 0.15B\)이므로 세 채널의 잡음이 모두 섞여 들어오고, 독립 잡음은 제곱합으로 더해집니다.

$$\sigma_{R,\text{out}} = \sigma\sqrt{a_{11}^2 + a_{12}^2 + a_{13}^2} = \sigma\sqrt{1.70^2 + 0.55^2 + 0.15^2} \approx 1.79\,\sigma$$
각 채널 잡음이 표준편차 \(\sigma\)로 같고 서로 독립이라고 가정한 근사(실제 샷 노이즈는 신호 크기에 따라 다르다, 7장). 음수 원소도 잡음을 빼 주는 것이 아니라 더한다. 제곱하면 부호가 사라지기 때문이다.
SIMULATOR

색 보정 행렬: 색을 살리면 잡음도 자란다

CCM (직접 고쳐도 됩니다)
행 합 (R, G, B)—
잡음 증폭 √Σa² (R, G, B)—
평균 색 오차 ΔE*ab—
해볼 것: ① 보정 세기 s를 0 → 1로 올리며 왼쪽(센서 그대로)과 오른쪽(CCM 후)을 비교하세요. 각 칸 오른쪽 아래 작은 사각형이 목표 색입니다. s = 1에서 ΔE가 거의 0이 되지만 잡음 증폭은 약 1.6~1.8배입니다. ② 잡음 σ를 0.06 이상으로 올린 뒤 s를 0.5로 내려 보세요. 색은 조금 바래도 화면이 훨씬 깨끗합니다. 어두운 곳에서 CCM을 약하게 쓰는 이유입니다. ③ '행 합이 깨진 CCM'에서 아래 줄 회색 칸들이 분홍빛으로 물드는 것을 확인하세요. 모델: 센서 값 = 색 섞임 행렬 × 참 색(선형 sRGB) + 독립 가우스 잡음. 화이트 밸런스는 이미 적용됐다고 가정하고, 색 섞임 행렬은 표준 CCM의 역행렬로 정했습니다. 24색은 표준 색 차트를 흉내 낸 근삿값이며 ΔE는 CIE 1976 공식으로 잡음 없이 계산합니다.
현업의 선택 같은 센서라도 밝은 곳(잡음 작음)에서는 CCM을 강하게, 어두운 곳(잡음 큼)에서는 약하게 쓰는 방식이 널리 쓰이는 것으로 알려져 있습니다. 조명의 색온도에 따라 CCM 여러 개를 보간하기도 합니다. 색 정확도와 잡음 사이의 이 줄다리기는 ColorBook과 SensorBook에서 자세히 다룹니다.

고유벡터: 변환해도 방향이 안 바뀌는 축

부재는 어느 방향으로 갈라지나

기계 부품의 한 점에 걸린 힘의 상태는 응력 텐서라는 2×2(3차원이면 3×3) 대칭 행렬 \(\sigma\)로 표현됩니다. 어떤 면의 법선 방향 \(\mathbf{n}\)을 넣으면 그 면에 걸리는 힘 \(\sigma\mathbf{n}\)이 나옵니다. 보통은 힘이 면에 비스듬히 걸려 미끄러지게(전단) 만들지만, 힘이 면에 정확히 수직으로만 걸리는 특별한 방향이 있습니다. 그 방향의 인장이 가장 크면 취성 재료는 그 수직 방향으로 갈라집니다. 이 방향을 어떻게 찾을까요?

질문을 변환의 언어로 옮기면 이렇습니다. "\(A\mathbf{v}\)가 \(\mathbf{v}\)와 같은 직선 위에 있는 \(\mathbf{v}\)는?" 대부분의 벡터는 변환되면 방향이 돌아가지만, 몇몇 특별한 방향은 늘어나거나 줄어들거나 뒤집힐 뿐 직선을 벗어나지 않습니다. 이것이 고유벡터(eigenvector)이고, 그때의 배율이 고유값(eigenvalue)입니다.

$$A\mathbf{v} = \lambda\mathbf{v} \;\Longleftrightarrow\; (A-\lambda I)\mathbf{v} = \mathbf{0} \;\Longleftrightarrow\; \det(A-\lambda I) = 0$$
0이 아닌 \(\mathbf{v}\)를 0으로 보내려면 \(A-\lambda I\)가 공간을 납작하게 만들어야 하므로(2절) det = 0이다. 2×2에서는 \(\lambda^2 - (\operatorname{tr}A)\lambda + \det A = 0\)이라는 2차 방정식이 된다. 두 근의 합은 대각합, 곱은 행렬식이다.

먼저 손으로 찾아봅시다. 아래에서 v를 끌어 돌리면 Av가 따라 움직입니다. 두 화살표가 한 직선 위에 겹치는 순간이 고유벡터입니다.

SIMULATOR

고유벡터를 손으로 찾기

v의 끝점을 끌어 돌려 보세요
원소 직접 입력
—
v와 Av 사이 각도—
|Av| / |v|—
고유값 λ₁, λ₂—
해볼 것: ① '대칭' 행렬에서 v를 한 바퀴 돌리며 Av와 겹치는 방향 두 개를 찾으세요. 두 방향이 서로 직각임을 확인합니다(대칭 행렬의 성질). ② 'v ← Av' 버튼을 여러 번 누르면 v가 어떤 방향으로 끌려가나요? 가장 큰 |λ|의 고유벡터입니다(거듭제곱법). ③ '회전 40°'에서는 아무리 돌려도 겹치지 않습니다. 고유값이 복소수가 됩니다. 모델: 2×2 실수 행렬. v와 Av의 각도가 1.5° 이내(또는 180°에서 1.5° 이내)면 고유벡터로 판정합니다. 'v ← Av'는 방향만 따라가도록 길이를 1.1로 다시 맞춥니다.

시뮬레이터에서 발견한 세 가지가 고유값 이론의 요점입니다.

고유값은 구조물의 공진 모드다

지진이 오면 건물은 어떤 모양으로 흔들리나

3층 건물의 각 층은 기둥이라는 스프링으로 아래층과 연결돼 있습니다. 1층이 움직이면 2층이 끌려가고, 2층은 다시 1층과 3층을 당깁니다. 세 층의 운동이 서로 얽힌 연립 미분방정식이라 하나씩 풀 수 없습니다. 그런데 지진파의 어떤 주파수에서는 건물이 크게 흔들리고 어떤 주파수에서는 잠잠합니다. 그 위험한 주파수는 몇 개이고, 각각 건물은 어떤 모양으로 흔들릴까요?

층 질량을 \(m\), 층간 강성을 \(k_i\)라 하고 각 층의 수평 변위를 \(\mathbf{x} = (x_1, x_2, x_3)\)라 하면 뉴턴 법칙은 행렬 하나로 정리됩니다.

$$M\ddot{\mathbf{x}} + K\mathbf{x} = \mathbf{0}, \qquad K = \begin{bmatrix}k_1+k_2 & -k_2 & 0\\ -k_2 & k_2+k_3 & -k_3\\ 0 & -k_3 & k_3\end{bmatrix},\; M = mI$$
\(K\)의 \(i\)행은 "\(i\)층에 걸리는 복원력이 각 층 변위에 얼마씩 의존하나"다. 2층의 힘은 1층·3층 변위와 얽혀 있다(비대각 원소). 대칭이라는 것에 주목하자. 작용–반작용이 같기 때문이다.

여기서 고유벡터가 등장합니다. 건물이 모양을 유지한 채 한 주파수로 흔들리는 해 \(\mathbf{x}(t) = \boldsymbol{\phi}\cos\omega t\)를 찾아 대입하면

$$K\boldsymbol{\phi} = \omega^2 M\boldsymbol{\phi} \quad\xrightarrow{M = mI}\quad \frac{K}{m}\boldsymbol{\phi} = \omega^2\boldsymbol{\phi}$$
고유값 \(\omega_n^2\)의 제곱근이 고유진동수, 고유벡터 \(\boldsymbol{\phi}_n\)이 모드 형상이다. 3자유도면 모드가 3개. \(K\)가 대칭이므로 모드 형상들은 서로 직교한다.

이게 왜 문제를 푸는지가 핵심입니다. 모드 형상들을 새 좌표축으로 삼으면(\(\mathbf{x} = \sum q_n\boldsymbol{\phi}_n\)), 얽혀 있던 3개의 방정식이 서로 무관한 1자유도 진동자 3개로 풀립니다. 행렬을 고유벡터 기저로 바꾸면 대각 행렬이 되기 때문입니다(diagonalization). 각각은 4장의 단순 조화 진동자일 뿐입니다.

+0.45+0.80+1.001차 모드 · 3.0 Hz마디(부호 바뀜) 0개−1.00−0.45+0.802차 모드 · 8.4 Hz마디(부호 바뀜) 1개+0.80−1.00+0.453차 모드 · 12.2 Hz마디(부호 바뀜) 2개
그림 3-6. 층 질량 20 t, 층간 강성 36 MN/m가 모두 같은 3층 전단 건물 모델의 세 모드(숫자는 최대 변위로 정규화한 모드 형상). 고유진동수 비는 1 : 2.80 : 4.05. 높은 모드일수록 층 사이에서 방향이 바뀌는 곳(마디)이 늘어난다.
SIMULATOR

3층 건물의 고유진동수와 모드 형상

보기
고유진동수 f₁, f₂, f₃—
모드 형상 (1층, 2층, 3층)—
꼭대기 응답 배율—
해볼 것: ① '지반 가진'을 고르고 주파수 슬라이더를 천천히 움직여 오른쪽 그래프의 봉우리(f₁, f₂, f₃)를 지날 때 건물 모양이 각 모드 형상으로 바뀌는 것을 보세요. ② 1층 강성 비율을 0.3으로 낮추면(1층이 기둥만 있는 필로티 구조) 1차 진동수가 내려가고 변형이 1층에 몰립니다. ③ 감쇠비를 키우면 봉우리가 낮고 넓어집니다. 모델: 층 질량이 같은 3자유도 전단 건물(층 바닥은 강체, 기둥은 수평 스프링), 모드 감쇠비 ζ가 모든 모드에 같다고 가정. 그래프는 지반 가속도에 대한 꼭대기 층 상대 변위를 정적 변위(가진 주파수 → 0)로 나눈 배율입니다. 애니메이션은 실제 진동수와 상관없이 눈에 보이도록 느리게 재생하며, 진폭은 화면에 맞게 정규화했습니다.

건물 설계에서 1차 고유주기(\(T_1 = 1/f_1\))는 내진 설계 하중을 정하는 가장 중요한 숫자 중 하나입니다. 지반이 그 주기 근처로 흔들리면 응답이 크게 증폭되기 때문입니다. 2017년 포항 지진에서 1층을 기둥만으로 띄운 필로티 건물들의 기둥 피해가 주목받은 것도, 시뮬레이터에서 본 것처럼 강성이 약한 층에 변형이 몰리는 현상과 관련이 있습니다. 같은 수학이 스마트폰 카메라의 손떨림 보정(OIS) 액추에이터, 반도체 장비의 스테이지, 자동차 서스펜션의 공진 설계에 그대로 쓰입니다.

타코마 다리는 공진 때문에 무너지지 않았다 1940년 미국 타코마 내로스 다리 붕괴는 "바람과 다리의 공진"의 예로 자주 소개되지만, 정확하지 않습니다. 바람은 일정한 주파수로 다리를 밀지 않았습니다. 다리의 비틀림 운동이 주변 공기 흐름을 바꾸고, 바뀐 공기력이 다시 비틀림을 키우는 되먹임, 즉 공기탄성 플러터(aeroelastic flutter)가 원인으로 설명됩니다. 수학적으로는 외부 가진이 아니라 시스템 행렬의 고유값 실수부가 양수가 되어(감쇠가 음수가 되어) 스스로 자라는 불안정입니다. 이것도 결국 고유값 문제입니다.

SVD: 모든 행렬은 회전, 늘이기, 회전

고유벡터가 없는 행렬은 어떻게 해부하나

고유값 분해는 강력하지만 조건이 까다롭습니다. 회전 행렬은 실수 고유벡터가 없고, 전단 행렬은 고유벡터가 하나뿐이며, 직사각 행렬(예: 1000명 × 50개 측정값 데이터, 640 × 480 이미지)은 \(A\mathbf{v} = \lambda\mathbf{v}\)라는 질문 자체가 성립하지 않습니다(입력과 출력의 차원이 다르니까요). 어떤 행렬에나 통하는 해부 도구가 필요합니다.

답은 질문을 살짝 바꾸는 데 있습니다. "방향이 안 바뀌는 축"이 아니라 "서로 직교하는 입력 축 중에서, 변환 뒤에도 서로 직교하는 축"을 찾습니다. 그런 축은 언제나 존재하고, 이것이 특이값 분해(SVD, Singular Value Decomposition)입니다.

$$A = U\,\Sigma\,V^\mathsf{T} \qquad A\mathbf{v}_i = \sigma_i\mathbf{u}_i$$
\(V\)의 열 \(\mathbf{v}_i\): 입력 공간의 직교 축(오른쪽 특이벡터). \(U\)의 열 \(\mathbf{u}_i\): 출력 공간의 직교 축(왼쪽 특이벡터). \(\Sigma\): 대각에 특이값 \(\sigma_1\ge\sigma_2\ge\dots\ge0\). \(U, V\)는 직교 행렬(회전 또는 반사). \(\sigma_i^2\)은 대칭 행렬 \(A^\mathsf{T}A\)의 고유값이다.

기하적으로 읽으면 아름답습니다. 단위원을 아무 2×2 행렬로 변환하면 언제나 타원이 됩니다. 타원의 장축·단축 반지름이 \(\sigma_1, \sigma_2\)이고, 그 축 방향이 \(\mathbf{u}_1, \mathbf{u}_2\), 그 축으로 가는 원래 원의 두 반지름 방향이 \(\mathbf{v}_1, \mathbf{v}_2\)입니다. 변환은 세 단계로 쪼개집니다. ① \(V^\mathsf{T}\)로 돌려 \(\mathbf{v}_i\)를 좌표축에 맞추고, ② \(\Sigma\)로 축 방향으로만 늘이고, ③ \(U\)로 다시 돌립니다.

원래: 단위원→① Vᵀ: 회전→② Σ: 축 방향 늘이기→③ U: 회전 → Av₁, v₂ (직교)σ₁ = 1.98, σ₂ = 0.63σ₁u₁, σ₂u₂ (직교)
그림 3-7. A = [1.5 1; 0.25 1]의 SVD. 단위원 위의 직교하는 두 방향 v₁, v₂를 ① 회전으로 좌표축에 맞추고 ② 축 방향으로 σ₁ = 1.98배, σ₂ = 0.63배 늘인 뒤 ③ 다시 회전하면 A가 만든 것과 같은 타원이 된다. 두 화살표는 마지막까지 직교한다.
SIMULATOR

단위원 → 타원: SVD 세 단계 분해

—
특이값 σ₁, σ₂—
회전각 Vᵀ, U—
조건수 σ₁/σ₂—
해볼 것: ① 단계 슬라이더를 0 → 3으로 움직여 원이 ① 돌고 ② 축 방향으로 늘어나고 ③ 다시 도는 것을 보세요. 마지막 모양은 점선(A로 직접 변환한 타원)과 정확히 겹칩니다. ② 초록·빨강 점(A의 두 열)을 끌어 거의 평행하게 만들면 σ₂ → 0, 조건수가 치솟습니다(4절의 크로스토크와 같은 그림). ③ '반사 포함'에서는 ② 단계에서 한 축이 음수 배율로 뒤집힙니다. 모델: 2×2 실수 행렬. 반사가 있으면 U, V를 회전으로 두고 Σ의 둘째 원소에 부호를 넣어 그렸습니다(표준 SVD에서는 σ ≥ 0이고 U 또는 V가 반사를 포함).

SVD가 고유값 분해보다 일반적인 대가로, 입력 축 \(V\)와 출력 축 \(U\)가 서로 다릅니다. 대칭 양의 정부호 행렬(공분산, 강성)에서는 둘이 같아지고 SVD와 고유값 분해가 일치합니다. 4절의 조건수 \(\kappa = \sigma_1/\sigma_n\)이 "타원이 얼마나 납작한가"라는 것도 이제 그림으로 보입니다.

저랭크 근사: 큰 특이값만 남겨 이미지 압축하기

4096개의 숫자 중 정말 필요한 것은 몇 개인가

64×64 흑백 이미지는 4,096개의 숫자, 즉 64×64 행렬입니다. 하지만 하늘은 위아래로 부드럽게 변하고, 벽은 넓은 면이고, 이웃 행끼리는 거의 비슷합니다. 행렬의 행들이 서로 거의 비슷하다면 정보는 4,096개보다 훨씬 적을 것입니다. 그 "진짜 정보량"을 어떻게 재고, 어떻게 덜어 낼까요?

SVD를 열벡터와 행벡터의 곱(바깥곱)으로 풀어 쓰면 행렬은 랭크 1 조각들의 합입니다. 조각 하나는 "세로 패턴 \(\mathbf{u}_i\) × 가로 패턴 \(\mathbf{v}_i^\mathsf{T}\)"이고 세기는 \(\sigma_i\)입니다. 큰 \(\sigma\)부터 \(k\)개만 남기면

$$A = \sum_{i=1}^{r}\sigma_i\,\mathbf{u}_i\mathbf{v}_i^\mathsf{T} \;\approx\; A_k = \sum_{i=1}^{k}\sigma_i\,\mathbf{u}_i\mathbf{v}_i^\mathsf{T}, \qquad \frac{\|A-A_k\|_F}{\|A\|_F} = \sqrt{\frac{\sum_{i>k}\sigma_i^2}{\sum_i\sigma_i^2}}$$
에커트–영 정리(Eckart–Young): 랭크가 \(k\) 이하인 모든 행렬 중에서 \(A_k\)가 \(A\)에 가장 가깝다(프로베니우스 노름과 2-노름 모두). 저장량은 \(m\times n\) 대신 \(k(m+n+1)\)개.
SIMULATOR

SVD 이미지 압축: rank-k 근사

이미지 (64×64)
저장량 k(m+n+1) / mn—
상대 오차 ‖A − A_k‖ / ‖A‖—
PSNR—
해볼 것: ① '풍경'에서 k = 1, 3, 8, 20을 차례로 보세요. k = 1은 "세로 패턴 × 가로 패턴" 하나라서 줄무늬 격자처럼 보입니다. ② '막대'는 k = 2에서 완벽해집니다. 행이 두 종류뿐이라 랭크가 2이기 때문입니다. ③ '잡음'은 특이값이 천천히 줄어들어 압축이 거의 안 됩니다. 정보가 고르게 퍼져 있으면 줄일 것이 없습니다. 모델: 밝기 0~1의 64×64 행렬을 그대로 분해(평균을 빼지 않음). 아래 그래프는 특이값의 로그 스케일이고, 색칠한 부분이 남긴 몫입니다. 저장량은 숫자 개수 기준으로 비트 수와 엔트로피 부호화는 고려하지 않았습니다.

실제 JPEG는 SVD가 아니라 고정된 기저(이산 코사인 변환, 5장)를 씁니다. SVD의 기저 \(U, V\)는 이미지마다 달라서 그것까지 저장해야 하고(저장량 공식의 \(m+n\)), 계산도 무겁기 때문입니다. 대신 SVD는 "이 데이터에 가장 잘 맞는 축"을 데이터에서 직접 찾아 준다는 점에서 비교할 수 없는 장점이 있습니다.

PCA는 SVD다 데이터 행렬(행 = 샘플, 열 = 측정 항목)에서 각 열의 평균을 빼고 SVD를 하면, \(V\)의 열이 주성분 방향, \(\sigma_i^2/(N-1)\)이 각 방향의 분산입니다. 주성분 분석(PCA), 얼굴 인식의 고유얼굴, 추천 시스템의 행렬 분해, 공정 데이터의 이상 탐지가 모두 같은 계산입니다.

이 도구가 쓰이는 곳

"공간 전체를 한 번에 변환한다"는 관점은 시리즈의 거의 모든 책에 등장합니다.

핵심 정리

  1. 선형 변환은 기저벡터가 가는 곳만으로 완전히 정해진다. 행렬의 열 = 기저벡터의 행선지이고, \(A\mathbf{v}\)는 "열들을 성분만큼 더하라"는 뜻이다.
  2. det = 넓이(부피) 배율. 음수면 방향이 뒤집히고, 0이면 공간이 납작해져 정보가 사라진다. \(\det(AB) = \det A\det B\).
  3. 행렬 곱 = 변환의 합성(오른쪽이 먼저). 일반적으로 AB ≠ BA라서 회전·전단·화이트 밸런스·CCM의 순서가 중요하다.
  4. Ax = b는 "어떤 입력이 b로 가나". det = 0이면 해가 없거나 무수히 많고, det ≠ 0이어도 조건수 κ = σ₁/σ₂가 크면 잡음이 κ배까지 증폭된다.
  5. CCM은 센서 RGB를 표준 RGB로 옮기는 3×3 행렬. 대각 > 1, 비대각 < 0, 행 합 = 1(회색 보존). 채도를 살릴수록 잡음 증폭 \(\sqrt{\sum_j a_{ij}^2}\)이 커진다.
  6. 고유벡터 = 방향이 안 바뀌는 축, 고유값 = 그 축의 배율. 대칭 행렬은 실수 고유값과 직교 고유벡터를 가지며, 구조물의 \(K\boldsymbol\phi = \omega^2 M\boldsymbol\phi\)에서 고유값은 고유진동수², 고유벡터는 모드 형상이다.
  7. SVD: 모든 행렬 = 회전 · 축 방향 늘이기 · 회전. 단위원은 반지름 σ₁, σ₂의 타원이 되고, 큰 σ만 남긴 rank-k 근사가 최선의 근사다(에커트–영). PCA는 평균을 뺀 데이터의 SVD다.

확인 퀴즈

Q1. 행렬 \(\begin{bmatrix}0 & -1\\ 1 & 0\end{bmatrix}\)은 평면에 무엇을 하나?

열을 읽는다. 1열 (0, 1): î가 위쪽으로, 2열 (−1, 0): ĵ가 왼쪽으로 갔다. 동쪽이 북쪽으로, 북쪽이 서쪽으로 가는 것은 반시계 90° 회전이다. det = 0·0 − (−1)·1 = 1로 넓이와 방향이 보존된다는 것도 확인된다.

Q2. 어떤 2×2 변환의 행렬식이 −3이다. 옳은 설명은?

|det|는 넓이 배율, 부호는 방향이다. 길이 배율은 방향마다 다를 수 있어 det만으로는 알 수 없다(그것은 특이값이 알려 준다). det ≠ 0이므로 역변환은 존재하며 그 행렬식은 −1/3이다.

Q3. 카메라 CCM의 각 행의 합을 1로 맞추는 가장 직접적인 이유는?

출력의 R 성분은 g × (1행의 합)이다. 세 행의 합이 모두 1이면 (g, g, g) → (g, g, g). 즉 (1, 1, 1)이 고유값 1인 고유벡터가 된다. 행 합과 행렬식은 별개이고(표준 CCM 예시의 det는 1이 아니다), 잡음 증폭은 행 합이 아니라 제곱합 √Σa²이 정한다.

Q4. CCM의 한 행이 (1.8, −0.6, −0.2)일 때, 세 채널에 독립적인 같은 크기의 잡음 σ가 있다면 이 출력 채널의 잡음은 약 몇 σ인가?

독립 잡음의 분산은 계수의 제곱으로 가중해 더한다: √(1.8² + 0.6² + 0.2²) = √3.64 ≈ 1.91. 신호는 행 합(=1)만큼 유지되지만 잡음은 1.91배가 되니 SNR이 약 5.6 dB 나빠진다. 음수 계수도 제곱하면 양수라 잡음을 줄이지 못한다.

Q5. 실수 2×2 행렬의 고유값이 0.9 ± 0.3i로 나왔다. 이 변환을 한 벡터에 반복 적용하면?

복소 고유값이면 실수 고유벡터(방향이 유지되는 축)가 없고 회전 성분이 있다. 크기 |λ| = √(0.81 + 0.09) ≈ 0.949 < 1이므로 한 번 돌 때마다 약 5%씩 줄어드는 나선이다. 진동하며 감쇠하는 시스템(감쇠 진동자)의 이산 시간 모델이 정확히 이 모양이다.

Q6. 1차 고유진동수가 3 Hz인 3층 건물에서, 모든 층의 질량을 4배로 늘리면(강성은 그대로) 1차 고유진동수는?

M = mI이면 고유값 문제는 (K/m)φ = ω²φ. m이 4배가 되면 모든 고유값 ω²이 1/4, 진동수는 1/2이 된다. 모드 형상(고유벡터)은 바뀌지 않는다. 행렬에 상수를 곱하면 고유벡터는 그대로, 고유값만 같은 배율로 변한다.

Q7. 256×256 이미지를 SVD로 rank-16 근사하면 저장할 숫자는 원래의 약 몇 %인가?

rank-k 근사는 u 벡터 k개(각 m개), v 벡터 k개(각 n개), 특이값 k개를 저장한다: 16 × (256 + 256 + 1) = 8,208개. 원래 65,536개의 약 12.5%다. 16/256이 아닌 이유는 이미지마다 다른 기저 U, V까지 저장해야 하기 때문이다.