Attention is all you need (이하 transformer) 리뷰
seq2seq 모델은 인코더-디코더 구조를 가지며, 인코더를 통해 입력 시퀀스가 고정된 크기의 context vector로 압축하고, 이를 다시 디코더의 입력으로 넣어 출력 시퀀스를 만들어냅니다.
이 방법의 크게 두가지의 단점을 가지는데요.
1. 하나의 고정된 크기의 vector에 모든 입력은 압축하므로 정보 손실이 발생
2. RNN의 고질적인 문제인 기울기 소실 (vanishing gradient) 문제 발생
seq2seq의 문제를 해결하기 위해 나온 모델 구조가 Attention 입니다.
디코더에서 출력 단어를 예측하는 매 시점(time step)마다, 인코더에서의 전체 입력 문장을 다시 한 번 참고한다는 점입니다. 단, 전체 입력 문장을 전부 다 동일한 비율로 참고하는 것이 아니라, 해당 시점에서 예측해야할 단어와 연관이 있는 입력 단어 부분을 좀 더 집중(attention)해서 보게 됩니다. 이는 attention value를 통해 할 수 있는데, attention value를 구하는 간단한 과정은 아래와 같습니다.
t 시점의 디코더의 hidden state 와 인코더의 각 hidden state와 내적(dot-poduct attention 기준)하여 attention score를 구합니다.
구한 attention score에 softmax를 취해 attention distribution을 구하는데, distribution의 원소를 attention weight (가중치)라고 합니다.
어텐션의 최종 결과값을 얻기 위해서 각 인코더의 은닉 상태와 어텐션 가중치값들을 곱하고, 최종적으로 모두 더하는 가중합(Weighted Sum)으로 attention value를 얻습니다.
이후 attention value를 디코더의 t시점의 hidden state와 concat하여 하나의 벡터로 만들어 예측 연산의 입력으로 사용합니다. 이렇게 인코더로부터 얻은 정보를 활용하여 출력값를 좀 더 잘 예측할 수 있게 됩니다.
따라서 seq2seq의 문제인 정보손실의 해결하는 방법으로 RNN 계열 모델의 보정을 위해 Attention을 함께 사용합니다.
그런데 어텐션을 RNN의 보정을 위한 용도가 아니라 아예 어텐션으로 인코더와 디코더를 만들어보면 어떨까? 에서 시작된 논문입니다.
Transformer는 self-attention과 point-wise feed-forward layer가 쌓여있는 구조를 Encoder와 Decorder에서 모두 가집니다.
1.1 Encoder Decoder Stacks
Encoder
6개의 Encoder가 쌓여있으며 각 Encoder는 2개의 sub-layer로 구성됩니다.
두 서브레이어 모두 residual connection을 가지며, 이후 layer normalization을 거칩니다. 따라서 sub-layer의 출력은 LayerNorm(x+Sublayer(x)) 이며 Sublayer(x) 는 해당 서브 레이어의 함수입니다. 시퀀스의 임베딩 차원은 = 512
Decoder
6개의 Decoder가 쌓여있으며 각 Decoder는 3개의 sub-layer로 구성됩니다.
1.2 Attention
Transformer는 attention을 병렬로 수행하여 결과를 concat하는 Multi-head attention을 사용합니다. 이를 이해히기 위해 먼저 single attention인 Scaled Dot-Product Attention의 구조와 동작방식을 자세히 살펴보겠습니다.
Scaled Dot-Product Attention
1. query, key, value vector의 행렬 형태인 Q,K,V 행렬 구하기
2. Q와 모든 단어의 K를 내적하여 Attention score 구하기
3. K의 차원의 제곱근인 로 나누어 scaling
4. (디코더의 경우) 이후 시점의 단어의 확률을 0으로 만드는 masking
5. Softmax
6. V와 행렬 곱으로 attention value matrix 얻음
각 순서를 하나씩 살펴보겠습니다.
1. query, key, value vector의 행렬 형태인 Q,K,V 행렬 구하기
먼저 input input sequence를 차원으로 임베딩하여 혀형태로 만들어 Encoder의 입력으로 넣어줍니다.
이 임베딩 벡터를 를 이용하여 Q,K,V 행렬로 변환합니다. 뒤의 내적을 위해 Q와 K의 shape은 같습니다. 논문에서 는 인 64로 설정했습니다.
2. Q와 모든 단어의 K를 내적하여 Attention score 구하기
위에서 하나의 임베딩 벡터 이 query vector 으로 변환되었습니다. 하나의 query vector는 모든 임베딩 벡터(n개라고 가정)의 key 벡터인 과 내적을 통해 score를 구합니다. 그 결과는 입니다.
이 과정을 행렬 연산으로 처리하면 입력 문장의 길이를 seq_len 이라고 할 때 가 되고 이 되어 shape 은 seq_len 크기인 정방행렬이 됩니다.
3. K의 차원의 제곱근인 로 나누어 scaling
벡터 dimension = 크기가 크면, 내적을 했을 때 그 값이 너무 커져서 Softmax를 취한값이 너무 작아져 gradient도 작아지는 문제가 발생합니다. 이를 막기위해 각 score값을 로 나누어 scaling을 합니다.
4. (디코더의 경우) 이후 시점의 단어의 확률을 0으로 만드는 masking
현재 단어와 이전 단어만 볼 수 있게 행렬의 대각선을 기준으로 우상단 triangle의 값을 으로 만들어 softmax를 취했을 때 0이 되도록합니다.
5. Softmax
scaling 한 행렬에 softmax를 취해 attention distribution 을 구합니다.
6. V와 행렬 곱으로 attention value matrix 얻음
각 단어들의 value vector 과 weighted sum을 통해 최종적으로 의 길이를 가지는 하나를 만들어냅니다.
입력 시퀀스의 길이가 seq_len이면 최종 행렬곱의 결과는 입니다.
이 모든 과정을 수식으로 나타내면 다음과 같습니다.
행렬 연산으로 일괄 처리되는 과정을 그림으로 보면 다음과 같습니다.
결과적으로 1~6까지 적용하여 나오는 Attention Value Matrix의 크기는 입니다.
Multi-head Attention
Transformer 연구진은 한 번의 어텐션을 하는 것보다 여러번의 어텐션을 병렬로 사용하는 것이 더 효과적이라고 판단하였습니다.
이유는 각 어텐션 헤드는 모두 서로 다른 가중치 행렬 을 가지고, 이에 따라 서로 다른 시각으로 정보를 수집할 수 있기 때문입니다.
따라서 앞서 보았듯이 논문에서는 차원을 가지는 임베딩 벡터를 8로 나눈 64 차원의 Q,K,V 벡터로 축소시켜 8개의 head에서 병렬적으로 Attention을 수행합니다. head의 차원을 줄임으로써 계산 복잡도가 낮아지는 이점도 있습니다.
이후 각 head에서 나온 z를 concat 하여 하나로 만들어줍니다. 모두 연결된 행렬의 크기는 이 됩니다. ()
이 행렬에 또 다른 가중치 행렬 와 곱해져 최종적으로 모든 정보를 담은 행렬이 만들어집니다.
전체과정을 수식으로 표현하면 다음과 같습니다.
Where the projections are parameter matrices and
최종 결과 행렬이 인코더의 입력 행렬과 크기가 동일한데, 트랜스포머는 다수의 인코더를 쌓은 형태이므로 인코더에서의 입력의 크기가 출력에서도 동일 크기로 계속 유지되어야만 다음 인코더에서도 다시 입력이 될 수 있기 때문입니다.
Applications of Attention in our Mode
Transformer는 이 multi head attention을 3부분에서 사용합니다.
1.3 Position-wise Feed-Forward Networks
FFN은 2층짜리 fully connected feed-forward network이다.
여기서 x는 앞서 멀티 헤드 어텐션의 결과로 나온 의 크기를 가지는 행렬을 말합니다. 가중치 행렬
은
의 크기를 가지고, 가중치 행렬 은
의 크기를 가집니다. 논문에서 은닉층의 크기인
는 2,048의 크기를 가집니다.activation은 ReLU를 사용합니다.
1.4 Embeddings and Softmax
Encoder 블록으로 들어가기전 input Embedding 하나, Decoder 블록으로 들어가기전 output Embedding 하나, Decoder output을 다시 단어를 추론하기 위한 vocab size 길이의 벡터로 바꿔주는 linear까지 모두 같은 learned embedding weight matrix를 사용합니다. 단 embedding layer들에 한해 weight에 을 곱해줍니다.
1.5 Positional Encoding
Transformer는 recurrence와 convolution이 없으므로 sequence 안의 토큰의 상대적/절대적 위치에 대한 정보를 가지고 있어야 합니다. 이를 위해 인코더, 디코더 스택의 input embedding에 positonal encoding 벡터를 추가합니다. 이 벡터는 각 토큰의 위치, 또는 시퀀스 내에서 두 토큰의 거리에 대한 정보를 가지며 , 차원은 embedding 멕터의 차원과 같은 입니다.
논문에서는 positonal encoding 벡터를 만들 때 다른 frequencies를 가지는 sin, cos함수를 사용했습니다. pos는 시퀀스 내에서의 단어의 위치, i는 각 단어의 임베딩 벡터에서 몇 번째 dimension(index)인지를 나타냅니다.(학습되거나 하이퍼 파라미터가 아닌 미리 고정된 값)
이를 통해 가변적인 시퀀스길이와 상관없이 문장의 위치정보를 잘 전달할 수 있다고 합니다.
d차원을 갖는 다양한 길이의 입력 시퀀스 을 고정된 길이의 시퀀스 으로 바꿀 때 self-attention을 사용하는 것의 이점을 3가지 측면에서 비교했습니다.
종합하면 Self-attention이 RNN보다 훨씬 빠르게 학습을 할 수 있습니다.
영어를 독일어로, 영어를 프랑스어로 변환할 때 다른 모델들보다 높은 BLEU 달성
Ref
https://jalammar.github.io/illustrated-transformer/
https://wikidocs.net/31379
https://velog.io/@donggunseo/Day-28-29-Boostcamp-AI-Tech-Attention-is-All-You-Need-%EB%A6%AC%EB%B7%B0