검색
← 모듈 로드맵

어텐션만 있으면 된다 (트랜스포머)

논문 · 준전문가 · Ashish Vaswani 외 7명 · 2017 · arXiv

원제 · Attention Is All You Need

순환 없이 어텐션만으로 번역 모델을 만든 트랜스포머 — 스케일드 닷-프로덕트 · 멀티헤드 어텐션 · 위치 인코딩의 수식과 의미

먼저 알아야 할 것

seq2seq바다나우 어텐션레이어 정규화잔차 연결

초록

저자가 쓴 초록을 옮긴 것입니다.

지금까지 시퀀스 변환에서 주로 쓰인 모델은 인코더-디코더 구조의 복잡한 순환 신경망이나 합성곱 신경망이었습니다. 가장 성능이 좋은 모델은 여기에 어텐션 메커니즘으로 인코더와 디코더를 잇습니다. 이 논문은 순환과 합성곱을 완전히 버리고 어텐션 메커니즘만으로 이루어진 새롭고 단순한 신경망 구조, 트랜스포머를 제안합니다. 두 기계 번역 과제에서 실험한 결과, 이 모델은 번역 품질이 더 뛰어나면서도 병렬화가 더 잘 되고 학습 시간이 크게 줄었습니다. WMT 2014 영어→독일어 번역에서 28.4 BLEU를 기록해, 앙상블을 포함한 기존 최고 결과보다 2 BLEU 넘게 앞섰습니다. WMT 2014 영어→프랑스어 번역에서는 GPU 8개로 3.5일 학습해 단일 모델 최고 기록인 41.8 BLEU를 세웠는데, 이는 기존 문헌의 최고 모델들이 쓴 학습 비용의 일부에 불과합니다. 또한 학습 데이터가 많을 때와 적을 때 모두 영어 구문 분석에 성공적으로 적용해, 트랜스포머가 다른 과제에도 잘 일반화됨을 보였습니다.

해설

어텐션만 있으면 된다 (트랜스포머)

문장을 한 단어씩 차례로 읽던 번역 모델을 버리고, 모든 단어가 서로를 한 번에 바라보는 '어텐션'만으로 번역 모델을 만든 논문입니다. 더 빨리 학습하면서 더 잘 번역했고, 지금 쓰는 거의 모든 대형 언어 모델(Claude · GPT · Gemini)의 뼈대가 되었습니다.

항목내용
원제Attention Is All You Need
저자Ashish Vaswani 외 7명 (Google Brain · Google Research · 토론토대)
발표2017 · NeurIPS · arXiv 1706.03762
트랙 · 수준NLP·트랜스포머 · 중급
먼저 알면 좋은 것행렬 곱 · 소프트맥스, seq2seq, 바다나우 어텐션, 레이어 정규화, 잔차 연결

들어가기 전에

이 해설은 아래 내용을 안다고 보고 씁니다. 처음이라면 먼저 읽고 오면 수식과 손계산을 훨씬 쉽게 따라올 수 있습니다.

한눈에 보기

  • 왜 예전 번역 모델(RNN)은 느리고, 멀리 떨어진 단어 관계를 잘 못 배웠는지
  • 어텐션 공식 softmax(QK⊤/dk) V\mathrm{softmax}(QK^\top/\sqrt{d_k})\,V 가 실제로 무엇을 계산하는지 — 작은 숫자로 직접 계산해 봅니다
  • 왜 dk\sqrt{d_k} 로 나누는지, 왜 헤드를 여러 개 쓰는지, 순서 정보는 어떻게 넣는지
  • 트랜스포머 한 층이 RNN 한 층보다 왜 빠른지
  • 이 구조가 BERT · GPT · 오늘날의 LLM으로 어떻게 이어졌는지

초록 (번역)

