본문 바로가기
Paper Review/Basics

[논문리뷰] Attention is All You Need (Transformer)

by 헤이즐넛 좋아하는 개발자 2024. 8. 17.

시작하기 전에

해당 논문은 2017년 6월 NIPS에서 발행된 논문이다.

 

Link

논문: https://arxiv.org/pdf/1706.03762

코드: https://github.com/huggingface/transformers


I. Introduction

Recurrent model은 순차적으로 진행된다는 특징으로 인해 병렬 실행이 불가능했다. 또한 Attention은 recurrent network와 같이 사용되어왔다.

Transformer는 온전히 attention 메커니즘만으로 되어있는 모델이며, 병렬 실행이 가능하고 번역 퀄리티도 매우 좋았다. 아래에서 더 자세히 살펴보자.


II. Model

Figure 1

Transformer 모델

[Figure 1]과 같다. 5개의 메인 구성을 살펴볼 것이다.

  1. Encoder and Decoder
  2. Attention
  3. Feed-Forward Networks
  4. Embeddings and Softmax
  5. Positional Encoding

Encoder

  • N=6으로 6개의 동일한 layer가 stack되어 하나의 Encoder를 이룬다. Encoder 왼쪽에 보면 N×라고 써있는 것을 볼 수 있다. 각 layer는 2개의 sub-layer로 이루어져 있다.
  • 하나는 multi-head self-attention 메커니즘이고, 다른 하나는 position-wise fully connected feed-forward network이다.
  • 각각의 sub-layer 뒤에 layer normalization이 있다. sub-layer의 결과는 LayerNorm(x+Sublayer(x))가 된다.
  • xSublayer(x)가 합쳐질 수 있게 모든 sub-layer 결과의 차원을 dmodel=512로 통일했다.

Decoder

  • 마찬가지로 N=6 동일한 layer가 stack되어 하나의 Decoder를 이룬다. 각 layer의 sub-layer에 하나가 추가된다.
  • Encoder stack으로부터의 결과를 입력받는 multi-head attention이 추가되었다.
  • layer normalization은 동일하다.
  • self-attention에 masking이 적용된다. 이는 위치 i의 예측이 오직 i보다 앞 위치에만 영향을 받도록 하는 역할을 한다.

Attention

Figure 2

Scaled Dot-Product Attention

  • [Figure 2]의 좌측 그림을 보자. Input은 dk 차원의 queries, keys와 dv 차원의 values로 이루어져 있다.
  • query와 모든 keys를 내적하고, 각각을 dk로 나누고, softmax 함수를 적용한 값이 values에 대한 weight가 된다.
  • queries를 동시에 계산하기 위해 이를 matrix Q로 합친다. keys, values도 마찬가지다.
  • 식으로 표현하면 아래와 같다.
    Attention(Q,K,V)=softmax(QKTdk)V
  • dk가 매우 큰 경우 QKT matrix의 요소 값들이 모두 크기 때문에 바로 softmax 함수를 취하면 다 비슷한 값을 가지게 된다. 따라서 softmax 함수를 취하기 전에 dk로 나눈다.

Multi-Head Attention

  • Single attention을 사용했다면 keys, values, queries가 모두 dmodel 차원이 된다. 이보다 더 효율적인 방식을 사용했다.
  • [Figure 2]의 우측 그림을 보자. 대신 multi-head attention을 사용함으로써 queries, keys, values를 각각 dk, dk, dv 차원으로 하여 h번 선형변환하도록 하였다. 이 덕분에 병렬 실행이 가능해지고, 동시에 계산된 값들을 한 번에 concatenate한다.
  • 식으로 표현하면 아래와 같다.
    MultiHead(Q,K,V)=Concat(head1,...,headh)WO headi=Attention(QWiQ,KWiK,VWiV)
  • 파라미터 matrix들의 차원은 WiQRdmodel×dk, WiKRdmodel×dk, WiVRdmodel×dv, WORhdv×dmodel이다.
  • Head가 8개, h=8를 사용했다. dk=dv=dmodel/h=64이 된다.

Position-wise Feed-Forward Networks

  • [Figure 1]을 보면, attention sub-layer(multi-head attention) 뒤에 fully connected Feed-Forward Network가 있다. 2개의 선형 변환(linear transformation) 중간에 ReLU가 있는 형태이며, 식은 아래와 같다.
    FFN(x)=max(0,xW1+b1)W2+b2
  • Input 차원이 dmodel=512이고, xW1+b1을 지나면서 차원이 dff=2048로 확장되었다가, ReLU를 적용한 후 W2를 통해 다시 차원을 dmodel=512로 축소한다.
  • Feed-Forward Networks를 사용하는 이유는, 어텐션 메커니즘까지는 선형 변환으로 이루어지기 때문이다. 따라서 ReLU 활성화함수를 활용하여 비선형 변환인 PW-FFN을 추가함으로써 어텐션 메커니즘이 잡아내지 못하는 복잡한 패턴을 학습하고, 각 위치에서 독립적으로 데이터를 처리할 수 있도록 한다.

