1장. 준비 수학과 Transformer 개요
Transformer 전체 구조 한눈에 보기
새 아파트의 설계도를 처음 보면 복잡해 보입니다. 그래도 "현관 → 거실 → 방" 순서로 따라가면 길이 보입니다. Transformer 의 구조도도 아래에서 위로, 입력이 들어와 출력이 나가는 순서로 따라가면 됩니다. 왼쪽 기둥이 원문을 읽는 Encoder, 오른쪽 기둥이 번역문을 쓰는 Decoder 입니다. Seq2Seq 의 두 통역사가 RNN 대신 Attention 으로 일하게 된 모습입니다.
강사자료 그림은 원 논문(Vaswani 등, 2017)의 Figure 1 위에 번호를 붙였습니다. ① 입력 문장(번역할 원문 토큰) → ② 입력 표현(Input Embedding + 위치 정보) → ③ Encoder(입력 전체의 문맥 표현 만들기) → ④ 이전 출력 토큰(Outputs, shifted right) → ⑤ Decoder(Masked Self-Attention + Cross-Attention) → ⑥ 출력 확률(Linear + Softmax → 다음 토큰) 순서입니다.
구조도의 여섯 칸
| 번호 | 칸 | 하는 일 | 이 장에서 배운 것과의 관계 | 자세히 보는 장 |
|---|---|---|---|---|
| ① | 입력 문장 | 번역할 원문을 토큰으로 자른다 | 문장은 순서 데이터 | 2장 |
| ② | 입력 표현 | 토큰을 벡터로 바꾸고 위치 정보를 더한다 | 벡터, (낱말 수, d_model) 행렬 | 2장 |
| ③ | Encoder | Self-Attention 과 FFN 으로 문맥을 담는다 | 내적, Softmax, 행렬곱 | 3장 |
| ④ | 이전 출력 토큰 | 지금까지 쓴 번역문을 한 칸 밀어 넣는다 | Seq2Seq 의 Decoder 입력 | 4장 |
| ⑤ | Decoder | 앞 낱말만 보며(Masked) 원문을 흘끗 본다(Cross) | Attention 의 네 단계 | 4장 |
| ⑥ | 출력 확률 | Linear 로 낱말 수만큼 점수를 내고 Softmax 로 확률 | 점수를 확률로 | 4장, 6장 |
그림은 구조도를 세 부분으로 묶어 이 과정의 어느 장에서 다루는지 보여 줍니다. 입력 표현은 2장, Encoder 는 3장, Decoder 는 4장에서 봅니다.
짧은 예시
import numpy as np
def softmax(z):
e = np.exp(z - z.max(axis=-1, keepdims=True))
return e / e.sum(axis=-1, keepdims=True)
rng = np.random.default_rng(0)
d_model, vocab = 8, 10 # 낱말 하나 = 숫자 8개, 사전에 든 낱말 = 10개(장난감 크기)
# ①② 원문 토큰 번호 5개를 임베딩 표에서 찾아 (5, 8) 행렬로
embed_table = rng.normal(size=(vocab, d_model)) # (10, 8): 낱말 번호마다 숫자 8개
src = embed_table[[1, 4, 2, 7, 3]]
print("입력 표현:", src.shape) # 결과: 입력 표현: (5, 8)
# ③ Encoder 는 shape 를 바꾸지 않고 숫자만 문맥에 맞게 바꾼다(여기서는 행렬곱 하나로 흉내)
W_enc = rng.normal(size=(d_model, d_model))
memory = src @ W_enc
print("Encoder 출력:", memory.shape) # 결과: Encoder 출력: (5, 8)
# ④⑤ 지금까지 쓴 번역문 토큰 3개가 Decoder 를 지나도 (3, 8)
tgt = embed_table[[0, 5, 6]]
print("Decoder 출력:", tgt.shape) # 결과: Decoder 출력: (3, 8)
# ⑥ Linear: (3, 8) @ (8, 10) → 자리마다 낱말 10개의 점수, Softmax 로 확률
W_out = rng.normal(size=(d_model, vocab))
probs = softmax(tgt @ W_out)
print("출력 확률:", probs.shape, probs.sum(axis=1).round(2)) # 결과: 출력 확률: (3, 10) [1. 1. 1.]이 코드가 뜻하는 것
구조도의 ①~⑥을 shape 만 따라가 보았습니다. 실제 Encoder 와 Decoder 는 Attention 과 FFN 을 여러 층 쌓은 것이지만, 들어간 shape 와 나온 shape 가 같다는 점을 행렬곱 하나로 흉내 냈습니다. 여기서 사전이 embed_table, 원문이 src, Encoder 가 만든 문맥이 memory, 다음 낱말 확률이 probs 입니다.
| 줄 | 하는 일 | 쉽게 말하면 |
|---|---|---|
embed_table[[1, 4, 2, 7, 3]] | 번호 5개의 행을 골라 (5, 8) 로 | 상품 번호로 성격표 꺼내기 |
src @ W_enc | (5, 8) @ (8, 8) → (5, 8) | 모양은 그대로, 내용만 문맥에 맞게 |
tgt @ W_out | (3, 8) @ (8, 10) → (3, 10) | 자리마다 낱말 10개의 점수 |
softmax(...) | 행마다 합 1 | 다음 낱말 확률 |
(3, 10) 의 마지막 숫자 10은 사전의 낱말 수입니다. 실제 LLM 은 이 숫자가 수만~십오만쯤이어서, 자리마다 그만큼의 점수 가운데 다음 낱말을 고릅니다.
주의할 점
- 원 논문의 Transformer 는 번역용으로 Encoder 와 Decoder 를 모두 씁니다. 이 과정에서 파인튜닝할 Qwen 같은 생성형 LLM 은 Decoder 쪽만 쌓은 모양입니다. 5장에서 봅니다.
- 구조도의 Nx 는 같은 블록을 N 번 쌓았다는 뜻입니다. 원 논문은 Encoder 와 Decoder 를 각각 6층 쌓았습니다.