[Paper Review] Attention is all you need

먼지감자·2021년 9월 14일
0

인공지능

목록 보기
4/25

Attention is all you need (이하 transformer) 리뷰

seq2seq


seq2seq 모델은 인코더-디코더 구조를 가지며, 인코더를 통해 입력 시퀀스가 고정된 크기의 context vector로 압축하고, 이를 다시 디코더의 입력으로 넣어 출력 시퀀스를 만들어냅니다.

이 방법의 크게 두가지의 단점을 가지는데요.
1. 하나의 고정된 크기의 vector에 모든 입력은 압축하므로 정보 손실이 발생
2. RNN의 고질적인 문제인 기울기 소실 (vanishing gradient) 문제 발생

Ref https://wikidocs.net/24996

Attention

seq2seq의 문제를 해결하기 위해 나온 모델 구조가 Attention 입니다.
디코더에서 출력 단어를 예측하는 매 시점(time step)마다, 인코더에서의 전체 입력 문장을 다시 한 번 참고한다는 점입니다. 단, 전체 입력 문장을 전부 다 동일한 비율로 참고하는 것이 아니라, 해당 시점에서 예측해야할 단어와 연관이 있는 입력 단어 부분을 좀 더 집중(attention)해서 보게 됩니다. 이는 attention value를 통해 할 수 있는데, attention value를 구하는 간단한 과정은 아래와 같습니다.



t 시점의 디코더의 hidden state StS_t와 인코더의 각 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을 함께 사용합니다.

Ref https://wikidocs.net/22893

Transformer

그런데 어텐션을 RNN의 보정을 위한 용도가 아니라 아예 어텐션으로 인코더와 디코더를 만들어보면 어떨까? 에서 시작된 논문입니다.

1. Model Architecture


Transformer는 self-attention과 point-wise feed-forward layer가 쌓여있는 구조를 Encoder와 Decorder에서 모두 가집니다.

1.1 Encoder Decoder Stacks

Encoder
6개의 Encoder가 쌓여있으며 각 Encoder는 2개의 sub-layer로 구성됩니다.

  • Multi-head Self-Attention
  • Position-wise fully connected feed-forward network

두 서브레이어 모두 residual connection을 가지며, 이후 layer normalization을 거칩니다. 따라서 sub-layer의 출력은 LayerNorm(x+Sublayer(x)) 이며 Sublayer(x) 는 해당 서브 레이어의 함수입니다. 시퀀스의 임베딩 차원은 dmodeld_{model} = 512

Decoder
6개의 Decoder가 쌓여있으며 각 Decoder는 3개의 sub-layer로 구성됩니다.

  • Masked Multi-head Self Attention
    Masking은 다음 순서의 단어들에 대해 확률을 모두 0으로 만들어 디코더가 다음 position에 나올 단어를 예측할 때 아직 등장하지 않은 뒤의 단어들은 고려하지 않고 이전의 단어들만 고려하도록 합니다.
  • Encoder-Decoder Attention
    Self Attention이 아닌 이유는 query, key, value vector의 출처가 다르기 때문입니다. key, value는 인코더의 출력에서 가져오는 구조입니다.
  • Position-wise fully connected feed-forward network

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의 차원의 제곱근인 dk\sqrt{d_k}로 나누어 scaling
4. (디코더의 경우) 이후 시점의 단어의 확률을 0으로 만드는 masking
5. Softmax
6. V와 행렬 곱으로 attention value matrix 얻음

각 순서를 하나씩 살펴보겠습니다.
1. query, key, value vector의 행렬 형태인 Q,K,V 행렬 구하기

먼저 input input sequence를 dmodel=512d_{model} = 512차원으로 임베딩하여 x1,x2...x1, x2 ...혀형태로 만들어 Encoder의 입력으로 넣어줍니다.
이 임베딩 벡터를 WQRdmodel×dk,WKRdmodel×dk,WVRdmodel×dvW^Q \in \R^{d_{model} \times d_k}, W^K \in \R^{d_{model} \times d_k}, W^V \in \R^{d_{model} \times d_v}를 이용하여 Q,K,V 행렬로 변환합니다. 뒤의 내적을 위해 Q와 K의 shape은 같습니다. 논문에서 dk,dvd_k, d_vdmodel/num_heads=512/8d_{model}/{num\_heads} = 512/8인 64로 설정했습니다.