Embeddings and Softmax

[Figure 1]을 보면, inputs과 outputs 뒤에 있는 Embedding과 decoder 출력 뒤에 있는 Linear, Softmax의 역할을 알아보자.

 

Embeddings

  • Input 토큰과 output 토큰을 모델에서 처리할 수 있는 벡터로 전환하는 역할을 한다.
  • dmodel 차원의 벡터로 전환된다. 예를 들어, 이는 단어를 숫자로 나타낸 후, 해당 숫자를 벡터로 변환한다.

Linear and Softmax

  • 디코더 출력은 결국 다음 단어(토큰)를 예측하기 위함이므로 선형 변환과 softmax 함수에 의해 처리된다.
  • 디코더의 출력 벡터가 선형 변환을 통해 예측 벡터로 변환되고, 이 벡터에 softmax가 적용되어 각 토큰이 다음에 나올 확률을 계산한다. Softmax가 왜 확률로 이어지는지 아래 접은글에서 확인할 수 있다.

가중치 행렬 공유

  • Embedding 레이어와 softmax 직전의 선형 변환(Linear)에서 동일한 가중치 행렬을 사용한다. 이는 모델의 파라미터 수를 줄이고, 학습을 효율적으로 수행하도록 한다.
  • 이 가중치 행렬은 Embedding 레이어에서 dmodel이 곱해진다. 이는 모델이 입력 임베딩의 크기를 적절하게 조정하도록 한다.

Restricted self-attention

아래 표가 하나 나온다. Transformer 모델에서 self-attention 외에 다른 레이어를 사용했을 때와 비교한 것이다. n은 시퀀스의 길이로, 문장의 단어 수이고, d는 표현 차원으로, 입력 토큰을 벡터로 변환한 후의 차원 수이고, k는 커널 크기로, 한 번에 처리할 단어 수이고, r은 이웃 크기로, 각 위치에서 참조할 수 있는 이웃 단어의 수이다.

Table 1

Restricted self-attention은 이웃 크기를 설정하는 것이다. 즉, 각 단어에서 문장의 모든 단어를 참조하는 것이 아니라 참조할 수 있는 이웃 단어 수의 범위를 제한하는 것이다. 이를 Self-attention과 Convolutional 레이어와 비교했을 때 complexity per layer와 maximum path length를 어느 정도 조율해서 가져감을 확인할 수 있다. Recurrent layer에서는 sequential operations가 O(n)인데, 이는 다른 layer는 병렬 처리가 가능한 반면 recurrent layer는 순차적 처리가 필요하기 때문이다.

 

※ Softmax란?

더보기

※ Softmax란?

합을 1로 바꿈으로써 확률처럼 만든다. 어떤 값을 선택해야 할 지 확률로서 바라볼 수 있다.

 


Positional Encoding

  • Transformer는 recurrence나 convolution을 포함하지 않고, 문장의 단어 전체를 벡터화해 한 번에 입력으로 넣기 때문에 시퀀스의 순서에 대한 정보를 추가로 넣어줄 필요가 있다. 따라서 인코더와 디코더의 입력 임베딩에 positional encoding을 더해준다.
  • 이는 임베딩과 쉽게 더해질 수 있도록, 같은 차원 dmodel을 갖는다.
  • Positional embedding에는 사인과 코사인 함수를 이용했다. 식은 아래와 같다:
    PE(pos,2i)=sin(pos/100002i/dmodel)PE(pos,2i+1)=cos(pos/100002i/dmodel)
    pos는 position을, i는 dimension을 뜻한다.
  • 각 차원에서의 positional encoding을 sinusoid 함수로 설정함으로써 PEpos+kPEpos의 linear function으로 표현될 수 있는 장점이 있다.

Self-Attention의 장점