지금까지 시퀀스 변환에서 주로 쓰인 모델은 인코더-디코더 구조의 복잡한 순환 신경망이나 합성곱 신경망이었습니다. 가장 성능이 좋은 모델은 여기에 어텐션 메커니즘으로 인코더와 디코더를 잇습니다. 이 논문은 순환과 합성곱을 완전히 버리고 어텐션 메커니즘만으로 이루어진 새롭고 단순한 신경망 구조, 트랜스포머를 제안합니다. 두 기계 번역 과제에서 실험한 결과, 이 모델은 번역 품질이 더 뛰어나면서도 병렬화가 더 잘 되고 학습 시간이 크게 줄었습니다. WMT 2014 영어→독일어 번역에서 28.4 BLEU를 기록해, 앙상블을 포함한 기존 최고 결과보다 2 BLEU 넘게 앞섰습니다. WMT 2014 영어→프랑스어 번역에서는 GPU 8개로 3.5일 학습해 단일 모델 최고 기록인 41.8 BLEU를 세웠는데, 이는 기존 문헌의 최고 모델들이 쓴 학습 비용의 일부에 불과합니다. 또한 학습 데이터가 많을 때와 적을 때 모두 영어 구문 분석에 성공적으로 적용해, 트랜스포머가 다른 과제에도 잘 일반화됨을 보였습니다.

무엇을 풀었나

예전 방식: 한 단어씩 차례로

2017년 이전 번역 모델은 대부분 RNN(순환 신경망)이나 LSTM을 쓴 seq2seq 구조였습니다. "나는 학교에 간다"를 읽을 때 '나는'을 읽고 기억을 만들고, 그 기억을 들고 '학교에'를 읽고, 다시 그 기억을 들고 '간다'를 읽는 식입니다.

비유하면 전화 돌리기 게임입니다. 첫 사람의 말이 마지막 사람에게 가려면 모든 사람을 거쳐야 합니다.

이 방식에는 두 가지 문제가 있었습니다.

  1. 느립니다. tt번째 단어의 기억 hth_t를 만들려면 바로 앞 기억 ht−1h_{t-1}이 먼저 있어야 합니다. 그래서 GPU가 수천 개의 계산을 동시에 할 수 있어도, 단어 순서대로 하나씩 기다려야 합니다.
  2. 멀리 떨어진 단어 관계를 잘 못 배웁니다. 50번째 단어가 1번째 단어를 참고하려면 정보가 49단계를 거쳐 와야 하고, 그 사이에 흐려집니다. 학습 신호(기울기)도 같은 길을 거꾸로 가야 해서 약해집니다.

이 논문의 질문

어텐션은 이미 쓰이고 있었습니다(바다나우 어텐션, 2014). 다만 RNN에 덧붙이는 장치였습니다. 이 논문은 "RNN을 아예 빼고 어텐션만 남기면 어떨까?"를 물었습니다. 그러면 모든 단어를 동시에 처리할 수 있고, 어느 두 단어든 한 번에 연결됩니다.

전체 흐름

mermaid
flowchart LR
  A[입력 문장 단어들] --> B[단어 임베딩 + 위치 인코딩]
  B --> C[인코더 블록 x 6<br/>셀프 어텐션 → 피드포워드]
  C --> D[인코더 출력<br/>문장 전체의 의미]
  E[지금까지 만든 번역 단어들] --> F[임베딩 + 위치 인코딩]
  F --> G[디코더 블록 x 6<br/>가린 셀프 어텐션 → 인코더-디코더 어텐션 → 피드포워드]
  D --> G
  G --> H[다음 단어 확률]

인코더가 원문 문장 전체를 읽어 의미를 만들고, 디코더가 그 의미를 보면서 번역 단어를 하나씩 만듭니다. 학습할 때는 디코더도 모든 위치를 한 번에 계산합니다(뒤쪽 정답은 가려 둡니다).

핵심 아이디어

1. 스케일드 닷-프로덕트 어텐션 — "누구를 얼마나 참고할까"

직관. 도서관에서 책을 찾는 장면을 떠올리면 쉽습니다. 내가 찾는 주제가 질의(Query), 책 등에 붙은 분류표가 키(Key), 책 내용이 값(Value)입니다. 질의와 분류표가 잘 맞는 책일수록 그 내용을 많이 가져옵니다.

단계별로.

  1. 각 단어 벡터에서 세 가지를 만듭니다: 질의 qq, 키 kk, 값 vv. (학습되는 행렬 WQ,WK,WVW^Q, W^K, W^V를 곱해서 만듭니다.)
  2. 지금 단어의 qq와 모든 단어의 kk를 내적합니다. 내적이 클수록 "관련이 높다"는 뜻입니다.
  3. 점수를 dk\sqrt{d_k}로 나눕니다(이유는 아래).
  4. 소프트맥스로 점수를 합이 1인 비율로 바꿉니다.
  5. 그 비율대로 값 vv들을 섞습니다. 이것이 그 단어의 새 표현입니다.

