[Transformer] Attention is all you need 논문리뷰

드디어 Attention is all you need 논문을 리뷰하네요.
 
이제는 NLP task를 넘어 vision 분야에서도 활발히 쓰이지만
많이 쓰임에도 불구하고 개인적으로 기초가 잘 다져지지 않으면 이해하기 어려운 논문 중 하나라고 생각합니다.. (제가 말하는 기초는 딥러닝 + 자연어 처리의 극극 기초..) 공교롭게도 저는 nlp task 보다 vision task로 제대로 이 논문을 읽기 시작했던 것 같습니다..
 
transformer 이론은 우리가 잘 알고있는 Chat GPT 모델에도 탑재가 되어있죠?
제가 이해하기 위해 차근차근 정리해보았습니다. 오류나 정정이 필요한 부분은 댓글 달아주시면 감사하겠습니다🫣
 
논문은 2017년 발행되었으며, 원문은 아래 링크에서 확인하실 수 있습니다.
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 논문은 Google에서 발표한 sequence task를 위한 논문입니다. 따라서 주로 NLP task 에서 많이 사용되었죠.
기존의 Language model 들의 경우 RNN(Recurrent Neural Network) 백본을 이용하여 모델이 구성됐었죠.
하지만 제 전 게시글에도 나타났듯이, RNN 을 이용한 모델은 짧은 문장 수준에선 유용할 수 있으나, context 가 길어질수록 효과가 현저히 떨어졌습니다.
 
2024.01.18 - [AI (인공지능) Paper Review/NLP] - RNN(Recurrent Neural Network) & LSTM (Long short term Memory) 
 
그래서 transformer 구조를 이용하여 문장 전체의 문맥을 모두 이해하지 않아도, 단어간의 중요도와 유사도 등을 통해 문장을 생성 해 낼 수 있는 방법이 고안된 겁니다..!
transformer 구조를 함축적으로 정리하면 아래와 같습니다.
 

요약

  • Attention 매커니즘만으로 구성된 sequence model
  • Machine Translation task에서 우수한 성능
  • 병렬화 기능과  CNN 대비 줄어든 training 시간

 
** 급하게 이해를 해야한다면 Model Architecture 위주로 보세요!! **
 

Abstract

기존의 sequence 모델들은 다음과 같은 과정들을 거쳐왔습니다.
 
복잡한 RNN, CNN 기반의 Encoder, Decoder를 지니는 모델에서 Seq2Seq 논문에서 소개된 Attention 개념을 거쳐  보다 더 좋은 성능을 내기 시작했었죠. 본 논문 Attention is all you need 에서는 말 그대로 attention 기법만 사용한 sequence 모델을 제안합니다. 바로 "Transformer" 입니다.
 
Transformer 모델은 데이터를 병렬화 처리할 수 있다는 특징이 있습니다. 특히 양방향 기계 번역 task 에서 높은 성능을 보였다고 합니다.
 
 

Introduction & Background

 Recurrent 모델들은 일반적으로 input, output sequence의 기호 위치를 따라 연산이 수행됩니다. hidden layer에서 이전 hidden state의 영향을 받아 weight 들이 계산되었습니다. 하지만 이런 recurrent 모델의 순차적인 특성 때문에, 병렬 연상이 불가능하고 시퀀스 길이가 길어질수록 메모리 제한으로 인해 예제간 배치를 제한하게 됩니다.
 
하지만, Attenion 모델의 경우에는 input output sequence의 길이에 상관없이 task 모델링 수행이 가능합니다. 
그러나 기존 연구들에서는 Attention mechanism이 단독으로 쓰이기보다는 recurrent network 와 conjunction되어 사용되어 왔습니다.
 

Q. 왜 기존 연구에서는 Attention Mechanism이 Recurrent Network 와 같이 사용되었을까요?

: 애초에 Attention mechanism은 RNN 의 장기의존성(Long-term dependencies)을 해결하기 위해 고안되었으며, RNN의 출력에 대한 "가중치"를 조절하는 역할로만 사용되어 왔습니다. 즉, "보조적인 매커니즘"의 형태라는 인식이 다분했죠. 게다가 Attention 만을 사용하는 것이 계산적으로 비효율적이라고 생각되어 Transformer 이전에는 Attention Mechanism 이 단독으로 쓰이는 일은 없었습니다.
 
 
 따라서 본 논문에서는 Recurrent network 를 배제하고, input과 output 간의 global dependency를 향상시키기 위해,
