Artificial Intelligence/논문 리뷰

Attention Is All You Need (NIPS 2017)

dew₍ᐢ.ˬ.⑅ᐢ₎ 2025. 6. 20. 18:03

https://arxiv.org/abs/1706.03762

 

Attention Is All You Need

The dominant sequence transduction models are based on complex recurrent or convolutional neural networks in an encoder-decoder configuration. The best performing models also connect the encoder and decoder through an attention mechanism. We propose a new

arxiv.org

정말정말 유명한 논문! 마침 인공지능 수업 시간에 Transformer&Attention 파트를 자세하게 다루게 되어 겸사겸사 읽는다!

0. Abstract

기존에는 RNN, CNN + encoder-decoder 구조를 필수적으로 사용했다. 성능이 좋은 모델들은 인코더&디코더를 attention으로 연결하기도 했다.

*encoder-decoder 구조란?

:입력 문장을 인코딩하고, 그 벡터를 바탕으로 출력 문장을 생성하는 구조

 

이 논문에서 제안하는 Transformer은 오직 attention mechanism만으로만 이루어진 모델아키텍처를 제안한다! 실험 결과 두 가지 machine translation tasks에서 병렬화가 더 쉬우면서도 적은 시간으로 좋은 성능을 내는 데 성공하였다.

1. Introduction

그동안의 sequence transduction model → RNN, LSTM, GRU

얘네는 language modeling, machine translation 같은 task들에서 state of the art를 찍었다.

*sequence transduction이란?

입력 시퀀스를 다른 시퀀스로 바꾸는 작업. 예를 들면, 번역(영어 → 한국어), 음성 인식(음성 → 텍스트) 등이 있다.

 

Recurrent Model의 계산

Recurrent Model은 한 단어씩 시간 순서대로 분해하여 계산한다.

$$ h_t=f(h_{t-1},x_t) $$

문제점: 하나씩 처리해야 하므로 병렬화 불가 → 느리다

즉, 긴 문장일수록 더 큰 문제가 되고, GPU도 비효율적으로 사용된다.

 

요즘 연구들은 factorization tricks, conditional computation을 통해 계산효율을 달성한다. 그럼에도 근본적인 sequential computation의 한계는 여전히 존재한다. 

=>트릭으로 개선은 했지만 RNN의 순차 처리 자체는 피할 수 없었고, 그래서 근본적으로는 새로운 접근이 필요했다!

 

Attention Mechanism

- attention mechanism은 sequence modeling, transduction model의 다양한 task들에서 필수적인 요소가 되었다.

- input, output 시퀀스 내에서 거리와 무관하게 의존성을 모델링할 수 있게 한다

- → long dependency 문제 해결 가능!

- 하지만 대부분의 경우, 이러한 어텐션 메커니즘은 RNN+Attention 이렇게 함께 사용 (Self-Attention only 구조는 이 논문이 사실상 처음!)

 

Transformer을 제안한다!

-순환 구조 버리고,

-input-output 사이의 global dependency를 모델링하기 위해

- 오직 어텐션 메커니즘에만 의존!

- 짧은 학습 시간 + 높은 성능 → 효율성과 품질을 동시에 잡은 구조!

 

 

2. Background

sequential computation을 줄여보자는 시도!

-Extended Neural GPU, ByteNetm ConvS2S(대표적인 번역 모델 중 하나였고, 전체 시퀀스를 동시에 처리할 수 있다는 장점이 있었다고 한다) (저도 뭔지 몰라요)

-얘네는 모두 CNN을 basic building block으로 사용 + 입력과 출력의 모든 위치에 대해 hidden representation들을 병렬로 계산

-두 임의의 입력/출력 위치 간의 정보 연결에 필요한 연산 수 →  위치 간 거리에 따라 증가 (ConvS2S는 선형적으로, ByteNet은 로그적으로 증가했다) (의존 거리가 멀어질수록 계산이 늘어나는 구조)

=>멀리 떨어진 단어들 간 관계 (예: “The book that I read yesterday was…”에서 “book” ↔ “was”) 를 학습하기 어렵다

 

 