문장 전체를 행렬로 쌓으면 위 다섯 단계가 한 줄로 끝납니다.

Attention(Q,K,V)=softmax ⁣(QK⊤dk)V\mathrm{Attention}(Q, K, V) = \mathrm{softmax}\!\left(\frac{QK^\top}{\sqrt{d_k}}\right) V
기호뜻크기
QQ질의를 단어 수만큼 쌓은 행렬n×dkn \times d_k
KK키를 쌓은 행렬m×dkm \times d_k
VV값을 쌓은 행렬m×dvm \times d_v
QK⊤QK^\topii번째 단어가 jj번째 단어를 보는 점수표n×mn \times m
dkd_k질의 · 키 벡터의 차원 수숫자 하나
softmax\mathrm{softmax}각 행을 합이 1인 비율로 바꾸는 함수—

숫자로 해 보기 (해설용 예시, 논문 수치 아님). 단어 3개, dk=2d_k = 2라고 해 봅시다.

  • 키: k1=(1,0)k_1 = (1, 0), k2=(0,1)k_2 = (0, 1), k3=(1,1)k_3 = (1, 1)
  • 값: v1=(1,0)v_1 = (1, 0), v2=(0,2)v_2 = (0, 2), v3=(3,1)v_3 = (3, 1)
  • 1번 단어의 질의: q=(1,0)q = (1, 0)
  1. 내적: q⋅k1=1q\cdot k_1 = 1, q⋅k2=0q\cdot k_2 = 0, q⋅k3=1q\cdot k_3 = 1
  2. 2≈1.414\sqrt{2} \approx 1.414로 나누기: 0.707, 0, 0.7070.707,\ 0,\ 0.707
  3. 소프트맥스: e0.707≈2.028e^{0.707} \approx 2.028, e0=1e^{0} = 1 이므로 합은 5.0565.056 → 비율 0.401, 0.198, 0.4010.401,\ 0.198,\ 0.401
  4. 값 섞기: 0.401 (1,0)+0.198 (0,2)+0.401 (3,1)=(1.604, 0.797)0.401\,(1,0) + 0.198\,(0,2) + 0.401\,(3,1) = (1.604,\ 0.797)

1번 단어는 자기와 키가 비슷한 1번 · 3번 단어를 많이 참고하고, 2번 단어는 적게 참고했습니다. 결과 벡터 (1.604,0.797)(1.604, 0.797)이 "문맥을 반영한 1번 단어"입니다.

왜 dk\sqrt{d_k}로 나누나. qq와 kk의 각 성분이 평균 0, 분산 1인 값이라면, 내적 q⋅k=∑i=1dkqikiq \cdot k = \sum_{i=1}^{d_k} q_i k_i는 dkd_k개를 더한 것이라 분산이 dkd_k가 됩니다. 논문 기본값 dk=64d_k = 64면 점수의 표준편차가 8이나 됩니다. 점수 차이가 이렇게 크면 소프트맥스가 거의 한 단어에만 1을 주고 나머지에 0을 줘서, 학습 신호(기울기)가 거의 사라집니다. 64=8\sqrt{64} = 8로 나누면 표준편차가 다시 1 근처로 돌아옵니다.

왜 이 방식을 골랐나. 논문은 점수를 작은 신경망으로 계산하는 '덧셈 어텐션'도 비교합니다. 내적 방식은 행렬 곱 한 번이면 끝나서 GPU에서 훨씬 빠르고 메모리도 덜 씁니다. 대신 차원이 크면 위의 쏠림 문제가 생기므로 dk\sqrt{d_k}로 나눈 것입니다.

2. 멀티헤드 어텐션 — "여러 관점으로 동시에 보기"

직관. 한 문장을 읽을 때 사람은 여러 관계를 함께 봅니다. "누가 했나(주어-동사)", "무엇을(목적어)", "그것이 가리키는 것(대명사)". 어텐션 한 번은 한 가지 관점에 치우치기 쉬워서, 관점을 여러 개(헤드) 두고 각각 따로 어텐션한 뒤 결과를 합칩니다.

