본문 바로가기
C.W.K.
Stream
Lesson 11 of 12 · published

어텐션의 돌파구

~22 min · attention, self-attention, transformer

Level 0호기심
0 XP0/73 lessons0/11 achievements
0/120 XP to next level120 XP to go0% complete

한 문장으로 이해하는 어텐션

어텐션은 값 벡터의 가중평균을 계산해. 가중치는 query 벡터를 key 벡터 집합과 비교해 구하지. 각 출력 위치는 자신에게 중요한 입력에 주목하고, 가중치는 역전파를 통해 처음부터 끝까지 함께 학습돼.

셀프 어텐션은 query, key, 값이 모두 같은 시퀀스에서 나오는 특수한 경우야. 이제 모든 토큰이 다른 모든 토큰을 한 단계에서 직접 볼 수 있어. 순환 구조도, 고정 크기 은닉 상태도 필요 없어. 덕분에 장거리 의존성을 아주 쉽게 표현할 수 있지.

팁: 이 퀘스트 전체에서 논문을 한 편만 읽는다면 'Attention Is All You Need' (Vaswani et al., 2017)를 읽어. 단 8쪽에 모든 현대 LLM을 구동하는 아키텍처가 설명되어 있어.

어텐션 헤드 하나의 수학

Q, K, V가 주어졌고 각각의 형태가 [B, T, d_k]라면 다음과 같이 계산해: attention(Q, K, V) = softmax(Q K^T / sqrt(d_k)) V. sqrt(d_k)는 차원이 커질수록 내적값이 지나치게 커지는 것을 막아. 소프트맥스는 내적값을 입력 토큰에 대한 확률 분포로 바꿔 주지. 결과의 형태는 [B, T, d_k]로, 입력과 같아.

멀티헤드 어텐션

어텐션 헤드 하나는 한 종류의 관계를 학습해. 멀티헤드 어텐션은 여러 헤드를 병렬로 실행하고, 각 헤드가 저마다 Q, K, V 투영을 사용하게 한 뒤 결과를 이어 붙여. 직관적으로 보면, 서로 다른 헤드가 구문, 상호 참조, 위치, 의미 유사성처럼 서로 다른 관계를 하나의 가중치 집합 안에서 경쟁하지 않고 학습할 수 있는 거야.

어텐션을 병렬화할 수 있는 이유

RNN과 달리 어텐션은 모든 위치의 출력을 동시에 계산할 수 있어. 모든 내적이 서로 독립적이기 때문이야. Transformer가 GPU에서 RNN보다 훨씬 빠르게 학습되는 이유가 바로 여기에 있어.

원칙: 어텐션은 지난 10년 동안 등장한 가장 중요한 아키텍처 구성 요소야. 순전파에서 정확히 무엇을 계산하는지, 즉 Q, K, V에서 시작해 소프트맥스를 거쳐 V의 가중합을 구하는 과정을 이해해야 모든 현대 LLM의 토대를 이해할 수 있어.

Code

밑바닥부터 구현하는 스케일드 점곱 어텐션·python
import torch
import torch.nn.functional as F
import math

def scaled_dot_product_attention(Q, K, V, mask=None):
    # Q, K, V: [B, H, T, d_k]
    d_k = Q.size(-1)
    scores = Q @ K.transpose(-2, -1) / math.sqrt(d_k)   # [B, H, T, T]
    if mask is not None:
        scores = scores.masked_fill(mask == 0, float("-inf"))
    weights = F.softmax(scores, dim=-1)                 # [B, H, T, T]
    return weights @ V                                  # [B, H, T, d_k]

# PyTorch has a fused, fast version too
out = F.scaled_dot_product_attention(Q, K, V, attn_mask=None)
nn.MultiheadAttention을 활용한 멀티헤드 어텐션·python
import torch
import torch.nn as nn

mha = nn.MultiheadAttention(embed_dim=512, num_heads=8, batch_first=True)
x = torch.randn(2, 16, 512)            # [B, T, d_model]
out, weights = mha(x, x, x)            # self-attention: q=k=v=x
print(out.shape)                       # [2, 16, 512]
print(weights.shape)                   # [2, 16, 16] averaged over heads

External links

Exercise

Scaled dot-product 어텐션을 직접 구현해 봐. numpy 또는 순수 PyTorch 연산을 사용하고, F.scaled_dot_product_attention는 쓰지 마. 같은 Q, K, V를 넣었을 때 PyTorch 내장 구현과 출력이 일치하는지 확인해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.