오직 attention module만을 이용한 Transformer를 제안합니다.
 

Self-Attention

  • Self-Attention의 경우, 독해, 생성 요약, textual entailment(텍스트 함의) 등 Down stream task에 강점을 보임

End-to-End memory networks

  • recurrent attention mechanism 을 기초로 함
  • 한 가지 언어의 question, language modeling task에서 강점을 보임

 
 

Model Architecture

 그럼, 모델 구조를 한 번 살펴봅시다.

Transformer Mechanism

 

대략적인 모델의 흐름

 
transformer 모델은 다음과 같이 크게 Encoder와 Decoder로 구분되어 있습니다.
대다수의 tranduction model(sequence to sequene 형태의 모델, ex. 기계번역)이 다음과 같은 encoder-decoder 형태를 띄기 때문입니다.
 
 
모델 구조를 크게 반으로 나누어 보았을 때, 왼쪽 모델은 Encoder 모델, 오른쪽 모델은 Decoder 모델을 의미합니다.
 
 
transformer의 각 model은 Auto-regressive model 이라는 특징이 있습니다. 이는 자기 자신을 입력 데이터로 하여 스스로를 예측하는 모델이며, 현재 시점까지 생성한 output을 사용하여 다음 시점에 대한 output 예측을 수행한다는 것을 의미합니다.
 

<Encoder>

 
Encoder 부터 시작하며 차근히 따라가 봅시다.
 
Input data가 입력되면, Input embedding 을 시작합니다. 문장을 벡터화 시키는 것이죠. 문장을 토큰(=단어)으로 쪼개 벡터화시키게 되면 각 단어가 의미하는 숫자를 컴퓨터는 기억하게 됩니다. (벡터 값) 그리고 추가적으로 Positional Encoding 을 진행합니다. 이를 진행하는 이유는 Transformer 가 오직 Attention 기반의 모델이기 때문입니다. 기존의 sequence model 들의 경우에는 RNN, LSTM 등을 이용하여 문장을 기억하여 단어간의 관계를 파악했었죠? 하지만 transformer는 그런 RNN 백본을 사용하지 않기 때문에 단어가 문장 내 어느 부분에 주로 위치하는지를 기억해 줄 장치가 필요했습니다.
이것이 바로 Positional Encoding 입니다.
 
모델 그림을 확인하면, Embedding 후 Positional Encoding과 + 연산이 일어납니다.
즉, Embedding 된 벡터 값에 위치 값 (Positional Encoding 값)을 추가해주는 것이죠. 그럼 각 단어들은 위치에 대한 정보를 포함한 채로 위의 Encoder box에 진입하게 됩니다.
 
벡터에 대한 + 연산이 수행되었기 때문에 단어들은 여전이 Embedding 된 벡터의 형태로 존재합니다.
이에 대해 Attention + Self attention + Multi-head Attention 기능이 수행됩니다. 또 그런 과정에서 Residual Connection과 Layer Normalization이 수행되죠. 이에 대한 자세한 과정은 더 아래에서 다뤄보도록 할게요.
 
 

<Decoder>

 
Decoder 그림을 봅시다.
 
Decoder는 Encoder와는 달리 3개의 sub-layer를 가진 형태입니다. Decoder 모듈에서는 여태까지 transformer 모델을 통해 생성된 output을 다시 재활용합니다. 바로 output embedding으로 들어가는 것이죠. output embedding 도 encoder 에서와 마찬가지로, embedding 과정과 positional encoding 과정을 거쳐 Decoder box로 진입합니다.
 
하지만 여기서 Encoder와의 차이점이 존재합니다. Output embedding에 대한 Multi-head attention을 수행할 때 "Masked" Multi-head attention을 수행합니다. 모델이 아직 생성하지 않은 token에 대한 정보를 참조하지 못하도록 하는 것이죠. 
다음으로 두 번째 layer 에서는 앞서 Encoder에서 넘어온 정보와 output embedding 에 대한 Multi-head attention 결과를 함께 다시 Multi-head attention 을 진행합니다.
 
그리고 타 신경망 모델들과 같이 Linear, Softmax 과정을 거친 후 확률을 뽑아내게 됩니다. 
 
 

Attention Mechanism

 