2. Q와 모든 단어의 K를 내적하여 Attention score 구하기
위에서 하나의 임베딩 벡터 x1x_1이 query vector q1q1으로 변환되었습니다. 하나의 query vector는 모든 임베딩 벡터(n개라고 가정)의 key 벡터인 k1,k2,..,knk_1, k_2 ,.., k_n과 내적을 통해 score를 구합니다. 그 결과는 (q1k1,q1k2,..,q1kn)(q_1\cdot k_1, q_1\cdot k_2, .. , q_1\cdot k_n) 입니다.

이 과정을 행렬 연산으로 처리하면 입력 문장의 길이를 seq_len 이라고 할 때 Q×KTQ \times K^T가 되고 (seq_len×dk)×(dk×seq_len)(seq\_len \times d_k)\times(d_k \times seq\_len)이 되어 shape 은 seq_len 크기인 정방행렬이 됩니다.

3. K의 차원의 제곱근인 dk\sqrt{d_k}로 나누어 scaling
벡터 dimension = dkd_k 크기가 크면, 내적을 했을 때 그 값이 너무 커져서 Softmax를 취한값이 너무 작아져 gradient도 작아지는 문제가 발생합니다. 이를 막기위해 각 score값을 dk\sqrt{d_k}로 나누어 scaling을 합니다.

4. (디코더의 경우) 이후 시점의 단어의 확률을 0으로 만드는 masking
현재 단어와 이전 단어만 볼 수 있게 행렬의 대각선을 기준으로 우상단 triangle의 값을 -\infty으로 만들어 softmax를 취했을 때 0이 되도록합니다.

5. Softmax
scaling 한 행렬에 softmax를 취해 attention distribution 을 구합니다.

6. V와 행렬 곱으로 attention value matrix 얻음
각 단어들의 value vector v1,v2,...,vnv_1, v_2, ... , v_n과 weighted sum을 통해 최종적으로 dvd_v의 길이를 가지는 z1z_1하나를 만들어냅니다.
입력 시퀀스의 길이가 seq_len이면 최종 행렬곱의 결과는 (seq_len,dv)(seq\_len, d_v)입니다.

이 모든 과정을 수식으로 나타내면 다음과 같습니다.
Attenion(Q,K,V)=softmax(QKTdk)VAttenion(Q,K,V) = softmax(\frac{QK^T}{\sqrt{d_k}})V

행렬 연산으로 일괄 처리되는 과정을 그림으로 보면 다음과 같습니다.
결과적으로 1~6까지 적용하여 나오는 Attention Value Matrix의 크기는 (seq_len,dv)(seq\_len, d_v) 입니다.

Multi-head Attention
Transformer 연구진은 한 번의 어텐션을 하는 것보다 여러번의 어텐션을 병렬로 사용하는 것이 더 효과적이라고 판단하였습니다.


이유는 각 어텐션 헤드는 모두 서로 다른 가중치 행렬 (WQ,WK,WV)(W^Q, W^K, W^V)을 가지고, 이에 따라 서로 다른 시각으로 정보를 수집할 수 있기 때문입니다.


따라서 앞서 보았듯이 논문에서는 dmodeld_{model} 차원을 가지는 임베딩 벡터를 num_headsnum\_heads 8로 나눈 64 차원의 Q,K,V 벡터로 축소시켜 8개의 head에서 병렬적으로 Attention을 수행합니다. head의 차원을 줄임으로써 계산 복잡도가 낮아지는 이점도 있습니다.


이후 각 head에서 나온 z를 concat 하여 하나로 만들어줍니다. 모두 연결된 행렬의 크기는 (seq_len,dmodel)(seq\_len, d_{model})이 됩니다. (dmodel=dv×num_heads=64×8d_{model} = d_v \times num\_heads = 64 \times 8) zRseq_len×dv×num_headsz \in \R^{seq\_len \times d_v \times num\_heads}