Transformer은 이 연산수를 상수 크기의 연산수로 줄였다. (Self-Attention은 모든 단어가 모든 단어를 한번에 참조 가능→거리 상관X)

그거에 따른 부작용: attention-weighted position들을 평균내는 걸로 인해서 effective resolution이 줄어드는 문제가 발생할 수 있지만 3.2절에서 설명하고 있는 Multi-Head Attention으로 해결해보겠다!

*effective resolution이 줄어든다는 게 무슨 뜻?

모든 정보를 평균내므로 세밀한 정보 손실 우려가 있다는 뜻이다

 

Self-Attention(=intra-attention)

:하나의 시퀀스 내의 서로 다른 위치 간 관계를 연관시킴→ 그 시퀀스의 representation을 계산 하는 메커니즘

- 트랜스포머 이전에도 self-attention은 다양한 작업에 실험적으로 사용되었고, 효과적이었다 (물론 얘만 단독으로 사용한 건 Transformer가 처음!)

- 이게 Transformer의 핵심블록이다!

 

Attention을 핵심으로 사용한 성공적인 시도 중 Sequence aligned recurrence 대신에 Recurrent attention mechanism을 사용한 end-to-end memory networks가 있다. 이들도 "attention 중심 구조"지만, 여전히 RNN적 반복 구조를 가지고 있었고, Transformer은 여기서 더 나아가 RNN을 완전히 제거했다는 점에서 차별성이 있다.

 

=>우리가 아는 한, 트랜스포머는 sequence-aligned RNN이나 CNN을 사용하지 않고, 오직 self-attention만으로 입력과 출력의 표현을 계산하는 최초의 transduction 모델이다 !!

 

 

3. Model Architecture

대부분의 경쟁력 있는 neural sequence transduction 모델들은 encoder-decoder 구조를 사용한다.

encoder: 입력 symbol representation 시퀀스 (x₁, …, xₙ)를 연속 표현 시퀀스 z = (z₁, …, zₙ)로 변환 (입력 → 고차원 벡터)

decoder: 주어진 z를 바탕으로 출력 시퀀스 (y₁, …, yₘ)를 하나씩 생성 (벡터 → 다시 단어)

각 step에서 모델은 auto-regressive 방식으로 동작한다.

*auto-regressive 방식이란?

- 각 단계에서 이전에 생성된 symbol들을 추가 입력으로 사용하면서 다음 symbol을 생성

- 예: 번역 중 “나는” → “I am” → “I am going…”

- 매번 직전까지의 결과를 바탕으로 다음 단어를 예측

 

Transformer은 encoder, decoder 각각에서 stacked-self attention과 point-wise, fully connected layers를 사용한다.

 

  • stacked self-attention: 여러 층의 self-attention 블록으로 깊이를 쌓아 정보 전달력을 강화
  • point-wise fully connected layer: 각 단어별로 독립적으로 적용되는 작은 MLP (두 개의 선형 변환 + ReLU)
스택된 self-attention 각 인코더 & 디코더 레이어의 첫 번째 서브-레이어 문맥 전체를 직접 참조, 전역 정보 통합
포인트 와이즈 완전 연결층 각 인코더 & 디코더 레이어의 마지막 서브-레이어 단어별 독립 처리, 비선형 변환 (ReLU)

3.1 Encoder and Decoder Stacks

Encoder

- 6개의 동일한 layers

- 각 layer들은 2개의 sub-layer 갖고 있음 (multi-head slef-attention mechanism / position-wise fully connected feed-forward network)

- 2개의 sub-layer들 사이에 residual connection 적용→layer normalization

- 이걸 원활하게 하기 위해 embedding layers를 포함한 모델 내 모든 sub-layer들의 dimension $d_{model}=512$로 통일했다

 

*residual connection이란?

입력과 출력의 차이를 더해주면서 gradient 흐름을 원활히 하는 것

$$ Output=x+Sublayer(x) $$

