[AIB 18기] Section 3 - Sprint 2 - Note 4 - Transformer

ysk1230·2023년 4월 28일
0

Transformer 개요

RNN 기반 모델이 가진 구조적 단점은 단어가 순차적으로 들어온다는 점입니다.

그렇기 때문에 처리해야 하는 시퀀스가 길수록 연산 시간이 길어지는데요.

트랜스포머는 이런 문제를 해결하기 위해 등장한 모델입니다.

모든 토큰을 동시에 입력받아 병렬 처리하기 때문에 GPU 연산에 최적화되어 있습니다.

아래는 트랜스포머의 구조를 단순하게 시각화한 그림입니다.

Encoder, Decoder로 표현된 사각형을 각각 인코더 블록과 디코더 블록이라고 합니다.

트랜스포머는 인코더 블록과 디코더 블록이 6개씩 모여있는 구조를 하고 있습니다.

positional_encoding


positional_encoding

왼쪽은 인코더 블록 하나를 나타내고 오른쪽은 디코더 블록 하나를 나타냅니다.

인코더 블록은 크게 2개의 sub-layer ▶️ [Multi-Head (Self) Attention, Feed Forward] 로 나눌 수 있습니다.

디코더 블록은 3개의 sub-layer ▶️ [Masked Multi-Head (Self) Attention, Multi-Head (Encoder-Decoder) Attention, Feed Forward] 로 나눌 수 있습니다.

Positional Encoding (위치 인코딩)

pe 트랜스포머에서는 병렬화를 위해 모든 단어 벡터를 동시에 입력받습니다.
그렇게 되면 컴퓨터는 어떤 단어가 어디에 위치하는지 알 수 없는데요.
컴퓨터가 단어의 위치를 알 수 있도록 위치 정보를 담은 벡터를 따로 제공해주어야 합니다.
단어의 상대적인 위치 정보를 담은 벡터를 만드는 과정을 **Positional Encoding** 이라고 합니다.

Self-Attention (셀프-어텐션)

트랜스포머의 주요 메커니즘인 Self-Attention 에 대해 알아보도록 하겠습니다.

아래와 같은 문장이 있다고 해보겠습니다.

The animal didn't cross the street because it was too tired

위 문장을 제대로 번역하려면 "it" 과 같은 지시대명사가 어떤 대상을 가리키는지 알아야 합니다.

그렇기 때문에 트랜스포머에서는 번역하려는 문장 내부 요소의 관계를 잘 파악하기 위해서, 문장 자신에 대해 어텐션 메커니즘을 적용합니다.

이를 Self-Attention 이라고 합니다.

아래는 "it" 이 어떤 단어와 가장 연관되어 있는 지를 시각화한 그림입니다.

self_attention_visualization

Self-Attention은 어떤 과정이길래 단어 사이의 관계를 알아낼 수 있을까요?

Self-Attention에서도 쿼리(Query)-키(Key)-밸류(Value)의 아이디어가 동일하게 등장합니다.

각각의 벡터가 어떤 역할을 하는지 알아보겠습니다.

  • 쿼리(q)는 분석하고자 하는 단어에 대한 가중치 벡터입니다.
  • 키(k)는 각 단어가 쿼리에 해당하는 단어와 얼마나 연관있는 지를 비교하기 위한 가중치 벡터입니다.
  • 밸류(v)는 각 단어의 의미를 살려주기 위한 가중치 벡터입니다.

Self-Attention은 세 가지 가중치 벡터를 대상으로 어텐션을 적용합니다.

