선형 변환: 행렬은 공간을 어떻게 움직이나

행렬을 공간 전체를 늘이고, 돌리고, 기울이고, 납작하게 만드는 함수로 이해해요. 행렬의 열이 기저 벡터의 도착점이라는 핵심 관점, 행렬 곱이 변환의 합성인 이유, 그리고 신경망에 활성화 함수가 꼭 필요한 이유까지 연결해요.

중급강의 3 / 6약 9분

지난 강의에서 행렬은 벡터를 받아 다른 벡터를 내놓는 함수라고 했어요. 이번에는 그 함수가 공간 전체를 어떻게 움직이는지 그림처럼 봐요. 이 관점이 잡히면 행렬 곱, 역행렬, 행렬식, 고유값이 모두 하나의 이야기로 이어지고, 딥러닝이 "공간을 접고 펴서 데이터를 나누는 기계"라는 말이 이해되기 시작해요.

선형 변환이란

공간의 모든 점(벡터)을 다른 점으로 옮기는 함수를 변환이라고 해요. 그중 다음 두 조건을 만족하는 것이 선형 변환이에요.

T(u+v)=T(u)+T(v),T(cv)=cT(v)T(\mathbf{u} + \mathbf{v}) = T(\mathbf{u}) + T(\mathbf{v}), \qquad T(c\mathbf{v}) = cT(\mathbf{v})

말로 풀면 "더한 뒤 옮기나, 옮긴 뒤 더하나 같다", "늘린 뒤 옮기나, 옮긴 뒤 늘리나 같다"예요. 그림으로 보면 이런 뜻이에요.

  • 원점은 제자리에 있어요.
  • 곧은 선은 곧은 선으로 옮겨져요.
  • 모눈종이의 격자선은 평행하고 간격이 고른 채로 남아요.

모눈종이를 잡아 늘이거나, 돌리거나, 비스듬히 밀어도 격자가 휘지만 않으면 선형 변환이에요. 반대로 격자가 구부러지거나 원점이 움직이면 선형 변환이 아니에요.

핵심: 열은 기저 벡터의 도착점

2차원 평면의 모든 벡터는 두 기저 벡터의 선형 결합으로 쓸 수 있어요.

i^=[10],j^=[01],[xy]=xi^+yj^\hat{\mathbf{i}} = \begin{bmatrix} 1 \\ 0 \end{bmatrix}, \quad \hat{\mathbf{j}} = \begin{bmatrix} 0 \\ 1 \end{bmatrix}, \qquad \begin{bmatrix} x \\ y \end{bmatrix} = x\hat{\mathbf{i}} + y\hat{\mathbf{j}}

선형 변환은 선형 결합을 보존하니까

T([xy])=x T(i^)+y T(j^)T\left(\begin{bmatrix} x \\ y \end{bmatrix}\right) = x\,T(\hat{\mathbf{i}}) + y\,T(\hat{\mathbf{j}})

두 기저 벡터가 어디로 가는지만 알면 모든 벡터가 어디로 갈지 결정돼요. 그리고 그 두 도착점을 열로 나란히 세운 것이 바로 행렬이에요.

A=[∣∣T(i^)T(j^)∣∣]A = \begin{bmatrix} | & | \\ T(\hat{\mathbf{i}}) & T(\hat{\mathbf{j}}) \\ | & | \end{bmatrix}

예를 들어 A=[2101]A = \begin{bmatrix} 2 & 1 \\ 0 & 1 \end{bmatrix}이라면, i^\hat{\mathbf{i}}는 (2,0)(2, 0)으로, j^\hat{\mathbf{j}}는 (1,1)(1, 1)로 가요. 그러면 (3,2)(3, 2)는 3×(2,0)+2×(1,1)=(8,2)3 \times (2, 0) + 2 \times (1, 1) = (8, 2)로 가요. 지난 강의에서 본 "열들의 선형 결합으로 읽기"가 바로 이 그림이에요.

행렬 읽는 법 행렬을 보면 숫자를 계산하기 전에 열부터 보세요. "첫 열은 x축 화살표가 가는 곳, 둘째 열은 y축 화살표가 가는 곳." 이것만으로 변환의 모양이 머릿속에 그려져요.

대표적인 변환들

확대와 축소

[2000.5]\begin{bmatrix} 2 & 0 \\ 0 & 0.5 \end{bmatrix}

가로로 2배 늘이고 세로로 반으로 줄여요. 대각 행렬은 축마다 따로 늘이고 줄이는 변환이에요.

회전

반시계 방향으로 θ\theta만큼 돌리는 행렬이에요.

Rθ=[cos⁡θ−sin⁡θsin⁡θcos⁡θ]R_\theta = \begin{bmatrix} \cos\theta & -\sin\theta \\ \sin\theta & \cos\theta \end{bmatrix}

90도 회전이면 [0−110]\begin{bmatrix} 0 & -1 \\ 1 & 0 \end{bmatrix}이에요. 열을 보면 i^\hat{\mathbf{i}}가 (0,1)(0, 1), 즉 위쪽으로, j^\hat{\mathbf{j}}가 (−1,0)(-1, 0), 즉 왼쪽으로 가요. 정확히 90도 회전이죠. 공식을 외울 필요 없이 열만 보면 돼요.

