본문 바로가기
대학원 이야기/관련 공부

정말 간단한 Transformer의 구조/동작 과정 정리

by misconstructed 2020. 12. 1.
728x90

Transformer는 기존의 RNN 류(LSTM, GUR 등)의 recurrence 를 제거하고 오직 linear layers, attention, normalization 만으로 구성된 모델이다. Sequence-to-sequence 모델과 비슷하게 encoder와 decoder로 구성되어 있다. 한 부분씩 보면서 어떤 순서대로 동작하는지 확인해보자. Transformer를 처음으로 제안한 논문 "Attention is all you need" 의 리뷰는 여기에서 확인해볼 수 있다. 너무 오래전에 읽고 정리한 내용이라 이번 포스트 이후에 다시 읽어보고 다시 처음부터 정리해봐야겠다.


# Encoder

인코더에서는 입력으로 제공된 sequence $ X = (x_1, x_2, ..., x_n) $ 에 대한 context vector $ Z = (z_1, z_2, ..., z_n) $ 을 생성한다. Hidden state가 아니라 context vector 라고 부르는 이유는 context vector $ Z $ 는 전체 입력 sequence에 대해서 self-attention을 수행하기 때문에, 자신 이전에 오는 단어 뿐만 아니라, 이후에 오는 단어들에 대한 정보(문장 전체에 대한 정보)를 포함하고 있기 때문이다. 인코더의 동작 순서는 다음과 같다.

  1. 입력 token을 제공한다.
  2. 입력 token에 대한 positional embedding을 생성한다.
    • Transformer는 RNN과 다르게 recurrent하지 않기 때문에 각 입력에서 제공되는 토큰의 순서를 알지 못한다. 그렇기 때문에 현재 입력에서 제공하는 문장에서의 현재 토큰의 위치를 알려주기 위한 positional embedding을 함께 제공해야 한다. (쉽게 말해 위치 정보를 제공한다.) 
    • "Attention is all you need" 논문에서는 positional embedding을 따로 학습하지 않고, fixed static embedding을 사용한다. 하지만, BERT와 같이 Transformer를 활용한 다른 모델들에서는 positional embedding을 사용한다. 
  3. 입력 토큰과 positional embedding의 element-wise sum을 수행한다.
    • 입력 토큰의 정보와 해당 토큰의 위치 정보를 모두 포함하고 있는 벡터를 생성한다.
  4. Dropout 적용
  5. N 개의 encoder layer를 거쳐서 최종 결과 $ Z $ 를 생성한다.
    1. 입력 문장과 입력 문장에 대한 input mask를 입력으로 제공한다.
    2. 입력에 대한 multihead attention 을 수행한다.
      1. 입력으로 들어온 토큰이 Q(Query), attention을 하는(다른 입력 토큰들) 토큰을 각각 K(Key), V(Value)로 지정한다.
      2. Q, K, V 값을 구하기 위해 matrix $ W^Q, W^K, W^V $ 를 각각 입력값($ Q, K, V $)에 대해서 곱한다.
      3. 2번에서 계산한 Q, K, V 값을 head의 개수만큼 나눈다. 
        • 이렇게 나눠서 각각 병렬적으로 연산을 수행하기 때문에 multihead 라고 표현한다.
      4. 모든 attention이 계산이 되었으면 계산 결과를 합친다.
        • $ i $ 번째 head에 대해서 $ head_i = Attention(QW^Q, KW^K, VW^V) $ 을 수행한다.
        • $ Attention(Q, K, V) = softmax(\frac{QK^T}{\sqrt{d_k}})V $
          • $ \sqrt{d_k} $ 로 scaling을 해서 dot product의 결과값이 너무 커지는 것을 방지한다.
          • softmax 함수를 통해서 0에서 1사이의 값으로 결과를 제공한다. = attention weight
      5. 합친 결과에 대해서 linear layer를 통과시킨다. ($W^O $ 과 곱한다.)
    3. dropout 적용
      • dropout 을 적용하기 때문에, attention vector의 전체 합이 1이 되지 않는다.
    4. residual connection 수행 : 입력으로 제공된 문장을 더해준다.
    5. LayerNormalization : mean = 0, std = 1 으로 만들어서 학습하기 쉽게 한다.
    6. Positionwise feedforward layer
      1. linear layer를 통해서 hidden dim(논문에서는 512 차원) 을 pf_dim (2048 차원) 으로 늘린다.
      2. ReLU 를 적용한다.
      3. Dropout을 적용한다.
      4. 다른 linear layer를 통해서 pf_dim 에서 다시 hidden dim(512 차원)으로 줄인다.
    7. Dropout
    8. Residual connection
    9. Layer Normalization
    10. Output $ Z $

# Decoder

디코더에서는 인코더에서 생성산 context vector $ Z $ 를 기반으로 target sentence $ \hat{Y} $ 을 생성한다. 생성한 결과 $ \hat{Y} $ 은 실제 정답 문장인 $ Y $ 와 비교된다. 인코더와 거의 동일한 방식으로 수행되지만, 2개의 multihead attention을 수행한다는 점이 다르다. (masked multihead attention,multihead attention over input sequence)

  1. 디코더의 입력 토큰이 제공된다.
  2. 입력에 대한 positional embedding 생성
  3. Dropout 적용
  4. M 개의 decoder layer를 통과한다.
    1. 입력에 대한 self-attention을 수행한다.
      • target mask를 함께 사용하는데, 이것은 디코더에서는 현재 존재하는 위치 이후의 단어에 대한 attention을 수행하면 cheating이 될 수 있기 때문에, 현재 단어까지만 1, 그 이후에 대해서는 0으로 지정한다.
    2. Dropout 
    3. Residual connection
    4. Layer normalization
    5. multihead attention
      • 인코더에서 생성한 context vector를 K, V, 현재 디코더의 토큰을 Q 로 지정해서 attention을 수행한다.
    6. Dropout
    7. Residual connection
    8. Layer normalization
    9. Positionwise feedforward layer (인코더와 동일하게 수행)
    10. Dropout
    11. Residual connection
    12. Layer normalization
  5. Linear layer
  6. Softmax

# 기타

Optimizer : Adam을 사용하는데, "Attention is all you need" 에서는 Adam optimizer의 learning rate을 'warm-up' 단계와 'cool-down' 단계로 구분해서 learning rate을 바꿔주면서 학습을 진행했다. 하지만 transformer를 사용한 다른 논문들은 그냥 고정된 learning rate을 사용하는 경우가 더 많다.

728x90

댓글