제1부 기반: 언어모델과 트랜스포머
1.3 신경망·최적화 복습 — LLM에 필요한 만큼
트랜스포머를 열어 보면 안에 대단한 것이 없다. 행렬을 곱하고, 비선형 함수를 한 번 통과시키고, 다시 행렬을 곱한다. 그것이 한 층이고, 같은 모양의 층을 수십 번 쌓은 것이 GPT다. 이 밋밋한 함수가 사람처럼 글을 쓰는 이유는 구조가 기발해서가 아니라, 그 안의 수십억 개 숫자(파라미터)를 데이터에 맞게 조율했기 때문이다. 그 조율이 학습이고, 학습의 전부는 놀랍도록 짧은 순환 하나로 요약된다 — 순전파로 예측을 내고, 손실로 얼마나 틀렸는지 재고, 역전파로 각 파라미터가 그 손실에 얼마나 기여했는지 구하고, 그 반대 방향으로 파라미터를 조금 민다. 이 네 걸음을 수십만에서 수백만 번 반복하면 모델이 된다.
이 장은 그 순환을 1.4의 트랜스포머를 읽을 수 있을 만큼만 복습한다. 1.1에서 "언어모델 = 다음 토큰의 확률분포를 내는 함수"를, 1.2에서 "토큰을 벡터로 바꾼다"를 봤는데, 그 함수의 속을 채우는 것이 신경망이고 그 함수를 데이터에 맞추는 것이 최적화다. 여기서 다루는 부품 — 완전연결층·softmax·교차엔트로피·역전파·AdamW·잔차연결 — 은 하나도 빠짐없이 1.4에서 다시 조립된다. 트랜스포머의 FFN은 여기서 볼 MLP 그대로이고, 어텐션의 softmax는 여기서 미분할 그 softmax이며, 수십 층을 안정적으로 쌓는 잔차·정규화는 여기서 세울 원리 그대로다. 행렬곱·벡터·편미분의 정의 자체가 바뀐다면 부록 A.1을 먼저 보고 오는 편이 낫다. 그리고 이 장에 나오는 숫자들 — 활성값·손실·기울기 — 은 방향을 보여 주려는 개략값이지 특정 모델의 실측이 아니다. 여기서 익힐 것은 정확한 값이 아니라 무엇이 무엇을 밀고 당기는가다.
1.3.1 완전연결층과 순전파를 행렬로
신경망은 파라미터 $\theta$(가중치와 편향)로 조절되는 하나의 큰 함수 $f_\theta$다. 학습이란 데이터를 보며 이 $\theta$를 조금씩 바꿔 $f_\theta$가 우리가 원하는 입출력 관계에 가까워지게 하는 것이고, 언어모델이라면 그 관계는 "앞 토큰들 $\to$ 다음 토큰 확률"이다. 이 큰 함수를 이루는 가장 작은 구성 단위가 뉴런이다. 뉴런은 입력 벡터 $\mathbf{x}$를 받아 가중합을 내고 거기에 비선형 함수를 씌운다.
$$y = \sigma(\mathbf{w}^\top \mathbf{x} + b) = \sigma\!\Big(\textstyle\sum_i w_i x_i + b\Big)$$
$\mathbf{w}$는 각 입력의 중요도를 담은 가중치, $b$는 문턱을 옮기는 편향(bias), $\sigma$는 비선형 활성함수다. 뉴런 하나는 입력을 한 방향으로 사영해 점수를 내는 셈인데, 이것을 여러 개 나란히 두면 완전연결층(fully-connected layer, 밀집층·Linear)이 된다. 층의 모든 출력 뉴런이 모든 입력에 연결되므로, 뉴런마다 따로 있던 가중치 벡터들을 행 하나씩 쌓아 행렬 $W$ 하나로 묶을 수 있다.
$$\mathbf{h} = \sigma(W\mathbf{x} + \mathbf{b}), \qquad W \in \mathbb{R}^{d_{\text{out}} \times d_{\text{in}}},\ \ \mathbf{x}\in\mathbb{R}^{d_{\text{in}}},\ \ \mathbf{b},\mathbf{h}\in\mathbb{R}^{d_{\text{out}}}$$
$W$의 $j$번째 행이 곧 $j$번째 뉴런의 가중치다. 층 하나가 "행렬 곱 + 편향 덧셈 + 비선형" 세 연산이라는 이 사실이 신경망 계산의 골격 거의 전부다. 완전연결층을 여러 개 쌓으면 다층 퍼셉트론(Multi-Layer Perceptron, MLP), 곧 가장 단순한 심층 신경망이 된다. 트랜스포머 블록 안의 위치별 FFN이 바로 이 2층 MLP다(1.4). 언어모델 관점에서 순전파(forward pass)는 임베딩에서 시작해 층을 통과하며 마지막에 어휘 크기의 로짓을 내고, 거기에 softmax를 씌워 다음 토큰 분포로 끝난다.
각 화살표가 한 층이고, 순전파 전체가 미분 가능한 연산들의 합성이라는 점이 결정적이다 — 그래야 나중에 역전파로 기울기를 구해 학습할 수 있다. 숫자로 한 번 만져 보면 명확해진다. 입력 $\mathbf{x}=[1,\,2]$, 가중치 $W=\begin{bmatrix}1&0\\1&1\end{bmatrix}$, 편향 $\mathbf{b}=[0,\,-1]$, 활성함수는 ReLU라 하자. $W\mathbf{x}=[1,\,3]$, 편향을 더하면 $[1,\,2]$, ReLU를 씌우면 $\mathbf{h}=[1,\,2]$다. 층을 지날 때마다 벡터가 이렇게 변형될 뿐이고, 학습이 바꾸는 것은 오직 $W$와 $\mathbf{b}$의 숫자들이다.
실무에서는 입력을 한 번에 하나씩 넣지 않고 $B$개를 행으로 쌓아 행렬 $X\in\mathbb{R}^{B\times d_{\text{in}}}$로 만든 뒤, 층 전체를 하나의 큰 행렬 곱으로 처리한다.
$$H = \sigma\!\left(X W^\top + \mathbf{b}\right), \qquad X\in\mathbb{R}^{B\times d_{\text{in}}},\ \ H\in\mathbb{R}^{B\times d_{\text{out}}}$$
($\mathbf{b}$는 각 행에 브로드캐스트로 더해진다.) 이렇게 쓰는 이유는 수식이 간결해서만이 아니다. GPU는 크고 통통한 행렬 곱(GEMM)에서 압도적으로 빠르고, 신경망이 사실상 "행렬 곱의 사슬"인 덕에 그 하드웨어를 온전히 쓸 수 있다. 이 배칭이 학습에서는 처리량을, 추론에서는 지연·처리량을 지배한다는 이야기가 5.1에서 되돌아온다. 앞으로 등장할 기호는 이 정도다.
| 기호 | 뜻 | 전형적 크기 |
|---|---|---|
| $B$ | 배치 크기(한 번에 처리하는 예시 수) | 수십~수천 |
| $d_{\text{in}}, d_{\text{out}}$ | 입력·출력 차원 | 수백~수만 |
| $W$ | 가중치 행렬(학습됨) | $d_{\text{out}}\times d_{\text{in}}$ |
| $\mathbf{b}$ | 편향 벡터(학습됨) | $d_{\text{out}}$ |
| $X, H$ | 입력·출력 활성값(배치) | $B\times d$ |
1.3.2 비선형이 없으면 깊이는 없다
활성함수 $\sigma$를 빼면 무슨 일이 벌어지는지부터 명시하고 가야 한다. 이것을 확실히 이해하지 못하면 왜 트랜스포머의 FFN이 굳이 넓혔다 좁히며 비선형을 삽입하는지(1.4.13)가 영영 흐릿하게 남는다. 활성함수 없이 두 선형 층을 통과시키면
$$W_2\,(W_1 \mathbf{x} + \mathbf{b}_1) + \mathbf{b}_2 = (W_2 W_1)\,\mathbf{x} + (W_2\mathbf{b}_1 + \mathbf{b}_2) = W'\mathbf{x} + \mathbf{b}'$$
이 된다. 두 층이 합쳐져 하나의 아핀 변환(행렬 하나 + 벡터 하나)으로 붕괴한다. 편향을 넣어도 결과는 여전히 아핀이다. 100개를 쌓든 1000개를 쌓든 마찬가지라, 결국 단일 층 하나와 똑같은 표현력밖에 못 낸다 — 입력 공간에 직선(고차원에서는 초평면)밖에 못 긋는다. 언어처럼 복잡하게 굽은 관계를 이런 것으로 배울 수는 없다. 깊이가 힘을 갖는 유일한 이유가 층 사이에 삽입한 비선형성이다.
왜 비선형 하나가 그렇게 큰 차이를 내는지는 ReLU로 보면 선명하다. ReLU는 입력 공간을 "$W_1$의 각 뉴런이 켜졌나 꺼졌나"로 여러 조각으로 나누고, 각 조각 안에서만 선형으로 동작한다. 이런 층을 하나 더 쌓으면 앞 층이 나눈 조각을 뒤 층이 또 나눠, 전체가 표현하는 조각난 선형 영역의 수가 깊이에 대해 지수적으로 늘어난다. 같은 파라미터를 폭으로만 늘리는 것보다 깊이로 늘리는 편이 훨씬 복잡한 함수를 표현하게 되는 근본 이유가 이것이다. 이론적으로도, 은닉층 하나에 뉴런을 충분히 많이 두면 임의의 연속 함수를 원하는 정밀도로 근사할 수 있다는 것이 보편 근사 정리인데, 실무에서 폭 대신 깊이를 택하는 이유는 같은 표현력을 훨씬 적은 파라미터로 얻기 때문이다. 어느 쪽이든 전제는 하나다 — 층 사이에 비선형이 있어야 한다.
그 비선형을 무엇으로 쓸지가 활성함수의 선택이고, 역사가 담겨 있다.
| 활성함수 | 정의 | 특징 | 주 용도 |
|---|---|---|---|
| Sigmoid | $\dfrac{1}{1+e^{-x}}$ | 출력 $(0,1)$, 양끝에서 포화(기울기$\to$0) | 옛 은닉층·이진 확률·게이트 |
| Tanh | $\dfrac{e^x-e^{-x}}{e^x+e^{-x}}$ | 출력 $(-1,1)$, 0 중심, 역시 포화 | 옛 은닉층·RNN 게이트 |
| ReLU | $\max(0,x)$ | 양수는 그대로, 음수는 0. 포화 없음·빠름 | 딥러닝 표준 은닉층 |
| GELU | $x\,\Phi(x)$ ($\Phi$=정규 CDF) | ReLU의 매끄러운 사촌 | 트랜스포머(1.5) |
| SiLU/Swish | $x\,\sigma(x)$ | 매끄럽고 음수 약간 통과 | 최신 아키텍처 |
핵심 대비는 포화형(sigmoid·tanh)과 비포화형(ReLU·GELU)이다. 포화형은 입력이 조금만 커지면 곡선이 평평해져 기울기가 0에 가까워지고, 그 지점을 지나는 학습 신호가 사라진다. 뒤에서 볼 그래디언트 소실(1.3.12)의 단초가 여기 있다. ReLU·GELU 계열은 양수 구간에서 기울기가 1 근처로 죽지 않아 깊은 망 학습을 훨씬 쉽게 만들었고, 그래서 2010년대 이후 은닉층의 기본이 됐다. 트랜스포머의 FFN은 보통 GELU나 SwiGLU 같은 매끄러운 계열을 쓰는데, 왜 하필 그 선택인지의 세부는 1.5에서 다룬다. 여기서는 "포화하는 함수는 깊이에서 위험하다"는 방향만 쥐면 된다.
1.3.3 로짓을 확률로 — softmax와 수치 안정
언어모델의 마지막 층은 어휘 크기만큼의 로짓 벡터 $\mathbf{z}$를 낸다. 각 토큰에 대한 점수인데, 부호도 크기도 자유로운 실수라 그 자체로는 확률이 아니다. 이것을 확률분포로 바꾸는 표준 도구가 softmax다.
$$p_i = \operatorname{softmax}(\mathbf{z})_i = \frac{e^{z_i}}{\sum_{j} e^{z_j}}$$
지수를 씌워 전부 양수로 만들고, 합으로 나눠 총합을 1로 맞춘다. 왜 하필 지수인가는 두 가지로 답할 수 있다. 지수는 어떤 로짓이든 항상 양수로 보내므로 확률의 비음성 조건을 추가 비용 없이 만족시키고, 또 로짓의 차이를 곱셈 비율로 바꿔 준다 — $p_i/p_j = e^{z_i - z_j}$라, 두 토큰의 상대 확률이 로짓 차이에만 달리고 전체를 상수만큼 이동해도 분포가 안 변한다. 대신 지수라서 격차가 증폭된다. 로짓이 조금만 커도 그 토큰이 분포를 크게 차지한다. 이 날카로움을 온도 파라미터로 조절하는 것이 샘플링이고(1.7), 어텐션에서 점수를 $\sqrt{d_k}$로 나눠 이 포화를 막는 것이 1.4.6의 스케일링이다 — 둘 다 같은 softmax의 성질을 다루는 형제다.
이 지수가 구현에서는 골칫거리다. $e^{z_i}$는 로짓이 조금만 커도 부동소수 범위를 넘겨 오버플로한다($e^{1000}$은 무한대가 된다). 그래서 모든 구현은 각 성분에서 최댓값 $m=\max_j z_j$를 먼저 빼고 계산한다.
$$p_i = \frac{e^{z_i - m}}{\sum_j e^{z_j - m}}$$
분자와 분모에 똑같이 $e^{-m}$이 곱해져 상쇄되므로 결과는 수학적으로 완전히 같지만, 이제 지수의 인자가 전부 0 이하가 되어 오버플로가 사라진다. 이 "max 빼기" 트릭은 softmax·교차엔트로피·어텐션 어디에나 있고, FlashAttention이 어텐션을 타일 단위로 계산할 때 최댓값을 온라인으로 갱신하는 온라인 softmax의 토대이기도 하다(1.4.17). 저정밀도(FP16·BF16)에서 이런 수치 안정 장치가 왜 학습 안정성을 가르는지는 2.6에서 본다.
1.3.4 교차엔트로피와 그 기울기의 완전 유도
이제 예측 확률 $\mathbf{p}$가 정답과 얼마나 가까운지를 하나의 숫자로 재야 한다. 분류와 언어모델의 표준은 교차엔트로피(cross-entropy, CE)다. 정답이 원-핫일 때 — 정답 토큰 $y$만 1이고 나머지는 0 — 식이 놀랍도록 간단해진다.
$$L = -\sum_i y_i \log p_i = -\log p_{y}$$
정답 토큰에 부여한 확률의 음의 로그다. 정답에 확률 1을 주면 손실 0, 확률을 낮게 줄수록 손실이 급격히 커진다(0에 가까운 확률의 로그는 $-\infty$로 발산한다). 언어모델 전체 손실은 시퀀스의 모든 위치에서 이 값을 평균한 것으로, 1.1에서 본 음의 로그가능도(NLL)와 정확히 같다.
$$L = -\frac{1}{T}\sum_{t=1}^{T} \log p_\theta\!\left(x_t \mid x_{<t}\right)$$
이 손실에 지수를 씌우면 1.1의 퍼플렉서티 $\text{PPL}=e^{L}$가 된다. 교차엔트로피와 퍼플렉서티는 같은 것의 두 표현이다(평가 관점은 4.1).
여기서 이 책 전체에서 몇 번이고 다시 쓸 결과 하나가 나온다. softmax와 교차엔트로피를 로짓으로 미분하면 복잡한 지수가 전부 상쇄되고 $\partial L/\partial z_k = p_k - y_k$라는 깨끗한 식이 남는다. 결론만 제시하지 말고 끝까지 유도하자. 두 조각으로 나눈다. 먼저 softmax 자체의 야코비안, 그다음 손실과의 결합이다.
softmax $p_i = e^{z_i}/S$($S=\sum_j e^{z_j}$)를 $z_k$로 미분한다. $i=k$인 대각 성분과 $i\ne k$인 비대각 성분을 나눠 몫의 미분법을 쓴다.
$$\frac{\partial p_i}{\partial z_k} = \begin{cases} \dfrac{e^{z_i}S - e^{z_i}e^{z_i}}{S^2} = p_i - p_i^2 = p_i(1-p_i) & i=k \\[8pt] \dfrac{0\cdot S - e^{z_i}e^{z_k}}{S^2} = -p_i p_k & i\ne k \end{cases}$$
두 경우를 크로네커 델타 $\delta_{ik}$($i=k$면 1, 아니면 0)로 한 줄에 묶으면
$$\frac{\partial p_i}{\partial z_k} = p_i(\delta_{ik} - p_k)$$
이다. 이 야코비안이 1.4.6에서 어텐션의 softmax가 포화하면 기울기가 소실된다고 할 때 쓰는 바로 그 식이다. 이제 손실 $L=-\sum_i y_i\log p_i$를 $z_k$로 미분하며 연쇄법칙으로 이 야코비안을 대입한다. $\partial(\log p_i)/\partial z_k = (1/p_i)\,\partial p_i/\partial z_k$이므로
$$\frac{\partial L}{\partial z_k} = -\sum_i y_i \frac{1}{p_i}\frac{\partial p_i}{\partial z_k} = -\sum_i y_i \frac{1}{p_i}\,p_i(\delta_{ik}-p_k) = -\sum_i y_i(\delta_{ik}-p_k)$$
합을 두 조각으로 가른다. 첫 조각 $\sum_i y_i \delta_{ik} = y_k$, 둘째 조각 $p_k\sum_i y_i = p_k$다(정답 분포의 합이 1이므로 $\sum_i y_i=1$). 따라서
$$\frac{\partial L}{\partial z_k} = -(y_k - p_k) = p_k - y_k$$
이 식이 그렇게 반가운 이유는 뜻이 직관적이라서다. 로짓에 대한 기울기가 "예측 확률 빼기 정답"이다. 경사하강은 기울기의 반대로 움직이므로, 정답 토큰($y_k=1$)에서는 기울기가 음수라 그 로짓을 높이고, 오답 토큰($y_k=0$)에서는 기울기가 양수라 그 로짓을 내린다. 예측이 정답과 일치할수록($p_k\to y_k$) 기울기가 0으로 사그라들어 학습이 멈춘다. 이 우아한 형태가 softmax와 교차엔트로피의 조합을 딥러닝의 사실상 표준 출력으로 만들었고, 프레임워크의 cross_entropy가 로짓을 직접 받아 softmax를 따로 취하지 않는 이유이기도 하다 — 로짓에서 곧장 $p-y$로 가는 이 경로가 수치적으로도 안정적이다.
숫자로 확인해 보자. 로짓 $\mathbf{z}=[2.0,\,1.0,\,0.1]$, 정답이 0번 클래스라 하자. 지수는 $e^{2.0}\approx7.389$, $e^{1.0}\approx2.718$, $e^{0.1}\approx1.105$이고 합은 약 $11.21$이라, 확률은 $\mathbf{p}\approx[0.659,\,0.242,\,0.099]$다. 손실은 $L=-\log(0.659)\approx0.417$. 기울기는 위 식대로 $\mathbf{p}-\mathbf{y}=[0.659-1,\,0.242,\,0.099]=[-0.341,\,0.242,\,0.099]$이다. 정답 로짓만 음수라 경사하강이 그 값을 높이고, 두 오답은 양수라 낮춘다. 이 세 숫자가 다음 절부터 시작될 학습의 최초 신호다.
1.3.5 학습은 경사를 내려가는 것 — 경사하강과 학습률
손실 $L(\theta)$는 파라미터 $\theta$의 함수다. 학습이란 이 $L$을 가장 작게 만드는 $\theta$를 찾는 것인데, 파라미터가 수십억 개라 방정식으로 풀 수는 없다. 대신 기울기를 따라 조금씩 내려간다. 기울기 $\nabla_\theta L$은 $L$이 가장 가파르게 증가하는 방향이므로, 그 반대로 한 걸음 가면 손실이 준다.
$$\theta \leftarrow \theta - \eta\, \nabla_\theta L$$
$\eta$가 학습률(learning rate), 한 걸음의 크기다. 신경망에서 단일 하이퍼파라미터로 가장 중요한 것을 꼽으라면 대개 이것이다. 너무 크면 골짜기를 건너뛰어 발산하거나 진동하고(손실 스파이크·NaN, 2.6), 너무 작으면 수렴이 한없이 느리고 얕은 함정에 갇힌다. 이 개념을 1차원에서 직접 익혀 두면 대규모에서도 변동하지 않는다.
$L(\theta)=\theta^2$을 보자. 최소는 $\theta=0$, 기울기는 $\nabla L=2\theta$다. 시작 $\theta=1.0$, 학습률 $\eta=0.1$로 갱신을 밟으면
| 스텝 | $\theta$ | $\nabla L=2\theta$ | 갱신 후 $\theta$ |
|---|---|---|---|
| 0 | 1.000 | 2.000 | $1.0-0.1(2.0)=0.800$ |
| 1 | 0.800 | 1.600 | 0.640 |
| 2 | 0.640 | 1.280 | 0.512 |
| 3 | 0.512 | 1.024 | 0.410 |
매 스텝 $\theta$가 0.8배씩 최소점으로 다가간다. 갱신을 한 줄로 정리하면 $\theta \leftarrow \theta - \eta\cdot 2\theta = (1-2\eta)\theta$라, 수렴하려면 $|1-2\eta|<1$이어야 하고 이는 $0<\eta<1$을 뜻한다. $\eta=0.5$면 한 번에 정확히 최소점에 도달하고, $\eta=1$이면 $\theta$가 부호만 바꾸며 영원히 진동하며, $\eta>1$이면 매 스텝 커져 발산한다. 학습률 하나가 성패를 가르는 것이다.
이 장난감 문제가 실제 학습에 주는 교훈은 학습률이 손실 표면의 곡률과 맞물려야 한다는 것이다. 일반적인 2차 근사 $L=\tfrac12 a\theta^2$에서는 갱신이 $(1-\eta a)\theta$가 되어 $\eta<2/a$일 때만 수렴한다 — 곡률 $a$가 큰(가파른) 방향에서는 작은 학습률만 안전하다. 그런데 신경망은 방향마다 곡률이 천차만별이라, 단일 $\eta$로는 어떤 방향에서는 너무 크고 어떤 방향에서는 너무 작다. 이 불균형을 파라미터마다 스텝을 조절해 완화하는 것이 뒤에 볼 Adam이고(1.3.9), 학습 초기의 곡률이 특히 험할 때 학습률을 서서히 높여 발산을 피하는 것이 웜업이다(1.3.10). 실제 LLM 학습은 이 1차원 그림을 수십억 차원에서 하는 셈이고, 매 스텝 그 방향을 새로 재는 것이 다음 절의 역전파다.
1.3.6 기울기는 어디서 오나 — 계산 그래프와 역전파
수십억 개 파라미터 각각에 대한 $\partial L/\partial\theta$를 어떻게 다 구하나. 직접 미분하는 것은 불가능하고, 파라미터 하나하나를 섭동해 손실 변화를 재는 수치미분은 파라미터 수만큼 순전파를 다시 해야 해서 절망적으로 느리다. 답은 연쇄법칙을 계산 그래프에 체계적으로 적용하는 역전파(backpropagation)다. 연쇄법칙은 합성함수의 미분이 국소 미분들의 곱이라고 말한다. $L$이 $y$를 거쳐 $\theta$에 의존하면 $\partial L/\partial\theta = (\partial L/\partial y)(\partial y/\partial\theta)$다. 순전파는 곱·합·활성함수 같은 작은 연산들의 그래프이고, 역전파는 손실에서 거꾸로 이 그래프를 훑으며 각 노드에서 "상류 기울기 × 국소 미분"을 곱해 입력 쪽으로 전달한다.
작은 예로 $a=wx$, $\hat y=a+b$, $L=(\hat y-t)^2$를 보자.
값 $w=2$, $x=3$, $b=1$, $t=10$을 넣으면 순전파는 $a=6$, $\hat y=7$, $L=(7-10)^2=9$다. 이제 손실에서 거꾸로 각 노드의 기울기를 누적한다.
| 노드 | 국소 미분 | 역전파 계산 | 기울기 |
|---|---|---|---|
| $L$ | — | 시작 | $\partial L/\partial L = 1$ |
| $\hat y$ | $\partial L/\partial\hat y = 2(\hat y-t)$ | $2(7-10)$ | $-6$ |
| $b$ | $\partial\hat y/\partial b = 1$ | $-6\times1$ | $-6$ |
| $a$ | $\partial\hat y/\partial a = 1$ | $-6\times1$ | $-6$ |
| $w$ | $\partial a/\partial w = x = 3$ | $-6\times3$ | $-18$ |
그러면 경사하강이 $w \leftarrow 2 - \eta(-18)$로 $w$를 키운다($\eta=0.01$이면 $w=2.18$). 여기서 챙길 것이 두 가지다. 첫째, 곱셈 노드에서 $w$로 가는 국소 미분이 $x$라는 점 — 곱셈의 역전파는 "상류 기울기에 반대편 입력을 곱한다"로, 이 구조가 나중에 층이 깊어질 때 기울기가 왜 가중치 크기에 따라 증폭·감쇠하는지(1.3.12)의 근원이다. 둘째, 국소 미분을 계산하려면 순전파 때의 값($x=3$, $\hat y=7$ 등)이 필요하다는 점 — 그래서 역전파는 순전파에서 계산한 활성값을 저장해 둬야 하고, 이것이 학습 시 메모리를 크게 차지하는 이유다. 이 활성값 메모리를 시간과 맞바꿔 줄이는 것이 그래디언트 체크포인팅이다(2.4).
역전파가 대규모 학습을 가능하게 한 실제 비결은 비용에 있다. 한 번의 순전파와 한 번의 역전파로 모든 파라미터의 기울기를 동시에 얻고, 그 역전파의 비용이 순전파와 같은 차수다. 파라미터가 70억 개든 7000억 개든, 기울기 전부를 구하는 데 순전파의 두세 배 연산이면 충분하다. 이 효율(리버스 모드 자동미분의 핵심 성질)이 없었다면 큰 신경망은 학습 자체가 성립하지 않았을 것이다. 2.2의 학습 컴퓨트 $6ND$에서 순전파가 $2$, 역전파가 $4$의 몫을 차지하는 것도 정확히 이 이유다 — 역전파가 순전파의 대략 두 배 연산을 쓴다.
1.3.7 자동미분 — 프레임워크가 대신 미분한다
실무에서 위 표를 직접 채울 일은 없다. PyTorch·JAX 같은 프레임워크는 순전파를 실행하며 어떤 연산이 어떤 순서로 일어났는지 계산 그래프를 기록해 두고, .backward() 한 줄에 그 그래프를 거꾸로 훑으며 위 표를 자동으로 수행한다. 이것이 자동미분(autodiff)이다. 방금 예를 그대로 코드로 옮기면
import torch
w = torch.tensor(2.0, requires_grad=True)
b = torch.tensor(1.0, requires_grad=True)
x, t = 3.0, 10.0
y_hat = w * x + b # 순전파: 7.0, 이 연산이 그래프에 기록된다
loss = (y_hat - t) ** 2 # 9.0
loss.backward() # 역전파(자동미분): 그래프를 거꾸로 훑음
print(w.grad, b.grad) # tensor(-18.), tensor(-6.) ← 위 표와 일치
우리가 할 일은 순전파를 미분 가능한 연산으로 조립하는 것뿐이고, 기울기 계산은 프레임워크가 책임진다. 이 편리함에는 암묵적 제약이 하나 딸려 온다 — 순전파의 모든 연산이 미분 가능해야 한다. 여기 함정이 있다. argmax로 토큰을 뽑거나, 이산 샘플링을 하거나, 조건에 따라 분기하는 연산은 기울기를 끊어 버린다. 미분값이 거의 어디서나 0이거나 정의되지 않아, 그 지점 너머로 학습 신호가 전달되지 않는다. 그래서 신경망 안에서 "이산적 선택"이 필요할 때는 softmax 같은 미분 가능한 근사로 부드럽게 풀거나(어텐션이 딕셔너리 조회를 부드럽게 푸는 1.4.3이 바로 이 정신이다), 강화학습처럼 별도의 기울기 추정 기법을 쓴다. 정렬에서 보상을 최대화할 때 왜 곧장 역전파하지 못하고 정책 경사 같은 우회로가 필요한지(3.4·3.7)의 근원이 여기, "샘플링은 미분이 안 된다"에 있다.
1.3.8 옵티마이저 I — 미니배치·SGD·모멘텀
경사하강의 골격은 "기울기 반대로 한 걸음"이지만, 얼마나 어떻게 걷느냐를 정교화한 것이 옵티마이저다. LLM 학습은 사실상 전부 AdamW를 쓰므로 거기까지의 계보를 밟자. 먼저 기울기를 어디서 재느냐부터 정해야 한다. 전체 데이터로 기울기를 한 번 재고 한 걸음 걷는 풀 배치는 데이터가 수조 토큰이면 애초에 불가능하고, 예시 하나마다 걷는 순수 확률적 경사하강(Stochastic Gradient Descent, SGD)은 잡음이 너무 크다. 실전 표준은 그 사이인 미니배치로, 수천에서 수백만 토큰을 묶어 그 배치의 평균 기울기를 참값의 추정으로 쓴다.
$$\theta \leftarrow \theta - \eta\,\nabla_\theta L_{\text{batch}}$$
미니배치를 쓰는 이유는 셋이다. 메모리에 들어가고, GPU 행렬 곱이 배치에서 효율적이며, 기울기에 섞인 잡음이 오히려 얕은 함정을 탈출하는 데 도움이 되기도 한다. 배치 크기는 잡음과 안정성·처리량 사이의 맞바꿈이고, LLM에서의 배치·시퀀스 설계와 큰 배치 학습의 미묘함은 2.2·2.3에서 정밀하게 다룬다.
순수 SGD는 좁고 긴 골짜기의 양쪽 경사면 사이를 오가며 지그재그로 느리게 내려간다. 곡률이 큰 방향으로는 튕기고 완만한 방향으로는 굼뜬 탓이다. 모멘텀(momentum)은 과거 기울기를 지수평균으로 누적한 "속도"를 두어, 일관된 방향으로는 가속하고 왔다 갔다 하는 진동은 상쇄한다.
$$\mathbf{v} \leftarrow \beta\,\mathbf{v} + \nabla_\theta L, \qquad \theta \leftarrow \theta - \eta\,\mathbf{v}$$
$\beta\approx0.9$가 흔하다. 공이 언덕을 굴러 내려가며 관성이 붙듯, 여러 스텝에 걸쳐 방향이 일관되면 그만큼 속도가 누적되어 유효 스텝이 커진다 — 대략 $1/(1-\beta)$배, $\beta=0.9$면 약 열 배다. 반대로 방향이 매번 뒤집히는 진동 성분은 평균에서 서로 지워진다. 이 단순한 관성 하나가 수렴을 눈에 띄게 빠르게 하고, 다음 절 Adam의 1차 모멘트가 바로 이 모멘텀이다.
1.3.9 옵티마이저 II — Adam·AdamW와 상태 메모리
파라미터마다 기울기의 크기가 천차만별이면 단일 학습률이 맞을 리 없다. Adam은 모멘텀(1차 모멘트 $\mathbf{m}$)에 더해 기울기 제곱의 지수평균(2차 모멘트 $\mathbf{v}$)을 추적해서, 각 파라미터의 스텝을 자기 기울기의 최근 크기로 정규화한다 — 늘 크게 변동하는 파라미터는 작게, 작게만 움직이는 파라미터는 크게 밟는다. 1.3.5에서 본 "방향마다 곡률이 달라 단일 학습률이 안 맞는다"를 파라미터별 스케일로 눅이는 셈이다.
$$ \begin{aligned} \mathbf{m}_t &= \beta_1\mathbf{m}_{t-1} + (1-\beta_1)\,\mathbf{g}_t \\ \mathbf{v}_t &= \beta_2\mathbf{v}_{t-1} + (1-\beta_2)\,\mathbf{g}_t^2 \\ \hat{\mathbf{m}}_t &= \frac{\mathbf{m}_t}{1-\beta_1^{t}}, \qquad \hat{\mathbf{v}}_t = \frac{\mathbf{v}_t}{1-\beta_2^{t}} \\ \theta_t &= \theta_{t-1} - \eta\,\frac{\hat{\mathbf{m}}_t}{\sqrt{\hat{\mathbf{v}}_t}+\epsilon} \end{aligned} $$
여기서 $\mathbf{g}_t=\nabla_\theta L$이고, 흔히 $\beta_1=0.9$, $\beta_2=0.999$(LLM에서는 $\beta_2=0.95$로 낮추기도 한다), $\epsilon\approx10^{-8}$을 쓴다. 셋째 줄의 편향 보정이 왜 필요한지 정리해 두면 식이 덜 신비로워진다. $\mathbf{m}$과 $\mathbf{v}$를 0에서 시작하면 초기 몇 스텝 동안 지수평균이 0 쪽으로 치우쳐 실제보다 작게 추정된다. $1-\beta^t$로 나누는 보정이 이 초기 저평가를 되돌린다 — $t$가 커지면 $\beta^t\to0$이라 보정이 사라지고, 초기에만 크게 작동한다. 마지막 줄의 나눗셈 $\hat{\mathbf{m}}/(\sqrt{\hat{\mathbf{v}}}+\epsilon)$이 Adam의 핵심으로, 분자의 모멘텀 방향을 분모의 최근 크기로 나눠 스텝의 실효 크기를 파라미터마다 1 근처로 맞춘다. 이 때문에 Adam은 학습률 선택에 덜 민감하고 잡음에 강해 딥러닝의 기본값이 됐다.
LLM이 실제로 쓰는 것은 AdamW다. AdamW는 가중치 감쇠(weight decay)를 기울기에서 떼어 내(decoupled) 순수한 $-\eta\lambda\theta$ 항으로 따로 적용한다.
$$\theta_t = \theta_{t-1} - \eta\!\left(\frac{\hat{\mathbf{m}}_t}{\sqrt{\hat{\mathbf{v}}_t}+\epsilon} + \lambda\,\theta_{t-1}\right)$$
원래 Adam에 L2 정규화를 기울기 안에 섞어 넣으면, 그 정규화 항까지 2차 모멘트로 나뉘어 스케일이 왜곡된다 — 크게 변동하는 파라미터는 감쇠가 약해지고 잔잔한 파라미터는 강해지는 식으로, 의도한 균일한 감쇠가 붕괴한다. AdamW는 감쇠를 적응 스케일 바깥으로 빼내 이 왜곡을 없앤다. 거의 모든 현대 LLM 사전학습이 AdamW를 쓰며, 정확한 하이퍼파라미터와 스케줄은 2.3에서 다룬다.
옵티마이저를 고를 때 반드시 함께 세야 하는 것이 메모리다. 이것을 빠뜨리면 대규모에서 반드시 OOM으로 실패한다.
| 옵티마이저 | 파라미터당 추가 상태 | 핵심 아이디어 | 상태 메모리 |
|---|---|---|---|
| SGD | 없음 | 기울기 반대로 | 0 |
| SGD+모멘텀 | 속도 $\mathbf{v}$ | 관성으로 가속·진동 완화 | 1× |
| Adam / AdamW | $\mathbf{m}, \mathbf{v}$ | 모멘텀 + 파라미터별 적응 | 2× |
Adam·AdamW는 파라미터마다 $\mathbf{m}$과 $\mathbf{v}$ 두 개의 상태를 들고 다니므로, 옵티마이저 상태만으로 파라미터 메모리의 두 배를 더 차지한다. 여기에 기울기 자체를 담을 자리(1×)가 붙는다. 숫자로 확정해 보자. 70억 파라미터 모델을 순진하게 전부 FP32(원소당 4바이트)로 학습하면, 파라미터 $7\text{B}\times4=28$ GB, 기울기 28 GB, Adam 상태 $\mathbf{m},\mathbf{v}$ 각 28 GB로 상태만 56 GB, 도합 약 112 GB다. 파라미터 자체는 28 GB인데 학습에 필요한 총량이 그 네 배로 뛴 것이다. 여기에 순전파가 저장해 둔 활성값까지 더해지면 단일 GPU 메모리를 훌쩍 넘는다. 이 옵티마이저 상태를 여러 GPU로 분할하는 것이 ZeRO·FSDP의 첫 번째 동기이고(2.4), 상태를 저정밀도로 두어 바이트를 줄이는 것이 혼합정밀도 레시피의 일부다(2.6) — 실제 레시피는 파라미터·기울기·상태를 서로 다른 정밀도로 두므로 위 112 GB는 가장 단순한 상한 계산임을 밝혀 둔다.
1.3.10 학습률 스케줄 — 웜업과 코사인
학습률을 학습 내내 한 값으로 고정하는 일은 드물다. LLM 사전학습의 전형적 스케줄은 웜업 뒤 코사인 감쇠다. 웜업은 처음 수백에서 수천 스텝 동안 학습률을 0에서 목표치까지 선형으로 높인다. 초기에는 파라미터가 무작위라 기울기가 크고 방향이 불안정하며, Adam의 2차 모멘트 추정도 아직 몇 스텝밖에 데우지 못해 신뢰할 수 없다 — 이때 곧장 큰 학습률을 쓰면 1.3.5에서 본 "곡률에 비해 큰 스텝"이 되어 발산하기 쉽다. 웜업이 이 초기 험로를 낮은 학습률로 조심스럽게 지난다. 목표치에 도달한 뒤에는 코사인 곡선을 따라 학습률을 부드럽게 낮춰 0(또는 소량)으로 데려가, 후반에 스텝을 줄여 손실 표면의 좁은 최소에 정착시킨다.
$$\eta_t = \eta_{\max}\frac{t}{t_{\text{warmup}}}\ (\text{웜업}), \qquad \eta_t = \eta_{\min} + \tfrac{1}{2}(\eta_{\max}-\eta_{\min})\!\left(1 + \cos\frac{\pi\,(t - t_{\text{warmup}})}{T - t_{\text{warmup}}}\right)\ (\text{감쇠})$$
여기서는 "왜 고정이 아니라 스케줄인가"의 직관만 이해하면 된다. 웜업 길이·피크 학습률·최소값·감쇠 형태의 선택과 그 근거, 그리고 코사인 대신 쓰는 대안들은 2.3에서 본격적으로 다룬다.
1.3.11 일반화가 목표다 — 과적합·정규화
학습의 실제 목표는 학습 데이터의 손실을 0으로 만드는 것이 아니라 처음 보는 데이터에서 잘하는 것, 곧 일반화다. 모델이 학습 데이터의 잡음과 특이사항까지 전부 외우면 학습 손실은 계속 내려가는데 검증 손실은 오히려 오르는 과적합이 일어난다. 반대로 용량이 모자라 둘 다 나쁘면 과소적합이다. 학습 손실과 검증 손실의 벌어진 간격을 일반화 격차라 부르고, 이 격차가 벌어지기 시작하는 지점이 대략 "그만 학습해야 할 때"다.
과적합을 억제하는 장치가 정규화이고, 실무에서 마주치는 둘이 가중치 감쇠와 드롭아웃이다. 가중치 감쇠(weight decay, L2 정규화)는 손실에 $\frac{\lambda}{2}\lVert\theta\rVert^2$를 더한 것과 같은 효과로 가중치를 작게 유지해 함수를 매끄럽게(단순하게) 만든다 — AdamW의 그 $\lambda$가 바로 이것이다(1.3.9). 드롭아웃(dropout)은 학습 중 각 뉴런을 확률 $p$로 무작위로 꺼서 모델이 특정 뉴런에 의존하지 못하게 하고, 매 스텝 조금씩 다른 부분망을 학습시켜 앙상블 비슷한 효과를 낸다(추론 때는 끈다).
여기서 흔히 하는 오해를 조용히 깨 두자. "정규화는 세게 걸수록 좋다"는 조건부로만 맞다. 대규모 사전학습은 데이터가 워낙 방대해 같은 예시를 두 번 보는 일이 거의 없으므로 과적합이 주된 걱정이 아니고, 실제로 큰 LM의 사전학습은 드롭아웃을 0에 가깝게 두고 가중치 감쇠만 약하게 거는 경우가 많다(구체 값은 레시피마다 다르다). 반대로 좁은 데이터로 파인튜닝하거나(3.2) LoRA로 소수 파라미터만 학습할 때(3.8)는 과적합이 실재해 정규화·조기 종료·데이터 증강이 중요해진다. 즉 "얼마나 정규화하나"는 절대적 규칙이 아니라 데이터 대비 모델 용량이 정하는 것이고, 이 관점의 정량화가 스케일링 법칙이다(2.2).
1.3.12 깊이가 기울기를 소실시키는 법 — 소실과 폭발
깊이가 표현력을 준다면서 왜 오래도록 깊은 망을 학습하지 못했나. 역전파가 연쇄법칙이라 층을 거슬러 갈 때마다 국소 미분(야코비안)을 곱하기 때문이다. $L$개 층을 통과한 초기 층의 기울기는 대략 이런 형태이다.
$$\frac{\partial L}{\partial \mathbf{h}_1} = \frac{\partial L}{\partial \mathbf{h}_L}\ \prod_{l=2}^{L}\frac{\partial \mathbf{h}_l}{\partial \mathbf{h}_{l-1}}$$
문제는 이 긴 곱이다. 각 야코비안의 크기(정확히는 가장 큰 특이값, 스펙트럼 반경)가 평균적으로 1보다 작으면 곱이 층 수에 대해 지수적으로 0으로 사라지고(소실), 1보다 크면 지수적으로 폭발한다. 스칼라로 단순화해 층당 인자를 각각 0.6과 1.5로 두고 깊이에 따라 어떻게 되는지 계산하면 지수 거동이 한눈에 보인다.
| 층 깊이 $k$ | 인자 0.6 (소실) | 인자 1.5 (폭발) |
|---|---|---|
| 5 | $0.078$ | $7.6$ |
| 10 | $6.0\times10^{-3}$ | $57.7$ |
| 20 | $3.7\times10^{-5}$ | $3.3\times10^{3}$ |
| 40 | $1.3\times10^{-9}$ | $1.1\times10^{7}$ |
소실이면 초기 층에 학습 신호가 사실상 도달하지 못해 깊은 부분이 학습되지 않고, 폭발이면 기울기가 발산해 파라미터가 급등하고 손실이 NaN이 된다(2.6의 손실 스파이크). 이 소실을 특히 악화시킨 것이 포화형 활성함수였다. sigmoid의 도함수는 $\sigma'(x)=\sigma(x)(1-\sigma(x))$인데, 이 값의 최댓값이 $x=0$에서 겨우 $0.25$이고 입력이 조금만 커져도 급격히 0으로 떨어진다. 층마다 이런 $\le0.25$ 크기의 인자가 곱해지면 열 층만 지나도 $0.25^{10}\approx9.5\times10^{-7}$로, 신호가 백만분의 일로 쪼그라든다. ReLU 계열이 양수 구간에서 도함수를 1로 유지해 이 지수적 소멸을 막은 것이 깊은 망 학습의 첫 번째 돌파구였던 이유가 이 숫자에 있다.
이것이 2010년대 초까지 깊은 망을 제대로 학습하기 어려웠던 근본 이유다. 그런데 트랜스포머는 수십에서 수백 층을 쌓고도 정상적으로 학습된다. 활성함수를 바꾼 것만으로는 부족하고, 이 긴 곱 자체를 다스리는 몇 가지 장치가 더 필요했다 — 다음 절의 주제다.
1.3.13 깊이를 되살리는 세 장치 — 잔차·정규화·초기화
깊은 망을 실제로 학습 가능하게 만든 축이 셋 있고, 셋 다 트랜스포머 블록에 그대로 들어간다(1.4·1.5). 여기서는 각각이 왜 통하는지의 일반 원리만 세우고, 트랜스포머 안에서의 구체적 배치와 변형은 이후 장으로 넘긴다.
첫째는 잔차연결(residual connection)이다. 아이디어는 단순하다. 층이 출력을 처음부터 새로 만들게 하지 말고, 입력에 변화분만 더하게 한다.
$$\mathbf{y} = \mathbf{x} + F(\mathbf{x})$$
왜 이것이 소실을 푸는지는 이 블록을 미분하면 곧장 나온다. $\partial\mathbf{y}/\partial\mathbf{x} = I + \partial F/\partial\mathbf{x}$이다. 항등항 $I$ 덕분에 기울기에 늘 "+1의 통로"가 확보되어, $\partial F/\partial\mathbf{x}$가 아무리 작아도 기울기가 최소한 $I$를 통해 그대로 전달된다. 여러 층을 지나면 1.3.12의 순수한 곱 $\prod J_l$이 $\prod(I+J_l)$로 바뀌는데, 항등항이 살아 있어 이 곱은 지수적으로 사라지지 않는다. 트랜스포머에서 층을 관통해 흐르는 이 덧셈 경로를 잔차 스트림이라 부르고, 모델이 수십·수백 층 깊어질 수 있는 일차적 이유가 이것이다(1.4.16). 잔차가 없는 깊은 트랜스포머는 사실상 학습이 안 된다.
둘째는 정규화(normalization)다. 각 층의 활성값 분포가 학습 중 제멋대로 커지거나 작아지면 그 위를 지나는 기울기도 함께 불안정해진다. 정규화 층은 활성값을 매 층에서 평균·분산 기준으로 다시 스케일해 안정된 범위에 유지한다. 활성값의 크기를 통제하면 야코비안의 크기도 통제되어, 앞 절의 긴 곱이 폭주하거나 소멸할 여지가 줄어든다. 트랜스포머가 쓰는 LayerNorm과 RMSNorm의 정확한 정의, 그리고 정규화를 서브층 앞에 두느냐 뒤에 두느냐(Pre-LN 대 Post-LN)가 깊은 모델의 학습 가능 여부를 어떻게 가르는지는 1.4.12와 1.5에서 다룬다 — 여기서는 "활성 스케일을 붙잡으면 기울기도 안정된다"는 원리만 쥐면 된다.
셋째는 초기화다. 학습 시작 시점의 가중치 값도 소실·폭발을 좌우한다. 전부 0으로 두면 모든 뉴런이 똑같이 움직여 대칭이 깨지지 않아 학습이 안 되고, 너무 크거나 작으면 첫 순전파부터 활성값이 층을 지나며 폭발하거나 소멸한다. 그래서 층을 지나도 활성값과 기울기의 분산이 대략 보존되도록 스케일을 맞춘 무작위 초기화를 쓴다 — 입출력 차원의 균형을 맞추는 Xavier/Glorot, ReLU 계열에 맞춘 He/Kaiming이 대표다. 아주 깊은 모델에서는 층 수에 맞춰 잔차 기여분을 $1/\sqrt{2L}$ 같은 인자로 줄여 초기화해, 잔차 스트림의 크기가 층이 쌓이며 폭주하지 않게 하기도 한다(그 세부는 1.4·2.6). 여기에 기울기의 노름이 임계값을 넘으면 잘라 폭발을 막는 그래디언트 클리핑이 더해지면, 깊은 망이 발산하지 않고 완주할 조건이 갖춰진다.
세 장치를 한 줄로 요약하면 이렇다 — 깊이가 기울기를 소실시키지 않게 통로를 열고(잔차), 활성 스케일을 제어하고(정규화), 좋은 출발점에서 시작한다(초기화). 이 위에 1.4의 셀프어텐션을 추가하면 트랜스포머 블록이 된다. 그 장에서 우리는 여기서 세운 부품들이 하나씩 제자리를 찾는 것을 보게 된다. FFN은 이 장의 MLP이고, 어텐션의 가중 평균은 이 장의 softmax로 정규화되며, 블록을 수십 개 쌓아도 학습이 되는 것은 방금 본 잔차·정규화·초기화 덕이고, 그 전체를 미는 것은 처음의 그 네 걸음 순환 — 순전파, 손실, 역전파, 갱신 — 이다. 위치 인코딩·정규화·활성함수의 구체적 선택은 1.5에서, 더 깊은 수학 배경이 필요하면 부록 A.1에서 채운다.