대칭(반사)

[100−1]\begin{bmatrix} 1 & 0 \\ 0 & -1 \end{bmatrix}

j^\hat{\mathbf{j}}가 (0,−1)(0, -1)로 뒤집혀요. x축을 거울 삼아 위아래를 뒤집는 변환이에요.

밀기(전단)

[1101]\begin{bmatrix} 1 & 1 \\ 0 & 1 \end{bmatrix}

i^\hat{\mathbf{i}}는 그대로, j^\hat{\mathbf{j}}는 (1,1)(1, 1)로 비스듬히 밀려요. 직사각형이 평행사변형이 돼요. 책 더미를 옆으로 미는 모양이에요.

투영(사영)

[1000]\begin{bmatrix} 1 & 0 \\ 0 & 0 \end{bmatrix}

j^\hat{\mathbf{j}}가 원점으로 가요. 평면 전체가 x축 위로 납작해져요. 그림자가 바닥에 드리우는 것과 같아요. 이 변환은 정보를 잃어요. (3,5)(3, 5)와 (3,−2)(3, -2)가 둘 다 (3,0)(3, 0)으로 가서, 결과만 보고는 어디서 왔는지 알 수 없어요. 그래서 되돌리는 변환(역변환)이 존재하지 않아요. 다음 강의의 역행렬과 행렬식으로 이어지는 중요한 관찰이에요.

넘파이로 확인하기

정사각형의 네 꼭짓점을 변환해 볼게요.

import numpy as np

square = np.array([[0, 1, 1, 0],
                   [0, 0, 1, 1]])          # 열마다 꼭짓점 하나

theta = np.pi / 2
rotate = np.array([[np.cos(theta), -np.sin(theta)],
                   [np.sin(theta),  np.cos(theta)]])
shear = np.array([[1, 1],
                  [0, 1]])

print(np.round(rotate @ square, 2))   # 90도 돌아간 정사각형
print(shear @ square)                  # [[0 1 2 1] [0 0 1 1]]  평행사변형

꼭짓점들을 열로 쌓아 행렬 하나로 곱하면 모든 점이 한꺼번에 옮겨져요. 게임과 3D 그래픽이 수백만 개의 점을 매 프레임 이렇게 움직여요.

행렬 곱 = 변환의 합성

먼저 AA로 변환하고 이어서 BB로 변환하면, 전체 변환은 BABA예요.

B(Ax)=(BA)xB(A\mathbf{x}) = (BA)\mathbf{x}

오른쪽부터 왼쪽으로 적용된다는 점에 주의하세요. 함수의 합성 g(f(x))g(f(x))에서 f가 먼저인 것과 같아요. 행렬 곱의 계산 규칙은 바로 이 합성이 성립하도록 정해진 거예요.

순서를 바꾸면 결과가 달라지는 것도 그림으로 보면 당연해요.

rotate90 = np.array([[0, -1], [1, 0]])
stretch_x = np.array([[2, 0], [0, 1]])
v = np.array([1, 1])

print(stretch_x @ rotate90 @ v)   # 회전 먼저, 늘이기 나중: [-2  1]
print(rotate90 @ stretch_x @ v)   # 늘이기 먼저, 회전 나중: [-1  2]

옷을 입고 세탁기에 들어가는 것과 세탁기에 들어갔다 옷을 입는 것이 다르듯, 변환의 순서도 결과를 바꿔요.

행렬식 맛보기: 넓이가 몇 배가 되나

변환이 공간을 늘이거나 줄이면, 넓이도 일정한 비율로 바뀌어요. 단위 정사각형(넓이 1)이 변환 후 넓이가 얼마가 되는지를 행렬식이라고 해요.

det⁡[abcd]=ad−bc\det \begin{bmatrix} a & b \\ c & d \end{bmatrix} = ad - bc
  • [2003]\begin{bmatrix} 2 & 0 \\ 0 & 3 \end{bmatrix}: 행렬식 6. 넓이가 6배.
  • 회전 행렬: 행렬식 1. 돌리기만 하고 넓이는 그대로.
  • 전단 [1101]\begin{bmatrix} 1 & 1 \\ 0 & 1 \end{bmatrix}: 행렬식 1. 모양은 바뀌어도 넓이는 그대로(밀어도 책 더미의 부피는 같죠).
  • 투영 [1000]\begin{bmatrix} 1 & 0 \\ 0 & 0 \end{bmatrix}: 행렬식 0. 납작해져서 넓이가 0.
  • 대칭: 행렬식 -1. 음수는 공간이 뒤집혔다는 뜻이에요(시계 방향과 반시계 방향이 바뀜).

행렬식이 0이면 공간이 찌그러져 정보가 사라지고, 되돌릴 수 없어요. 다음 강의의 핵심이에요.

신경망에 활성화 함수가 필요한 이유