Self-attention layer가 Recurrent layer, Convolutional layer와 비교했을 때 갖는 장점은 다음과 같다.

  1. 계산 복잡도
    앞에서도 언급했듯이 계산 복잡도가 Recurrent layer보다 낮고, 특히 시퀀스 길이 n이 표현 차원 d보다 작을 때 더 빠르다. 긴 시퀀스 처리에서는 Self-attention의 각 위치당 참조하는 이웃 영역을 어느 정도 제한하면, 계산 성능을 향상시킬 수 있다.
  2. 병렬 처리 가능성
    Self-attention은 모든 입력 단어들을 위치까지 고려하면서 동시에 처리할 수 있어 순차적 연산이 필요하지 않다. 반면, Recurrent layer는 O(n)의 순차적 연산이 필요해 병렬화가 어렵다.
  3. 장거리 의존성 학습
    Self-attention은 두 입력 위치 간의 경로 길이가 O(1)로, 첫 번째 단어와 마지막 단어 사이의 관계를 학습할 때 바로 연결이 이루어질 수 있음을 뜻한다. 이로 인해 장거리 의존성을 학습하기에 유리하다.
    반면, Recurrent layer는 O(n)로, 첫 번째 단어와 n번째 단어 사이의 관계를 학습할 때 n단계를 거쳐야 한다. Convolutional layer도 O(logk(n))의 경로 길이를 가진다.

이를 통해 개별 어텐션 헤드가 문장의 syntactic, semantic 구조에 관련된 행동을 학습한다.


III. 과정 총정리

여기까지는 모델 아키텍처에서 각각의 구조에 대해 자세히 설명했다. 이제는 총 과정을 정리해보자.

[Figure 1]을 동시에 보면서 따라오면 좋겠다.

 

목표

프랑스어를 영어로 변환하는 것이다.

 

Inputs

"Je suis etudiant" 문장이 들어온다. (이를 "I am a student"로 변환하면 된다)

 

Input Embedding

"Je", "suis", "etudiant" 각각의 단어를 dmodel = 512차원의 단어 벡터로 임베딩시킨다.

이는 각 단어가 단어장에서 고유한 인덱스로 매핑된 후, 임베딩 레이어를 통해 512차원의 벡터로 변환된다고 이해하면 된다.

 

Positional Encoding

Transformer는 모든 입력을 한 번에 집어넣으므로 위치에 대한 정보를 추가해준다. 이는 차원에 따라 사인, 코사인이 번갈아 나타나는 형식으로 되어 있으며, 임베딩과 더해지기 쉽게 같은 512차원으로 되어 있다.

 

Multi-Head Attention

이 과정은 쪼개서 더 세밀하게 봐야 한다. 우선 Self-attention의 과정을 살펴본 후 Multi-head가 하는 역할을 설명하겠다.

 

Query, Key, Value 벡터 생성

512차원의 각 단어 벡터들에 (512, 64) 차원의 WQ, WK, WV이 곱해져 64차원의 query, key, value 벡터들이 생성된다.

WQ, WK, WV은 Transformer 모델의 학습 가능한 파라미터로, 학습을 통해 최적화된다.

아래 그림은 "Thinking Machines"를 Input으로 넣은 경우다.

 

연산

  1. 특정 단어(그림에서 첫 번째 단어)의 query 벡터와 각 단어의 key 벡터롤 곱해서 Score를 구한다. 행렬곱을 진행할 수 있게 key 벡터를 transpose시켜 곱해준다. (3, 1)차원과 (1, 3) 차원이 곱해지니 결과는 하나의 값이 나온다.
  2. 안정적인 gradient를 위해 key 벡터 차원의 루트값만큼 나눠준다. dk가 64였으므로 8로 나눠준다.
  3. Softmax 함수를 적용함으로써 각 단어 간의 유사도를 확률처럼 나타낼 수 있게 하고, 해당 값들의 합을 1로 만든다. 예를 들어, Inputs에서 "Je"("I")와 "etudiant"("student")는 높은 관계성을 갖고 있으니 x1x3과의  score를 softmax 처리한 값이 크게 나올 것이다.
  4. Value 벡터를 곱해줌으로써 sum하기 전에 형태를 값에서 벡터로 바꾼다. 또한 softmax를 곱해주기 때문에 관계성이 없는 단어는  sum에서 영향력이 작아지게 된다.
  5. 특정 단어에 대한 벡터들을 구했다. 이를 모두 더하면 결과 벡터 z를 구할 수 있다.

Matrix 통한 연산

위에서 말한 과정을 기준 단어를 잡아 번갈아가면서 진행하지 않고 행렬 연산을 통해 한 번에 진행할 수 있다.

 

x1, x2, ... 각각에 WQ, WK, WV를 곱해서 query, key, value 벡터들을 구했던 과정을 아래 그림과 같은 행렬 연산으로 한 번에 연산이 가능하다.

 

또한 그 뒤 연산 또한 아래 그림과 같은 행렬 연산으로 한 번에 가능하다.

 

결과 벡터들을 각각의 행으로 가진 Z 결과 벡터가 생성된다. 차원은 (입력 단어 벡터 수, 64)이다.

 

Multi-Head