x=입력벡터, Sublayer(x)=해당 sublayer의 계산 결과

 

왜필요?

1. Gradient 흐름을 개선

  • 깊은 네트워크에서는 역전파 중에 gradient가 작아지거나(=vanishing) 혹은 커져버려서(=exploding) 학습이 불안정
  • 잔차 연결은 xx를 직접 더해주므로, gradient가 더 빠르게 전달돼서 vanishing/exploding 문제를 완화

2. 정보 손실 방지

  • 층이 많아질수록 입력 정보가 왜곡되거나 손실될 수 있다
  • Residual 연결은 “이전 입력 정보”를 그대로 유지하면서 새로운 정보(서브-레이어 결과)를 보완

왜 gradient 흐름이 더 원활해지나?

 

 

*layer normalization이란?

각 단어 벡터를 정규화하여 학습 안정화하는 것

왜 필요?

1. 분포 안정화

  • 각 단어의 벡터 값이 너무 크거나 작아지지 않도록 “평균 0, 분산 1” 형태로 맞춰준다
  • 이런 정규화는 가중치 업데이트가 안정적으로 이루어지게 해준다

2. 학습 속도 향상

  • 정규화 덕분에 gradient가 너무 크거나 작아지는 걸 막아준다 → 더 빠르게 수렴.

Decoder

- decoder도 마찬가지로 6개의 identical layers로 구성 + 각 레이어 별로 2개의 sub-layers + 3rd sub-layer

- 3rd sub-layer: encoder stack의 output에 multi-head attention 적용

- encoder이랑 마찬가지로 sub-layer들 사이에 residual connection 적용→layer normalization

→  모든 블록: (입력 + 블록 결과) → 정규화

- 이후 position을 참조하면 안되니까 decoder 스택의 self-attention sub-layer이 수정된다

  • decoder은 auto-regressive(순차적) 이어야 한다
  • 따라서 미래 단어는 볼 수 없도록 마스킹!
  • masking+출력 임베딩의 한 위치 offset을 결합=>i번째 위치의 예측은 i보다 앞선 위치만 참조할 수 있도록 보장한다.

3.2 Attention

Attention function: 쿼리(query)와 키-값 쌍(key-value pairs)을 출력으로 매핑하는 함수 (query, keys, values, outputs는 모두 벡터)

 

  • 쿼리(query): “어떤 정보를 찾을지”를 나타내는 벡터
  • 키(key): 각 입력 단어의 특징 벡터
  • 값(value): 각 단어의 실제 정보
  • 최종 출력은 “가중치를 곱한 값들의 합”으로 나온다!
    • 이때 가중치=쿼리-해당 키 간의 적합성(compatibility)을 계산하는 함수
    • 핵심 아이디어: 쿼리가 어떤 키와 “얼마나 잘 맞는지” 계산 → softmax로 정규화 → 각 값에 가중치를 곱해 더해줌.

 

3.2.1 Scaled Dot-Product Attention

  • input: queries, keys (dimension=dk, values=dv)

  1. query-key 쌍을 내적 → 연관도 점수 (score)
  2. 각각을 $\sqrt{d_k}$로 나눔 → 스케일 보정
    • dk가 클수록 내적값이 커져서 softmax gradient가 작아짐 → 학습 어려움
    • $\sqrt{d_k}$로 나눠서 스케일을 보정해 gradient 안정화하기 위해

   3. softmax 적용 => 값의 weight을 얻는다 → 확률적 가중치

   4. 값 V와 곱해 weighted sum → 최종 attention 출력!

 

주로 사용되는 attention function은 additive attention & dot-product(multiplicative) attentoion

  • dot-product attention: 우리 알고리즘과 동일
    • 한가지 다른 점은 scaling factor($\sqrt{d_k}$로 나눠서 스케일 보정하는 부분)
    • 더 빠르고 공간효율적→highly optimized matrix multiplication code에서 사용 가능
  • additive attention(Bahdanau et al., 2014):  feed-forward network + single hidden layer => compute compatibility function
    • 입력 쿼리와 키를 concat(또는 element-wise sum)으로 결합 → 작은 feed-forward 네트워크를 거쳐서 유사도(score)를 계산!

