편미분과 그래디언트: 여러 변수의 기울기

변수가 여러 개인 함수를 등고선 지도로 보고, 한 변수씩 미분하는 편미분과 그 묶음인 그래디언트를 익혀요. 그래디언트가 가장 가파른 오르막을 가리키는 이유, 방향 도함수, 그리고 선형 회귀의 손실을 그래디언트로 줄여 실제로 학습시키는 과정까지 해 봐요.

중급강의 3 / 6약 7분

지금까지 다룬 함수는 입력이 하나였어요. 하지만 집값은 면적, 위치, 층수에 따라 달라지고, 신경망의 손실은 수백만 개의 파라미터에 따라 달라져요. 이번 강의에서는 입력이 여러 개인 함수의 미분을 배워요. 핵심은 그래디언트라는 화살표 하나예요. 이 화살표가 가리키는 반대쪽으로 걸어가는 것, 그게 현대 AI 학습의 거의 전부예요.

여러 변수의 함수

f(x,y)=x2+3y2f(x, y) = x^2 + 3y^2

입력은 점 (x,y)(x, y)이고 출력은 높이 하나예요. 그래프로 그리면 곡면, 즉 지형이 돼요. 이 함수는 원점이 가장 낮은 골짜기이고, 바깥으로 갈수록 높아지는 그릇 모양이에요. y 방향으로는 계수가 3이라 더 가파르게 올라가요.

등고선 지도

3차원 곡면을 매번 그리기는 어려워서, 높이가 같은 점들을 이은 등고선으로 위에서 내려다본 지도를 그려요. 등산 지도와 똑같아요.

  • 등고선이 촘촘한 곳은 가파르고,
  • 등고선이 성긴 곳은 완만해요.

f(x,y)=x2+3y2f(x, y) = x^2 + 3y^2의 등고선은 가로로 긴 타원들이에요. y 방향이 가팔라서 그쪽으로 등고선이 촘촘해요. 머신러닝 책에 손실 함수가 타원 등고선으로 그려져 있다면 바로 이런 지형이에요.

편미분: 한 방향의 기울기

여러 변수 중 하나만 움직이고 나머지는 고정했을 때의 변화율이 편미분이에요. 동쪽으로 한 걸음 갔을 때의 경사, 북쪽으로 한 걸음 갔을 때의 경사를 따로 재는 거예요.

∂f∂x=2x,∂f∂y=6y\frac{\partial f}{\partial x} = 2x, \qquad \frac{\partial f}{\partial y} = 6y

∂\partial는 "편미분"을 뜻하는 둥근 d예요. xx로 편미분할 때는 yy를 그냥 상수 취급하면 돼요. 그러니 3y23y^2은 상수라 미분하면 0이 되고, x2x^2만 미분해서 2x2x가 남아요. 지난 강의의 규칙이 그대로 통해요.

조금 더 섞인 예를 볼게요.

g(x,y)=x2y+5xy3g(x, y) = x^2 y + 5xy^3
∂g∂x=2xy+5y3,∂g∂y=x2+15xy2\frac{\partial g}{\partial x} = 2xy + 5y^3, \qquad \frac{\partial g}{\partial y} = x^2 + 15xy^2

그래디언트: 편미분을 모은 화살표

모든 편미분을 벡터로 묶은 것이 그래디언트예요.

∇f=[∂f/∂x∂f/∂y]=[2x6y]\nabla f = \begin{bmatrix} \partial f / \partial x \\ \partial f / \partial y \end{bmatrix} = \begin{bmatrix} 2x \\ 6y \end{bmatrix}

∇\nabla는 "나블라"라고 읽어요. 점 (1,1)(1, 1)에서 그래디언트는 (2,6)(2, 6)이에요. 각 점마다 화살표가 하나씩 붙는 거예요.

그래디언트의 세 가지 성질

  1. 가장 가파른 오르막 방향을 가리켜요. 그 점에서 어느 쪽으로 한 걸음 가야 높이가 가장 빨리 오르는지 알려 줘요.
  2. 길이가 그 가파른 정도예요. ∥∇f∥\|\nabla f\|가 크면 가파르고, 0이면 평평해요.
  3. 등고선과 수직이에요. 등고선을 따라가면 높이가 안 변하니, 가장 빨리 변하는 방향은 그에 직각이에요.

그래서 가장 빨리 내려가려면 그래디언트의 반대 방향 −∇f-\nabla f로 가면 돼요.