이 행렬에 또 다른 가중치 행렬 WORnum_heads×dv×dmodelW^O \in \R ^{num\_heads \times d_v \times d_{model}} 와 곱해져 최종적으로 모든 정보를 담은 output=ZRseq_len,dmodeloutput = Z \in \R^{seq\_len, d_{model}} 행렬이 만들어집니다.

전체과정을 수식으로 표현하면 다음과 같습니다.

MultiHead(Q,K,V)= Concat (head1,, head h)WO where head i=Attention(QWiQ,KWiK,VWiV)\begin{aligned} \operatorname{MultiHead}(Q, K, V) &=\text { Concat }\left(\operatorname{head}_{1}, \ldots, \text { head }_{\mathrm{h}}\right) W^{O} \\ \text { where head }_{\mathrm{i}} &=\operatorname{Attention}\left(Q W_{i}^{Q}, K W_{i}^{K}, V W_{i}^{V}\right) \end{aligned}

Where the projections are parameter matrices WiQRdmadel ×dk,WiKRdmadde ×dk,WiVRdmodel ×dvW_{i}^{Q} \in \mathbb{R}^{d_{\text {madel }} \times d_{k}}, W_{i}^{K} \in \mathbb{R}^{d_{\text {madde }} \times d_{k}}, W_{i}^{V} \in \mathbb{R}^{d_{\text {model }} \times d_{v}} and WORhdv×dmodel W^{O} \in \mathbb{R}^{h d_{v} \times d_{\text {model }}}

최종 결과 행렬이 인코더의 입력 행렬과 크기가 동일한데, 트랜스포머는 다수의 인코더를 쌓은 형태이므로 인코더에서의 입력의 크기가 출력에서도 동일 크기로 계속 유지되어야만 다음 인코더에서도 다시 입력이 될 수 있기 때문입니다.

Applications of Attention in our Mode
Transformer는 이 multi head attention을 3부분에서 사용합니다.

  • Encoder-decoder attention layer
    q는 디코더의 이전레이어에서, k,v는 인코더의 아웃풋에서 옵니다. 이는 디코더의 모든 시점에서 인코더의 모든 시점을 참고할 수 있게 합니다다. 이는 seq2seq의 ecoder-decoder 구조와 비슷합니다.
  • Encoder self-attention layer
    self-attention은 k,v,q 벡터의 출처가 같습니다. 논문에서는 인코더의 이전레이어가 출처. 인코더의 각 posotion은 이전 layer의 position을 참고합니다.
  • Decoder self-attention layer
    디코더의 각 position이 이전까지의 디코더의 position을 참고합니다. 이 때 auto-regressive model의 속성을 보존하기 위해 왼쪽으로 가는 정보흐름을 막아야합니다. 즉 이후에 나올 단어를 미리 참조하면 안된다. 이를 위해 내적한 결과를 -\infty로 masking하여 softmax를 취했을 때 0이 되도록 합니다.

1.3 Position-wise Feed-Forward Networks

FFN(x)=max(0,xW1+b1)W2+b2\begin{aligned} FFN(x) = max(0, xW_1 + b_1)W_2 + b_2 \end{aligned}

FFN은 2층짜리 fully connected feed-forward network이다.
여기서 x는 앞서 멀티 헤드 어텐션의 결과로 나온 (seq_len,dmodel)(seq\_len, d_{model})의 크기를 가지는 행렬을 말합니다. 가중치 행렬 W1W_1
(dmodel,dff)(d_{model}, d_{ff})
의 크기를 가지고, 가중치 행렬 W2W_2
(dff,dmodel)(d_{ff}, d_{model})의 크기를 가집니다. 논문에서 은닉층의 크기인 dffd_{ff}
는 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에 dmodel\sqrt {d_{model}}을 곱해줍니다.

1.5 Positional Encoding

