[자연어처리 논문리뷰] Attention Is All You Need

2022. 8. 28. 08:25자연어처리

딥러닝 분야를 공부하는 사람이라면 무조건 마스터 해야 할 Attention 매커니즘을 공부한다. 방대한 자료가 있으나, 밑바닥부터 시작하는 딥러닝, 성균관대학교 이지형 교수/고영중 교수의 강의 및 동 대학 이종욱 교수 교안을 참고하여 공부하였고, 해당 이해를 기반으로 논문 리뷰를 진행했다.

 

논문: 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

PyTorch 코드: https://pytorch.org/tutorials/beginner/transformer_tutorial.html

 

Transformer Overview

Parallel corpus를 이용해서 기계 번역을 하기 위해 개발된 알고리즘이다. RNN의 많은 Seq2Seq 모델 대비 우수한 성능을 보이며, 병렬 처리성을 증가시킬 수 있다. Attention Mechanism이 내재되어 있고, 이를 이용하는 과정에서 자연스럽게 Global Dependency를 가져가게 된다. Encoder와 Decoder가 각각 모듈화 되어 있는 구조를 갖는데, 이로 인해 Encoder 및 Decoder를 원하는만큼 쌓아 올리기 용이하다. Transformer를 공부하면서 Attention을 반드시 숙지하고 넘어가야 하는데, 자연어처리 외에 이미지, 추천 등 다양한 영역에서 경계 없이 Attention Mechanism을 활용하고, 헷갈리고 애매한 부분이 있는만큼 새로운 분야에의 적용과 이해 속도가 느려지기 때문이다.


Abstract

Transformer 이전 모델들이 다양한 앙상블과 복잡한 RNN/CNN 구조를 이용하여 기계 번역을 시도한 반면, Transformer는 거의 Attention Mechanism에만 의존한 간단한 구조를 이용해서 성공적인 기계 번역 성능을 증명했다. 당시까지의 알고리즘 중 단일 모델로서 SOTA 성능을 보였다. 뿐만 아니라, 병렬 처리, 학습에 소요되는 시간, 일반화 측면에서도 매우 우수한 알고리즘이다.

 

1. Introduction

Transformer는 Recurrent한 구조를 사용하지 않는다. 대신, Attention Mechanism에만 의존해서 Input과 Output 간 Global Dependency를 가져간다. 즉 번역 전 후의 문장에 있어서 번역 전 단어간의 거리와 번역 후 단어간의 거리가 번역 품질에 영향을 미치지 않도록 한다는 것이다. 또한 병렬화가 잘 되어 있어서 8개의 P100 GPU를 사용해서 12시간만에 고성능의 번역을 할 수 있다.

 

2. Background

Transformer에서는 Input과 Output간의 관계를 통해 만들어지는 Representation을 계산하는데 들어가는 시간을 상수화 하였다. (다른 알고리즘은 많은 개선 이후에도 linear/logarithmical하게 증가한다.)

 

3. Model Architecture

아래 그림을 통해 전체 구조를 살펴볼 수 있다. 본 논문에서는 크게 Encoder and Decoder Stacks, Attention, Point-wise Feed-Forward Networks, Embedding and Softmax, Positional Encoding, 이렇게 6가지 관점에서 구조를 살펴본다.

 

3.1) Encoder and Decoder Stacks

 

[Encoder]

  • Multi-Head self-attentioin mechanism
    : Attention Mechanism의 Head를 여러 개 사용한다.
  • Position-wise fully connected feed-forward network
    : 초창기 Attentioni Mechanism이 제안됐을 때 사용되던 LSTM같은 구조는 사용하지 않는다.
  • Add & Norm
    : Add는 Residual Connection, Norm은 Layer Normalization을 의미한다.
    : Attention 결과에 Residual Connection으로 Input을 더한다. 그 결과에 Layer Norm을 적용한다.
    : Feed Forward 결과에 Residual Connection으로 이전 단계의 결과를 더한다. 그 결과에 Layer Norm을 적용한다
  • 본 논문에서는 이와 같은 Encoder 구조를 6번 반복한다. Embedding 및 각 Encoder의 Output dimension은 512로 가져간다.

 

