수학 개념 지도
딥러닝과 언어 모델

자동 미분(Automatic differentiation)

프로그램을 덧셈, 곱셈, sin 같은 기본 연산으로 쪼개고 각 연산의 미분⁠(differentiation)⁠을 연쇄법칙⁠(chain rule)⁠으로 이어 붙여, 도함수⁠(derivative function)⁠의 값을 반올림 오차⁠(round-off error)⁠ 수준까지 정확하게 계산하는 방법. 입력 쪽에서 나르는 전진 모드⁠(forward mode)⁠와 출력 쪽에서 거꾸로 나르는 후진 모드⁠(reverse mode)⁠가 있고, 후진 모드는 출력이 하나면 모든 기울기⁠(slope)⁠를 한 번에 준다.

vˉi=∑j: i→jvˉj ∂vj∂vi,(a+bε)(c+dε)=ac+(ad+bc) ε,ε2=0\bar v_i = \sum_{j:\, i \to j} \bar v_j\,\frac{\partial v_j}{\partial v_i}, \qquad (a + b\varepsilon)(c + d\varepsilon) = ac + (ad + bc)\,\varepsilon, \quad \varepsilon^2 = 0

신경망⁠(neural network)⁠을 학습시키려면 수십억에서 수조 개에 이르는 가중치⁠(weight)⁠ 하나하나에 대해 '이 수를 조금 바꾸면 손실이 얼마나 변하나'를 알아야 합니다. 방정식을 뉴턴 방법⁠(Newton's method)⁠으로 풀 때도 같은 종류의 값이 필요합니다. 이런 변화율을 주는 함수⁠(function)⁠가 도함수입니다. 컴퓨터는 도함수의 값을 어떻게 계산할까요?

방법은 크게 셋입니다. 식을 기호로 미분하는 기호 미분⁠(symbolic differentiation)⁠, 입력을 조금 움직여 보고 차이를 재는 수치 미분⁠(numerical differentiation)⁠, 그리고 자동 미분입니다. 예로 f(x1,x2)=ln⁡x1+x1x2−sin⁡x2f(x_1, x_2) = \ln x_1 + x_1x_2 - \sin x_2를 (2, 5)에서 봅시다(ln은 자연로그⁠(natural logarithm)⁠). 입력이 둘이니 변화율도 둘입니다. ∂f/∂x1\partial f/\partial x_1('라운드 f 라운드 x₁'으로 읽습니다)은 x₂는 그대로 두고 x₁만 조금 움직일 때 f가 변하는 비율이고, 이것을 편미분⁠(partial derivative)⁠이라 합니다. 손으로 구해 봅니다. ln x를 미분하면 1/x, sin x를 미분하면 cos x입니다. x₁x₂를 x₁로 미분하면 x₂를 상수로 보므로 x₂이고, x₂로 미분하면 x₁입니다. 그래서 ∂f/∂x1=1/x1+x2=1/2+5=5.5\partial f/\partial x_1 = 1/x_1 + x_2 = 1/2 + 5 = 5.5, ∂f/∂x2=x1−cos⁡x2=2−cos⁡5≈2−0.284=1.716\partial f/\partial x_2 = x_1 - \cos x_2 = 2 - \cos 5 \approx 2 - 0.284 = 1.716입니다. 자동 미분은 식 전체를 미분하지 않습니다. 계산을 ln, 곱셈, sin, 덧셈, 뺄셈 같은 기본 연산 하나하나로 쪼개고, 각 연산의 미분만 알면 연쇄법칙으로 이어 붙여 도함수의 값을 냅니다. 쪼갠 모양이 아래의 계산 그래프입니다.

v1=ln⁡x1,v2=x1x2,v3=sin⁡x2,v4=v1+v2,v5=v4−v3=fv_1 = \ln x_1,\quad v_2 = x_1x_2,\quad v_3 = \sin x_2,\quad v_4 = v_1 + v_2,\quad v_5 = v_4 - v_3 = f

x1=x_1 = , x2=x_2 = , 방식:

칸 위의 파란 수는 값입니다. 아래의 분홍 수는 전진 모드에서는 v̇(고른 입력에 대한 변화율), 후진 모드에서는 v̄(f를 그 칸의 값으로 미분한 것)입니다. 변 위의 수는 그 변의 국소 미분이고, 변에 마우스를 올리면 식이 나옵니다.

전진 모드. 값과 함께 '고른 입력을 조금 움직이면 이 값이 얼마나 움직이나'를 나릅니다. 이것을 점을 찍어 v˙\dot v로 씁니다. 각 칸의 v˙\dot v는 들어오는 변마다 (국소 미분) × (앞 칸의 v˙\dot v)를 더한 것입니다. 씨앗으로 x˙1=1,x˙2=0\dot x_1 = 1, \dot x_2 = 0을 넣으면 끝에서 ∂f/∂x1\partial f/\partial x_1(지금 )을 얻습니다. 이것은 이중수⁠(dual number)⁠의 계산과 같습니다. 이중수는 ε2=0\varepsilon^2 = 0으로 약속한 기호 ε(엡실론)를 붙인 수 a+bεa + b\varepsilon입니다. 예를 들어 (3+ε)2=9+6ε+ε2=9+6ε(3 + \varepsilon)^2 = 9 + 6\varepsilon + \varepsilon^2 = 9 + 6\varepsilon이고, ε의 계수 6이 x2x^2의 x = 3에서의 미분계수(2 × 3)입니다. 일반적으로 곱하면 (a+bε)(c+dε)=ac+(ad+bc)ε+bd ε2=ac+(ad+bc)ε(a + b\varepsilon)(c + d\varepsilon) = ac + (ad + bc)\varepsilon + bd\,\varepsilon^2 = ac + (ad + bc)\varepsilon입니다. 다항식⁠(polynomial)⁠이면 이렇게 전개해서 늘 f(a+bε)=f(a)+f′(a) b εf(a + b\varepsilon) = f(a) + f'(a)\,b\,\varepsilon임을 확인할 수 있습니다. 여기서 f′(a)f'(a)('f 프라임 a')는 a에서의 미분계수입니다. ln, sin, cos 같은 함수도 마찬가지입니다. 이런 함수를 다항식처럼 항이 끝없이 이어지는 합으로 펼친 것이 테일러 전개인데, 거기에 a+bεa + b\varepsilon를 넣으면 ε2\varepsilon^2 이후의 항이 모두 사라지기 때문입니다. i2=−1i^2 = -1로 약속한 복소수⁠(complex number)⁠처럼, ε2=0\varepsilon^2 = 0으로 약속한 수 체계⁠(number system)⁠가 미분을 싣고 다니는 셈입니다.

후진 모드. 먼저 앞으로 계산하며 중간값을 모두 기록해 두고, 끝에서 거꾸로 vˉ=∂f/∂v\bar v = \partial f/\partial v를 나릅니다. 각 칸의 vˉ\bar v는 나가는 변마다 (뒤 칸의 vˉ\bar v) × (국소 미분)을 더한 것입니다. x1x_1처럼 두 갈래로 나가는 칸에서는 두 길로 돌아온 값을 더합니다. 한 번의 거꾸로 계산으로 ∂f/∂x1\partial f/\partial x_1(지금 )과 ∂f/∂x2\partial f/\partial x_2(지금 )가 함께 나옵니다. 신경망의 역전파⁠(backpropagation)⁠는 후진 모드 자동 미분을 신경망에 쓴 것입니다.

무엇이 얼마나 드나. 입력이 n개, 출력이 m개인 계산을 생각합니다. 위의 예는 n = 2, m = 1입니다. 출력 하나하나를 입력 하나하나로 편미분한 값을 m줄 n칸의 표로 늘어놓은 것을 야코비 행렬⁠(Jacobian matrix)⁠ J라 합니다. 위의 예라면 J는 한 줄짜리 (5.5, 1.716)입니다. 전진 모드 한 번은 '입력을 정해 둔 한 방향(씨앗)으로 움직일 때 모든 출력이 얼마나 변하나'를 줍니다. 식으로는 J에 세로 벡터⁠(vector)⁠ 하나를 곱한 Jv⃗J\vec v입니다. 후진 모드 한 번은 '출력 하나(또는 출력들을 정해 둔 비율로 섞은 것)가 모든 입력에 대해 얼마나 변하나'를 줍니다. 식으로는 가로 벡터 하나에 J를 곱한 u⃗TJ\vec u^{\mathsf T}J입니다(ᵀ는 '전치'로 읽고, 세로 벡터를 가로로 눕힌다는 뜻입니다). 어느 쪽이든 한 번의 비용은 원래 계산의 작은 상수 배입니다. 그러니 J 전체가 필요하면 전진 모드는 n번, 후진 모드는 m번 돌려야 합니다.

신경망 학습은 수십억에서 수조 개의 가중치를 입력으로 손실 하나(m = 1)를 내는 계산이라, 후진 모드 한 번이면 모든 기울기가 나옵니다. 전진 모드로는 가중치 수만큼 돌려야 합니다. 사칙연산으로 이루어진 계산이라면 기울기 전체를 원래 계산의 상수 배(입력의 개수와 상관없는) 연산으로 얻을 수 있다는 것을 1983년 발터 바우어와 폴커 슈트라센이 증명했습니다. 반대로 입력 하나에 출력이 많은 계산, 이를테면 매개변수⁠(parameter)⁠ 하나를 바꿀 때 시뮬레이션 궤적 전체가 어떻게 변하는지를 알고 싶을 때는 전진 모드가 맞습니다.

후진 모드의 대가는 메모리입니다. 거꾸로 갈 때 쓰려고 앞으로 계산의 중간값을 기억해 두어야 해서, 큰 신경망에서는 이것이 메모리의 큰 몫을 차지합니다. 일부만 기억하고 나머지는 필요할 때 다시 계산하는 체크포인팅⁠(checkpointing)⁠으로 시간과 메모리를 맞바꿉니다.

후진 모드가 싼 까닭도 기억에 있습니다. 각 칸의 vˉ\bar v를 한 번만 계산해 적어 두고 그 앞의 모든 칸이 나눠 쓰니, 입력에서 출력으로 가는 수많은 길을 하나하나 따로 더할 필요가 없습니다. 겹치는 부분 문제⁠(overlapping subproblems)⁠의 답을 적어 두고 다시 쓰는 동적 계획법⁠(dynamic programming)⁠과 같은 생각입니다.

수치 미분은 왜 안 쓸까. 입력이 n개면 기울기 하나에 f를 n + 1번 계산해야 한다는 비용 말고도 정밀도⁠(precision)⁠의 문제가 있습니다. 앞으로 h만큼 움직여 보는 앞차분⁠(forward difference)⁠ (f(x+h)−f(x))/h\bigl(f(x + h) - f(x)\bigr)/h는 h가 크면 곡선이 휘어서 틀리고(잘라 낸 오차, h에 비례), h가 작으면 거의 같은 두 수를 빼면서 유효숫자를 잃어 틀립니다(반올림 오차, 1/h에 비례). 위의 f를 x1x_1로 미분하는 경우입니다. h=10kh = 10^{k}, k =

가로축은 h, 세로축은 참값과의 오차(둘 다 로그 눈금)입니다. 분홍은 앞차분, 청록은 가운데차분입니다. 노란 점선은 부동소수점⁠(floating point)⁠ 수의 반올림 한계(기계 엡실론⁠(machine epsilon)⁠ × |∂f/∂x₁|, 기계 엡실론은 1과 그다음으로 큰 부동소수점 수의 차이로 약 2.2×10⁻¹⁶)로, 자동 미분의 오차는 대개 이 근처에 있습니다.

지금 앞차분의 오차는 , 가운데차분⁠(central difference)⁠ (f(x+h)−f(x−h))/2h\bigl(f(x+h) - f(x-h)\bigr)/2h의 오차는 입니다. 가장 좋은 h는 두 오차가 비슷해지는 곳입니다. 컴퓨터는 보통 실수⁠(real number)⁠를 유효숫자 약 16자리까지만 기억하는 배정밀도⁠(double precision)⁠ 부동소수점 수로 저장합니다. 이때 앞차분은 h가 10−710^{-7} 안팎, 가운데차분은 10−510^{-5} 근처가 그런 곳입니다. 처음 값 (2, 5)에서 가장 좋은 h를 골라도 앞차분에는 10−810^{-8} 안팎, 가운데차분에는 10−1110^{-11} 안팎의 오차가 남습니다. 자동 미분은 연산마다 정확한 미분 공식을 쓰므로 고를 h도, 잘라 낸 오차도 없고, 원래 계산에서처럼 반올림 오차만 남습니다. 기호 미분은 정확하지만, 곱이 여러 겹이면 곱의 미분 법칙이 항을 계속 늘려 도함수의 식이 부풀고, 반복문과 조건문이 있는 프로그램에는 쓰기 어렵습니다. 수치 미분은 그래도 쓸모가 있어서, 자동 미분 코드가 맞는지 확인할 때 몇 방향만 골라 비교합니다.

오해하기 쉬운 점. 자동 미분은 실행된 프로그램을 미분합니다. ∣x∣|x|를 'x > 0이면 x, 아니면 −x'로 짠 프로그램은 x = 0에서 지나간 쪽의 기울기 −1을 냅니다. 수학적으로는 x = 0에서 미분계수⁠(derivative)⁠가 없는데도 말입니다. 신경망에서 흔히 쓰는 ReLU max⁡(0,x)\max(0, x)(음수는 0으로, 양수는 그대로 내보내는 함수)도 x = 0에서 미분계수가 없지만, 도구들은 대개 0으로 정해 둡니다. 또 프로그램이 참 함수의 근사라면(반복을 정해진 횟수에서 끊는 계산처럼), 자동 미분이 주는 것은 근사의 미분이지 참 함수의 미분이 아닙니다.

역사. 자동 미분은 신경망 학습보다 먼저, 수치 계산의 도구로 나왔습니다. 1964년 로버트 웽거트는 「간단한 자동 도함수 계산 프로그램」이라는 짧은 논문에서, 식을 중간값의 목록으로 쪼개 값과 도함수를 함께 나르는 전진 모드를 보였습니다. 후진 모드는 1970년 헬싱키 대학의 세포 린나인마가 핀란드어로 쓴 석사 논문에 나옵니다. 그는 계산 도중 연산마다 생기는 작은 반올림 오차가 최종 결과에 얼마나 쌓이는지를 알고 싶었고, 그러려면 출력을 각 중간값으로 미분한 값이 모두 필요했습니다. 그것을 한 번에 얻으려고 끝에서부터 거꾸로 미분을 모은 것이 후진 모드입니다. 같은 방법은 1980년대에 신경망 학습에 쓰이며 역전파라는 이름으로 널리 퍼졌고, 특히 1986년 러멜하트, 힌턴, 윌리엄스의 논문이 계기가 되었습니다.

이어지는 곳.

범주론⁠(category theory)⁠을 아는 독자에게연쇄 법칙 D(g∘f)x=Dgf(x) DfxD(g \circ f)_x = Dg_{f(x)}\, Df_x(점 x에서 g∘f의 미분은, f(x)에서 g의 미분과 x에서 f의 미분을 합성한 것)는 '합성의 미분은 미분의 합성'이라는 말입니다. 그래서 점과 그 점에서의 방향을 함께 보내는 사상 (x,v)↦(f(x), Dfxv)(x, v) \mapsto (f(x),\, Df_x v)가 합성을 지키는 함자⁠(functor)⁠가 됩니다. 전진 모드는 바로 이 함자를 계산의 한 걸음 한 걸음에 적용하는 것입니다.
관련 인물제프리 힌턴
이 개념이 나오는 큰 생각선형화: 휘어진 것을 곧게 보기

이 개념이 나오는 긴 글

미분에서 회전까지 · 1편 · 미분 순간의 속도 속도계는 '지금 이 순간'의 속도를 보여 준다. 순간에는 시간이 흐르지 않는데, 무엇을 재는 걸까? 신경망과 기계 학습 배우는 기계 예를 보여 주면 규칙을 스스로 찾는 기계. 1958년의 퍼셉트론에서 오늘의 심층 신경망까지, 그 밑바닥에는 미분과 연쇄법칙이 있다. 타입 이론과 범주론 증명은 프로그램이다 러셀의 역설을 막으려던 '타입'이 프로그램의 실수를 막는 장치가 되었다. 명제를 타입으로, 증명을 프로그램으로 읽으면 둘이 규칙 하나하나까지 맞아떨어진다. 오늘날 수학자들은 그 사실로 컴퓨터에게 증명을 검사받는다. 언어 모델 다음 단어를 맞히는 기계 다음 낱말을 짐작하는 일만으로 어디까지 갈 수 있을까? 마르코프의 글자 세기에서 섀넌의 추측 게임, 트랜스포머와 규모의 법칙, 사람의 선호까지. 밑바닥에는 확률의 곱셈 규칙과 로그 하나가 있고, 그 수학은 모델이 왜 그럴듯하게 틀리는지도 말해 준다. 범주론 화살표만으로 본 수학 최대공약수와 교집합과 '그리고'는 같은 것이고, 화살표를 뒤집으면 최소공배수와 합집합과 '또는'이 된다. 무엇으로 만들었는지 묻지 않고 어떻게 이어지는지만 보는 언어로, '자연스럽다'는 말의 뜻, 관계만으로 대상을 알아보는 요네다의 생각, 함자로 본 연쇄법칙, 어디에나 있는 수반까지 사이트의 여러 분야를 가로지른다.

이 개념을 언급하는 페이지

이 페이지가 가리키는 개념