티스토리 뷰
논문: https://arxiv.org/abs/1706.03762v7
NLP 분야에서 sequential 처리의 비효율을 없앤 구조를 제안한다. 향후 vision 분야에도 접목되어 지금(2024년)까지도 다양한 변형으로 활용되고 있는 transformer를 제시한 논문이다.
0. Abstraction
RNN, CNN 구조를 사용하던 기존의 transduction(번역 등) model이 아닌, 오로지 attention mechanism만을 활용한 구조를 제안한다. sequence의 serial 처리가 아닌 한번에 병렬 처리할 수 있게 하여 학습시간을 크게 감소 시켰다.
1. Introduction

RNN, LSTM, GRMM 과 같은 recurrent model은 sequence의 token의 position을 하나의 step으로 하여 token 수 만큼의 계산을 하게 된다. t-1번째 step의 계산 결과가 h_t-1이라면, t번째 step을 계산하기 위해 h_t-1을 사용하는 구조(Sequential computation)이기 때문이다. 문제는, 이런 sequential 구조때문에 sequence의 token들을 동시에 처리할 수 없는 문제가 발생한다. 특히 sequence가 길어질수록 memory 사용량을 포함해 다양한 문제가 발생한다.
Attention mechanism은 token 간의 거리에 대한 제약을 받지 않으면서 좋은 성능을 보여왔지만 여전히 recurrent 구조와 함께 쓰여 sequential computation에 대한 한계를 벗어나지 못하고 있었다.
Transformer는 recurrent 구조를 완전히 배제하여 input, output 간의 global dependency를 파악할 수 있으며 병렬처리 또한 가능하게 했다.
2. Background
Sequential computation을 줄이기 위해 hidden representation 을 convolution block으로 계산해 병렬처리가 가능하게 한 연구들(Extended Neural GPU, ByteNet, ConvS2S)이 있었으나 input과 output의 position이 멀어질수록 계산량이 많아지면서 dependency를 학습하기 어려운 문제가 있었다. 반면 transformer는 한번에 모든 token을 넣기 때문에 distance에 상관없이 계산량이 일정하다. attention을 하는 과정에서 weighted sum을하며 각 token에 있는 position 정보가 섞여 resolution이 떨어지지만 attention을 여러번(multi head attention)하여 다양한 관점에서 문장의 맥락을 고려할 수 있게 하여 여 이를 보완했다.
또한 transformer는 recurrent없이 self-attension mechanism을 사용해 input과 output sequence의 representation(문맥 정보)를 계산해낸 최초의 모델이다.
3. Model Architecture

input sequence는 tokenize되어 n개의 token(symbol)로 한번에 들어가고 self-attention, FFN을 통해 shape을 유지한채 encoding된 sequence z를 얻어낸다. 이는 decoder에 context로 제공된다. decoder는 이 context와 지금까지 생성해낸 token들을 입력으로 하여 하나의 token씩 생성해낸다.
하지만 training할 때는 target sequence를 생성해낸 token 대신에 집어 넣어 한번에 모든 output token을 뽑아내도록 한다. 이는 학습이 잘 되지 않은 모델이 이상한 output token을 뽑아냈을 때 그 이상한 token을 기반으로 그 뒤의 token을 뽑아내는 상황을 막기 위함이다. 예를 들어, target output이 "인도 식당은 맛있다."인 상황에서 두번 째 토큰이 잘 못 뽑혀 "인도 보도블럭" 까지 output을 뽑아낸 상황이라면, 세번쨰 token인 "맛있다."를 뽑기 위해 "인도 보도블럭"를 넣는 것은 무의미한 작업일 수 있다. "인도 보도블럭 맛있다." 라는 문장이 생성되길 기대할 수 없기 때문이다. 따라서 세번째 "맛있다" token을 뽑기 두번째 까지 생성된 token이 아닌 두번쨰 까지의 정답 token을 넣는 트릭을 사용하는 것이다. 이를 teacher forcing이라고 부르고 이렇게 함으로 써 학습을 빠르고 정확하게 할 수 있을 뿐만 아니라 output token을 순차적이 아닌 한번에 뽑아낼 수 있어 병렬처리가 가능하다.
3.1 Encoder and Decoder Stacks
Encoder

Encoder layer는 2개의 sub-layer (self-attension, feed forward)로 구성된다. attension layer는 "Multi-head" "self" attension을 사용하고 feed forward net은 단순한 MLP이다. 각각의 sub-layer는 shortcut을 갖고 있으며 중요한 점은 sub layer들을 포함한 encoder layer 자체로 반복되기 때문에 layer의 input과 output은 언제나 같은 dimenstion(token vector의 dimension)을 유지한다.
Decoder