단계별로.

  1. Q,K,VQ, K, V를 헤드마다 다른 행렬로 작은 공간에 투영합니다.
  2. 헤드마다 어텐션을 따로 계산합니다.
  3. 결과를 이어 붙이고, 행렬 WOW^O로 원래 크기로 되돌립니다.
MultiHead(Q,K,V)=Concat(head1,…,headh) WO,headi=Attention(QWiQ, KWiK, VWiV)\mathrm{MultiHead}(Q,K,V) = \mathrm{Concat}(\mathrm{head}_1, \dots, \mathrm{head}_h)\,W^O, \quad \mathrm{head}_i = \mathrm{Attention}(QW_i^Q,\, KW_i^K,\, VW_i^V)
기호뜻
hh헤드 수 (논문 기본 모델은 8)
WiQ,WiK,WiVW_i^Q, W_i^K, W_i^Vii번째 헤드가 쓰는 투영 행렬
WOW^O이어 붙인 결과를 되돌리는 행렬
dmodeld_{\text{model}}모델 전체의 표현 차원 (기본 512)

숫자로 보면. 기본 모델은 dmodel=512d_{\text{model}} = 512를 헤드 8개로 나눠, 헤드마다 dk=dv=512/8=64d_k = d_v = 512 / 8 = 64차원을 씁니다. 큰 어텐션 한 번을 작은 어텐션 8번으로 쪼갠 셈이라, 전체 계산량은 비슷하면서 관점은 8개가 됩니다.

3. 인코더 · 디코더 블록 — "어텐션 + 작은 신경망, 그리고 지름길"

직관. 블록 하나는 "주변 단어를 둘러보고(어텐션) → 혼자 생각을 정리하는(피드포워드)" 두 단계입니다. 이 블록을 여러 층 쌓을수록 더 복잡한 관계를 표현합니다.

인코더 블록 (6층).

  1. 셀프 어텐션: 원문 단어들이 서로를 봅니다.
  2. 피드포워드: 단어마다 따로 같은 작은 신경망을 통과합니다.

디코더 블록 (6층).

  1. 가린(masked) 셀프 어텐션: 지금까지 만든 번역 단어들이 서로를 봅니다. 아직 만들지 않은 뒤쪽 단어는 못 보게 점수에 −∞-\infty를 더합니다(소프트맥스 후 0이 됨). 시험 볼 때 답안지 뒤쪽을 가리는 것과 같습니다.
  2. 인코더-디코더 어텐션: 번역 단어(질의)가 원문 단어들(키 · 값)을 봅니다. "이 번역어를 만들려면 원문의 어디를 봐야 하나"입니다.
  3. 피드포워드.

모든 단계를 감싸는 두 장치.

출력=LayerNorm(x+Sublayer(x))\text{출력} = \mathrm{LayerNorm}\big(x + \mathrm{Sublayer}(x)\big)
  • 잔차 연결(x+x +): 입력을 출력에 그대로 더하는 지름길입니다. 층이 깊어져도 정보와 기울기가 지름길로 잘 흐릅니다.
  • 레이어 정규화: 값의 크기를 일정하게 맞춰 학습을 안정시킵니다.

피드포워드 신경망.

FFN(x)=max⁡(0, xW1+b1) W2+b2\mathrm{FFN}(x) = \max(0,\, xW_1 + b_1)\, W_2 + b_2

512512차원을 dff=2048d_{ff} = 2048차원으로 넓혔다가(ReLU를 거쳐) 다시 512512로 줄입니다. 넓은 공간에서 잠깐 생각을 펼쳤다가 정리하는 단계라고 보면 됩니다.

4. 위치 인코딩 — "순서 정보를 숫자로 붙이기"

직관. 어텐션은 단어를 '봉지에 담긴 낱말들'처럼 다뤄서, 순서를 모릅니다. "개가 사람을 문다"와 "사람이 개를 문다"를 구별하지 못합니다. 그래서 단어마다 자리 번호표를 붙입니다. 번호표는 숫자 하나가 아니라, 여러 주기의 사인 · 코사인 물결로 만든 벡터입니다. 시계의 초침 · 분침 · 시침이 각자 다른 속도로 돌아서 그 조합만 보면 시각을 알 수 있는 것과 같습니다.

