(7강) Transformer I

💡
RNN 기반 번역 모델의 단점을 Self-Attention 구조로 극복한 Transformer에 대해 알아본다.

RNN : Long-Term Dependency

Transformer는 아주 높은 성능으로 현재는 모든 RNN 구조를 대체해나가고 있다. 이에 대해 알아보기 전에 RNN에 대해 되짚어보자.

RNN은 매 Time Step마다 {xt,ht1}\{ x_t, h_{t-1} \}를 통해 Hidden State Vector를 계산하는데, 초반에 등장한 Long Term의 Input은 정보는 여러 Hidden State Vector를 거쳐서 전달될 수 밖에 없다. 이 과정에서 Data가 왜곡되거나 소실될 수 있었으며, 역전파 단계에서도 문제가 발생할 수 있다.

'I'나, 'Some'과 같은 Input은 마지막 Hidden State에 온전히 도달하기 어렵다.

이를 해결하기 위해 Bi-Directional RNN이 제시되기도 했다. 먼저 hth_txt+1x_{t+1}의 정보를 담을 수 없는 이슈와, 초반의 정보가 유실되는 이슈를 해결하고자 했다. Forward와 Backward로 부터 얻은 Hidden State Vector를 Concatenate함으로써 최종 hth_t를 얻는 방식이다. Encoding Vector는 기존 RNN에 비해서 문장 전체의 정보를 담으며, 2배의 Dimension을 갖는 형태가 된다.

하지만 여전히 Long Term Dependency의 모든 문제를 해결할 수 없었고, Transformer가 등장했다.

Transformer's Mechanism of Encoding

Transformer의 공식 논문 제목은 "Attention is all you need"이다. 이전의 NLP 모델은 RNN을 기반으로 하고, Attention Mechanism을 Add-on Module로 사용했다. Transformer는 RNN구조 없이 오직 Attention Mechanism으로 구현되었다. Transformer는 Attention만으로 Sequential Data를 입력받고 출력하는 것이다.

Transformer는 Time Step의 개념 없이 Input Data xix_i에 대해 Encoding Vector인 hih_i를 생성해낸다.

Input → Output 관점으로 보면, xix_ihih_i이다. 이를 수행하는 {WQ,WK,WV}\{ W^Q, W^K, W^V \}가 Transformer의 Self Attention Module이다.

이 과정을 위의 예시로 자세히 알아보자.

x1x_1인 'I'에 대해서 출력 Vector h1h_1가 생성된다. 이때, 'I'는 생성하고자 하는 정보이자 요청이다. 이는 RNN with Attention에서 보았던, Decoder의 hth_t역할을 하는 것이다. Transformer에서는 이를 표현하기 위해, 'I'에 대한 Query Vector를 생성한다.

'I'는 같이 입력된 다른 단어들과의 관계를 확인하고, 중요한 정보를 선별하게 된다. 각 단어간의 유사도를 구하기 위해 내적을 수행하게 된다. 이는 RNN with Attention에서 보았던, Encoder의 hˉs\bar h_s와의 내적과 유사하다. Transformer에서는 이를 위해 모든 단어인 'I', 'go', 'home'의 Key Vector를 생성한다. 이는 유사도를 측정하기 위한 일종의 재료로 사용된다.

Attention Score를 계산하기 위해 Q Vector는 각각의 K Vector와 내적을 수행한다. 이 값을 Softmax에 통과시켜 Attention Vector를 얻게 된다. 이는 RNN with Attention에서 보았던 과정이며, 마찬가지로 데이터에 대한 가중평균의 역할을 수행한다.

가중평균의 의미를 가진 Attention Vector와 각각의 단어의 Value Vector의 곱을 통해 'I'에 대한 Context Vector를 얻을 수 있다. 이렇게 얻은 Context Vector는 'I'에 대한 Encoding Vector로 이해할 수 있다.

위와 같은 과정을 일반화 하면, 모든 단어에 대한 Encoding Vector를 얻을 수 있다. 이 과정에서 모든 Input Data는 총 Q, K, V 각각 3개의 역할을 수행하게 된다. 각 단어를 Encoding 할 때 바뀌는 것은 오직 그 단어에 해당하는 Q Vector뿐이다.

각각의 hih_i의 관점으로 보았을 때, 이는 xix_i로부터 생성된 Q Vector와 K Vector로 유사도를 측정하기 때문에, 본인과의 관계도 포함하며 정보가 더 많이 포함될 확률이 높다. 이와 같은 과정과 특징으로, 이를 Self-Attention Module이라고 칭한다.

Self-Attention Module's Operation

