
📓Google Colab에서 실습하기
이 레슨은 PyTorch/GPU가 필요합니다. 노트북을 다운로드 후 Google Colab에서 열어주세요.
학습 내용
Self-Attention - Transformer의 핵심 엔진
학습 목표
이 레슨을 완료하면:
- •Self-Attention이 무엇이고 왜 "Self"인지 설명할 수 있다
- •Query, Key, Value의 역할을 일상적 비유로 설명할 수 있다
- •Attention Score 계산 과정을 단계별로 이해한다
- •Scaled Dot-Product Attention 공식을 numpy로 직접 구현할 수 있다
- •Softmax와 스케일링이 왜 필요한지 설명할 수 있다
핵심 메시지
"Self-Attention은 문장 속 각 단어가 다른 모든 단어에게 질문하는 것이다." "나와 가장 관련 있는 단어는 누구야?"라고 물어보고, 관련 있는 단어의 정보를 더 많이 가져옵니다.
Self-Attention이란?
"Self"의 의미
"Self-Attention"에서 "Self"란 같은 문장 안에서 자기들끼리 서로를 참조한다는 뜻입니다.
| 종류 | 설명 | 예시 |
|---|---|---|
| Cross-Attention | 두 개의 서로 다른 시퀀스 | 영어 문장이 한국어 문장을 참조 |
| Self-Attention | 하나의 시퀀스 안에서 서로 참조 | "먹었다"가 "사과를"과 "나는"을 참조 |
비유: 교실에서 질문하기
비유: 교실에 학생들이 앉아 있습니다. 선생님이 "서로에게 질문해서 관련 있는 정보를 모아보세요"라고 합니다.
📝 문장: "고양이가 생선을 먹었다"
| "먹었다"가 질문 | 상대방 대답 | 관련도 |
|---|---|---|
| "고양이가"에게 | "응, 나는 주어야!" | 🟡 높음 |
| "생선을"에게 | "응, 나는 목적어야!" | 🟢 매우 높음 |
| 자기 자신에게 | "나는 나지..." | ⚪ 보통 |
💡 결과: "먹었다"는 "생선을"에서 가장 많은 정보를 가져옵니다.
이것이 Self-Attention의 핵심입니다. 모든 단어가 동시에 이 과정을 수행합니다.
Query, Key, Value 이해하기
비유: 도서관 검색 시스템
📚 도서관 검색과 Self-Attention의 유사성
| 요소 | Self-Attention | 도서관 비유 |
|---|---|---|
| Query | 질문 벡터 | 검색창에 입력하는 검색어 |
| Key | 키 벡터 | 각 책의 제목과 키워드 |
| Value | 값 벡터 | 각 책의 실제 내용 |
💡 원리: Query와 Key를 비교 → 관련도가 높은 Value를 더 많이 가져옴
| 요소 | 역할 | 비유 |
|---|---|---|
| Query (Q) | "나는 무엇을 찾고 있나?" | 검색어 |
| Key (K) | "나는 어떤 정보를 제공할 수 있나?" | 책 제목 |
| Value (V) | "내가 가진 실제 정보" | 책 내용 |
핵심: 같은 입력(X)에서 Q, K, V 세 가지를 모두 만듭니다.
는 학습 가능한 파라미터입니다.
Attention Score 계산 - 단계별 설명
전체 과정
- •와 의 내적 → 유사도 점수 행렬
- •로 나누기 → 스케일링 (값 안정화)
- •softmax 적용 → 확률 분포로 변환
- •확률과 를 곱하기 → 최종 출력
스케일링이 필요한 이유
차원이 커지면 내적 값도 커져서 softmax가 극단적으로 됩니다:
| 스케일링 전 | softmax 결과 | 문제 |
|---|---|---|
| 너무 극단적! | ||
| 적절 |
해결: 로 나누어 값의 범위를 안정화합니다.
실행해보기: numpy로 Self-Attention 직접 구현
pythonimport numpy as np np.random.seed(42) words = ["고양이가", "생선을", "먹었다"] seq_len, d_model, d_k = 3, 4, 3 X = np.random.randn(seq_len, d_model) print("===== 입력 임베딩 X =====") for i, word in enumerate(words): print(f" {word}: {np.round(X[i], 3)}") # 단계 1: Q, K, V 생성 W_Q = np.random.randn(d_model, d_k) * 0.5 W_K = np.random.randn(d_model, d_k) * 0.5 W_V = np.random.randn(d_model, d_k) * 0.5 Q, K, V = X @ W_Q, X @ W_K, X @ W_V print() print(f" Q 크기: {Q.shape}, K 크기: {K.shape}, V 크기: {V.shape}") # 단계 2: Attention Score scores = Q @ K.T print() print(f"===== Attention Score (스케일링 전) =====") print(f" {np.round(scores, 3)}") # 단계 3: 스케일링 scaled_scores = scores / np.sqrt(d_k) print() print(f"===== 스케일링 후 (/ sqrt({d_k})) =====") print(f" {np.round(scaled_scores, 3)}") # 단계 4: 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(scaled_scores) print() print(f"===== Attention 가중치 (softmax) =====") header = " " + " ".join(f"{w:>8}" for w in words) print(header) for i, word in enumerate(words): row = f" {word:>8} " + " ".join(f"{attention_weights[i,j]:>8.4f}" for j in range(seq_len)) print(row) # 단계 5: 가중 합계 output = attention_weights @ V print() print(f"===== 최종 출력 =====") for i, word in enumerate(words): max_idx = np.argmax(attention_weights[i]) print(f" {word} → 가장 주목: {words[max_idx]} ({attention_weights[i, max_idx]:.1%})")
Self-Attention이 문맥을 이해하는 방법
동음이의어 해결
예문 1: "나는 은행에 돈을 맡겼다"
- •"은행": "돈", "맡겼다"에 주목 → 금융기관 의미
예문 2: "나는 강 은행에 앉았다"
- •"은행": "강", "앉았다"에 주목 → 강가 의미
같은 단어도 주변 문맥에 따라 다른 표현을 갖게 됩니다!
대명사 해석
예문 1: "The cat sat on the mat because it was tired."
- •"it" → "cat"에 높은 가중치 (피곤한 것은 고양이)
예문 2: "The cat sat on the mat because it was soft."
- •"it" → "mat"에 높은 가중치 (부드러운 것은 매트)
Self-Attention의 장점과 약점
| 장점 | 설명 | 비교 |
|---|---|---|
| 장거리 의존성 | 멀리 떨어진 단어도 직접 연결 | RNN은 거리에 따라 정보 희석 |
| 병렬 처리 | 모든 위치를 동시에 계산 | RNN은 순차 처리 필수 |
| 해석 가능성 | Attention 가중치로 판단 근거 확인 | RNN은 해석 어려움 |
| 유연한 문맥 | 같은 단어도 문맥에 따라 다른 표현 | 고정 임베딩은 항상 같은 벡터 |
약점: O(n^2) 계산 복잡도
| 문장 길이 | 연산 수 |
|---|---|
| 100 | 10,000 |
| 1,000 | 1,000,000 |
| 10,000 | 100,000,000 |
문장이 10배 길어지면 계산량은 100배 증가! 해결: Sparse Attention, Linear Attention, Flash Attention 등
PyTorch로 보는 Self-Attention (참고용)
import torch
import torch.nn as nn
import torch.nn.functional as F
class SelfAttention(nn.Module):
def __init__(self, d_model, d_k):
super().__init__()
self.d_k = d_k
self.W_Q = nn.Linear(d_model, d_k)
self.W_K = nn.Linear(d_model, d_k)
self.W_V = nn.Linear(d_model, d_k)
def forward(self, x):
Q, K, V = self.W_Q(x), self.W_K(x), self.W_V(x)
scores = torch.matmul(Q, K.transpose(-2, -1)) / (self.d_k ** 0.5)
attn_weights = F.softmax(scores, dim=-1)
return torch.matmul(attn_weights, V), attn_weights
핵심 요약
| 개념 | 설명 | 비유 |
|---|---|---|
| Self-Attention | 같은 문장 내 단어들이 서로 참조 | 교실에서 서로에게 질문 |
| Query (Q) | 현재 단어의 질문 | 검색어 |
| Key (K) | 각 단어의 명함 | 책 제목 |
| Value (V) | 각 단어의 실제 정보 | 책 내용 |
| 스케일링 | 로 나누어 값 안정화 | 점수 범위 조절 |
핵심 공식:
학습 체크리스트
- • Self-Attention에서 "Self"가 의미하는 바를 설명할 수 있다
- • Q, K, V 각각의 역할을 비유로 설명할 수 있다
- • 스케일링이 필요한 이유를 설명할 수 있다
- • numpy 데모의 각 단계를 이해했다
다음 레슨: Multi-Head Attention - 여러 전문가가 각기 다른 관점에서 분석하는 원리를 배웁니다.
레슨 정보
- 레벨
- Level 7: Transformer & LLM 원리
- 예상 소요 시간
- 50분
- 참고 영상
- YouTube 링크
💡실습 환경 안내
이 레벨은 PyTorch/GPU가 필요하여 Google Colab 사용을 권장합니다.
Colab은 무료 GPU를 제공하여 PyTorch, CNN, Transformer 등을 실행할 수 있습니다.