Decoder layer는 3개의 sub-layer (self-attension, cross-attension, feed forward)로 구성된다. FFN은 encoder와 동일하고, multi-head self-attension의 경우에는 약간의 변형이 있다. 바로 masking을 추가한다는 점이다. 위에 얘기한대로 학습을 할 때 정답도 input으로 넣어주게 되는데 output token을 만들 때 정답을 보고 생성하는 것을 방지하기 위해 masking을 한다. 예를 들어 보자. 위에서 얘기 하겠지만 self-attension은 각각의 token이 자신의 의미만 갖고 있는 것에서 전체 문장의 의미도 token에 반영하는 작업이다. "인도 식당", "인도 옆에 차도" 이 두 문장에서 "인도" 라는 토큰만 보게되면 이게 나라인지, 보도 인지 구분할 길이 없다. 하지만 전체 문장을 보면 "인도" 라는 token이 이 문장에서 어떤 인도인지를 알 수 있게 된다. 이런 맥락의 정보를 토큰에 녹이는 작업이 self-attention 이다. 다시 masking으로 돌아와서, 이제는 i 번째 token을 생성할 때 정답 sequence의 i-1번째 까지의 토큰이 i번째 token 뿐만 아니라 그 뒤의 token 정보도 담고 있다는 것을 알게 되었다. 그렇기 때문에 i-1번째 token은 전체 맥락이 아닌 i 번째 이후의 맥락은 배제하도록 masking 작업을 하는 것이다. 계산적으로 설명하면 i 번째 token 이후는 모두 0으로 만들어 weighted sum에서 배제하는 것이다.
마지막 세번째 sub-layer(중간의 sub layer)는 cross-attension을 한다. i번째 정답 token (0~i번째 semantic을 담고 있는)과 연관 있는 vector를 전체 input 문장의 encoding vector를 기준으로 생성해낸다.
추가로, shifted right의 의미는 i-1 번째 token을 기준으로 i번째 token을 예측하는 행위의 index(position)을 align하기 위해 target sequence를 넣을 때 오른쪽으로 한칸 밀어서 넣는 트릭이다. (i-1번째 token이 i번째로 이동하면서 i번째 data로 i번째 output을 생성하는 꼴이 된다.)
3.2 Attention
Attention은 하나의 token을 기준으로 query를 날려 대상 token들 중 관련 있는 token들의 비중을 높혀 weigthed sum으로 새로운 token을 생성하는 작업이다. Attension에는 Q(query), K(key), V(value) 세가지가 참여한다. Q는 token 하나의 vector다. K, V는 Q와는 다른 space에 있는, Q를 통해 얻고 싶은 대상이다(Query에 대응하는 Response라고 할 수 있겠다). K, V는 projection을 통해 차원을 다르게 만들지만 결국 같은 값에서 나온다. 다만 사용용도를 위해 복사해서 하나는 K로, 하나는 V로 만든 것이다. K, V는 query token을 통해 얻고자 하는 대상 token"들"을 갖고 있는 matrix이다.
query token은 key token들 각각에 대해 내적을 한다. 내적은 두 벡터의 유사도를 측정하는 metric이다. QT 계산을 통해 query token과 key token들 간의 유사도를 모두 구한다(이후에 softmax를 적용해서 값을 확률(weight)로 만든다.). 이렇게 구해진 유사도를 가지고 V를 조합해 새로운 token을 만든다. 이것이 Query를 날려 얻은 Response space에서 얻는 output이다.
정리하자면 Query token을 날려 response token들(K)과 유사도를 측정해 response token들(V)의 weigted sum을 구해내는 것이다. 한글 -> 영어 번역이라면, 영어 단어를 날려 한글 문장의 각 단어들을 조합해 query한 그 영단어와 비슷한 한글 단어(실제로는 vector지만 encoder space에서 생성되었다는 의미)를 생성해내는 것이다. 그리고 이 한글단어 vertor를 decoder의 마지막에 영어 단어로 generate하는 것이다. (영어 단어라고 했지만 self-attention으로 그 단어는 지금까지 생성된 문장 전체의 의미를 담고 있으며, 따라서 단어 query에 대한 output은 지금까지 생성된 문장 뒤에 올 가장 적합한 단어가 된다.)
3.2.1 Scaled Dot-Product Attention


