Transformer의 수식들은 어떤 원리나 근거로 선택되었는가?
핵심부터 말하면 이렇습니다.
Transformer의 수식들은
“이론적으로 반드시 이렇게 해야만 한다”라기보다,
1. 학습 가능해야 하고
2. 표현력이 충분해야 하고
3. 긴 시퀀스를 잘 다뤄야 하고
4. GPU에서 병렬 계산이 잘 되어야 하고
5. gradient가 안정적으로 흘러야 하고
6. 실험적으로 잘 작동해야 한다
는 조건을 만족하도록 선택된 계산 구조입니다.
즉 Transformer의 식들은 수학적으로 “유일한 정답”이 아닙니다. 하지만 각각은 꽤 명확한 설계 이유를 가지고 있습니다.
1. 먼저 큰 관점: 딥러닝 모델은 “학습 가능한 계산 그래프”입니다
Transformer를 수식 모음으로 보면 복잡합니다.
하지만 설계 관점에서 보면 Transformer는 다음 목표를 가진 계산 그래프입니다.
입력 토큰 시퀀스
↓
벡터 시퀀스
↓
여러 번 변환
↓
다음 토큰 확률
이 계산 그래프는 다음 조건을 만족해야 합니다.
조건 1. 모든 계산이 미분 가능해야 한다
모델은 학습 중 loss를 줄이는 방향으로 파라미터를 조정해야 합니다.
그러려면 각 파라미터가 loss에 어떤 영향을 줬는지 계산해야 합니다.
loss가 W_Q에 얼마나 민감한가?
loss가 embedding matrix에 얼마나 민감한가?
loss가 FFN의 W1에 얼마나 민감한가?
이걸 계산하려면 전체 계산 과정이 대부분 미분 가능해야 합니다.
그래서 Transformer 안의 주요 연산들은 미분 가능한 연산입니다.
행렬 곱
덧셈
softmax
activation
LayerNorm
가중합
cross-entropy loss
전부 gradient를 계산할 수 있습니다.
조건 2. 충분히 복잡한 함수를 표현할 수 있어야 한다
언어는 단순하지 않습니다.
단어 의미
문법
문맥
지시 대상
논리
코드 구조
수학적 관계
긴 거리 의존성
대화 의도
를 모두 다뤄야 합니다.
따라서 모델은 단순한 선형 변환 하나로는 부족합니다.
입력 벡터 × 행렬 = 출력 벡터
만으로는 복잡한 조건 분기나 조합을 표현하기 어렵습니다.
그래서 Transformer는 다음을 조합합니다.
Linear transformation
+ attention
+ softmax
+ nonlinear activation
+ 여러 layer 반복
조건 3. 시퀀스의 토큰들이 서로 정보를 주고받아야 한다
문장 안의 토큰은 서로 독립적이지 않습니다.
철수는 영희에게 책을 주었다. 그는 기뻐했다.
여기서 그는을 이해하려면 앞의 철수, 영희 등을 봐야 합니다.
따라서 모델에는 다음 능력이 필요합니다.
현재 토큰이 문맥의 어떤 토큰을 봐야 하는지 선택하는 능력
이 역할을 하는 것이 attention입니다.
조건 4. 병렬 계산이 잘 되어야 한다
RNN 같은 이전 구조는 토큰을 순서대로 처리하는 경향이 강했습니다.
x1 처리
↓
x2 처리
↓
x3 처리
↓
x4 처리
이 구조는 긴 문장에서 느립니다.
Transformer는 입력 토큰들을 한꺼번에 행렬로 처리할 수 있습니다.
X = 모든 토큰 hidden state 행렬
Q = XW_Q
K = XW_K
V = XW_V
이런 행렬 연산은 GPU에서 매우 빠르게 병렬 처리됩니다.
즉 Transformer 수식들은 단순히 수학적으로 예쁜 식이 아니라:
대규모 병렬 계산에 적합한 식
이기도 합니다.
2. Transformer 식들은 “필연”이 아니라 “좋은 귀납 편향”입니다
머신러닝에서 중요한 개념이 inductive bias, 즉 귀납 편향입니다.
쉽게 말하면:
모델이 어떤 방식으로 세상을 바라보게 할 것인가?
입니다.
Transformer의 귀납 편향은 대략 이렇습니다.
토큰들은 벡터다.
각 토큰은 다른 토큰들을 선택적으로 참고해야 한다.
관련도는 query와 key의 유사도로 계산할 수 있다.
가져올 정보는 value 벡터에 담는다.
토큰 간 정보 교환 후, 각 토큰별로 비선형 가공을 한다.
이 과정을 여러 번 반복하면 복잡한 언어 패턴을 표현할 수 있다.
이게 Transformer의 설계 철학입니다.
다만 이게 유일한 방법은 아닙니다.
다른 구조도 가능합니다.
RNN
LSTM
GRU
CNN
State Space Model
Mamba 계열
Perceiver 계열
Mixture of Experts
Transformer가 널리 쓰이는 이유는 “이론상 유일해서”가 아니라:
언어 모델링에 잘 맞고,
대규모 학습이 잘 되고,
GPU에서 효율적이고,
실험적으로 매우 강했기 때문
입니다.
3. 그러면 각 수식은 왜 그런 모양인가?
이제 주요 수식별로 보겠습니다.
4. Embedding lookup은 왜 쓰나요?
문장은 문자입니다.
하지만 모델은 숫자 계산만 합니다.
그래서 먼저 토큰 ID를 벡터로 바꿔야 합니다.
token ID → embedding vector
이때 수식이라기보다는 lookup을 합니다.
embedding = E[token_id]
여기서 E는 학습되는 임베딩 매트릭스입니다.
왜 이렇게 할까요?
토큰 ID 숫자 자체에는 의미가 없습니다.
"사과" = 5321
"자동차" = 5322
라고 해서 두 토큰이 비슷하다는 뜻은 아닙니다.
그래서 각 토큰마다 학습 가능한 벡터를 줍니다.
"사과" → [ ... ]
"바나나" → [ ... ]
"자동차" → [ ... ]
학습이 진행되면서 비슷한 문맥에서 쓰이는 토큰들은 비슷하게 처리될 수 있습니다.
즉 embedding lookup의 설계 근거는 이것입니다.
이산적인 토큰 ID를
연속적인 학습 가능 벡터 공간으로 옮긴다.
연속 벡터 공간으로 옮기면 행렬 곱, 내적, softmax 같은 미분 가능한 계산을 할 수 있습니다.
5. Linear transformation, 즉 xW + b는 왜 쓰나요?
가장 기본적인 신경망 계산입니다.
y = xW + b
이 식의 역할은:
입력 벡터의 성분들을 학습된 방식으로 섞어서 새로운 벡터를 만드는 것
입니다.
예를 들어 어떤 hidden state가 다음 정보를 분산해서 가지고 있다고 합시다.
성분 1, 8, 37, 103, 900 ...
모델은 이 성분들을 조합해서 새로운 특징을 만들고 싶습니다.
새 특징 = 0.2×성분1 - 0.7×성분8 + 1.1×성분37 + ...
이런 조합을 수천 개 동시에 만드는 것이 행렬 곱입니다.
그래서 Transformer 곳곳에서 Linear transformation을 씁니다.
Q = XW_Q
K = XW_K
V = XW_V
FFN 중간 벡터 = XW_1 + b_1
logits = hW_out
설계 근거는 이것입니다.
벡터 안의 정보를 학습 가능한 방식으로 재조합한다.
6. Q, K, V는 왜 나누나요?
attention에서 핵심 문제는 이것입니다.
현재 토큰이 문맥의 어떤 토큰을 얼마나 참고해야 하는가?
이를 “검색”처럼 생각하면 Q, K, V가 자연스럽습니다.
Query:
내가 지금 찾고 싶은 것
Key:
각 토큰이 어떤 검색 조건에 걸릴 수 있는지
Value:
그 토큰에서 실제로 가져올 정보
예를 들어 현재 토큰이 대명사 그는이라면 Query는 이런 역할을 할 수 있습니다.
내가 가리키는 남성 인물은 누구인가?
앞 토큰들의 Key는 이런 역할을 합니다.
철수: 남성 인물
영희: 여성 인물
책: 사물
그러면 Query와 Key를 비교합니다.
q_그는 · k_철수 → 높음
q_그는 · k_영희 → 낮음
q_그는 · k_책 → 낮음
관련도가 높은 토큰의 Value를 더 많이 가져옵니다.
여기서 중요한 설계 아이디어는:
“무엇을 찾는가”와
“어떤 조건으로 검색되는가”와
“실제로 가져올 정보”를 분리한다.
입니다.
왜 그냥 하나의 벡터만 쓰지 않을까요?
하나의 hidden state는 여러 역할을 동시에 해야 합니다.
하지만 attention에서는 역할을 분리하면 더 유연해집니다.
Q: 검색자 역할
K: 색인 역할
V: 내용물 역할
이 구조는 정보 검색의 query-key-value 구조와 비슷한 직관을 가집니다.
7. 왜 Q와 K를 내적하나요?
attention score는 보통 다음처럼 계산합니다.
score_ij = q_i · k_j
내적은 두 벡터의 방향이 얼마나 잘 맞는지를 측정할 수 있습니다.
방향이 비슷함 → 내적 큼
방향이 다름 → 내적 작음
방향이 반대 → 내적 음수 가능
따라서 내적은 다음 용도로 적합합니다.
현재 Query와 각 Key가 얼마나 잘 맞는가?
물론 내적만 가능한 것은 아닙니다.
다른 유사도 함수도 쓸 수 있습니다.
cosine similarity
additive attention
MLP 기반 score
kernel 기반 score
하지만 dot product는 장점이 큽니다.
1. 계산이 단순하다.
2. 행렬 곱으로 한꺼번에 계산할 수 있다.
3. GPU에서 빠르다.
4. 미분 가능하다.
5. 대규모 모델에서 잘 작동한다.
그래서 Transformer에서는 dot-product attention을 사용합니다.
수식으로는 전체 토큰에 대해 한 번에 이렇게 계산합니다.
scores = QK^T
이 한 줄이 모든 토큰 쌍의 관련도 점수를 계산합니다.
8. 왜 sqrt(d_k)로 나누나요?
attention score는 보통 이렇게 계산합니다.
scores = QK^T / sqrt(d_k)
여기서 d_k는 key/query 벡터 차원입니다.
왜 나눌까요?
Query와 Key 벡터의 차원이 커지면 내적 값의 크기도 커지는 경향이 있습니다.
예를 들어 차원이 64일 때보다 4096일 때, 많은 성분을 곱해 더하므로 score의 분산이 커질 수 있습니다.
score 값이 너무 커지면 softmax가 매우 뾰족해집니다.
예를 들어:
softmax([2, 1, 0])
≈ [0.665, 0.245, 0.090]
그런데 값이 커지면:
softmax([20, 10, 0])
≈ [0.99995, 거의 0, 거의 0]
이렇게 한쪽으로 너무 몰립니다.
그러면 gradient가 불안정해질 수 있습니다.
그래서 sqrt(d_k)로 나눠서 score 크기를 적당히 조절합니다.
설계 근거는 이것입니다.
벡터 차원이 커져도 attention score의 스케일이 너무 커지지 않게 한다.
softmax가 너무 빨리 포화되는 것을 막는다.
학습 안정성을 높인다.
9. 왜 softmax를 쓰나요?
QK 내적으로 얻은 score는 그냥 점수입니다.
[3.2, 1.7, -0.4, 0.9]
이걸 가지고 Value들을 섞으려면 “비율”이 필요합니다.
토큰 1을 70% 참고
토큰 2를 20% 참고
토큰 3을 3% 참고
토큰 4를 7% 참고
softmax는 점수를 이런 비율로 바꿔줍니다.
attention_weights = softmax(scores)
softmax 결과는:
모두 0 이상
합이 1
입니다.
그래서 weighted sum에 쓰기 좋습니다.
attention_output = attention_weights × V
softmax를 쓰는 설계 근거는 이것입니다.
여러 후보 중 어디를 얼마나 참고할지
미분 가능한 방식으로 선택하게 한다.
여기서 “선택”이라고 했지만 hard selection은 아닙니다.
하나만 고르는 것:
미분이 어렵고 불안정함
softmax로 부드럽게 고르는 것:
여러 토큰을 비율로 섞을 수 있고 미분 가능함
즉 softmax attention은:
differentiable soft retrieval
이라고 볼 수 있습니다.
10. 왜 Value의 가중합을 하나요?
attention weight를 얻었다고 합시다.
[0.6, 0.3, 0.1]
각 토큰에는 Value 벡터가 있습니다.
v1, v2, v3
attention output은 다음입니다.
0.6v1 + 0.3v2 + 0.1v3
왜 이렇게 할까요?
현재 토큰이 여러 문맥 정보를 섞어서 새로운 표현을 만들어야 하기 때문입니다.
예를 들어 어떤 토큰이 다음 정보를 함께 참고해야 할 수 있습니다.
주어
목적어
동사
앞 문장의 핵심 개체
코드의 변수 선언 위치
하나만 참고하는 것이 아니라, 여러 토큰의 정보를 가중합으로 가져오는 것이 유연합니다.
설계 근거는 이것입니다.
관련 있는 토큰들의 정보를 연속적이고 미분 가능한 방식으로 섞는다.
11. 왜 Multi-head attention을 쓰나요?
하나의 attention만 있으면 한 종류의 관련성만 보기 쉽습니다.
하지만 언어에서는 여러 관계를 동시에 봐야 합니다.
예를 들어 문장 안에서 동시에 이런 관계들이 있습니다.
주어-동사 관계
동사-목적어 관계
대명사-선행사 관계
형용사-명사 관계
문장 구조
코드에서 변수 사용 위치
괄호 매칭
Multi-head attention은 여러 개의 attention을 병렬로 둡니다.
Head 1: 어떤 관계를 봄
Head 2: 다른 관계를 봄
Head 3: 또 다른 관계를 봄
...
각 head는 자기만의 projection matrix를 가집니다.
W_Q^head1, W_K^head1, W_V^head1
W_Q^head2, W_K^head2, W_V^head2
...
물론 실제로 각 head가 사람이 해석 가능한 특정 관계를 깔끔하게 담당한다고 단정할 수는 없습니다.
하지만 설계 의도는 다음과 같습니다.
여러 표현 공간에서 서로 다른 attention 패턴을 학습하게 한다.
설계 근거는 이것입니다.
한 번의 attention보다 여러 개의 attention을 병렬로 두면
다양한 관계를 동시에 포착할 수 있다.
12. 왜 Attention 다음에 FFN을 두나요?
Transformer block은 대략 이렇게 반복됩니다.
Attention
↓
FFN
이 구조를 직관적으로 보면:
Attention:
토큰들 사이에서 정보를 가져온다.
FFN:
각 토큰 위치에서 가져온 정보를 가공한다.
즉 attention은 통신입니다.
이 토큰이 저 토큰을 참고한다.
저 토큰의 정보를 이 토큰으로 가져온다.
FFN은 계산입니다.
가져온 정보를 바탕으로 각 위치의 hidden state를 변환한다.
예를 들어 먹었다 토큰이 attention을 통해 나는, 사과 정보를 가져왔다고 합시다.
그러면 그 위치의 hidden state에는 이런 정보들이 섞입니다.
주어: 나는
목적어: 사과
동작: 먹었다
문장 종결 가능성
FFN은 이 정보를 가공합니다.
다음 토큰으로 "."가 올 가능성이 높다
이 문장은 완결된 과거형 서술이다
같은 예측에 유용한 표현으로 바꿉니다.
설계 근거는 이것입니다.
Attention으로 위치 간 정보를 섞고,
FFN으로 각 위치의 표현을 비선형적으로 가공한다.
Transformer는 이 두 과정을 반복합니다.
정보 교환 → 정보 가공 → 정보 교환 → 정보 가공 → ...
13. Activation은 왜 하필 FFN 안에 들어가나요?
사용자님 질문의 핵심입니다.
도대체 왜 그 순간에 비선형성을 넣어야 하는가?
먼저 FFN 수식을 다시 보겠습니다.
FFN(x) = W2 · activation(W1 · x + b1) + b2
여기서 구조는 다음입니다.
x
↓
W1
↓
넓은 중간 feature 공간
↓
activation
↓
W2
↓
원래 hidden size로 복귀
직관적으로는 이렇습니다.
W1은 특징 후보들을 만든다
W1 · x + b1
은 현재 hidden state에서 여러 “중간 특징 후보”를 계산합니다.
예를 들어 개념적으로:
이 위치가 문장 끝인가?
이 위치가 함수 호출 안인가?
이 토큰이 명사구 안에 있는가?
이 문맥에서 다음에 마침표가 자연스러운가?
같은 특징들을 계산한다고 볼 수 있습니다.
실제로 이렇게 해석 가능한 단일 뉴런이 항상 존재한다는 뜻은 아니지만, 직관은 그렇습니다.
Activation은 특징을 통과시키거나 억제한다
activation은 중간 특징에 비선형성을 넣습니다.
예를 들어 ReLU라면:
값이 양수면 통과
값이 음수면 0으로 차단
즉:
이 특징이 충분히 활성화되면 사용하고,
그렇지 않으면 거의 무시한다.
는 게이트처럼 작동합니다.
GELU나 SiLU는 ReLU보다 부드러운 게이트라고 볼 수 있습니다.
W2는 활성화된 특징들을 다시 조합한다
마지막으로 W2는 activation을 통과한 중간 특징들을 조합해서 원래 hidden size의 벡터로 되돌립니다.
활성화된 특징들
↓
W2로 조합
↓
다음 hidden state에 더할 변화량
따라서 FFN 안에서 activation을 넣는 이유는:
W1으로 여러 조건/특징 후보를 만들고,
activation으로 조건별 반응을 만들고,
W2로 그 결과를 다시 조합하기 위해서
입니다.
14. 왜 선형 변환만으로는 부족한가?
사용자님 말대로 W는 학습된 파라미터이기 때문에 선형 변환만으로도 의미 있는 일을 합니다.
맞습니다.
하지만 선형 변환에는 결정적인 한계가 있습니다.
선형 변환은 입력을 일정한 방식으로만 섞는다.
입력 상태에 따라 계산 방식 자체가 크게 달라지기 어렵습니다.
예를 들어 이런 조건을 생각해봅시다.
A 조건과 B 조건이 동시에 만족되면 강하게 반응한다.
그렇지 않으면 반응하지 않는다.
이런 “조건 조합”은 순수 선형 변환만으로 표현하기 어렵습니다.
비선형 activation이 들어가면 모델은 다음과 같은 패턴을 만들 수 있습니다.
어떤 특징이 임계값을 넘으면 활성화
여러 feature의 조합에 따라 다른 경로로 정보 전달
특정 문맥에서는 어떤 정보 강조
다른 문맥에서는 억제
즉 activation은 모델에 다음 능력을 줍니다.
입력에 따라 다르게 반응하는 능력
이것이 중요합니다.
15. “왜 그 순간”에 activation을 넣는가?
좀 더 구조적으로 답하겠습니다.
Transformer block 안의 attention은 이미 토큰 간 정보를 섞습니다.
각 토큰의 hidden state가 문맥 정보를 포함하게 됨
그다음 FFN은 각 토큰의 문맥화된 hidden state를 받아서 더 복잡하게 가공합니다.
문맥이 반영된 hidden state
↓
FFN
↓
비선형 특징 변환
이 위치에 activation을 넣는 이유는:
attention으로 모은 문맥 정보를 바탕으로
각 위치에서 복잡한 조건부 feature를 계산하기 위해서
입니다.
즉 순서는 이렇게 이해하면 됩니다.
1. Attention:
필요한 정보를 주변 토큰에서 가져온다.
2. FFN의 W1:
가져온 정보를 기반으로 여러 feature 후보를 만든다.
3. Activation:
어떤 feature를 살릴지 비선형적으로 결정한다.
4. FFN의 W2:
살아남은 feature들을 다시 hidden state로 조합한다.
이게 “왜 그 순간인가?”에 대한 가장 좋은 직관입니다.
다만 중요한 점이 있습니다.
이 위치가 수학적으로 유일하게 필연적인 위치는 아닙니다.
실제로 다양한 변형이 있습니다.
Attention과 FFN 순서를 바꾸는 구조
FFN을 더 크게 만드는 구조
activation을 GLU 형태로 바꾸는 구조
MoE FFN을 쓰는 구조
Norm 위치를 바꾸는 구조
하지만 “attention 후 FFN 안에서 비선형 변환”은 실험적으로 매우 잘 작동하는 표준 구조가 되었습니다.
16. Attention 안의 softmax도 비선형인데 activation이 또 필요한가?
중요한 질문입니다.
attention 안에도 softmax가 있으므로 Transformer 전체는 이미 비선형입니다.
attention_weights = softmax(QK^T)
그러면 FFN activation이 왜 또 필요할까요?
이유는 역할이 다르기 때문입니다.
Attention softmax:
어떤 토큰을 얼마나 참고할지 정한다.
즉 위치 간 정보 흐름을 조절한다.
FFN activation:
각 토큰의 feature 공간 안에서 비선형 변환을 한다.
즉 토큰별 내부 계산 능력을 높인다.
attention은 주로:
어디서 정보를 가져올까?
를 결정합니다.
FFN은 주로:
가져온 정보를 어떻게 가공할까?
를 담당합니다.
둘 다 필요합니다.
17. Residual connection은 왜 쓰나요?
Transformer block에는 보통 residual connection이 있습니다.
단순화하면:
output = x + sublayer(x)
예를 들어 attention 후에는:
h' = h + Attention(h)
FFN 후에는:
h_next = h' + FFN(h')
왜 입력을 다시 더할까요?
깊은 신경망에서는 layer가 많아질수록 학습이 어려워집니다.
각 layer가 기존 정보를 완전히 덮어써버리면 gradient가 불안정해질 수 있습니다.
Residual connection은 다음을 가능하게 합니다.
기존 정보를 유지하면서
필요한 변화량만 추가한다.
즉 layer가 이런 일을 하게 됩니다.
새 표현을 처음부터 다시 만들어라
가 아니라:
기존 표현에 필요한 수정만 더해라
가 됩니다.
이것이 훨씬 학습하기 쉽습니다.
설계 근거는 이것입니다.
깊은 모델에서도 정보와 gradient가 잘 흐르게 한다.
18. LayerNorm은 왜 쓰나요?
Transformer에는 LayerNorm이 자주 들어갑니다.
직관적으로 LayerNorm은 hidden state의 스케일을 안정화합니다.
딥러닝에서는 layer를 많이 거치면 벡터 값들이 너무 커지거나 작아질 수 있습니다.
너무 커짐 → softmax 포화, gradient 불안정
너무 작아짐 → 신호 약해짐
LayerNorm은 각 토큰의 hidden state를 정규화해서 값의 분포를 안정적으로 만듭니다.
hidden state의 평균과 분산을 조정
직관적으로는:
각 layer에 들어가는 신호의 크기를 적당한 범위로 맞춘다.
설계 근거는 이것입니다.
깊은 네트워크 학습을 안정화한다.
요즘 LLM에서는 보통 Pre-LN 구조가 많이 쓰입니다.
x → LayerNorm → Attention → residual
x → LayerNorm → FFN → residual
이런 구조는 깊은 모델 학습에 더 안정적인 경우가 많습니다.
19. Output projection은 왜 쓰나요?
마지막 hidden state는 예를 들어 4096차원 벡터입니다.
하지만 모델이 해야 하는 일은 vocabulary 전체에 대해 다음 토큰 점수를 내는 것입니다.
vocabulary 크기가 100,000이면, 100,000개의 점수가 필요합니다.
그래서 마지막에 행렬을 곱합니다.
logits = h W_out
여기서:
h: hidden size 차원
W_out: hidden size × vocab size
logits: vocab size 차원
즉 output projection은:
내부 hidden state를
각 토큰 후보에 대한 점수로 변환한다.
는 역할을 합니다.
설계 근거는 이것입니다.
모델 내부 표현을 vocabulary 위의 점수 분포로 바꾼다.
그다음 softmax를 적용하면 다음 토큰 확률이 됩니다.
20. Cross-entropy loss는 왜 쓰나요?
LLM은 다음 토큰 확률을 냅니다.
예를 들어 정답 다음 토큰이 먹었다라고 합시다.
모델 예측:
먹었다: 0.10
마셨다: 0.20
갔다: 0.05
...
정답인 먹었다의 확률이 낮습니다.
그러면 loss가 커야 합니다.
Cross-entropy loss는 정답 토큰에 모델이 부여한 확률이 높을수록 작고, 낮을수록 큽니다.
단일 정답 토큰에 대해 단순화하면:
loss = -log(P(정답 토큰))
예를 들어:
P(정답) = 0.9 → loss 작음
P(정답) = 0.1 → loss 큼
P(정답) = 0.001 → loss 매우 큼
설계 근거는 이것입니다.
정답 토큰의 확률을 높이는 방향으로 모델을 학습시키기 좋다.
그리고 softmax와 cross-entropy는 함께 쓰기에 수학적으로도 편리합니다.
gradient가 깔끔하게 계산되고 최적화가 잘 됩니다.
21. Causal mask는 왜 쓰나요?
decoder-only LLM은 다음 토큰 예측을 합니다.
x1 x2 x3 → x4 예측
학습 중에 x3 위치가 미래 토큰 x4, x5를 보면 안 됩니다.
그래서 attention score에서 미래 위치를 막습니다.
x1은 x1만 봄
x2는 x1, x2만 봄
x3는 x1, x2, x3만 봄
설계 근거는 이것입니다.
다음 토큰 예측 문제에서 미래 정답을 훔쳐보지 못하게 한다.
또 이 구조 덕분에 inference 때 autoregressive generation이 가능합니다.
지금까지 생성한 토큰만 보고 다음 토큰 생성
KV cache와 prompt caching도 이 causal 구조 덕분에 가능해집니다.
22. Positional encoding은 왜 필요한가?
attention은 기본적으로 토큰 집합을 다룹니다.
즉 토큰 순서를 알려주지 않으면 다음 두 문장을 구분하기 어렵습니다.
개가 사람을 물었다.
사람이 개를 물었다.
토큰 종류는 비슷하지만 순서가 다릅니다.
그래서 위치 정보가 필요합니다.
이 토큰은 1번째 위치
이 토큰은 2번째 위치
이 토큰은 3번째 위치
초기 Transformer는 sinusoidal positional encoding을 사용했고, 현대 LLM은 RoPE 같은 방식을 많이 씁니다.
설계 근거는 이것입니다.
모델이 토큰의 순서와 상대적 위치를 알 수 있게 한다.
23. Transformer block 전체를 설계 원리로 보면
이제 block 하나를 설계 관점에서 다시 봅시다.
입력 hidden states H
1단계: 정규화
H_norm = LayerNorm(H)
이유:
신호 크기 안정화
학습 안정화
2단계: attention
A = Attention(H_norm)
이유:
토큰들 사이의 정보 교환
문맥에서 중요한 토큰 선택
3단계: residual
H' = H + A
이유:
기존 정보 보존
gradient 흐름 개선
4단계: 다시 정규화
H'_norm = LayerNorm(H')
이유:
다음 sublayer 입력 안정화
5단계: FFN
F = FFN(H'_norm)
이유:
각 토큰별 비선형 feature 가공
6단계: residual
H_next = H' + F
이유:
기존 표현에 필요한 변화만 더함
따라서 Transformer block은 이렇게 볼 수 있습니다.
문맥 정보 교환
+ 안정화
+ 비선형 가공
+ 정보 보존
24. 왜 이런 식이 “그 순간”에 들어가는가?
Transformer는 대략 다음 문제를 반복해서 풉니다.
각 토큰의 현재 표현을 더 좋은 표현으로 바꿔라.
그러려면 각 layer에서 두 가지가 필요합니다.
1. 다른 토큰에서 필요한 정보를 가져오기
2. 가져온 정보를 바탕으로 자기 표현을 계산하기
그래서 자연스럽게 다음 구조가 됩니다.
Attention:
다른 토큰에서 필요한 정보를 가져온다.
FFN + activation:
각 토큰 위치에서 그 정보를 비선형적으로 해석하고 가공한다.
이 순서를 여러 번 반복합니다.
1번째 block:
낮은 수준의 문맥 관계 처리
2번째 block:
처리된 표현을 바탕으로 더 복잡한 관계 처리
3번째 block:
더 복잡한 패턴 처리
...
즉 activation이 FFN 안에 들어가는 이유는:
토큰 간 정보 교환이 끝난 뒤,
각 토큰이 받은 정보를 바탕으로
조건적이고 복잡한 feature 변환을 하게 하려는 것
입니다.
25. 그래도 “왜 반드시 이 식이어야 하나?”에 대한 답
반드시 이 식이어야 하는 것은 아닙니다.
이 점을 분명히 해야 합니다.
예를 들어 attention score는 꼭 dot product일 필요는 없습니다.
dot product attention
additive attention
linear attention
kernel attention
FFN activation도 꼭 GELU일 필요는 없습니다.
ReLU
GELU
SiLU
SwiGLU
GeGLU
정규화도 LayerNorm만 가능한 것은 아닙니다.
LayerNorm
RMSNorm
BatchNorm
position encoding도 여러 가지입니다.
absolute positional encoding
relative positional encoding
RoPE
ALiBi
즉 Transformer의 수식들은 다음 성격을 가집니다.
이론적으로 유일한 정답이라서 선택된 것이 아니라,
필요한 성질을 만족하고,
계산이 효율적이며,
실험적으로 잘 작동해서 표준이 된 구조
입니다.
26. 수식 선택의 근거를 세 단계로 나누면
Transformer의 각 수식은 보통 다음 세 종류의 근거를 가집니다.
1. 수학적 근거
예:
softmax는 양수이고 합이 1인 분포를 만든다.
sqrt(d_k) scaling은 내적 분산을 조절한다.
cross-entropy는 정답 확률을 높이는 학습 목표와 맞다.
2. 모델링 근거
예:
attention은 토큰 간 의존성을 표현한다.
Q/K/V 분리는 검색과 정보 전달 역할을 분리한다.
FFN은 각 위치의 비선형 feature 변환을 담당한다.
causal mask는 다음 토큰 예측 구조에 맞다.
3. 엔지니어링/실험적 근거
예:
행렬 곱은 GPU에서 빠르다.
residual은 깊은 모델 학습을 안정화한다.
LayerNorm은 스케일 폭주를 줄인다.
multi-head attention은 실험적으로 성능이 좋다.
이 세 가지가 합쳐져 현재의 Transformer 구조가 되었습니다.
27. “식이 먼저인가, 실험이 먼저인가?”
둘 다입니다.
Transformer의 많은 구성요소는 기존 아이디어에서 왔습니다.
embedding
softmax
cross-entropy
attention
residual connection
normalization
feed-forward network
각각은 이미 딥러닝에서 쓰이던 아이디어였습니다.
Transformer의 혁신은 이들을 다음 방식으로 조합한 것입니다.
RNN 없이 attention 중심으로 시퀀스를 처리하자.
모든 위치를 병렬로 처리하자.
attention으로 토큰 간 관계를 직접 모델링하자.
그 뒤 수많은 실험과 변형을 통해 현재 LLM 구조가 발전했습니다.
따라서 정답은:
수학적 직관으로 설계하고,
실험으로 검증하고,
엔지니어링 제약에 맞춰 다듬었다.
입니다.
28. 지금 단계에서 가져가야 할 가장 중요한 관점
Transformer 수식을 볼 때 이렇게 생각하면 좋습니다.
이 식은 무엇을 계산하는가?
왜 그 정보가 필요한가?
학습 가능한 파라미터는 어디에 있는가?
비선형성은 어디서 들어오는가?
토큰 간 정보 교환은 어디서 일어나는가?
계산 안정성 장치는 어디에 있는가?
예를 들어 attention 수식을 보면:
Q = XW_Q
K = XW_K
V = XW_V
라고 외우는 것이 아니라:
현재 hidden state를
검색자 Q,
검색 키 K,
가져올 내용 V
세 역할로 변환하는구나.
라고 봐야 합니다.
softmax(QK^T / sqrt(d_k))
는:
각 토큰이 어떤 토큰을 얼마나 참고할지
안정적인 스케일의 비율로 만드는구나.
라고 보면 됩니다.
AttentionWeights · V
는:
그 비율대로 문맥 정보를 가져오는구나.
라고 보면 됩니다.
FFN(x) = W2 activation(W1x + b1) + b2
는:
각 토큰 위치에서 중간 특징들을 만들고,
비선형 게이트를 통과시킨 뒤,
다시 hidden state 공간으로 조합하는구나.
라고 보면 됩니다.
29. 한 문장으로 정리
Transformer의 수식들은 임의로 붙은 것이 아니라, 다음 역할들을 만족하도록 선택되었습니다.
Embedding:
토큰을 학습 가능한 벡터로 바꾼다.
Linear projection:
벡터 정보를 학습된 방식으로 재조합한다.
Q/K/V:
검색, 매칭, 정보 전달 역할을 분리한다.
Dot product:
Query와 Key의 관련도를 빠르게 계산한다.
Scaling:
softmax 입력 크기를 안정화한다.
Softmax:
관련도 점수를 참고 비율로 바꾼다.
Weighted sum:
관련 토큰의 정보를 섞어 가져온다.
Multi-head:
여러 관계를 병렬로 포착한다.
FFN:
각 토큰의 표현을 비선형적으로 가공한다.
Activation:
조건부 반응과 복잡한 feature 조합을 가능하게 한다.
Residual:
기존 정보와 gradient 흐름을 보존한다.
LayerNorm:
계산 스케일을 안정화한다.
Causal mask:
미래 토큰을 보지 못하게 해서 다음 토큰 예측을 가능하게 한다.
Output projection:
최종 hidden state를 vocabulary 점수로 바꾼다.
Softmax + cross-entropy:
정답 다음 토큰 확률을 높이도록 학습시킨다.
가장 중요한 철학은 이것입니다.
Attention은 토큰들 사이의 정보 교환을 담당하고,
FFN은 각 토큰 내부의 비선형 계산을 담당한다.
Transformer block은 이 둘을 반복해서
각 토큰의 hidden state를 점점 더 유용한 표현으로 바꾼다.
그리고 사용자의 질문에 대한 가장 직접적인 답은 이것입니다.
activation을 그 순간에 넣는 이유는,
attention으로 문맥 정보를 모은 뒤
각 토큰 위치에서 그 정보를 단순 선형 조합이 아니라
조건부·비선형적으로 해석하고 가공하게 만들기 위해서입니다.
다만 그 위치와 함수 형태가 유일하게 필연적인 것은 아니며,
학습 가능성, 표현력, 안정성, 계산 효율, 실험 결과가 합쳐져
현재의 표준 구조가 된 것입니다.