(c.f.) Additive Attention vs Dot-Product Attention

계산
방식 쿼리와 키를 결합 → 작은 NN 통과 내적(유사도) 바로 계산
속도 상대적으로 느림 (NN 연산 추가) 훨씬 빠름 (행렬곱 연산으로 최적화됨)

 

dk가 작을 때는 성능 비슷, but dk가 클 때는 dot-product attention(without scaling)이 additive attention보다 성능이 떨어진다.

이유: dk가 클수록 쿼리와 키의 내적 값이 너무 커져서, softmax가 극단적인 영역으로 가버리고 → gradient가 거의 0이 되는 상황이 발생하기 때문이다. 

3.2.2 Multi-Head Attention

d_{model} 차원의 key,value, query들에 하나의 single attention 수행 > query, key, value를 h번 서로 다른 선형 변환으로 투영하여 각각 dk, dk, dv 차원으로 만든다

  • 그냥 한 번만 어텐션 → 한 가지 “관점”만 반영
  • 여러 번 (multi-head)로 쪼개면 → 다양한 관점(정보의 부분집합)에서 동시에 학습!

이렇게 각각 투영된 차원을 parallel하게 attention function 수행=>dv 차원의 output value 도출

 

1️⃣ 쿼리, 키, 값 (Q,K,V)를 각각 다른 선형 변환을 해서 헤드마다 새로운 쿼리, 키, 값을 만든다.
2️⃣ 각 헤드별로 Scaled Dot-Product Attention 계산 → 각 헤드 출력의 차원은 dv!
3️⃣ 여러 헤드의 출력들을 연결 (concat) → 다시 선형 변환으로 최종 출력으로 만듦.

 

결과적으로,

하나의 attention head에서 서로 다른 학습 파라미터 (다른 헤드의 “관점”을 학습!)를 학습할 수 있게 된다!

 

여기서는 h=8, 총 8개의 parallel attention layer(or heads)을 사용한다.

dk=dv=dmodel/h=64

=전체 벡터 512차원8개의 서로 다른 64차원 벡터로 나눠서 처리한다는 뜻

512차원을 single로 사용했을 때보다 head의 차원이 줄어서, 전체 computational cost는 single-head attention+full dimensionality를 사용했을 때와 비슷한 computational cost가 나온다. (계산량은 비슷하지만 표현력(정확도, 성능)은 더 좋은 방법!)

3.2.3 Applications of Attention in our Model

Transformer은 multi-head attention을 총 3가지 다른 방법으로 사용한다.

  1. Encoder-Decoder attention layer에서 사용: decoder이 encoder의 출력 참조(입력 문맥 반영)
    • queries: 이전 decoder 레이어에서 오고,
    • key와 value: 인코더의 output에서 나온다
    • =>decoder의 각 위치는 입력 시퀀스의 모든 위치를 참고할 수 있다
    • 디코더가 인코더의 정보를 참조하면서 번역을 진행하는 단계
    • sequence-sequence model들의 typical encoder-decoder mechanism들을 모방
  2. encoder에 포함된 self-attention layer: 문맥 정보 강화(전체 입력 참조)
    • 키, 값, 쿼리가 모두 인코더의 이전 레이어 출력에서 나온다
    • =>인코더의 각 위치는 이전 레이어의 모든 위치를 참조할 수 있다
    • 입력 문장의 각 단어가 서로 어떤 관계를 맺고 있는지 학습
  3. decoder에 포함된 self-attention layer: 이전 번역 결과만 참조(미래 차단)
    • 디코더의 각 위치가 자신을 포함한 이전 위치까지의 모든 위치를 참조할 수 있도록 한다
    • auto-regressive한 특성을 유지하기 위해 leftward information 유입 막아야 한다→masking
    • softmax 입력에서 “illegal connection”에 해당하는 값들은 마스킹하여 −∞로 설정
      • softmax(−∞) → 0!

