Transformer의 overall architecture은 아래의 그림과 같이 encoder-decoder structure로 이루어져있다. Encoder는 input sequence 를 받아 연속적인 representation 을 출력한다. 이때 model은 output sequence를 순차적으로 만들어내면서 이전에 만들어낸 출력을 decoder의 추가적인 input으로 사용한다.
가장 중요하고 핵심이 되는 연산인 Attention 함수는 query와 key-value pair 집합을 어떤 output으로 mapping하는 것으로 생각할 수 있다. 이 output은 value vactor의 weighted sum으로 계산되며, 이 weight은 query vector와 이에 상응하는 key vector와의 함수로 구한다.
Transformer에서 사용되는 attention은 Scaled Dot-Product Attention이고, 이를 multi-head로 나눠서 계산한다.
각 입력은 모두 각각의 query, key, value를 가지고 있다. 하나의 query를 모든 나머지 key와 dot product한 후, query와 key의 dimension인 로 나눈 값에 softmax를 취해 해당 key의 value에 대한 weight을 얻는다.
이때 로 나누는 이유는 가 커짐에 따라 dot product magnitude가 커질 것이고, 그러면 softmax function이 매우 작은 gradient 값을 가지게 되어 학습이 잘 안되므로 scaling을 해주는 것이다.
이해를 위해 encoder에서 입력의 흐름을 도식화한 그림을 보면, 가장 먼저 각 단어들은 정해진 channel, hidden size를 가지는 벡터로 embedding된다(그림에서 Input Embedding).
Embedding된 input setence의 word vector (”I”), (”am”), (”stutdent”)는 attention layer에 들어가서 weight vector 를 만나 Query, Key, Value의 3가지 벡터를 만든다. Query, Key, Value는 모든 입력 토큰이 각각 가지고 있는 어떤 hidden state의 토큰이다.
→ Attention은 결국 서로 얼마나 영향을 주고 받는지를 구하는 것이다. Query, Key, Value는 그 자체의 의미보다도 attention value를 구하는데 있어서 어떠한 역할을 하는지를 이해하는 것이 쉽다.
각 단어의 Query는 모든 단어의 Key에 대해 (자기 자신도 포함) dot product 연산을 통해 두 vector의 유사도를 측정하여 서로에게 얼마나 중요한지 (영향을 주는지) 파악한다. 이 유사도 값은 모든 단어에 대해 softmax 취하여 sum이 1이 되는 weight로 만들고 (를 전에 나누긴 함), 각 단어의 value에 weighted sum하여 attention value를 구할 수 있다.
정리하자면, 어떤 hidden state에서 각 token은 모두 Query, Key, Value를 가지고 있는데, 각 단어는 Query 이름표를 가지고 모든 단어의 Key 이름표와 비교해서 그 Key에 해당하는 Value를 다음 hidden state에 얼마나 받아올 것인지 정한다.
→ 집중하고자 하는 관련이 있는 단어의 영향은 남기고 관련이 없는 단어의 영향은 지우는 작업이라고 이해할 수 있음
Multi-Head Attention은 scaled dot production attention을 병렬 처리하기 위해 여러 개 사용한 것이다.
Query, Key, Value를 그대로 단일 attention function에 입력하는 것이 아니고, 각각 다르게 학습된 linear projection으로 project시켜 h번 병렬적으로 계산한다. (예를 들어 512-dimension을 가지는 Query를 64-dimension으로 8번 따로 projection시키고 따로 scaled dot-product attention을 연산시킨 후 concatenate한다)
이러한 병렬 연산은 모델이 서로 다른 위치에서 여러 개의 representation subspace에 대한 정보를 함께 사용하는 것과 같은 효과를 낼 수 있다. 마치 CNN에서 필터를 더 많이 사용하여 정보를 추출하는 것과 비슷한 의미로, single-head일 때보다 문맥을 이용하기 쉽다고 한다.
Transformer는 recurrent나 convolution이 없기 때문에 sequence 순서에 대한 정보를 사용하려면 추가적으로 상대적인 위치나 절대적인 위치 정보를 주입해야 한다. 이를 위해 encoder나 decoder에서 input vector embedding 시에 positional encoding을 추가하여 위치정보를 주입한다.
Positional encoding은 원래 모델 input dimension과 같게 하여 그냥 더해주는 방식을 채택하였다. 특히 이 논문에서는 서로 다른 frequency의 cos, sin 함수를 input embedding에 더해주어 relative position 정보를 주입하려 하였다.
논문에서는 recurrent와 convolution layer에 비해 self-attention이 갖는 장점을 아래와 같은 관점으로 설명함
각 layer에서 연산 복잡도가 더 작아 연산 속도가 빠르다. 보통 sequence lengh n에 비해서 vector dimension d가 훨씬 작은 경우가 많으므로, Table 1을 보면 recurrent와 convolution에 비해서 연산복잡도가 낮다는 것을 확인할 수 있다. 하지만 sequence가 매우 길어지는 input을 받을 때에는 이 이점이 사라질 수 있다. 이를 위해 attention하는 neighborhood size를 정해주는 restriicted self-attention의 개념도 있다.
Recurrent network의 경우 n개의 sequence를 처리하기 위해 순차적으로 n번 데이터를 forward해야하지만 (time n의 input이 forward되고 나온 output과 time n+1의 input이 다시 forward되는 것을 n번 반복) Transformer는 모든 sequence position을 연결하여 한번에 처리할 수 있다.
Sequence 정보를 처리할 때, 서로 거리가 먼 element 사이의 dependency를 배우는 것은 매우 중요하다. 이러한 dependency를 학습하는데 가장 중요한 것은 network를 지나는 forward signal고가 backward signal 사이의 path length이다. loss가 구해지고 back prop이 되는 경로를 생각해면, 이러한 관점에서도 attention이 다른 layer에 비해 강점이 있다.
Self-attention은 sequence data 내부 요소들 사이의 상관 관계를 학습하므로, attention 자체를 visuualize하는 것만으로 어느 정도 모델의 결과를 해석할 수 있다는 장점이 있다.
Encoder에서는 문장 내 단어와 문맥을 이해하고, Decoder에서는 순차적으로 번역된 문장을 내놓는다.
(1) Encoding
입력 문장이 들어가면 각 단어는 모두 벡터로 embedding되고 각 위치 정보도 positional embedding을 통해 들어간다.
Embedding된 word sequence는 곧바로 self-attentioin과 feed forward network을 포함하는 encoder block을 통해 encoding된다.
Encoding된 Vecor는 각 단어에 대한 의미와 각 단어가 서로 다른 단어와 어떤 관계를 가지고 있는지에 대한 정보를 포함한다.
(2) Decoding
Decoder는 번역된 결과를 내놓는 네트워크로, 순서대로 하나씩 output word를 출력으로 내놓는다.
이때 이전 sequence의 output은 다음 sequence의 입력으로 함께 사용한다. 예를 들어 맨 처음에는 start token이 들어가서 "나"라는 단어가 가장 높은 확률로 도출된다. "나"라는 단어는 다시 decoder의 입력으로 들어가서 "는"이라는 output이 나오고, "나"와 "는"은 다시 함께 decoder로 들어가 "현주"가 나오게 된다.
Decoder도 Encoder처럼 self-attention layer가 있어서 해당 position보다 이전의 모든 position의 출력을 참조하도록 한다. 이때, 위에서 설명한 것처럼 이전의 단어들만을 참조할 수 있도록 현재 positon 이후의 단어는 매우 작은 음수로 masking해서 softmax에서 영향을 주지 못하게 한다.
Decoder에서 masked self-attention 이후에 encoder의 출력으로 나온 key와 value를 사용하는 encoder-decoder attentioin layer가 있다. encoder-decoder attention layer에서 query는 decoder에서 이전 layer의 것을 사용하고, key, value는 encoder 출력을 사용하는데, decoder의 각 단어의 query를 이용해 input 단어들과 attention을 계산해서 decoder 내부 모든 position이 input sequence의 모든 위치의 단어를 참조하도록 한다.
→ Loss 계산은 decoder의 softmax output이 그 위치에 와야하는 단어의 database안에서 index와 같도록 학습이 된다.