Ch.7 Attention — AI의 집중력
Self-Attention 직접 구현
6단계로 어텐션을 만든다
'나는 고양이를 좋아한다' — 3개 토큰이 서로에게 얼마나 주목하는지 직접 계산해봅니다.
행렬 곱셈이 이렇게 많은데 차원이 안 꼬일까?
셀프 어텐션 구현 — 6단계 코드를 한 줄씩 따라가며 행렬 크기의 변화를 추적합니다.
핵심 내용
6단계로 어텐션을 처음부터 구현합니다
셀프 어텐션 구현 6단계: Step 0: 입력 임베딩 (3 토큰 × 4 차원) Step 1: 가중치 행렬 W_Q, W_K, W_V 생성 Step 2: Q, K, V 계산 (행렬 곱) Step 3: 어텐션 스코어 = Q × Kᵀ Step 4: 스케일링 (÷ √d_k) Step 5: 소프트맥스 → 확률 가중치 Step 6: 가중 합 = Weights × V
'나는 고양이를 좋아한다'로 셀프 어텐션을 계산합니다
import numpy as np
np.random.seed(42)
# Step 0: 입력 — 3개 토큰, 4차원 임베딩
tokens = ["나는", "고양이를", "좋아한다"]
X = np.array([
[1.0, 0.0, 1.0, 0.0], # "나는"
[0.0, 1.0, 0.0, 1.0], # "고양이를"
[1.0, 1.0, 0.0, 0.0], # "좋아한다"
])
d_k = 4
print("=== Step 0: 입력 임베딩 ===")
for token, vec in zip(tokens, X):
print(f" {token:6s} → {vec}")
# Step 1: 가중치 행렬
W_Q = np.random.randn(4, 4) * 0.5
W_K = np.random.randn(4, 4) * 0.5
W_V = np.random.randn(4, 4) * 0.5
# Step 2: Q, K, V 계산
Q = X @ W_Q # (3,4) × (4,4) = (3,4)
K = X @ W_K
V = X @ W_V
print(f"\n=== Step 2: Q, K, V 크기 = {Q.shape} ===")
# Step 3: 어텐션 스코어 = Q × K^T
scores = Q @ K.T # (3,4) × (4,3) = (3,3)
print(f"\n=== Step 3: 스코어 크기 = {scores.shape} ===")
# Step 4: 스케일링
scores_scaled = scores / np.sqrt(d_k)
# Step 5: Softmax → 확률 가중치
def softmax(x):
exp_x = np.exp(x - np.max(x, axis=-1, keepdims=True))
return exp_x / np.sum(exp_x, axis=-1, keepdims=True)
attention_weights = softmax(scores_scaled)
print(f"\n=== Step 5: 어텐션 가중치 ===")
print(" 나는 고양이를 좋아한다")
for i, token in enumerate(tokens):
w_str = " ".join(f"{w:.3f}" for w in attention_weights[i])
print(f" {token:6s} [{w_str}]")
# Step 6: 가중 합
output = attention_weights @ V # (3,3) × (3,4) = (3,4)
print(f"\n=== Step 6: 최종 출력 크기 = {output.shape} ===")
print("→ 각 토큰에 다른 토큰들의 정보가 섞여 들어갔습니다!")입력이 (3, 4)이고 W_Q가 (4, 4)일 때 Q = X × W_Q의 행렬 크기는?
어텐션 가중치 행렬의 각 행의 합은 항상 1이다 (소프트맥스를 적용했으므로).
3개 토큰, 4차원 임베딩일 때 어텐션 스코어 행렬(Q × Kᵀ)의 크기는?
다음 셀프 어텐션 코드의 빈칸을 채우세요. scores = Q @ K.T / np.sqrt(___) weights = softmax(scores)
Q @ K.T / np.sqrt(___)
셀프 어텐션에서 마스킹(masking)은 미래 토큰 정보의 유출을 방지하기 위해 사용한다.
셀프 어텐션 구현!
정리 노트
셀프 어텐션 6단계 구현 정리
구현 6단계
- Step 0
- 입력 임베딩 — (토큰 수 × 차원) 행렬 준비
- Step 1~2
- W_Q, W_K, W_V 생성 → 행렬 곱으로 Q, K, V 계산
- Step 3
- 어텐션 스코어 = Q × Kᵀ → (토큰 수 × 토큰 수)
- Step 4
- ÷ √d_k 스케일링으로 값 안정화
- Step 5
- Softmax → 각 행의 합 = 1인 확률 가중치
- Step 6
- 가중 합 = Weights × V → 문맥이 섞인 출력
차원 추적
- Q, K, V
- (토큰 수, d_k) — 입력과 동일한 크기
- 스코어 행렬
- (토큰 수, 토큰 수) — 모든 쌍의 유사도
- 최종 출력
- (토큰 수, d_k) — 문맥 정보가 반영된 벡터
Softmax 적용 후 각 행의 합은 항상 1 — 총 100%의 주의를 배분한다
시각 자료
핵심 정리
- 16단계로 셀프 어텐션 구현: 입력→Q,K,V→스코어→스케일→Softmax→가중합
- 2핵심 차원: (토큰수, 차원) 유지, 스코어는 (토큰수, 토큰수)
- 3각 토큰의 출력에 다른 토큰들의 정보가 '문맥'으로 섞임
퀴즈와 인터랙션으로 더 깊이 학습하세요
play_circle인터랙티브 레슨 시작