masking 단계에서 leftward는 가려서 softmax로 보냄

3.3 Position-wise Feed-Forward Networks

encoder과 decoder에는 fully-connected feed-forward network가 포함된다. 각각의 position에 따로따로(토큰마다 별도 처리)&동일하게 적용. feed-forward netwok는 문맥 상관없이, “해당 단어의 벡터만” 독립적으로 처리해주는 작은 MLP!

이 네트워크는 두 개의 선형 변환과 그 사이의 ReLU 활성화 함수로 구성된다.

 

이 선형 변환들은 다른 단어 위치들에는 같은 변환을 적용하지만, 레이어마다 서로 다른 파라미터를 사용한다. 도대체..무슨 말일까..

“각 단어마다 같은 네트워크”지만, 인코더의 1층/2층/… 각각은 다른 파라미터를 학습한다. 이렇게 하면 각 층마다 다른 “추상화”를 배우는 효과가 있다.

kernel size가 1인 2개의 convolution이라고 생각하면 되는데, 이때 input과 output은 d_model=512이고 inner-layer은 d_ff=2048의 차원을 가지고 있다. (512→1024→2048)

 

왜 필요?

1. 어텐션 결과를 더 non-linear하게 변환

  • self-attention은 “단어끼리의 관계”를 학습해줌
  • 이 feed-forward는 “각 단어의 정보”를 깊이 비선형적으로 변환시켜줌

2. 계산 효율

  • 병렬로 처리 가능 (각 단어별로 독립적으로 처리되니까!)

전체 구조

[Multi-Head Self-Attention]
   ↓
[Position-wise Feed-Forward]
   ↓
(Residual + LayerNorm은 각 서브-레이어마다!)

 

 

3.4 Embeddings and Softmax

다른 시퀀스 변환 모델들처럼,

learned embeddings를 사용하여 input tokes, output token->vectors of dimension d_model로 변환한다.

  • 임베딩: 단어를 고정된 차원의 벡터로 바꿔주는 층!
  • 트랜스포머는 입력도 출력도 모두 512차원의 임베딩으로 바꿔서 처리한다.

 

usual learned linear transformation & softmax function

: decoder output→predicted next-token probilities

 

이 모델은 2개의 embedding layer들(input embedding, output embedding)과 pre-softmax linear transformation(softmax 직전의 선형 변환)에서 같은 weight matrix를 공유한다.

  • 파라미터 수를 줄임
  • 성능이 좋아짐 (embedding-space의 일관성 유지)

 

embedding layer들에서는 $\sqrt{d_{model}}$을 곱한다. 임베딩 레이어를 그대로 쓰지 않고 루트 512를 곱하는 것

  • 초기 임베딩 값의 스케일을 맞추기 위해!
  • attention dot-product 계산할 때 너무 작거나 커지지 않도록 안정화해주는 역할.

 

3.5 Position Encoding

트랜스포머에서 “위치” 정보를 어떻게 임베딩에 주입하는지

우리 모델에는 recurrence나 convolution이 없기 때문에 "sequence"를 다루기 위해 추가 정보를 넣어야 한다. (토큰의 상대적이거나 절대적인 위치 정보) 그래서 "positional encodings"를 encoder, decoder stack의 제일 아래부분에 넣어준다.  차원은 d_model이랑 같게 해서 두 개가 더해질 수 있도록 한다. 

 

positional encoding에는 여러 방법이 있는데 이 논문에서는 다양한 frequency의 sine, cosine함수를 사용하는 fixed 방식을 사용.

고정된 거리 k를 가지는 위치 인코딩이 PE_{pos}의 선형 결합으로 표현될 수 있어, 상대적 위치에 따라 attention을 쉽게 학습할 수 있다고 가정했기 때문이다.

4. Why Self-Attention

 

5. Training

5.1 Training Data and Batching

5.2 Hardware and Schedule

5.3 Optimizer

5.4 Regularization

Residual Dropout

Label Smoothing

6. Results

6.1 Machine Translation

6.2 Model Variations

7. Conclusion