728x90
반응형
🎯 Attention이 왜 필요한가?
RNN이나 CNN 기반 모델은 입력을 처리할 때 고정된 창(sliding window) 혹은 순차 구조에 의존합니다.
하지만 실제 데이터(예: 문장)에서는 특정 단어가 멀리 떨어져 있어도 서로 강하게 연관되어 있는 경우가 많습니다.
예: “The cat, which was sitting on the mat, was black.”
여기서 “cat”과 “was black” 사이의 거리는 멀지만 의미적으로 연결돼 있습니다.
Attention Mechanism은 이런 문제를 해결합니다.
모델이 모든 입력을 동시에 바라보며, 어떤 부분에 집중할지 동적으로 판단할 수 있게 해줍니다.
🧠 기본 아이디어
Attention은 입력의 각 토큰(단어)이 다른 모든 토큰을 참조할 수 있도록 만듭니다.
이 과정에서 각 참조에는 **중요도를 나타내는 가중치(score)**가 부여됩니다.
핵심 구조: Scaled Dot-Product Attention
Attention(Q, K, V) = softmax(QKᵀ / √d_k) · V
- Q (Query): 현재 내가 집중하려는 위치
- K (Key): 참조할 모든 위치
- V (Value): 실제로 전달할 정보
- √dₖ: 안정성을 위한 스케일링
📊 작동 예시
- "나는 오늘 아침에 커피를 마셨다."
→ "마셨다"는 동사이며, "커피"라는 명사를 주로 참조해야 의미가 완성됨.
Attention은 각 단어 간의 연관성을 수치화해서
“마셨다 → 커피” 간의 연결에 높은 가중치를 줍니다.
⚙️ 실전 예제 (PyTorch로 Self-Attention 구현)
import torch
import torch.nn as nn
import torch.nn.functional as F
class SelfAttention(nn.Module):
def __init__(self, embed_dim):
super().__init__()
self.embed_dim = embed_dim
self.q_proj = nn.Linear(embed_dim, embed_dim)
self.k_proj = nn.Linear(embed_dim, embed_dim)
self.v_proj = nn.Linear(embed_dim, embed_dim)
self.out_proj = nn.Linear(embed_dim, embed_dim)
def forward(self, x):
# x: (batch_size, seq_len, embed_dim)
Q = self.q_proj(x)
K = self.k_proj(x)
V = self.v_proj(x)
# Scaled dot-product attention
scores = Q @ K.transpose(-2, -1) / (self.embed_dim ** 0.5)
attn_weights = F.softmax(scores, dim=-1)
context = attn_weights @ V
return self.out_proj(context), attn_weights
# 예시 입력
batch_size, seq_len, embed_dim = 2, 5, 32
x = torch.randn(batch_size, seq_len, embed_dim)
attn = SelfAttention(embed_dim)
out, weights = attn(x)
print("Output shape:", out.shape) # (2, 5, 32)
print("Attention weights:", weights[0]) # 첫 번째 샘플의 attention matrix
import torch.nn as nn
import torch.nn.functional as F
class SelfAttention(nn.Module):
def __init__(self, embed_dim):
super().__init__()
self.embed_dim = embed_dim
self.q_proj = nn.Linear(embed_dim, embed_dim)
self.k_proj = nn.Linear(embed_dim, embed_dim)
self.v_proj = nn.Linear(embed_dim, embed_dim)
self.out_proj = nn.Linear(embed_dim, embed_dim)
def forward(self, x):
# x: (batch_size, seq_len, embed_dim)
Q = self.q_proj(x)
K = self.k_proj(x)
V = self.v_proj(x)
# Scaled dot-product attention
scores = Q @ K.transpose(-2, -1) / (self.embed_dim ** 0.5)
attn_weights = F.softmax(scores, dim=-1)
context = attn_weights @ V
return self.out_proj(context), attn_weights
# 예시 입력
batch_size, seq_len, embed_dim = 2, 5, 32
x = torch.randn(batch_size, seq_len, embed_dim)
attn = SelfAttention(embed_dim)
out, weights = attn(x)
print("Output shape:", out.shape) # (2, 5, 32)
print("Attention weights:", weights[0]) # 첫 번째 샘플의 attention matrix
✅ 위 예제는 단일 Self-Attention Block이며,
실제로 Transformer의 핵심 구조로 확장되는 기본 구성 요소입니다.
🔍 Self-Attention vs RNN
항목RNNSelf-Attention
병렬 처리 | ❌ 순차적 | ✅ 완전 병렬 가능 |
장기 의존성 | 약함 | 강함 |
학습 속도 | 느림 | 빠름 |
구조 단순성 | 복잡 | 단순 |
📦 실전 적용 예시
모델Attention 사용 위치
Transformer | Encoder, Decoder 모든 레이어 |
BERT | 입력 전체에 Self-Attention |
GPT | Decoder에 Causal Self-Attention |
ViT (Vision Transformer) | 이미지 패치 사이 Attention |
Stable Diffusion | 이미지 생성 컨트롤 핵심 메커니즘 |
✨ 마무리 요약
- Attention은 입력 내 모든 요소가 서로를 참조하는 방식
- 각 요소에 중요도 가중치를 부여하여 정보 전달
- Self-Attention은 Transformer, GPT, BERT 등 모든 현대 딥러닝 모델의 기반
- 코드로 직접 구현하며 핵심 로직을 이해하는 것이 실무에 매우 유용
728x90
반응형
'AI > AI Info' 카테고리의 다른 글
Layer Normalization: 배치가 아니라, ‘특정 샘플’을 정규화한다 (0) | 2025.06.24 |
---|---|
Residual Connection: 깊은 네트워크도 뚫고 가는 잔차의 힘 (0) | 2025.06.24 |
Gradient Clipping: 기울기 폭주를 막는 딥러닝의 안전장치 (0) | 2025.06.23 |
Weight Initialization: 시작이 엉키면 끝도 엉킨다 (0) | 2025.06.22 |
Activation Function: 딥러닝을 ‘딥’하게 만드는 비선형의 힘 (0) | 2025.06.22 |