PE(pos, 2i)=sin⁡ ⁣(pos100002i/dmodel),PE(pos, 2i+1)=cos⁡ ⁣(pos100002i/dmodel)PE_{(pos,\,2i)} = \sin\!\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right), \qquad PE_{(pos,\,2i+1)} = \cos\!\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right)
기호뜻
pospos단어 위치 (0, 1, 2, …)
ii차원 번호의 절반 (짝수 차원은 사인, 홀수 차원은 코사인)
100002i/dmodel10000^{2i/d_{\text{model}}}차원마다 다른 물결의 길이. 앞 차원은 빠르게, 뒤 차원은 느리게 변함

숫자로 해 보기 (해설용, dmodel=4d_{\text{model}} = 4로 축소). 위치 pos=1pos = 1이면

  • i=0i = 0: sin⁡(1)≈0.841\sin(1) \approx 0.841, cos⁡(1)≈0.540\cos(1) \approx 0.540
  • i=1i = 1: 분모가 100002/4=10010000^{2/4} = 100이므로 sin⁡(0.01)≈0.010\sin(0.01) \approx 0.010, cos⁡(0.01)≈1.000\cos(0.01) \approx 1.000

→ 위치 1의 번호표는 (0.841, 0.540, 0.010, 1.000)(0.841,\ 0.540,\ 0.010,\ 1.000)이고, 이 벡터를 단어 임베딩에 더합니다.

왜 이 방식을 골랐나. 논문은 위치마다 벡터를 학습하는 방식도 시험했는데 결과가 거의 같았다고 보고합니다. 사인 · 코사인을 고른 이유는, 학습 때보다 긴 문장에도 적용할 수 있을 것이라는 기대 때문이라고 밝힙니다. 또 고정된 거리 kk만큼 떨어진 위치의 번호표 PEpos+kPE_{pos+k}를 PEposPE_{pos}의 선형 변환으로 나타낼 수 있어, 모델이 "몇 칸 떨어졌나"를 배우기 쉽습니다.

5. 왜 빠른가 — 층 하나의 비용 비교

층 종류층당 계산량순차로 해야 하는 연산 수가장 먼 두 단어 사이 경로
셀프 어텐션O(n2⋅d)O(n^2 \cdot d)O(1)O(1)O(1)O(1)
순환(RNN)O(n⋅d2)O(n \cdot d^2)O(n)O(n)O(n)O(n)
합성곱O(k⋅n⋅d2)O(k \cdot n \cdot d^2)O(1)O(1)O(log⁡kn)O(\log_k n)

(nn: 문장 길이, dd: 표현 차원, kk: 합성곱 커널 크기)

읽는 법.

  • 순차 연산 수: RNN은 nn번 차례로 기다려야 하지만, 셀프 어텐션은 한 번에 모두 계산합니다. GPU를 꽉 채워 쓸 수 있는 이유입니다.
  • 경로 길이: 셀프 어텐션은 어느 두 단어든 한 번에 연결합니다. 전화 돌리기 대신 단체 대화방에 모두 들어와 있는 셈입니다.
  • 계산량: 셀프 어텐션은 n2n^2에 비례해, 문장이 길어지면 비싸집니다. 번역 문장은 보통 nn이 dd(512)보다 짧아서 이 논문에서는 오히려 더 쌌습니다.

6. 학습 설정 (논문 기준)

  • 옵티마이저 Adam(β1=0.9\beta_1 = 0.9, β2=0.98\beta_2 = 0.98, ϵ=10−9\epsilon = 10^{-9})
  • 학습률은 처음 4,000단계 동안 직선으로 늘렸다가, 이후 단계 수의 제곱근에 반비례해 줄입니다.
lr=dmodel−0.5⋅min⁡ ⁣(step−0.5, step⋅warmup−1.5)\text{lr} = d_{\text{model}}^{-0.5} \cdot \min\!\left(\text{step}^{-0.5},\ \text{step} \cdot \text{warmup}^{-1.5}\right)

처음부터 큰 학습률을 쓰면 아직 엉성한 모델이 크게 흔들리기 때문에, 천천히 올렸다가 내리는 '워밍업'을 둡니다.

  • 정규화: 드롭아웃 0.1, 라벨 스무딩 0.1 (정답에 100% 확신하지 않도록 조금 덜어 두는 기법)
  • 학습 시간: 기본 모델은 P100 GPU 8개로 약 12시간, 큰 모델은 3.5일