적용하는 방식은 기존 Attention 메커니즘과 거의 동일합니다.

  1. 먼저, 특정 단어의 쿼리(q) 벡터와 모든 단어의 키(k) 벡터를 내적합니다. 내적을 통해 나오는 값이 Attention 스코어(Score)가 됩니다.

  2. 트랜스포머에서는 이 가중치를 q,k,v 벡터 차원 dkd_k 의 제곱근인 dk\sqrt{d_k} 로 나누어줍니다.
    계산값을 안정적으로 만들어주기 위한 계산 보정으로 생각해주시면 됩니다.

  3. 다음으로 Softmax를 취해줍니다.

    이를 통해 쿼리에 해당하는 단어와 문장 내 다른 단어가 가지는 관계의 비율을 구할 수 있습니다.

  4. 마지막으로 밸류(v) 각 단어의 벡터를 곱해준 후 모두 더하면 Self-Attention 과정이 마무리됩니다.


그림으로 Self - Attention 다시보기

1. 가중치 행렬 WQ,WK,WVW^Q, W^K, W^V 로부터 각 단어의 쿼리, 키, 밸류(q, k, v) 벡터를 만들어냅니다.

transformer_15

2. 분석하고자 하는 단어의 쿼리 벡터(q)와 문장 내 모든 단어(자신 포함)의 키 벡터(k)를 내적하여 각 단어와 얼마나 관련 정도를 구합니다.

(아래 그림에서는 dk\sqrt{d_k}로 나누어 준 뒤에 Softmax를 취해주는 과정은 생략되었습니다.)
transformer_15

3. Softmax의 출력값과밸류 벡터(v)를 곱해준 뒤 더하면 해당 단어에 대한 Self-Attention 출력값을 얻을 수 있습니다.

transformer_15

4. 하나의 벡터에 대해서만 살펴보았지만 실제 Attention 계산은 행렬 단위로 병렬 계산됩니다.

transformer_15

실제로 각 벡터는 행렬(Q, K, V)로 한꺼번에 계산됩니다. WQ,WK,WVW^Q, W^K, W^V 는 학습 과정에서 갱신되는 파라미터로 이루어진 행렬입니다.

세 행렬과 단어 행렬을 내적하여 쿼리, 키, 밸류 행렬(Q, K, V)를 만들어냅니다.

transformer_12

위에서 살펴본 바와 같이

  1. 먼저 쿼리 행렬(Q)과 키 행렬(K)을 내적합니다.

  2. 결과로 나오는 행렬의 요소를 dk\sqrt{d_k}나누어 줍니다.

  3. 행렬의 각 요소에 소프트맥스(Softmax)를 취해줍니다.

  4. 마지막으로 밸류 행렬(V)과 내적하면 최종 결과 행렬(Z)이 반환됩니다.
    transformer_13


Multi-Head Attention

다음으로 Multi-Head Attention 에 대해 알아보겠습니다.

Multi-Head Attention 을 적용하면 여러 개의 Attention 메커니즘을 동시에 병렬적으로 실행합니다.

각 Head 마다 다른 Attention 결과를 내어주기 때문에 앙상블과 유사한 효과를 얻을 수 있으며, 병렬화 효과를 극대화 할 수 있습니다.

논문에서는 8개의 Head를 사용하였는데요.

8개의 Attention 메커니즘을 동시에 실행하여 각각의 출력 행렬 Z0,Z1,,Z7Z_0, Z_1, \cdots , Z_7 을 만들어냅니다.

transformer_16

출력된 행렬 Z0,Z1,,Z7Z_0, Z_1, \cdots , Z_7 은 이후에 이어붙여집니다(Concatenate).

그리고 또 다른 파라미터 행렬인 WoW^o 와의 내적을 통해 Multi-Head Attention의 최종 결과인 행렬 ZZ를 만들어지지요.

여기서 행렬 WoW^o의 요소 역시 학습을 통해 갱신되는 가중치입니다.

최종적으로 생성된 행렬 ZZ는 어텐션 메커니즘에 입력되는 행렬 XX동일한 형태(Shape)을 가지고 있습니다.
transformer_17

Layer Normalization & Skip Connection

lnorm_resicon

트랜스포머의 모든 sub-layer에서 출력된 벡터는 Layer normalizationSkip connection을 거치게 됩니다.

Layer normalization의 효과는 Batch normalization과 유사합니다. 학습이 훨씬 빠르고 잘 되도록 합니다.