Self-Attention Module은 입력을 Q, K, V Vectors로 변환하기 위해 각각의 {WQ,WK,WV}\{ W^Q, W^K, W^V \}를 갖는다. 같은 벡터에서도 역할에 따라서 다른 벡터로 변환하여 의미를 확장하는 형태를 갖는 것이다. 이와 같은 연산은 행렬 연산을 통해서 이루어진다.

'Thinking'과 'Machine'을 입력으로 하는 예시
X, Q, K, V 행렬은 각 Row Vector가 쌓여 있는 형태이다. Q와 K Vector는 내적을 위해 동일한 차원을 가져야만 한다.

Transformer는 위와 같은 과정을 통해서 동시에 Input을 처리한다. Input 간의 거리와 무관하게 관계를 통한 정보를 생성하기 때문에 기존 RNN의 근본적 한계를 극복하였다.

Self-Attention Module의 동작을 수식으로 확인해보자.

각 Data의 Encoding Vector를 구하는 식
모든 Data에 대해 일반화 한 식

이와 같이 연산을 행렬로 표현할 수 있기 때문에, GPU를 통한 병렬처리와 빠른 연산이 가능하다. 이런 특징으로 Transformer는 RNN에 비해 학습이 빠르다는 장점도 갖는다.

위 연산을 시각화하여 확인해보자.

각 행렬의 차원과 행렬 연산의 예시 최종 출력의 각 Row Vector는 각각 Q Vector에 대한 결과값으로 이해할 수 있다.

이를 통해 알 수 있는 제약사항은 다음과 같다. Q Vector와 K Vector는 내적을 통해 유사도 값을 구하기 때문에, 동일한 Dimension을 가져야 한다. V Vector는 다른 Dimension 가질 수 있으며, Encoding Vector의 Dimension을 결정한다. K Vector와 V Vector는 동일한 갯수로 1:1 대응 되어야 한다.

최종적인 연산을 시각화하여 확인해보자.

실제 연산에서는 dk\sqrt{d_k}로 나누어 Scaling을 수행한다.

Q Vector와 K Vector의 내적의 값은 차원에 따라 값의 분포가 커지는 이슈가 생긴다. Q와 K의 각 원소의 값이 평균이 0이고 분산이 1인 확률변수라고 가정하면, 내적 값의 평균은 dkd_k와 관계없이 0을 유지하나 분산은 dkd_k배가 된다. 벡터 내의 값의 분산이 커지는 경우, 벡터내의 각각의 Scalar 값은 큰 차이를 갖게된다. 이 상태에서 Softmax 함수를 통과하면 극단적인 확률 값을 갖게 된다.

표준편차의 값인 dk\sqrt{d_k}로 값으로 나누게 되면, 각 Scalar 값의 분산이 일정해질 수 있다. 즉 Scaling을 시행하는 것이다. 안정적인 확률값을 통해 Gradient Vanishing 이슈를 방지할 수 있고, 이를 통해 안정적인 학습을 보장할 수 있게 된다.

실습

GitHub Gist Link


(8강) Transformer II

💡
Transformer의 Encoder와 Decoder에 대해 자세히 알아본다.

Multi-Head Attention

단일한 Self-Attention 구조를 확장한 형태이다. Self-Attention 과정이 병렬적으로 동시에 여러 Head에서 일어나는 것이다. 이를 사용하는 이유는, 동일한 Input Data이더라도 다양한 관점에서 정보를 취합하기 위함이다.

예를 들어, 'I went to the school. I studied hard. I came home. I took the rest'와 같은 문장이 주어졌다고 가정하자. 이 입력을 여러 Head를 통해 Encoding하는 것의 의미는 다음과 같다. 특정 Head는 공간의 이동 정보에 많은 가중치를 두어 학습하고, 특정 Head는 행동 정보에 많은 가중치를 두어 학습하는 형태로 이해할 수 있다. 여러 Head가 상호보완적으로 작동하여, 더 풍부하게 정보를 포함하는 것이다. 즉, 좋은 품질의 Encoding Vector를 생성하기 위해 Multi-Head구조를 사용하는 것이다.

h만큼의 Head가 있는 것을 확인할 수 있다.

각각의 Head에서 Encoding이 일어나고, h의 갯수만큼 대응하는 Encoding Vector가 생성된다. 이를 Concatenate하고, 기존의 차원으로 변경하기 위해 WOW^O에 의한 선형변환이 일어난다.

이를 시각적으로 확인하면 다음과 같다.

동일한 Input으로부터 Multi-Head가 동작하는 예시