왜 가장 가파른 방향일까

단위 벡터 u\mathbf{u} 방향으로 아주 조금 갔을 때의 변화율, 즉 방향 도함수는 그래디언트와 그 방향의 내적이에요.

Duf=∇f⋅u=∥∇f∥cos⁡θD_{\mathbf{u}} f = \nabla f \cdot \mathbf{u} = \|\nabla f\| \cos\theta

선형대수의 내적 공식이 그대로 나와요. cos⁡θ\cos\theta는 θ=0\theta = 0, 즉 u\mathbf{u}가 그래디언트와 같은 방향일 때 가장 커요(오르막 최대). θ=180°\theta = 180°이면 가장 작아요(내리막 최대). θ=90°\theta = 90°이면 0, 등고선 방향이에요. 선형대수와 미적분이 여기서 만나요.

경사 하강법: 여러 변수 버전

지난 강의의 한 줄 공식을 벡터로 바꾸기만 하면 돼요.

w←w−η ∇L(w)\mathbf{w} \leftarrow \mathbf{w} - \eta \, \nabla L(\mathbf{w})

모든 파라미터를 각자의 편미분만큼 동시에 움직이는 거예요.

import numpy as np

def f(p):
    x, y = p
    return x**2 + 3 * y**2

def grad(p):
    x, y = p
    return np.array([2 * x, 6 * y])

p = np.array([4.0, 2.0])
for step in range(5):
    p = p - 0.1 * grad(p)
    print(np.round(p, 3))
[3.2 0.8]
[2.56 0.32]
[2.048 0.128]
[1.638 0.051]
[1.311 0.02 ]

y는 빠르게 0으로 가는데, x는 천천히 가요. y 방향이 더 가팔라서(그래디언트가 커서) 한 번에 많이 움직이기 때문이에요. 50번 반복하면 거의 원점에 도착해요.

학습률이 너무 크면

학습률을 0.34로 올려 볼게요. x 방향은 더 빨리 수렴하는데, y 방향은 한 번에 너무 많이 가서 골짜기 반대편으로 넘어가 버려요. 그때마다 조금씩 더 멀어져서 결국 발산해요. 계산해 보면 y는 매번 1−0.34×6=−1.041 - 0.34 \times 6 = -1.04배가 되거든요.

이 예는 실전에서 아주 중요한 교훈을 줘요. 가장 가파른 방향이 학습률의 상한을 정해요. 지형이 한 방향으로만 가파르고 다른 방향으로는 완만하면(길쭉한 타원 등고선), 가파른 쪽 때문에 학습률을 작게 잡아야 하고, 그러면 완만한 쪽은 엄청 느리게 움직여요. 그래서 경사 하강법이 지그재그로 헤매요. 이 문제를 줄이려고 특징을 표준화하고(지형을 둥글게 만들기), 모멘텀이나 Adam 같은 개선된 방법을 써요. 최적화 강의에서 다뤄요.

실전: 선형 회귀를 경사 하강법으로 학습시키기

데이터 (xi,yi)(x_i, y_i)에 직선 y^=ax+b\hat{y} = ax + b를 맞추고 싶어요. 오차는 평균 제곱 오차(MSE)로 재요.

L(a,b)=1n∑i=1n(axi+b−yi)2L(a, b) = \frac{1}{n}\sum_{i=1}^{n} (a x_i + b - y_i)^2

편미분을 구하면 (연쇄 법칙으로 제곱을 미분하고 안쪽의 미분을 곱해요)

∂L∂a=2n∑i(axi+b−yi) xi,∂L∂b=2n∑i(axi+b−yi)\frac{\partial L}{\partial a} = \frac{2}{n}\sum_{i} (a x_i + b - y_i)\, x_i, \qquad \frac{\partial L}{\partial b} = \frac{2}{n}\sum_{i} (a x_i + b - y_i)

선형대수 강의처럼 데이터를 행렬 XX(열: xx와 1), 파라미터를 벡터 w=(a,b)\mathbf{w} = (a, b)로 쓰면 한 줄로 정리돼요.

∇L(w)=2nXT(Xw−y)\nabla L(\mathbf{w}) = \frac{2}{n} X^T (X\mathbf{w} - \mathbf{y})

"예측의 오차(Xw−yX\mathbf{w} - \mathbf{y})를 입력(XTX^T)에 다시 곱해 모은다." 신경망의 역전파도 본질적으로 이 모양이에요.