Skip connection(혹은 Residual connection)은 역전파 과정에서 정보가 소실되지 않도록 합니다.

Sprint 3에서 배울 ResNet의 주요 메커니즘이므로 해당 부분에서 더욱 자세하게 다룰 예정입니다.

Feed Forward Neural Network

스크린샷 2021-03-29 오후 5 27 32

다음으로 FFNN(Feed forward neural network) 로 들어갑니다.
은닉층의 차원이 늘어났다가 다시 원래 차원으로 줄어드는 단순한 2층 신경망입니다.
활성화 함수(Activation function)으로 ReLU를 사용합니다.

FFNN(x)=max(0,W1x+b1)W2+b2\text{FFNN}(x) = \max(0, W_1x + b_1) W_2 +b_2

Masked Self-Attention

Masked Self-Attention은 디코더 블록에서 사용하기 위해서 마스킹 과정이 포함된 Self-Attention입니다.

언어 모델에서 디코더가 단어를 생성할 때에는 Auto-Regressive(왼쪽 단어를 보고 오른쪽 단어를 반복하여 예측)하게 진행되었습니다.

RNN을 사용한 번역 모델에서도 생성하려는 단어 이후의 왼쪽에 있는 단어 정보만을 고려하여 단어를 생성하였습니다.

이러한 방법은 트랜스포머에서도 유지해주게 되는데요.

단어가 순차적으로 입력되는 RNN과 달리 트랜스포머에서는 타깃 문장 역시 한 번에 입력되기 때문에
해당 위치 타깃 단어 뒤에 위치한 단어는 Self-Attention에 영향을 주지 않도록 마스킹(Masking)을 해주게 됩니다.

아래 그림을 통해 Masked Self-Attention에 대해 알아보도록 하겠습니다.

Masked_Self-Attention_in_structure Masked_Self-Attention_ex

Self-Attention (without Masking) vs Masked Self-Attention

Masked_Self-Attention_ex2

Self-Attention 메커니즘은 쿼리 행렬(Q)와 키 행렬(K)의 내적합니다.

결과로 나온 행렬을 차원의 제곱근 dk\sqrt{d_k} 로 나누어 준 다음,

Softmax를 취해주고 밸류 행렬(V)과 내적하였습니다.

Masked Self-Attention 에서는 Softmax를 취해주기 전, 가려주고자 하는 요소에만 -\infty 에 해당하는 매우 작은 수를 더해줍니다.

아래 코드 예시에서는 -10억(=-1e9)을 더해주었습니다.

이 과정을 마스킹(Masking)이라고 합니다.

마스킹된 값은 Softmax를 취해 주었을 때 0이 나오므로 Value 계산에 반영되지 않습니다.

masked_1 masked_2

Encoder-Decoder Attention

Encoder-Decoder_Attention

디코더에서 Masked Self-Attention 층을 지난 벡터는 Encoder-Decoder Attention 층으로 들어갑니다.

좋은 번역을 위해서는 번역할 문장과 번역된 문장 간의 관계 역시 중요합니다.

번역할 문장과 번역되는 문장의 정보 관계를 엮어주는 부분이 바로 이 부분입니다.

이 층에서는 디코더 블록의 Masked Self-Attention으로부터 출력된 벡터를 쿼리(Q) 벡터로 사용합니다.

키(K)와 밸류(V) 벡터는 최상위(=6번째) 인코더 블록에서 사용했던 값을 그대로 가져와서 사용합니다.

Encoder-Decoder Attention 층의 계산 과정은 Self-Attention 했던 것과 동일합니다.

아래는 Encoder-Decoder Attention 가 진행되는 순서를 나타낸 이미지입니다.

Encoder-Decoder_Attention_gif

Linear & Softmax Layer

Linear_Softmax

디코더의 최상층을 통과한 벡터들은 Linear 층을 지난 후 Softmax를 통해 예측할 단어의 확률을 구하게 됩니다.

0개의 댓글