Transformer는 recurrence와 convolution이 없으므로 sequence 안의 토큰의 상대적/절대적 위치에 대한 정보를 가지고 있어야 합니다. 이를 위해 인코더, 디코더 스택의 input embedding에 positonal encoding 벡터를 추가합니다. 이 벡터는 각 토큰의 위치, 또는 시퀀스 내에서 두 토큰의 거리에 대한 정보를 가지며 , 차원은 embedding 멕터의 차원과 같은 dmodeld_{model}입니다.

논문에서는 positonal encoding 벡터를 만들 때 다른 frequencies를 가지는 sin, cos함수를 사용했습니다. pos는 시퀀스 내에서의 단어의 위치, i는 각 단어의 임베딩 벡터에서 몇 번째 dimension(index)인지를 나타냅니다.(학습되거나 하이퍼 파라미터가 아닌 미리 고정된 값)

PE(pos,2i)=sin(pos/100002i/dmodel )PE(pos,2i+1)=cos( pos /100002i/dmodel )\begin{aligned} P E_{(p o s, 2 i)} &=\sin \left(p o s / 10000^{2 i / d_{\text {model }}}\right) \\ P E_{(p o s, 2 i+1)} &=\cos \left(\text { pos } / 10000^{2 i / d_{\text {model }}}\right) \end{aligned}

이를 통해 가변적인 시퀀스길이와 상관없이 문장의 위치정보를 잘 전달할 수 있다고 합니다.

2. Why Self-Attention

d차원을 갖는 다양한 길이의 입력 시퀀스 (x1,x2,...,xn)(x1,x2,...,xn)을 고정된 길이의 시퀀스 (z1,z2,...,zn)(z1,z2,...,zn)으로 바꿀 때 self-attention을 사용하는 것의 이점을 3가지 측면에서 비교했습니다.

  • Complexity per Layer
    각 Layer 마다의 연산량을 의미합니다.
    RNN과 비교했을 때 Self-Attention의 경우 내적 연산에서 n2n^2의 연산을 진행하고 이를 d개 모아야 하므로 총 n2dn^2 \cdot d의 연산량을 가집니다.
    반면 RNN의 경우 각 time step n번동안 WhhW_h \cdot h의 연산을 하게 되는데 이 행렬연산이 d2d^2의 연산량을 가지므로 총 n cdotd2n \ cdot d^2 의 연산량을 가집니다. 현실적으로 n이 d보다 훨씬 큰 값을 가지므로 complexity per layer 자체는 RNN이 더 낫다고 할 수 있습니다.
  • Sequential Operations
    Sequential Operations 에서 큰 차이가 발생합니다. Self Attention의 경우 한 시퀀스에 대한 representation을 만들기 위해 한번의 연산이면 해결이 되지만 RNN의 경우 시퀀스의 한 단어에 대한 연산이 끝나야지만 다음 단어로 넘어갈 수 있기 때문에 n의 연산량을 가집니다.
  • Maximum Path Length
    Maximum Path Length는 시퀀스 내 가장 멀리 떨어져 있는 단어끼리 연관성을 측정하기 위한 연산량을 의미하는데 Self-Attention은 한번의 연산으로 모든 단어끼리의 연관성을 측정하지만 RNN의 경우 처음 단어에서 끝단어까지 가는데 n번을 기다려야 하므로 여기서도 n의 연산량을 가지게 됩니다.

종합하면 Self-attention이 RNN보다 훨씬 빠르게 학습을 할 수 있습니다.

3. Training

  • Optimizer : Adam / lr warmup : 4000
  • Regularization : 3가지 사용
    • Residual Dropout : 0.1의 dropout rate로 각 sub_layer와 Add&Norm 사이에서 dropout을 진행합니다. 또 embedding과 positional encoding을 더하는 과정에도 dropout을 적용합니다.
  • Label smoothing
    0.1의 인자를 주어 Label Smoothing

4. Result


영어를 독일어로, 영어를 프랑스어로 변환할 때 다른 모델들보다 높은 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

profile
ML/AI Engineer

0개의 댓글