[Decoder]

  • Input
    : Decoder는 두 가지 Input을 사용한다.
    : Encoder의 Output, 그리고 지금까지의 번역 결과(Output) 이 두 가지를 모두 Input으로 받는다
  • Masked Multi-Head Attention
    : Decoder 모듈에서 처음으로 Process 되는 부분이다.
    : '나는 학교에 간다'를 'I go to school'로 번역할 경우, 현재까지 'I go' 까지만 번역되었다면, 학습 단계에서 'to school' 부분은 가리고 Input으로 넣어준다
  • Multi-Head Attention
    : Encoder와 Masked Multi-Head Attention의 Output을 Input으로 받는다.
    : Self-Attention이 아니라는 점을 제외하면 Encoder와 동일하다
  • Feed Forward 및 Add & Norm
    : Encoder와 동일하다.

 

3.2) Attention

Transformer 이해의 핵심이다. 다 놓치고 가더라도, 여기만큼은 깊은 이해를 필요로 한다.Query, Key, Value라는 세 개의 벡터를 넣어서, 특정 Representation을 Output으로 얻는 Mechanism이다.

 

Query는 내가 번역하고자 하는 지금 이 순간의 Target 단어이다. '지금 이 단어랑 제일 상관있는 단어가 뭐야?' 하고 질문을 날릴 때 사용하는 벡터이다. Key는 내가 번역하고자 하는 문장의 각 모든 단어들로, 상관있는 단어를 뽑아내기 위한 후보군들이다. V는 역시 Target 단어인데, Q와의 차이는 Q는 K와의 Similarity를 구하기 위해 사용되며, 이 Similarity와 V의 Similarity를 이용해서 최종 Representation을 얻어낸다.

 

 

[Scaled Dot-Product Attention]

본 논문에서는 dot-product를 이용해서 Attention 결과를 계산한다. 기존 Attention과의 차이점은 Softmax function에 들어가기 전, K의 차원 수를 이용해서 Scaling을 해준다는 점이다. 차원수에 따른 Similarity 왜곡을 방지하는 방법이다. 뿐만 아니라 Scaling을 통해 Softmax function에서 Gradient가 작아지는 현상을 방지할 수 있다.

[Multi-Head Attention]

Multi-Head Attention의 과정은 크게 "Q,K,V를 다양한 Matrix로 Linear Projection 하기 - Attention 하기 - Attention 결과 Concat - 마지막으로 Linear Projection 하여 Representation 얻기"로 이루어져 있다. Head의 개수와 Proejction의 차원을 적절히 조절하면, Single Head를 사용할 때와 비슷한 Computational Cost를 가지면서도 훨씬 더 풍성한 정보를 전달할 수 있다.

  • Q,K,V를 다양한 Matrix로 Linear Projection 하기 - Multi Head의 재료를 준비해주는 과정
    Q, K, V를 각각 다른 Matrix를 통해 Linear Transform(Projection) 해준다. 이 과정을 통해 Multi Head를 만들면, Attention은 각 단어를 다양한 관점에서 볼 수 있는 힘이 생긴다. 아래와 같은 Matrix를 이용해서,

        각각의 Q, K, V를 아래와 같이 Transform 한다.

        i의 크기만큼 다양한 Head가 생기게 되는데, Head의 재료를 준비해주는 과정이다.

  • Attention 하기 - Head가 생성되는 단계
    위의 결과를 이용해서 동일하게 Scaled Dot-Product Attention을 적용하면 된다. 이 Attention의 결과가 Head이며, 전 단계에서 사용한 Matrix Set의 개수, 즉 i만큼 Head가 생성된다.

  • Attention 결과 Concat
    하나의 Vector Representation을 만들기 위해 Concat한다.

  • 마지막으로 Linear Projection 하여 Representation 얻기 - 최종적으로 Multi Head가 생성되는 단계
    Concat한 결과를 최종 Projection하여 Multi Head를 얻어낸다.

[Applicationis of Attention in Transformer]