Q. 그럼 정확히 Attention 기법이라는게 뭘까요?

 Attention 기법을 정의하자면, query와 key-value 쌍을 output으로 내보낼 때, query, keys, values 그리고 다른 output vector들이 어디에 있는지 mapping 해 주는 것 입니다. 각 value들은 일치하는 key, query와 함께 가중치를 할당받게 되고, 그 가중치의 합에 따라 output이 계산됩니다.
 
 각 단어들의 의미하는 바는 아래와 같습니다.
 

  • Query(Q) : 현재 단어를 나타내는 벡터
  • Key(K) : 다른 모든 단어를 나타내는 벡터들
  • Values(V) : 다른 모든 단어의 값 벡터들, Key와 동일한 단어에 해당
Attention Mechanism

 
 먼저, 가장 근본이 되는 Scaled Dot-Product Attention을 봅시다.
 
 

<Scaled Dot-Product Attention>

 
 input이 되는 query와 key들은 $d_k$, value는 $d_v$의 차원을 가지고 있습니다. 먼저 같은 차원을 지닌 query와 key 에 대해 dot product를 진행하고 차원의 제곱근으로 나눠줍니다. 그 후 softmax를 적용하면 value에 대한 weight 값을 얻을 수 있습니다.
 

 
 그럼 수식에 대해 더 자세히 알아봅시다. query와 key를 가장 먼저 dot product를 진행해주는 이유는, query와 key 사이의 유사도를 구하기 위함 때문입니다. (유사도를 구하기 위해 종종 cosine 유사도를 이용하는 것을 알고있죠?) query-key 사이의 유사도를 구한 값에 차원의 제곱근을 나누어줌으로써 Scaling 을 진행합니다. Scaling 을 진행해주는 이유는, $d_k$ 값이 커지면 커질수록 높은 차원에서의 dot product 결과가 매우 커질 수 있기 때문에, Gradient vanishng 혹은 exploding 문제를 완화하기 위함입니다. 이에 대한 Softmax를 진행해주면, 각 Query가 각각의  Key와 얼마나 관련이 있는지를 확률 함수로 나타냅니다. 
 
 

<Multi-Head Attention>

 
 Multi-head attention 에서는, Attention Mechanism을 병렬로 여러 번 수행하는 "Head" 들이 존재합니다. 따라서 각 head 들이 동일한 입력 데이터에 대해 다른 세트의 학습 가능한 가중치를 이용하여 Query, Key, Value 벡터를 변한합니다.
 구체적인 방법은 다음과 같습니다.
먼저 Linear Projection을 이용하여 입력벡터 X에 대해, 각 head 에 대해 다른 가중치 행렬을 사용하여 Q, K, V 벡터를 독립적으로 계산합니다. 각 $d_k, d_k, d_v$ 차원에 대하여 서로 다른 Linear Projection을 진행하는 것이죠. 이 Projected 된 버전들은 각각의 병렬적인 Attention 기능을 수행합니다. 병렬적으로 수행된 Dot-Product Attention은 다시한번 concatenate + projected 되면서 마지막 Value를 만들어냅니다. 
 

 
여기서 ${W_i}^Q, {W_i}^K, {W_i}^V$ 는 각 head 에 대한 선형 변환을 위한 가중치 행렬을 의미하고 $W^O$ 는 최종 출력을 위한 가중치 행렬을 의미합니다.
Multi-head Attention을 통해 모델은 다양한 서브 스페이스와 표현 공간에서 정보를 동시에 학습할 수 있으며, 이는 복잡한 패턴과 상관관계를 더 잘 이해하고 전반적인 모델의 성능을 향상시키는 데 기여합니다.

본 논문에서는 8개의 head 를 이용하였고, $d_k = d_v = d_model / h = 64$ 가 되어 각 헤드의 차원이 줄어듦에 따라 전체 계산 비용은 전체 차원을 가진 단일 head attention mechanism 과 유사하게 됩니다.
 
 
 
