밑바닥부터 만드는 mini GPT 공부 시리즈 3편
embedding까지 끝나면 각 토큰은 벡터가 된다. 하지만 벡터가 되었다고 해서 문맥을 이해하는 것은 아니다. 각 위치의 토큰이 앞뒤 토큰과 어떤 관계를 맺는지 계산해야 한다.
self-attention은 같은 문장 안의 토큰들이 서로를 참고하는 방식이다. GPT에서는 여기에 causal mask가 붙어서 현재 토큰이 미래 토큰을 보지 못하게 만든다.
이번 글에서 다루는 것
- attention이 “어떤 토큰을 얼마나 참고할지” 정하는 방식
- Query, Key, Value를 너무 어렵게 보지 않는 방법
- causal mask가 왜 다음 토큰 예측에서 필수인지
- attention score, softmax, weighted sum의 흐름
1. Attention은 참고 비율을 계산한다
문장 안의 각 토큰은 혼자 의미를 가지지 않는다. “좋았다”라는 토큰은 앞에 “영화가”, “정말” 같은 토큰이 있을 때 더 분명해진다. attention은 현재 위치가 다른 위치를 얼마나 참고할지 비율을 계산한다.
실제 값은 사람이 정하지 않는다. Query와 Key의 유사도를 계산하고 softmax를 통과시켜 비율로 만든다.
현재 토큰의 score
영화가: 1.0
정말: 2.0
좋았다: 2.4
softmax 뒤 참고 비율
영화가: 0.12
정말: 0.33
좋았다: 0.55
score는 비교용 점수이고, softmax 뒤의 값은 합이 1인 참고 비율이다. 이 비율로 Value를 섞으면 현재 위치의 문맥 벡터가 된다.
2. Query, Key, Value는 역할 이름이다
Query, Key, Value라는 이름 때문에 처음에는 어렵게 느껴진다. 하지만 구현 관점에서는 같은 입력 벡터를 세 개의 다른 선형층에 통과시킨 결과다.
| 이름 | 직관 | 계산에서 하는 일 |
|---|---|---|
| Query | 내가 찾고 싶은 기준 | Key와 점곱해 attention score를 만듦 |
| Key | 각 토큰이 가진 검색용 표지 | Query와 얼마나 맞는지 비교됨 |
| Value | 실제로 가져올 정보 | attention weight와 곱해져 문맥 벡터가 됨 |
3. Causal mask는 미래 정답을 가린다
GPT는 다음 토큰을 맞히는 모델이다. 그런데 학습 중 현재 위치가 미래 토큰을 볼 수 있다면, 정답을 미리 훔쳐보는 셈이 된다. causal mask는 이 부정행위를 막는다.
| 토큰 0 | 보기 가능 | 가림 | 가림 | 가림 |
| 토큰 1 | 보기 가능 | 보기 가능 | 가림 | 가림 |
| 토큰 2 | 보기 가능 | 보기 가능 | 보기 가능 | 가림 |
구현에서는 보통 현재 위치보다 오른쪽 위 영역을 `-inf`로 채운다. 그러면 softmax를 통과한 뒤 그 위치의 확률이 0에 가까워진다.
attention 흐름 요약
x
-> Q, K, V
-> Q @ K.T / sqrt(head_dim)
-> causal mask
-> softmax
-> attention weight @ V
-> context vector
헷갈리기 쉬운 구분
- score는 아직 확률이 아니다. softmax 전의 비교 점수다.
- mask는 Value를 지우는 것이 아니라 score 단계에서 미래 위치를 막는다.
- 최종 출력은 attention weight 자체가 아니라, 그 weight로 Value를 섞은 벡터다.
스스로 점검
- Value는 언제 사용되는가?
- causal mask가 없다면 train loss는 좋아 보일 수 있지만 왜 위험한가?
- attention score를 softmax에 넣는 이유는 무엇인가?
다음 글 예고
다음 글에서는 여러 개의 attention head를 병렬로 사용하는 Multi-Head Attention을 정리한다.
한 줄 정리: self-attention은 문맥 안에서 참고 비율을 계산하고, causal mask는 현재 토큰이 미래 정답을 보지 못하게 막는다.