Transformer에서는 Attention이 세 가지 모양으로 활용된다. Encoder-decoder attention, Encoder의 Self-Attention, Decoder의 Self-Attention을 각각 살펴보자.

  • Encoder-decoder attention
    Encoder와 Decoder의 정보를 연결해주는 부분이다. 다른 Attention과는 다르게 Input이 삼지창 형태로 들어가지 않는데, 즉 Self-Attention이 아니라는 의미이다. 이 단계에서 알아내야 하는 것은 여태까지 'I go'까지 번역했는데, 그렇다면 '나는 학교에 갑니다' 중 어떤 요소를 뽑아서 번역된 문장의 다음 단어로 내놓아야 하는 것이다. 그러므로 여태까지 번역된 문장, 즉 Decoder의 Self-Attentio의 결과가 Q가 된다. 그리고 Encoder의 Output을 각각 K와 V로 활용하게 된다.

Decoder에서 가운데 위치한 Layer

  • Encoder의 Self-Attention
    Input을 Embedding + Positional Encoding한 결과를 입력 받아 Q, K, V로 활용하는 Self-Attention이다.

  • Decoder의 Self-Attention
    이미 언급되었지만, 가장 큰 특징은 Masked Attention이라는 것이다. '현재 시점'에서 알고 있을 수 없는 정보는 모두 Masking 처리를 해야 한다. (-∞로 값을 치환한다.)

3.3) Position-wise Feed-Forward Networks

Linear Transform - ReLU - Linear Transform 형태로 구성되어 있다.

3.4) Embedding and Softmax

특별한 내용 없음

 

3.5) Positional Encoding

Recurrent 모델에서 자연스럽게 가져가던 위치에 대한 정보를 반영할 방법이 없기 때문에(라고 서술하지는 않았다) Positional Encoding을 통해 위치 정보를 더해준다. Positional Encoding이 없다면 동일한 단어 또는 동음이의어가 동일한 Vector로 Encoding 되기 때문에 번역에 혼란을 야기할 수 있다.

class PositionalEncoding(nn.Module) :
    def __init__(self, d_model: int, dropout: float = 0.1, max_len: int = 5000):
        super().__init__()
        self.dropout = nn.Dropout(p=dropout)

        position = torch.arange(max_len).unsqueeze(1)
        div_term = torch.exp(torch.arange(0, d_model, 2) * (-math.log(10000.0) / d_model)) # arange term이 0이면 0에 가까운 값 더해주는 건지 확인해보기
        pe = torch.zeros(max_len, 1, d_model)
        pe[:, 0, 0::2] = torch.sin(position * div_term)
        pe[:, 0, 1::2] = torch.cos(position * div_term)
        self.register_buffer('pe', pe)

    def forward(self, x: Tensor) -> Tensor:
        '''
        Args:
            x: Tensor, shape [seq_len, batch_size, embedding_dim]
        '''
        x = x + self.pe[:x.size(0)]
        return self.dropout(x)

 

4. Why Self-Attention

Layer당 계산 복잡도, 병렬 처리, Long-range dependency 측면에서 모두 우수하다. 이러한 성능 측면은 물론, Interpretability 또한 상당히 우수하다. 현재 리뷰 포커스가 구현에 있기 때문에, 이 부분은 시간이 허락할 때 다시 업데이트 하는 것으로 한다. 아마도 업데이트되지 않을 것이다....

 

5. Training

Optimizer: Adam

Regularization: Residual Dropout, Label Smoothing

 

6. Results

최근 논문이 아니기 때문에 이 부분은 생략한다. 어쨋든 당시 SOTA 성능이었고, 여전히 강력한 모델로 존재하지만, 이제는 out of date한 느낌을 가질 수 밖에 없다.

 

7. Conclusion

핵심 로직이 Attention으로만 이루어진(Self-Attention, Multi Head Attention) 모델로, 기존 CNN 및 RNN 모델 대비 번역에 탁월한 성능을 보인다. 


더 알아볼 내용들

- Attention Mechanism은 어떤 측면에서 병렬 처리가 가능하게 되는가

- Position-wise Feed-Forward Networks? 기존 Attention에서 FFNN을 사용할 때는 단어를 임베딩해서 넣어주는 단계에서 썼던것 같은데, 여기서는 뭔가 이후 단계의 처리를 말하는것 같다.. 강의를 다시 보자

- Layer Normalization

- Masked Multi-Head Attention에서 Masking할 때 총 길이는 어떻게 정해주는지 확인 필요. 그리고 train시에만 사용하는건지도.... test 시점에 길이가 모자르다면 어떻게 처리?

'자연어처리' 카테고리의 다른 글

자연어 처리 기법 개요 - 단어를 의미로  (0) 2022.08.24