ii번째 Head가 생성한 ziz_i를 Concatenate한 결과와 이를 선형변환하여 zz를 생성하는 과정 예시 Concatenate한 ziz_i 행렬은 (dQ×dVi)( d_Q \times d_V \cdot i)의 형태를 갖는다. WOW^O행렬은 (dVi×dV)( d_V \cdot i \times d_V )의 형태를 갖는다.

Q Vector와 K Vector간의 관계와, 여러 Head가 가지는 특정 패턴을 시각화하여 확인해보자.

'its' Query에 대해 2개의 Head가 각각 다른 가중치를 두고 있다.
'making' Query에 대해 여러 Head가 각각 다른 패턴의 가중치를 가지는 것을 볼 수 있다.

RNN과 연산 비교

Self-Attention과 RNN의 연산을 비교해보자.

Self-Attention은 RNN에 비해 연산 시간은 짧으나, 많은 메모리를 요구한다.

RNN의 주 연산은 각 Whh×htW_{hh} \times h_t의 연산이다. 이를 매 Time Step에서 계산해야 하므로, O(nd2)O(n \cdot d^2)의 복잡도를 가진다. 행렬 연산은 GPU를 통해 상수시간으로 처리할 수 있으나, nn번의 Time Step 계산은 병렬 처리가 불가능 하기 때문에 O(n)O(n)의 시간 복잡도를 가진다. 즉, Sequence가 길어짐에 따라 학습 시간이 늘어난다는 의미이다.

Self-Attention의 주 연산은 QKTQ K^T이다. 이는 (n×d)×(d×n)(n \times d) \times (d \times n) 형태의 연산으로, O(n2d)O(n^2 \cdot d)의 복잡도를 가진다. 이 연산은 GPU의 병렬화 작업을 통해 상수시간으로 처리할 수 있다. 단, 그만큼 메모리에 모든 데이터가 올라가는 소요가 생긴다. 즉, Sequence가 길어짐에 따라 메모리의 요구량이 늘어난다는 의미이다.

Block-Based Model

Transformer는 Multi-Head Attention을 핵심 Module로 하고, 여러 후처리를 진행하여 하나의 Block 형태의 Module을 구성한다. 예시 사진을 통해 자세히 알아보자.

Block 형태의 Module 시각화

Multi-Head Attention에 들어가는 3개의 화살표는 Sequence로부터 변환된 각각 Q, K, V Vector를 의미한다. 이를 통해 얻어진 Encoding Vector를 Add & Norm Layer에 전달한다.

Add & Norm Layer는 Encoding Vector뿐만 아니라, Residual Connection을 통해 Add 연산을 수행한다. 이 연산을 수행한 후 Layer Normalization을 수행한다.

여기서 얻은 값을 Feed Forward Layer로 전달하고, 이후 다시 Add & Norm 연산을 수행한다.

Add 연산의 Residual Connection이란, Computer Vision에서 먼저 사용된 개념으로 Layer가 깊어지더라도 Gradient Vanishing 이슈가 생기지 않도록 하는 기법이다. 특정 Layer를 통과하기 전의 Vector와, Layer를 통과한 Vector를 더하여 결과 Vector를 생성한다. 이렇게 하게 되면, 해당 Layer는 Input과 Output의 차이값만을 고려하여 학습을 진행할 수 있게 된다. 이를 통해 Gradient Vanishing 이슈가 해결되고, 학습 속도까지 향상시킬 수 있다. Add 연산은 Element-wise Operation이기 때문에 이를 위해 Vector의 차원을 유지해야 한다. 앞서 보았듯 Transformer의 Self-Attention Module은 WOW^O를 통해 Output Vector의 차원을 유지시킨다.

Normalization연산은 주어진 다수의 샘플들에 대해서 해당 샘플들이 우리가 원하는 평균과 분산이 되도록 만드는 과정이다. 해당하는 샘플들의 평균을 0으로, 분산을 1로 만든 이후에 선형변환을 수행하여 원하는 분포를 얻을 수 있게 된다. 위 블록에서의 Normalization은 Layer Normalization을 의미하고, Layer의 샘플들의 기존 평균과 분산값을 버리고 최적의 평균과 분산을 갖는 값으로 변환시킨다. 이를 통해 학습을 안정화하고 성능을 향상시킬 수 있다.

위 수식은 평균과 분산을 초기화 하는 수식을 의미한다. Layer Normalization의 시각화 예시는 위와 같다.
각 Word 단위로, Column을 기준으로 평균과 분산을 초기화한다. 이후 Row를 기준으로 원하는 평균과 분산을 주입한다.

Positional Encoding

