일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- BOXPLOT
- Operation function
- 정규분포 MLE
- 표집분포
- Python 특징
- linalg
- 부스트캠프 AI테크
- ndarray
- Numpy data I/O
- 가능도
- namedtuple
- seaborn
- Python 유래
- Numpy
- dtype
- VSCode
- boolean & fancy index
- 딥러닝
- scatter
- 최대가능도 추정법
- python 문법
- Comparisons
- subplot
- unstack
- 카테고리분포 MLE
- type hints
- Array operations
- Python
- groupby
- pivot table
- Today
- Total
또르르's 개발 Story
[19] Transformer 이해하기 (2) 본문
[14-1] Transformer 이해하기 (1)에서 이어집니다.
[14-1] Transformer 이해하기 (1)
Sequential model에서 중간중간에 값이 빠져있거나, 순서가 뒤바뀐 값이 있으면 모델링하기 어렵다는 단점이 있습니다. 이런 문제를 해결하고 하는 것이 Transformer입니다. Transformer는 RNN과 같이 재귀
dororo21.tistory.com
1️⃣ Scaled Dot-Product Attention
Scaled Dot-Product Attention은 Transformer 구조에서 핵심적인 구조로 뽑힙니다.
여기서 사용되는 핵심 vector들의 이름과 수행하는 일은 아래와 같습니다.
- queries : 주어진 vector들 중에 어느 vector를 가져올지 기준이 되는 vector
- keys : 유사도가 계산되는 (내적이 되는) vector
- values : keys(유사도)와 매칭 되는 vector
여기서 queries와 keys vector는 dimension이 같아야 하지만 keys와 values는 dimension이 꼭 같지는 않아도 됩니다.
Queries vector와 key vector의 내적에 의한 유사도만 높다면 timestep이 멀리 있다 하더라도 손쉽게 가지고 올 수 있습니다. 그래서 self-attention 모델은 Long-Term Dependency 문제를 해결할 수 있습니다.
Scaled Dot-Product Attention은 queries, keys, values vector를 사용해서 아래와 같이 계산합니다.
(대문자로 주어진 K, V는 vector들을 row형태로 합쳐놓은 행렬)
$q$ vector와 K의 각각 vector $k_{j}$를 내적해서 유사도를 구한고, 내적값들을 다 더한 후, $i$번째 vector에서 가지는 유사도 확률을 구해줍니다. 이후, $i$번째 vector와 매칭되는 value vector를 곱해서 더한 것이 value vector에 대한 가중평균입니다. (최종적으로 $d_{v}$ 차원이 나오게됨)
이제 확장을 해보면 q vector가 아닌 Q matrix (q vector들의 row 집합)를 사용합니다. ($d_{k}$는 key vector가 가지는 dimension)
그래서 보면 Q에서 사용했던 첫 번째 vector는 마지막 (Q x d_v) 에서 첫 번째 vector에 매칭 되고 (빨간선), Q에서 사용된 두 번째 vector는 마지막 Q x d_v에서의 두 번째 vector에 매칭(초록선)됩니다. 따라서 각각의 query vector에 대한 각각의 output vector를 한 번에 계산하는 것입니다.
이후, Scaled Dot-Product Attention은 $\sqrt {d_{k}}$로 값을 나눠줍니다.
✅ 왜 하필 $\sqrt {d_{k}}$로 나눠줄까?
위 사진과 같이 $[a,b] \times [x,y]$가 내적을 수행한다고 가정합니다.
$a,b,x,y$가 각각 통계적으로 독립인 평균 : 0, 분산 : 1이라고 할 때,
- $ax+by$ 내적값의 평균 : 0
- $ax$ 분산 : 1
- $by$ 분산 : 1
- $ax+by$ 분산 : 2
을 따라갑니다.
만약 query와 key vector의 차원이 100차원일 때 내적을 수행하면 (평균 :0, 분산 : 1이라 가정), query와 key vector 내적값의 분산은 100이 됩니다(분산의 합). 표준편차는 10으로 나오게 되고, $QK^{T}$ 내적값의 요소 크기는 $[8,-11,7]$ 정도로 산출됩니다. (임의의 값이며 그 정도 크기의 값으로 산출된다는 의미)
만약, query와 key vector 내적값의 분산이 2 (분산의 합) 라고 하면, 표준편차는 $\sqrt{2}$가 나오고, $QK^{T}$ 내적값의 요소 크기는 $[1.1,-0.8,-1.7]$ 정도로 산출됩니다. (임의의 값이며 그 정도 크기의 값으로 산출된다는 의미)
문제는 분산 혹은 표준편차가 클수록 softmax의 확률분포가 큰 값에 몰리는 패턴이 나타납니다.
분산이 작은 경우에는 확률분포가 고르게 (uniform distribution에 가까운) 나타납니다.
이렇게 되면 gradient vanishing 문제가 발생해 학습이 전혀 되지 않는 위험성이 있습니다.
그래서 내적값을 일정하게 유지시키기 위해서 내적값에 $sqrt{d_{k}}$로 나눠줍니다.
$sqrt{d_{k}}$로 나눠줌으로써 분산에 좌지우지되지 않고 분산이 항상 1인 형태로 유지됩니다.
2️⃣ Multi-Head Attention
Multi-head Attetnion은 위의 그림에서 3개(일반, 반투명, 투명)의 구조가 같이 돌아가는 것처럼 서로 다른 버전 $i$의 Attention Q, K, V를 동시에 병렬적으로 돌립니다.
그러면 모든 버전의 encoding vector가 나오고, concat을 해서 해당 query vector에 대한 encoding vector를 최종적으로 얻게 됩니다.
아래 그림과 같이 Attention을 동시에 수행하면 Attention head들인 $Z_{0}, Z_{1}, ... , Z_{7}$이 나오게 됩니다.
나온 $Z_{0}, Z_{1}, ... , Z_{7}$를 $W^{0}$과 linear 해 최종 $Z$로 만듭니다.
Multi-Head Attention이 필요한 이유는 동일한 sequence가 주어졌을 때도 다른 기준으로 여러 측면에서 정보를 뽑아야 할 필요가 있기 때문입니다.
예를 들어, "I went to the school", "I study hard", "I took the rest" 등 여러 문자열이 존재할 때
첫 번째 head에서는 "I"라는 주체가 한 행동을 중심으로 정보를 뽑을 수 있고 (go, study, take),
두 번째 head에서는 "I"라는 주체에 대한 장소의 변화 (schoool 등)를 뽑을 수 있습니다.
이러한 다양한 정보를 병렬적으로 뽑고, 이 정보들을 모두 합치는(concat) 역할을 수행합니다.
Head들은 서로 다른 정보들을 상호보완적으로 뽑는 역할을 하게 됩니다.
3️⃣ Transformer 메모리 크기 & 연산속도
1) Complexity per Layer
Complexity per Layer는 layer의 복잡도, 즉, 사용되는 메모리 크기를 뜻합니다.
Self-Attention은 Q (n x d) x K (d x n) 크기 $n^{2} \times d$만큼의 연산을 수행해야 합니다. ($n$은 seqeunce이기 때문에 가변적인 길이이며, $d$는 임의로 설정할 수 있는 hyperparameter 값)
Self Attention에서는 더 많은 메모리가 필요합니다. query, key와 같은 값을 저장하고 있어야 하기 때문입니다.
RNN은 각 timestep $n$개에서 계산되는 $h_{t-1}$의 dimension은 $d$이고, $W_{hh}$의 dimension도 $d \times d$ 크기이므로, $d \times d$ 크기로 출력으로 내어주기 때문에 $n \times d^{2}$만큼의 계산량이 필요하게 됩니다.
2) Sequential Operations
Sequential Operations는 연산 속도를 나타냅니다.
Self-Attention은 GPU의 코어수가 많다면 이 모든 계산을 병렬화를 통해 O(1) 한 번에 계산할 수 있습니다.
RNN은 매 timestep마다 계산을 수행하기 때문에 O(n)의 계산이 필요합니다.
즉, Self Attention은 Rnn보다 많은 메모리를 필요로 하지만, 계산은 더 빨리 수행할 수 있습니다.
3) Maximum Path Length
Maximum Path Length는 Long-term dependency와 관련이 있습니다.
Self-Attention의 경우에는 가장 처음에 있는 단어라 하더라도 동일한 key, value vector를 보기 때문에 정보를 직접적으로 가지고 올 수 있습니다.
RNN은 과거의 word 정보를 현재 step에 반영하려면 $n$번의 step을 지나가야 합니다.
4️⃣ Add & Norm & Feed Forward
1) Add
CNN을 사용한 ResNet에서는 gradient vanishing 문제를 해결하기 위하여 Residual 함수를 사용했습니다. Transformer의 Add 부분에서도 gradient vanishing문제 해결, 학습 안정화를 위해 Residual를 사용합니다.
Residual 함수 즉, Residual connection은 input vector $x$와 Attention을 거친 vector $h(x)$를 더하는 ( $x+h(x)$ ) 방법입니다. Residual connection을 사용하면 $loss = y(x) - h(x)$에서 $loss = y(x) - h(x) + x$를 사용하게 되어, <1보다 작은 값이 나오는 경우에는 입력 $x$를 더해 vanishing을 방지할 수 있습니다.
주의할 점은 Add를 수행하려면 "input vector $x$"와 "Attention을 거친 vector $h(x)$"는 dimension이 동일해야 합니다.
2) Norm
Normalization layer는 주어진 다수의 sample들에 대해서 값들의 평균을 0, 분산을 1로 만들어준 후, 원하는 평균과 분산을 주입할 수 있는 선형변환으로 이루어져 있습니다.
예를 들어, $[3, 5, -2]$라는 벡터가 결과로 나왔을 때
평균 : $\frac {3+5-2} {3} = 2$
분산 : $\sqrt {(3-2)^{2}+(5-2)^{2}+(-2-2)^{2}} = \sqrt{26}$
이 값들을 Normalization 하면 평균 : 0, 분산 : 1인 표준화된 vector가 나오게 됩니다.
$$[\frac {3-2} {\sqrt{26}}, \frac {5-2} {\sqrt{26}}, \frac{-2-2} {\sqrt {26}} ]$$
그 이후에는 Affine transformation를 수행합니다.
예를 들어, $y = 2x+3$이 있을 때, $[\frac {3-2} {\sqrt{26}}, \frac {5-2} {\sqrt{26}}, \frac{-2-2} {\sqrt {26}} ]$를 $x$에 넣어서 $y$로 변환시킵니다.
이때, vector들의 평균 : 3 (y절편), 분산 : $2^2(기울기) = 4$로 바뀌는 것을 알 수 있습니다.
여기서 3(y절편), 2(기울기)는 neural network에 의해서 parameter로 존재하면서 계속 값을 최적화합니다. (즉, 3,2는 고정된 값이 아니라 계속 바뀔 수 있는 parameter 값)
아래 그림은 Layer Normalization의 또 다른 예시입니다.
맨 오른쪽에서 각 노드별로 $y=ax+b$ 형태의 Affine tranformation을 수행하는 것을 볼 수 있습니다.
3) Feed forward
word 별로 가지는 encoding 된 vector들을 fully connected layer에 통과시켜서 변환하는 과정입니다.
5️⃣ Positional Encoding
Self-attention는 ordering 순서를 고려하지 않는 것이 가장 큰 문제점입니다.
순서만 바뀐 문장 2개 "I go home"이나 "home go I"를 넣어도 self attention에서는 같은 hidden vector를 출력하게 됩니다.
이러한 문제를 해결하기 위해 Postional Encoding은 위치에 따라 vector끼리 구별이 될 만큼의 상수(Unique 상수)를 더해주는 방법입니다.
예를 들어, "I go home"이라는 문장에서 "I"의 input vector를 $[3,-2,4]$라고 할 때,
만약, "I"가 첫 번째 발견됐을 때는 첫번째 dimension에 1000이라는 값을 더해 $[1003, -2, 4]$라고 표현하고,
"I"가 세 번째 발견됐을 떄는 세번째 dimension에 1000을 더해 $[3,-2, 1004]$로 표현하는 방법입니다.
$[1003, -2, 4]$와 $[3,-2, 1004]$ vector는 명백히 차이가 나게 되고 위치에 따라 다른 값을 가지게 됩니다.
Postional Encoding은 $sin$과 $cos$으로 이루어진 주기 함수를 사용하고, 거기서 발생된 특정 값으로 위치 vector를 표시하게 됩니다. Postional Encoding의 상수는 다른 위치와 비교될 수 있는 unique 한 상수를 사용해야 하기 때문에 $sin$, $cos$ 주기함수를 사용함으로써, 각 위치와 dimension마다 모두 다른 unique 값을 뽑아낼 수 있습니다.
아래는 Postional Encoding을 구하는 수식입니다.
첫 번째 dimension은 sin, 두 번째 dimension은 cos, 세 번째 dimension은 다시 sin을 번갈아가면서 수식을 사용하고, 값을 부여합니다. (여기서 $pos$는 위치, $i$는 dimension, $d_{model}$은 $d_{k}$입니다.)
이런 식으로 값을 부여하게 되면 1,2,3,4... dimension에서는 특정한 position에서 모두 다른 (unique) 값을 가지게 되어 비교가 가능해집니다.
위의 사진에서 만약, 20번째 위치(=$x$축)에 있는 dim 4,5,6,7 값들은 각각 $[0.13, -0.89, 0.92, 0.27]$ vector가 나오게 되고, 이 unique vector들을 20번째 vector에 더해줘서 계산해주는 형태를 가지게 됩니다.
6️⃣ Learning Rate Scheduler
원래 모델들은 Adam 등의 최적화를 수행하는 과정에서 learning rate는 고정되어 있습니다.
하지만 learning rate Scheduling은 최적값에 빠르게 도달할 수 있도록 지속적으로 learning rate를 변경(scheduling)해주는 방법입니다.
아래 사진과 같이 Object function의 경사가 급격한 지점에서는 learning rate를 낮추고, loss 함수의 경사가 완만한 지점에서는 learning rate를 높이고, 최적값에 가까워질 때는 다시 learning rate를 낮춰서(극소점에 도달하지 못하고 그 주위를 맴도는 현상 발생) 빠르게 최적값에 도달하도록 합니다.
아래 그림은 learning rate Scheduling의 계산 방법과 그래프입니다.
7️⃣ Encoding Block
Encoding block을 N번 쌓아서 만들 수 있습니다. (각각의 encoding block은 독립적)
8️⃣ Decoder & Masked
1) Decoder
Decoder는 Encoder에서 사용되는 구조(Self-Attention, Add&Norm, Feed Forward)가 똑같습니다.
다만, key, value가 Encoder에서 받아서 입력에 들어가고, query가 maked multi-head attention을 거쳐서 입력으로 들어옵니다.
2) Masked
Decoder에서는 똑같이 Self attention을 사용하게 됩니다.
이때, Q vector와 K vector의 내적을 통해서 아래 사진과 같이 유사도를 측정합니다.
만약, <SOS>만 decoder에서 예측한 상태에서 "집에", "나는"과 같은 word의 유사도까지 계산하게 되면 decoder가 예측을 한다는 의미가 사라지게 됩니다. 따라서 나오지 않은 word vector에 대해서는 masked를 해줍니다.
아래와 같이 유사도를 다 구한 후에 값을 차단(masked)해주어야 합니다.
값을 차단하는(masked) 방법은 아직 나오지 않은 word에 대해 0으로 만들어버립니다.
그러고 나서 다시 Normalization을 수행합니다.
✅ Transformer는 다른 NLP 모델보다 성능이 뛰어납니다.
'부스트캠프 AI 테크 U stage > 이론' 카테고리의 다른 글
[21] 그래프(Graph) 개념 (0) | 2021.02.22 |
---|---|
[20] Self-Supervised Pre-Training Models (0) | 2021.02.19 |
[18-1] Beam Search와 BLEU score (0) | 2021.02.17 |
[18] Sequence to Sequence with Attention (0) | 2021.02.17 |
[17] RNN, LSTM, GRU 정리 (2) (0) | 2021.02.16 |