이번 포스팅과 다음 포스팅에서는 트랜스포머의 구조에 대해 알아보겠습니다
트랜스포머는 2017년 구글에서 발표한 논문 Attention Is All You Need에서 등장한 개념입니다
현재 자연어 처리 분야에서 사용되는 많은 모델들이 이 아키텍쳐에 기반을 두고 있으며
비전 분야에서도 트랜스포머에 기반한 ViT를 사용하기도 합니다
그러나 재미있는(?) 점은 논문의 저자들도 이게 왜 잘 되는지에 대한 설명을 하지 못한다는 겁니다
'이렇게 해보니 잘 되더라'라는 식의 내용이 많고 아직 제대로된 깔끔한 해석이 나오지 않은 상황입니다 (앞으로도 그럴 것 같습니다)
따라서 트랜스포머의 구조를 보시면서 '왜 이 레이어를 넣었지?', '왜 이렇게 했지?', '왜 이 연산을 한거지?' 라는 의문이 드시더라도
일단은 그 의문들을 잠시 넣어두시고 '트랜스포머가 이렇게 생겼구나' 정도로 넘어가시면 좋을 것 같습니다
트랜스포머는 인코더와 디코더 부분으로 나뉘는데 오늘은 인코더 부분만 먼저 살펴보도록 하겠습니다
인코더 블록
트랜스포머의 인코더를 이루는 핵심 요소는 어텐션 블록입니다. 어텐션 블록은 멀티헤드 어텐션, Add & Norm, Feed Forawrd라는 하위 구성을 가지고 있는 큰 단위입니다. 또한 그림상에선 하나만 표시되어있지만 여러개의 인코더가 사용될 수 있습니다. 먼저 인코더 블록의 하위 층 중 하나인 멀티헤드 어텐션에 대해 알아보겠습니다.
멀티헤드 어텐션 (Multi-head attention)
인코더 블록의 멀티헤드 어텐션은 이전 포스팅에서 설명했던 셀프 어텐션이 사용된 부분입니다. '멀티헤드'라는 단어가 붙은 이유는 셀프 어텐션이 여러 개 사용되었기 때문입니다. 셀프 어텐션을 여러 개 사용하는 이유는 셀프 어텐션을 하나만 사용할 경우 소프트 맥스가 유사도 중 하나에만 초점을 맞추는 경향이 생기기 때문입니다. 그래서 셀프 어텐션을 여러 개 사용해서 동시에 여러 곳에 집중(어텐션) 하겠다는 의도입니다.
트랜스포머에서는 셀프 어텐션 중에서도 스케일드 내적 셀프 어텐션(scaled dot-product self attention)을 사용했습니다. 기존 셀프 어텐션과 크게 다르지 않습니다. 식을 보면 그 차이를 쉽게 확인하실 수 있습니다:
기존 셀프 어텐션: $$Attention(Q, K, V) = Softmax(QK^{T})V$$
스케일드 내적 셀프 어텐션: $$Attention(Q, K, V) = Softmax(\frac{QK^{T}}{\sqrt{d_{k}}})V$$
보이시나요? $Q$와 $K$의 내적 결과를 $\sqrt{d_{k}}$로 나누어 준 것이 전부입니다. $d_{k}$는 키 벡터의 원소의 개수를 의미하는데 그것에 제곱근을 씌운 결과로 나누어준 것입니다. 이렇게 $d_{k}$로 나누어 주었을 때 학습이 더 안정적으로 진행되고 모형의 성능이 더 좋아진다고 합니다. (이유는 논문 저자도 모릅니다)
스케일드 어텐션을 여러 개 사용하면 멀티헤드 어텐션이라고 했습니다. 그래서 여러 개의 어텐션 결과를 이어 붙이는 concatenate을 해주면 멀티헤드 어텐션의 결과를 얻을 수 있습니다만... 논문에서는 여기에 몇 가지 가공을 조금 했습니다. 아래 식을 보시죠:
$$\begin{align} MultiHead(Q, K, V) = Concat(head_{1}, ..., head_{h})W^{O} \\ where\ head_{i} = Attention(QW_{i}^{Q}, KW_{i}^{K}, VW_{i}^{V})\end{align}$$
아랫줄을 먼저 보시면 기존의 어텐션과는 다르게 $Q, K, V$ 각각에 가중치 행렬을 곱해준 것을 확인할 수 있습니다. (이것을 선형 변환한다고 합니다) 각 헤드에서 선형변환된 $Q, K, V$를 이용한 스케일드 어텐션 결과를 얻어 concat 해준 후 다시 한번 $W^{O}$로 선형변환 해주면 멀티헤드 어텐션의 결과를 얻을 수 있습니다
이렇게 얻어진 멀티헤드 어텐션의 결과는 Add & Norm 모듈에 입력됩니다
Add & Norm
Add & Norm 층에서는 멀티헤드 어텐션 층이 출력하는 값과 인코더 블럭에 입력되는 값(멀티헤드 어텐션 층에 입력되는 임베딩)을 더한(Add) 후 계층 정규화(Layer Normalization)을 수행합니다. 이 과정을 수행하면 경사 소실(gradient descent) 문제를 줄여 학습이 더 안정적으로 진행된다고 합니다
여기서 나온 결과는 다시 피드 포워드(Feed Forward) 네트워크로 입력됩니다
피드 포워드 (Feed Forward)
피드 포워드 네트워크는 두 개의 선형 층으로 구성된 완전 연결 신경망입니다. 두 개의 층 중 첫 번째 층에서는 입력 차원이 네 배로 뻥튀기 되고 두 번째 차원에서 다시 원래 크기의 차원으로 되돌립니다. 이러한 과정을 거치면 모델의 표현력이 상승한다고 합니다
입력 임베딩
지금까지는 인코더 블록에 입력된 정보가 어떻게 가공되는지에 대해 알아봤다면 이 섹션에서는 인코더 블록에 어떤 정보가 입력되는지를 알아보겠습니다
위 그림을 보시면 Positional Encoding이라는 부분이 보이는데요, 이 부분은 임베딩 벡터에 위치 정보를 씌워주는 과정입니다. 위치 정보는 왜 심어줄까요? 아래 예시를 한 번 보겠습니다:
문장1. 나는 백화점에 갔다가 집에 도착했다
문장2. 나는 집에 갔다가 백화점에 도착했다
문장1과 문장2는 같은 단어로 구성된 다른 문장입니다. 그러나 단어의 위치가 바뀌면 문장이 가지는 의미도 달라지게 됩니다. 위치 인코딩은 문장의 각 단어(혹은 토큰)에 위치 정보를 각인해주는 과정입니다. 이런 과정이 필요한 이유는 트랜스포머가 모든 단어를 한 번에 입력받기 때문에 문장 내 각 단어의 선후 관계가 꼬일 수 있기 때문입니다.
위치 임베딩 벡터
위치 임베딩 벡터는 벡터의 각 위치에 대한 정보를 가지는 벡터입니다. 이 정보를 각 단어의 임베딩 벡터와 더해주면 인코더 블록에 입력할 최종 임베딩 벡터를 얻을 수 있게됩니다
위치를 인코딩하는 방법은 여러가지가 있는데 Attention Is All You Need 논문에서는 $sin$함수와 $cos$함수를 사용하는 방법을 택했습니다.
$$\begin{align} PE_{(pos, i)} = sin(\frac{pos}{10000^{i / d_{model}}}) \\ PE_{(pos, i)} = cos(\frac{pos}{10000^{i-1 / d_{model}}}) \end{align}$$
위 식에서
$pos$는 문장 내에서 단어의 위치를 나타냅니다. 예를 들어, I love you라는 문장이 있으면 I의 pos는 0, love의 pos는 1, you의 pos는 2가 됩니다.
$i$는 단어의 임베딩 벡터 내에서 요소의 위치를 나타냅니다. 예를 들어 love의 임베딩 벡터 $Embed_{love} = [0.5, 0.6, 0.7]$이라고 할 때 $0.5 (i=0), 0.6 (i=1), 0.7 (i=2)$ 입니다.
$d_{model}$은 단어의 임베딩 차원을 뜻합니다. 위치 임베딩 벡터를 만들 때에 i가 짝수일 때는 $sin$함수를, 홀수일 때는 $cos$함수를 이용합니다. 살짝 복잡한데 아래에 예시를 나타내 보았습니다
I love you라는 문장의 위치 임베딩은 다음과 같습니다. 단어의 임베딩 차원(열의 개수)은 4차원이라고 가정하겠습니다.
\begin{bmatrix} sin(\frac{0}{10000^{0 / 4}}) & cos(\frac{0}{10000^{0 / 4}}) & sin(\frac{0}{10000^{1 / 4}}) & cos(\frac{0}{10000^{1 / 4}})\\ sin(\frac{1}{10000^{0 / 4}})& cos(\frac{1}{10000^{0 / 4}}) & sin(\frac{1}{10000^{1 / 4}}) & cos(\frac{1}{10000^{1 / 4}})\\ sin(\frac{2}{10000^{0 / 4}}) & cos(\frac{2}{10000^{0 / 4}}) & sin(\frac{2}{10000^{1 / 4}}) & cos(\frac{2}{10000^{1 / 4}}) \end{bmatrix}
이제 이 위치 임베딩 행렬과 원래의 임베딩 행렬을 더해주면 인코더 블럭에 입력될 준비가 끝나게 됩니다
오늘은 트랜스포머의 구조 중에서도 인코더 부분에 대해 살펴봤습니다
다음 포스팅에서는 트랜스포머의 디코더 부분에 대해 알아보겠습니다
감사합니다
'딥러닝 > 트랜스포머' 카테고리의 다른 글
트랜스포머 시리즈 마지막편 트랜스포머의 구조 - 디코더 (0) | 2024.02.06 |
---|---|
트랜스포머 시리즈 3편 Q, K, V (0) | 2024.02.04 |
트랜스포머 시리즈 2편 Self-Attention 셀프 어텐션 (0) | 2024.02.02 |
트랜스포머 시리즈 1편 Attention 어텐션 (0) | 2024.02.01 |