Transformer는 주어진 Sequence를 Encoding할 때, 순서와 거리에 무관하게 수행된다. 이는 Sequence의 순서가 바뀌어도 동일하게 수행된다. 즉, 아직까지는 Encoding Vector에는 순서에 대한 정보가 없다는 의미이다. Transformer는 입력 벡터에 순서와 관련된 정보를 포함시키기 위해서 Positional Encoding을 실시한다. 각 위치와 차원에 해당하는 유니크한 특정 값을 미리 생성해놓고, 해당 값을 추가함으로써 Sequence의 위치에 대한 정보를 추가하는 것이다.

순서의 정보를 입력하기 위해 미리 정의한 Position Encoding Vector 시각화 예시

Warm-up Learning Rate Scheduler

학습을 진행할 때 Learning Rate을 고정된 값으로 사용하지 않고, 변동을 주는 기법이 LR Scheduling이다. 학습의 속도를 빠르게 하고, 성능을 개선하는 목적으로 사용된다.

Warm-up 기법은 초반에는 LR을 굉장히 작은 값으로 사용하고, 어느정도 Iteration에 도달했을 때 지역 최소값을 탈출하기 위해 LR을 올리게 된다. 이후 전역 최소값에 제대로 도달할 수 있도록 LR을 점차 줄여나가는 방식이다.

LR값이 작게 시작해서 급격히 커졌다가, 다시 작아지는 것을 볼 수 있다.

Decoder

Transformer의 Decoder 동작에 대해 확인해보자.

Transformer의 동작 구조

Decoder의 입력은 맞추고자 하는 문장을 한 스텝씩 미룬 형태로 전달된다. 예를 들어, '나는 학교에 간다'라는 문장이라면, '<SOS> 나는 학교에'와 같은 형식으로 입력되는 것이다.

입력된 Sequence Data는 Masked Multi-Head Attention을 거쳐 Encoding 된다. 이는, Seq2Seq with Attention의 Decoder가 Input에 대해 Hidden State Vector를 생성하는 것과 유사하게 이해할 수 있다.

Residual Connection을 통한 Add와 Norm 연산을 마친 Encoding Vector는 다시 Multi-Head Attention에 전달되는데, 이때 이 Vector는 오직 Query Vector로서의 역할만 수행한다. Key와 Value Vector는 Encoder로부터 전달받아 사용하게 된다. 이는 Seq2Seq with Attention에서 Encoder와 Decoder의 Hidden State Vector의 내적으로 유사도를 구하는 것처럼 이해할 수 있다. 즉, 각 Input마다 필요한 정보를 Encoder로부터 받아서 사용하는 것이다.

이후의 과정을 거치고 나서, Linear Layer를 통과하는데 이 때 해당 언어의 Vocab Size만큼의 차원을 갖게 된다. 예를 들어, 한국어의 경우에는 10만여개의 Vocab이 있으므로, 해당 Vector는 10만여 차원을 갖게 된다.

Vocab Size를 갖는 Vector를 Softmax에 통과시켜 확률값을 얻고, 가장 높은 확률 값을 갖는 단어를 최종 Output으로 사용한다. Output과 확률값은 실제 Ground Truth와의 비교를 통해 Loss를 생성하게 되고, 역전파를 통해 모든 Parameter를 업데이트 하게 된다.

Masked Self-Attention은 Decoder의 예측 과정에서 일부 정보에 접근하지 못하도록 변형한 Module이다. 예를 들어, '<SOS> 나는 집에'라는 Input Sequence가 주어졌을 때 '<SOS>' 대한 예측 Ground Truth는 '나는'이 된다. Encoding 과정에서 이미 Ground Truth에 대한 유사도를 가지고 정보를 취합하는 것은 목적에 맞지 않기 때문에, 이러한 정보를 갖지 못하도록 후처리하는 방식이다.

대각선 위쪽의 유사도는 0이 되고, 나머지의 값으로 1을 채운다.

실습

GitHub Gist Link


Reference

Transformer Paper

Explain Transformer with Illustration

Explain Transformer with Code

Explain Group Normalization

Paper of Attention's Explanation I

Paper of Attention's Explanation II

'네이버 부스트캠프 AI Tech' 카테고리의 다른 글

[U] Day 21 - 그래프 이론 기초 & 그래프 패턴  (0) 2021.03.26
[U] Day 20 - NLP V  (0) 2021.03.26
[U] Day 18 - NLP III  (0) 2021.03.26
[U] Day 17 - NLP II  (0) 2021.03.26
[U] Day 16 - NLP I  (0) 2021.03.26

+ Recent posts