rng = np.random.default_rng(1)
x = rng.uniform(0, 10, 100)
y = 3 * x + 2 + rng.normal(0, 1, 100)        # 진짜 관계: y = 3x + 2 (+ 잡음)

X = np.column_stack([x, np.ones_like(x)])
w = np.zeros(2)
n = len(y)
for step in range(5000):
    grad = (2 / n) * X.T @ (X @ w - y)
    w = w - 0.01 * grad
print(np.round(w, 3))                         # [3.002 1.931]

print(np.round(np.linalg.lstsq(X, y, rcond=None)[0], 3))   # [3.002 1.931]

경사 하강법이 찾은 답이 선형대수 강의의 최소 제곱 해와 똑같아요. 선형 회귀처럼 공식으로 바로 풀리는 문제도 있지만, 신경망은 공식이 없어서 이렇게 경사를 따라 내려가는 방법밖에 없어요. 그리고 이 방법은 파라미터가 2개든 1000억 개든 코드 모양이 똑같아요. 그래서 강력해요.

더 나아가: 야코비 행렬과 헤세 행렬

이름만 알아 두면 나중에 책에서 만났을 때 당황하지 않아요.

  • 야코비 행렬: 출력도 여러 개인 함수(벡터 → 벡터)의 모든 편미분을 모은 행렬이에요. 그래디언트를 출력 개수만큼 쌓은 거예요. 신경망의 한 층이 입력을 출력으로 바꿀 때의 "국소적인 선형 근사"예요.
  • 헤세 행렬: 이계 편미분을 모은 행렬이에요. 지형이 방향마다 얼마나 굽었는지(곡률)를 담아요. 헤세 행렬의 고유값이 크게 차이 나면 길쭉한 골짜기라는 뜻이고, 앞에서 본 지그재그 문제가 생겨요. 선형대수의 고유값이 최적화의 어려움을 설명하는 거예요.

실습

  1. f(x,y)=(x−2)2+(y+1)2f(x, y) = (x - 2)^2 + (y + 1)^2의 그래디언트를 구하고, 경사 하강법으로 최솟점 (2,−1)(2, -1)을 찾아보세요.
  2. 위 선형 회귀 코드에서 학습률을 0.05, 0.001로 바꿔 보세요. 각각 무슨 일이 일어나나요?
  3. x를 010이 아니라 01000 범위에서 뽑으면 학습률 0.01로 학습이 될까요? 안 된다면 왜일까요? (힌트: 지형의 모양)

자주 하는 실수

  • 편미분할 때 다른 변수를 0으로 두기. 다른 변수는 0이 아니라 상수예요. ∂∂x(xy)=y\frac{\partial}{\partial x}(xy) = y예요.
  • 그래디언트 방향으로 가기. 손실을 줄이려면 반대 방향이에요.
  • 모든 파라미터를 하나씩 따로 업데이트하기. 그래디언트는 같은 지점에서 한꺼번에 구해서 동시에 움직여요.
  • 특징 범위를 무시하기. 범위가 크게 다른 특징이 섞이면 지형이 길쭉해져 학습이 망가져요.

점검 문제

  1. f(x,y)=4x3y2f(x, y) = 4x^3 y^2의 ∂f∂x\frac{\partial f}{\partial x}와 ∂f∂y\frac{\partial f}{\partial y}는?
  2. 어떤 점에서 그래디언트가 (3,4)(3, 4)예요. 가장 가파른 오르막의 기울기(변화율)는?
  3. 그래디언트가 (0,0)(0, 0)인 점은 어떤 곳일까요?
  4. 등고선 지도에서 그래디언트는 등고선과 어떤 각도를 이루나요?

정답

  1. 12x2y212x^2 y^2와 8x3y8x^3 y
  2. 그래디언트의 길이 9+16=5\sqrt{9 + 16} = 5예요.
  3. 사방이 평평한 임계점이에요. 최솟점, 최댓점, 또는 말안장 모양의 점(한쪽으로는 오르막, 다른 쪽으로는 내리막)일 수 있어요.
  4. 수직(90도)이에요.

다음 강의

신경망은 함수 수백 개를 합성한 거대한 함수예요. 그런 함수의 그래디언트를 어떻게 효율적으로 구할까요? 답은 연쇄 법칙이고, 그것을 컴퓨터로 체계적으로 계산하는 방법이 역전파예요. 다음 강의에서 손으로 직접 역전파를 해 보고 코드로 확인해요.