Transformer 모델에서 Attention mechanism은 아래와 같은 원리로 동작합니다.
 
 먼저, "Encoder-Decoder Attention layer"에서는, 이전의 Decoder 층으로 부터 Query를 받고, Encoder의 output으로 부터 Key와 Value에 대한 Memory를 받아냅니다. 이를 통해 decoder의 모든 position이 input sequence의 모든 position에 대해 Attention 할 수 있습니다.
 
 Encoder 에서 소개한, Self-Attention layer에서는 모든 Key, Query, Value 이전 층의 encoder로 부터 출력된 output으로 부터 나온 것을 이용합니다. 따라서 Encoder의 각 position 에서는 이전 Encoder Layer의 모든 position들을 주목할 수 있습니다.
 
 마찬가지로 Decoder에서의 self-attention layer 또한 Decoder의 각 position이 해당 position을 포함하여 decoder 내의 모든 position을 주목할 수 있도록 합니다. 하지만 Decoder 에서는 앞서 말했듯, Masked attention 기능을 수행하는데 Auto-regressive property로 동작하는 Encoder-Decoder 모델에서, 미래의 토큰들에 대한 정보가 현재의 예측에 영향을 미치지 않도록 하기 위해 실제로 attention score에 $-inf$ 값을 적용하여 softmax 함수를 통과시켰을 때, 해당 위치의 출력이 0에 가까워지도록 하여 masking 기능을 수행합니다. 즉, 실질적으로 해당 위치가 출력에서 무시됨을 의미하며, 마스킹 처리된 토큰은 모델이 다음 토큰을 예측할 때 고려되지 않게 되는거죠.

optional part =&gt; Decoder 에 적용

 

FFN

 
 각 sub-layer 들에 대하여 attention을 수행하기 위해서, transformer 모델에서는 Position-wise Feed-Forward Network(FFN)를 진행합니다. FFN을 이용하게 되면, 각 위치에서의 특징을 비선형방식으로 변환하여 표현력을 높입니다. 더 복잡한 패턴과 상관관계에 대한 표현이 가능해 지는 것이죠.

 
 Feed-forward Network는 2개의 linear transform과 ReLU 함수로 이루어져 있습니다. 
수식에서 각각 $W_1, W_2$는 가중치를, $b_1, b_2$는 편향을 나타냅니다.
FFN은 시퀀스 내 벡터들에 각각 독립적으로 적용되며, layer 사이에서 매개변수를 공유하지 않습니다. 따라서 모델이 각 레이어에서 다양한 특징들을 학습할 수 있도록 합니다.
 
예를 들어, 이런 FFN 을 2개의 convolution 과 1의 kernel size로 표현할 수 있으며, input, output의 차원이 $d_{model} = 512$ 일 때, $d_{ff} = 2048$으로 설정할 수 있습니다. 첫 번째 선형 레이어는 입력차원 (512)을 확장하여 $d_{ff} = 2048$ 차원으로 만들고 비선형 활성화 함수가 적용된 후, 두 번째 선형 레이어를 통해 다시 원래 차원으로 축소되는 과정을 겪는 것 입니다.
 
 이렇게 FNN 을 이용해서 중간 계층 차원을 확장시킴으로써 transformer 네트워크는 더 복잡한 함수를 모델링 할 수 있습니다. 
 
 
각 module의 선형 복잡도는 아래와 같습니다. 

transformer model complexity per layer

 
$n$ 은 sequence의 길이를, $d$는 차원을, $k$는 convolution 의 kernel size를 의미합니다. $r$은 self-attention을 수핼할 때, 몇몇 이웃까지 포함할 것인지를 의미합니다.
 

Positional Encoding

 앞서, transformer에는 recurrent 와 convolution 모듈을 제외한 Attention 만으로 이루어진 모델임을 설명했습니다. 따라서 토큰간의 위치를 이해하기 위해 Positional Encoding 을 진행해 준다고 했었죠?

 
 각 위치 (pos)에 대하여 차원 i의 위치 인코딩은 위의 식을 통해 계산할 수 있습니다. sine, cosine 함수의 주기적인 패턴을 갖는 특성 때문에, 모델의 상대적인 위치 정보를 Encoding 하고 활용할 수 있습니다. 
 
앞서 모델의 전체적인 흐름에서 설명했듯, 각 encoder, decoder의 input 에서 sequence input과 더불어 position embedding을 진행해줌으로서 문장의 token 간의 상대적 관련성, 위치 정보를 함께 모델에 전달할 수 있는 것 입니다.
 


 
 transformer 모델이 정말 많은 범위에서 사용되는 만큼 (NLP를 넘어서 CV까지) transformer에서 가장 중심이 되는 Self-Attention 기법과 Encoder, Decoder 모듈에 집중하여 논문을 읽고 해석해보았습니다.
 
코드까지 함께 뜯어보며 이해하면 더할나위 없을 것 같으니 차차 코드리뷰도 올려보도록 하겠습니다🤗