이제 이 강의에서 가장 중요한 이야기예요. 신경망은 층마다 WxW\mathbf{x} 같은 선형 변환을 해요. 그럼 층을 100개 쌓으면 강력해질까요?

W3(W2(W1x))=(W3W2W1)x=WxW_3(W_2(W_1\mathbf{x})) = (W_3 W_2 W_1)\mathbf{x} = W\mathbf{x}

아니요. 선형 변환을 아무리 합성해도 결국 행렬 하나, 즉 선형 변환 하나예요. 100층짜리 선형 신경망은 1층짜리와 능력이 똑같아요. 격자를 아무리 늘이고 돌려도 격자는 곧은 채로 남으니, 구불구불한 경계로 데이터를 나눌 수가 없어요.

그래서 층 사이에 비선형 함수(활성화 함수)를 끼워 넣어요. 가장 많이 쓰는 ReLU는 음수를 0으로 바꾸기만 해요.

ReLU(x)=max⁡(0,x)\text{ReLU}(x) = \max(0, x)

이 단순한 꺾임이 공간을 접어요. 선형 변환으로 늘이고 돌린 뒤, ReLU로 접고, 다시 늘이고 돌리고 접고... 이걸 반복하면 아무리 뒤엉킨 데이터도 직선 하나로 나눌 수 있는 모양으로 펴낼 수 있어요. 딥러닝을 "고차원 종이접기"라고 부르는 사람들이 있는 이유예요.

def relu(x):
    return np.maximum(0, x)

x = np.array([1.0, -2.0])
W1 = np.array([[1, 2], [-1, 1]])
W2 = np.array([[1, -1], [2, 1]])

linear_only = W2 @ (W1 @ x)          # 그냥 행렬 하나와 같음
with_relu = W2 @ relu(W1 @ x)        # 공간이 접혀서 결과가 달라짐
print(linear_only, with_relu)

딥러닝 트랙의 첫 강의에서 이 그림을 다시 꺼낼 거예요.

아핀 변환과 이동

평행 이동 x↦x+b\mathbf{x} \mapsto \mathbf{x} + \mathbf{b}는 원점을 움직이니 선형 변환이 아니에요. 선형 변환에 이동을 더한 Ax+bA\mathbf{x} + \mathbf{b}를 아핀 변환이라고 해요. 신경망 한 층의 Wx+bW\mathbf{x} + \mathbf{b}가 정확히 아핀 변환이에요. 3D 그래픽에서는 좌표에 1을 하나 덧붙이는 동차 좌표라는 기법으로, 이동까지 행렬 곱 하나로 처리해요.

실습

  1. 30도 회전 행렬을 넘파이로 만들고, 12번 곱하면 단위 행렬이 되는지 확인해 보세요(360도 회전). np.linalg.matrix_power를 쓰면 편해요.
  2. 꼭짓점 (0,0),(2,0),(2,1),(0,1)(0,0), (2,0), (2,1), (0,1)인 직사각형에 전단 행렬을 적용한 뒤, 넓이가 그대로인지 신발끈 공식이나 행렬식으로 확인해 보세요.
  3. matplotlib를 설치해 정사각형과 변환 결과를 함께 그려 보세요. 눈으로 보면 이해가 훨씬 빨라져요.

자주 하는 실수

  • 합성 순서 거꾸로 쓰기. "A 다음 B"는 BABA예요.
  • 행과 열 관점 섞기. 기저 벡터의 도착점은 열이에요.
  • 이동을 선형 변환으로 착각하기. 원점이 움직이면 선형이 아니에요.
  • 층만 쌓으면 강해진다고 생각하기. 비선형 활성화 없이는 층을 쌓아도 소용없어요.

점검 문제

  1. 행렬 [0110]\begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix}은 어떤 변환인가요? 열을 보고 답하세요.
  2. 180도 회전 행렬은?
  3. 행렬식이 0인 변환을 되돌릴 수 없는 이유는?
  4. 활성화 함수 없이 층을 10개 쌓은 신경망은 왜 층 1개와 같나요?

정답

  1. i^\hat{\mathbf{i}}가 (0,1)(0, 1)로, j^\hat{\mathbf{j}}가 (1,0)(1, 0)으로 가요. x와 y를 맞바꾸는, 대각선 y=xy = x에 대한 대칭이에요.
  2. [−100−1]\begin{bmatrix} -1 & 0 \\ 0 & -1 \end{bmatrix}. 두 기저 벡터가 모두 반대쪽을 가리켜요.
  3. 공간이 선이나 점으로 찌그러져서 서로 다른 점들이 같은 곳으로 모이기 때문이에요. 결과만 보고 원래 점을 하나로 정할 수 없어요.
  4. 선형 변환의 합성은 행렬 곱 하나로 합쳐져서 결국 선형 변환 하나와 같기 때문이에요.

다음 강의

다음 강의에서는 연립방정식, 역행렬, 행렬식을 제대로 다뤄요. "이 변환을 되돌릴 수 있는가"라는 질문이 "이 방정식의 해가 하나로 정해지는가"와 같은 질문이라는 걸 보게 될 거예요.