가장 많이 사용되는 attention 방식 중에 하나인 dot product attention의 변형이다. 일반적인 것과 다른 점은 Q, K의 dimension인 sqrt(d_k)로 나누어 scaling을 한다는 점이다. d_k가 커짐에 따라 내적값이 커져 softmax의 양끝으로 이동하고 gradient가 0에 수렴하는 현상을 방지하기 위함이다.
3.2.2 Multi-Head Attention



Attention을 병렬로 해서 문맥의 정보를 다양한 방법으로 뽑아내는 방법이다. input, output vector 모두 d_model dimension으로 vector를 표현한다. Q와 K는 이를 h개로 나누어 d_k로 projection하고 V는 d_v로 projection하도록 한다(d_k와 같은 값을 씀). 그리고 attention을 h번 한 뒤 concat하여 projection을 통해 dimension을 다시 d_model로 맞춰준다. 중요하게 볼 점은 input인 Q의 dimension과 multi head attention의 output이 같은 shape을 유지한다는 점이다.
3.2.3 Applicatios of Attention in our Model
- Cross attention: encoder의 output을 K, V로 하고 이전 step의 decoder의 output(training 할 때는 정답 sequence)을 Q로 하여 attention을 한다. K, V는 input data 전체를 포함하고 있고 학습 시에는 Q도 output 전체를 포함하고 있기 때문에 병렬로 모든 attention을 처리할 수 있다.
- Encoder self-attention: input sequence 전체를 self-attention하여 각 token에 semantic 정보를 주입한다. 몇개의 encoder layer를 거치면서 정보는 더욱 다양해진다.
- Decoder self-attention: 학습 시에 output sequence 전체를 self-attention하지만 i번째 token이 i번째 이후의 token을 볼 수 없게 하기 위해 softmax의 결과를 0으로 만드는 행위가 추가된다.
3.3 Position-wise Feed-Forward Networks

특별할 거 없는 fc layer이다. 하나의 sub-layer에서 모든 token에 같은 weight이 적용되고 각 encoder 및 decoder layer는 다른 weight를 갖는다. 두 개의 layer로 구성되어 있고 512->2048->512로 역시나 input, output dimension은 유지한다.
3.4 Enbeddings and Softmax
Tokenizer, word2vec, vec2word 등은 일반적으로 많이 쓰는 거 사용했다.
3.5 Positional Encoding
Transformer는 recurrent하지 않고 한번에 token을 넣기 때문에 sequence의 position 정보가 담겨있지 않다(token matrix의 순서는 attention을 계산할 때 사용되지 않기 때문에 반영되지 않음). 따라서 각 token이 sequence의 어떤 위치에 있는지 정보를 token에 넣어줘야하는데 이 과정을 positional encoding이라 한다. embedding vector와 같은 d_model dimension의 position vector를 생성해 더해준다.

positional encoding vector는 위와 같이 만드는데 pos는 position index이고 i는 vector의 dimension index이다. 즉 PE의 element는 [sin, cos, sin, cos, .. ]이런 식인 것. positional embedding을 학습해서 사용해도 봤는데 성능차이는 나지 않았다.
4. Why Self-Attention

Self-attention layer를 recurrent, convolutional layer와 비교했고 세가지 이점이 있었다.
- Layer에서의 계산량이 적다.
- 병렬처리할 수 있다.
- input signal <-> output signal 간 path length가 상수다.
recurrent와 비교했을 때 n < d일 경우에 recurrent에 비해 계산량이 적은데 n < d인 경우가 대부분이다. sequence 길이만큼 step을 실행해야하는 것과 다르게 한번에 input, output token을 넣기 때문에 sequential operation 없이 병렬처리가 가능하며, 마찬가지로 첫 번째 input token의 signal이 마지막 output token의 signal이 되기 위해 sequentail operation을 반복하는 RNN과 달리 matrix 정보를 global로 볼 수 있기 떄문에 바로 계산이 가능하다는 장점이 있다.
또한 multi-head attention을 적용함으로써 여러 attention들이 다양한 역할을 하도록 학습되고 문장 전체적인 구문 및 문맥을 잘 파악하는 효과를 얻을 수 있었다.

5. Training
생략
6. Results
생략
7. Conclusion
Recurrent, convolutional 구조 없이 multi-head attention(self, cross)만을 사용한 모델 구조를 제안했다. 계산량을 줄이고 병렬처리를 가능하게 함으로써 학습속도를 대폭 올리고 position 간 먼 거리로 인해 정보가 소실되던 문제를 해결하여 성능 역시 더 좋아지는 결과를 얻을 수 있었다.