결과

  • WMT 2014 영어→독일어: 큰 모델 28.4 BLEU. 앙상블을 포함한 기존 최고보다 2 BLEU 넘게 높았습니다.
  • WMT 2014 영어→프랑스어: 큰 모델 41.8 BLEU(단일 모델 최고), GPU 8개로 3.5일 학습.
  • 영어 구문 분석에도 적용해, 번역 밖 과제에서도 잘 작동함을 보였습니다.

BLEU는 기계 번역이 사람 번역과 단어 조각이 얼마나 겹치는지 재는 점수로, 높을수록 좋습니다.

왜 중요한가 · 이후 영향

  • 대형 언어 모델의 뼈대: BERT는 인코더만, GPT 계열은 디코더만 가져다 썼습니다. 오늘날 Claude · GPT · Gemini도 이 블록을 바탕으로 합니다.
  • 규모를 키울 수 있게 됐습니다: 순차 계산이 사라져 큰 모델을 많은 데이터로 학습할 수 있게 됐고, 이것이 스케일링 법칙 연구로 이어졌습니다.
  • 언어 밖으로 퍼졌습니다: 이미지(ViT) · 음성 · 단백질 구조 · 강화학습(결정 트랜스포머)까지 같은 블록을 씁니다.

한계 · 주의할 점

  • 긴 문맥이 비쌉니다. 셀프 어텐션은 길이 nn에 대해 O(n2)O(n^2) 계산 · 메모리가 듭니다. 문서 전체나 긴 대화를 다루려면 플래시어텐션 · 희소 어텐션 · Mamba 같은 후속 연구가 필요해졌습니다.
  • 순서 정보는 덧붙인 것입니다. 위치 인코딩 방식은 이후 상대 위치 · 회전 위치(RoPE) 등으로 계속 바뀌었습니다.
  • 이 논문은 번역 모델입니다. 지금의 LLM은 디코더만 쓰고, 사전학습 · 지시 학습 · 정렬 단계가 더해진 것입니다. 이 논문만으로 LLM이 완성된 것은 아닙니다.

이어서 읽을 것

용어 정리

용어쉬운 뜻
시퀀스 변환단어 열을 다른 단어 열로 바꾸는 일 (번역 · 요약 등)
인코더 · 디코더입력을 읽어 의미로 바꾸는 쪽 · 그 의미로 출력을 만드는 쪽
임베딩단어를 숫자 벡터로 바꾼 것
셀프 어텐션같은 문장 안의 단어들끼리 서로를 참고하는 어텐션
소프트맥스점수들을 0~1 사이, 합이 1인 비율로 바꾸는 함수
잔차 연결입력을 출력에 그대로 더하는 지름길
레이어 정규화한 층의 값 크기를 일정하게 맞추는 처리
BLEU기계 번역 품질 점수 (높을수록 좋음)

스스로 점검

  1. RNN 번역 모델이 느렸던 가장 큰 이유는? — hth_t를 계산하려면 ht−1h_{t-1}이 있어야 해서, 단어 순서대로 하나씩 계산해야 했기 때문입니다.
  2. dk\sqrt{d_k}로 나누지 않으면 무슨 일이 생기나? — 차원이 클수록 내적 값의 분산이 커져 소프트맥스가 한 단어에 쏠리고, 기울기가 거의 0이 되어 학습이 잘 안 됩니다.
  3. 위치 인코딩이 없으면? — 어텐션은 단어 순서를 모르기 때문에, 같은 단어로 이루어진 다른 순서의 문장을 구별하지 못합니다.

다음에 볼 것

이 글을 이해했다면 이어서 보면 좋은 항목입니다.

출처

AI 원리부터 이해하기 · NLP·트랜스포머 모듈

NLP·트랜스포머 모듈 학습

이 글은 NLP·트랜스포머 모듈의 학습 자료입니다. 전체 23개 자료 중 12번째입니다.

AI 기초 과정은 현재 진도 저장을 지원하지 않습니다.

출처·원문

원문 보기

요약만

arXiv (논문별 상이)

arXiv 1706.03762