4장. Transformer Decoder와 작은 번역기
Decoder 블록과 전체 조립
Decoder 블록 하나는 세 번 일하는 작업대입니다. 먼저 지금까지 쓴 번역문을 돌아보고(Masked Self-Attention), 원문을 흘끗 보고(Cross-Attention), 마지막으로 낱말마다 혼자 다듬습니다(Feed Forward). 일이 하나 끝날 때마다 원본을 옆에 붙이고 눈금을 맞춥니다(Add & Norm). 이 작업대를 N층 쌓은 다음, 맨 위에서 "다음 낱말은 사전의 몇 번일까"를 점수로 매깁니다.
아래부터 읽습니다. Outputs (shifted right) 가 Output Embedding 과 Positional Encoding 을 거쳐 블록에 들어갑니다. ① Masked Self-Attention 은 Q·K·V 를 모두 Decoder 입력에서 만들고 뒤 낱말을 가립니다. ② Cross-Attention 은 Q 를 Decoder 에서, K·V 를 Encoder 출력에서 받습니다. 왼쪽에서 들어오는 화살표가 Encoder 출력입니다. ③ Feed Forward 는 낱말마다 따로 계산합니다. 회색 테두리 옆의 Nx 는 이 세 층 묶음을 N번 쌓는다는 표시입니다.
맨 위 블록이 내놓은 벡터는 아직 숫자 256개짜리 줄입니다. Linear 층이 이것을 사전의 토큰 수만큼의 점수(로짓)로 바꾸고, Softmax 가 합이 1인 확률로 바꿉니다. 그림에서는 "학생"의 확률이 0.67 로 가장 높습니다.
전체 지도의 마지막 칸, 출력입니다. 다음 토큰 예측은 결국 "사전 61,790개 가운데 하나를 고르는 분류 문제"입니다. 현재 문맥을 받아 어휘의 모든 토큰에 확률을 매기고 그중 하나를 고르기 때문입니다.
Decoder 블록의 세 층
| 차례 | 층 | Q 출처 | K·V 출처 | 하는 일 |
|---|---|---|---|---|
| ① | Masked Self-Attention | Decoder 입력 | Decoder 입력 | 앞쪽 번역문 돌아보기 |
| ② | Cross-Attention | Decoder | Encoder 출력 | 원문 흘끗 보기 |
| ③ | Feed Forward | 없음 | 없음 | 낱말마다 따로 다듬기 |
| 맨 위 | Linear + Softmax | 없음 | 없음 | 사전 크기의 확률로 바꾸기 |
손으로 계산하기
안전 점검 보고서를 뒤에 올 낱말의 로짓이 요약 3.0, 작성 2.2, 확인 2.0, 삭제 0.2 라고 해 봅니다. e³ ≈ 20.09, e^2.2 ≈ 9.03, e² ≈ 7.39, e^0.2 ≈ 1.22 이고 합은 37.73 입니다. 나누면 요약 0.53, 작성 0.24, 확인 0.20, 삭제 0.03 입니다. 실제 모델은 이 계산을 61,790개 토큰 전체에 대해 합니다. 가장 높은 것을 고르거나(greedy), 확률에 따라 뽑습니다(sampling). 6장에서 고르는 방법을 견줍니다.
짧은 예시
import numpy as np
words = ["요약", "작성", "확인", "삭제"]
logits = np.array([3.0, 2.2, 2.0, 0.2]) # Linear 가 내놓은 점수(로짓)
# Softmax: 점수를 합이 1인 확률로
probs = np.exp(logits) / np.exp(logits).sum()
for w, p in zip(words, probs):
print(w, round(float(p), 2))
# 결과: 요약 0.53 / 작성 0.24 / 확인 0.2 / 삭제 0.03
# argmax = argument of maximum(가장 큰 값의 자리). greedy 는 이 자리를 고른다
print("고른 낱말:", words[int(np.argmax(probs))]) # 결과: 고른 낱말: 요약이 코드가 뜻하는 것
후보 낱말 네 개에 매긴 점수를 투표 비율로 바꾸고, 표를 가장 많이 받은 낱말을 고른 코드입니다. 여기서 점수표가 logits, 투표 비율이 probs, 당선자가 np.argmax(probs) 의 자리입니다.
| 줄 | 하는 일 | 쉽게 말하면 |
|---|---|---|
np.exp(logits) / np.exp(logits).sum() | Softmax | 점수를 합 100% 비율로 |
np.argmax(probs) | 가장 큰 자리 | 1등 후보 고르기 |
words[...] | 자리를 낱말로 | 상품 번호를 상품 이름으로 |
손으로 한 0.53, 0.24, 0.20, 0.03 이 그대로 나옵니다. 숫자가 큰 순서는 로짓과 확률에서 같습니다. Softmax 는 순서를 바꾸지 않고 비율만 만듭니다.
주의할 점
- 사전이 크면 Linear 층도 커집니다. 실습 2의 번역기는 사전 61,790개 × 256칸 = 15,818,240개의 숫자를 단어 표로 씁니다. 전체 파라미터의 약 86% 입니다.
- 강사자료 그림의 0.67 이나 이 절의 로짓은 설명을 위한 예입니다. 실제 확률은 모델과 문맥마다 다릅니다.