Transformer에서는 8개의 head를 사용했다. Head가 여러 개면 아래 그림과 같이 query, key, value에 대한 가중치 행렬이 여러 세트가 존재한다. 장점은 2가지가 있다.

  1. 모델이 서로 다른 위치에 집중하는 능력이 향상된다.
    예를 들어, "The animal didn't cross the street because it was too tired"라는 문장을 번역하는 상황이라면 "it"이 무엇을 가리키는지 아는 것이 중요하다. 이러한 역할을 도와준다.
  2. 여러 관점에서 정보를 볼 수 있도록 도와준다.
    어려운 말로는 여러 개의 representation subspace를 제공한다. 여러 세트의 query, key, value 가중치 행렬을 사용하게 되면서 이들이 각각 다른 관점에서 입력 데이터를 해석하도록 학습할 수 있다.

 

아래 그림을 보면, Transformer에서 head가 8개이니 결과 벡터도 8개가 나온다.

 

  1. 생성된 결과 벡터 8개를 모두 concat하여 하나의 행렬을 만든다. 차원은 (단어 벡터 수, 64*8=512)이다.
  2. 학습된 WO 행렬을 곱해준다. 차원은 (512, 512)이다. 이 행렬을 곱한다고 해서 차원이 바뀌진 않지만 학습된 가중치에 따라 중요한 정보를 반영하도록 한다.
  3. 행렬곱의 결과로 FFN에 입력으로 들어갈 결과 벡터가 생성되며 차원은 (단어 벡터 수, 512)이다.

 

최종 결과 요약

아래 그림을 보면서 잘 이해했는지 확인해보자.

 

Add & Norm

Add 과정은 입력 x와 서브 레이어(Self-Attention 또는 Feed-Forward Network)의 출력 Layer(x)를 더한다. 이는 입력값을 다시 더해줌으로써 정보를 더 효과적으로 전달하게 한다.

식은 아래와 같다.

Add=x+Layer(x)

 

Norm 과정은 각 레이어의 출력값이 너무 튀지 않도록 이를 정규화하는 역할을 한다.

 

두 과정을 통해 Transformer는 더 빠르게 수렴하고, overfitting을 줄이는 데에도 도움을 준다.

전체 과정의 식은 아래와 같다.

Output=LayerNorm(x+Layer(x))

 

Feed-Forward Network

2개의 선형 변환 중간에 ReLU(비선형 변환)가 있는 형태이다. 어텐션 메커니즘까지 선형 변환으로 이루어지기 때문에 비선형 변환인 FFN을 추가해 어텐션 메커니즘이 잡아내지 못하는 복잡한 패턴을 학습한다.

Transformer Encoder는 이러한 Multi-Head Attention, Add&Norm, Feed-Forward Network, Add&Norm 구조가 N층 쌓인 스택 형태다.

 

Masked Multi-Head Attention

Decoder에서는 번역된 문장을 출력해줘야 하므로 Encoder와 다르게 각 위치에서 뒤의 단어를 참조하지 않아야 한다. 이에 따라 query와 key 벡터가 곱해진 이후, Softmax 함수가 적용되기 직전에 마스크 행렬을 곱한다.

마스크 행렬은 아래와 같이 생겼다.

[000000]

는 softmax 함수를 적용하면 0이 된다. 이는 미래 토큰에 대한 스코어가 0이 되도록 한다.

 

Linear & Softmax

Linear 레이어는 디코더 스택에서 나온 벡터를 훨씬 더 큰 벡터(logits vector)로 projection하는 완전 연결 신경망이다.

디코더 스택의 출력은 결과 벡터다.

예를 들어, 이 모델이 10,000개의 영단어를 알고 있다고 하자. (훈련 데이터셋에서 학습한 단어들이 10,000개다.) 그러면 logits vector는 10,000개의 칸을 가지며 각 칸은 각 단어에 해당하는 점수를 나타낸다.

그 후 Softmax 레이어가 이 점수들을 확률로 변환한다. 이 중에서 확률이 가장 높은 칸이 선택되고, 그 칸에 해당하는 단어가 출력된다.

 

Outputs

위의 결과로 출력된 단어가 다시 Outputs로 들어간다. 그러면 Output probabilities를 계산하여 두 번째 위치의 단어가 생성될 것이고, 첫 번째와 두 번째 단어가 다시 Outputs에 들어간다.

 

출처

잘 정리된 아래 글을 참고했다.

https://jalammar.github.io/illustrated-transformer/

 

The Illustrated Transformer

Discussions: Hacker News (65 points, 4 comments), Reddit r/MachineLearning (29 points, 3 comments) Translations: Arabic, Chinese (Simplified) 1, Chinese (Simplified) 2, French 1, French 2, Italian, Japanese, Korean, Persian, Russian, Spanish 1, Spanish 2,

jalammar.github.io