Skip to content

Transformer

Contents

Transformer

Attention

기계 번역 같은 seq2seq 문제를 푸는 인코더-디코더 구조로써, 기존에 RNN 이 사용되었다. RNN 2개를 연결하여 인코더 RNN으로 정보를 요약하고, 고정 차원의 컨텍스트 벡터 \(s\) 를 만들어서 디코더 RNN으로 전달해준다. 디코더 RNN은 컨텍스트 벡터를 받아서 출력을 내고, 이 출력을 다음 시간의 입력으로 전달하는 auto regressive한 방식을 갖는다. 이 모델의 목적은 입력 \(x^1, \dots, x^n\) 과 출력 \(y^1, \dots, y^m\) 에 대한 조건부 확률 분포 \(P(y^m | y^1, \dots, y^{m-1}, x^1, \dots, x^n)\) 를 학습하는 것이다. 이 조건부 확률 분포에서 각 \(y^i\) 들을 샘플링하여 출력 시퀸스를 만든다.

RNN 기반 seq2seq 모델의 문제는 인코더와 디코더의 정보의 연결이 컨텍스트 벡터 하나 라는 것이다. 인코더가 받는 정보가 많을 때 그것이 컨텍스트 벡터에 모두 요약되지 않아서 정보가 소실되고, 컨텍스트 벡터와 가까이 있는 토큰들의 정보는 잘 반영을 해주는데 멀리 있는 토큰들의 정보는 점차 소실된다. 이를 위하여 어텐션이 개발되었는데, 핵심 아이디어는 디코더가 인코더에서 필요한 정보를 조합하여 가져갈 수 있게 하는 것이다. 즉, 어텐션의 역할은 인코더의 정보를 디코더로 모두 전달하는 것이다.

디코더가 어텐션으로 정보를 가져오는 방식은 인코더의 각 시간 별 입력들에 가중치를 서로 다르게 하고 그 가중합을 디코더에 가져오는 것이다. 이로써 앞부분의 정보가 중요하다면 앞부분의 가중치를 강하게 주면 되고, 뒷부분의 정보가 중요하다면 뒷부분 가중치를 강하게 주면 된다. 이는 놀랍게도 입력 데이터와 독립적인 고정 가중치를 갖는 전통적인 모델 구조와 달리 어텐션이 입력 데이터에 따라 결정되는 동적 가중치를 갖는다는 것을 의미했다.

Attention 알고리즘의 IB: 어텐션은 입력되는 데이터(해결해야 할 문제, 근사해야 할 함수)가 다음과 같은 IB를 갖고 있다고 가정한다. 이 IB에 의하면, 주어진 시퀸스의 특정 원소를 해석할 때 특정 위치의 원소가 다른 것보다 더 주목(attend)받아야 한다.

  • 의미 결정법 공리: 시퀸스의 어떤 원소의 의미는 주변 원소의 맥락에 의하여 결정된다.
  • 불평등 공리: 시퀸스의 어떤 원소를 해석할 때 주변의 특정 원소가 다른 것보다 더 중요하다.

두 문장 "I swam across the river to get to the other bank." 와 "I walked across the road to get cash from the bank." 에 이 IB가 성립한다. bank는 강둑과 은행의 의미로 사용되며, 이 의미는 주변 단어의 맥락에 의해서만 관찰된다. bank 를 해석할 때 어떤 단어가 다른 단어보다 더 중요하다. 첫번째 문장에서는 swam과 river가, 두번째 문장에서는 cash가 더 중요하다. 따라서 bank의 의미를 해석하기 위하여 모델은 어떤 단어를 다른 것보다 더 주목해야 한다.

Transformer

트랜스포머는 임베딩이다. 단, 트랜스포머는 고정된 임베딩이 아니라 어텐션을 기반으로 토큰을 시퀸스 안의 다른 토큰의 맥락적 의미가 포함된 임베딩으로 변환한다. 위의 예시에서 트랜스포머는 2가지 bank를 서로 다른 임베딩으로 변환한다. 첫번째 bank는 water와 가까운 임베딩 벡터로 변환되고, 두번째 bank는 money와 가까운 표현으로 변환된다. 트랜스포머의 입출력은 다음과 같다.

  • 입력 데이터: \(n=1,\dots ,N\)에 대한 \(D\)차원 벡터 집합 \(\{\mathbf{x}_{n}\}\)이다. 이 데이터 벡터 \(\mathbf{x}_n\)를 토큰이라고 한다. 토큰의 한 원소 \(x _{ni}\)를 특징(feature)이라고 한다. 데이터 벡터 집합 \(\{\mathbf{x}_n\}\)\(N \times D\) 행렬 \(\mathbf{X}\)로 나타낸다. 이 행렬은 \(n = 1, \dots ,N\)에 대한 \(n\)번째 행이 토큰 벡터 \(\mathbf{x}_n ^{\top}\)로 구성된다. % 이 행렬은 입력 토큰의 한 집합을 나타낸다.
  • 출력: 트랜스포머는 어텐션 메커니즘으로 데이터 행렬 \(\mathbf{X}\)의 서로 다른 토큰 벡터의 특징들을 섞고, \(\mathbf{X}\)와 같은 차원의 행렬 \(\tilde{\mathbf{X}}= \text{TransformerLayer}[\mathbf{X}]\)을 출력한다.

어텐션 메커니즘과 셀프 어텐션(Self-Attention)

어텐션 메커니즘은 임베딩 공간에서의 입력 토큰 \(\{\mathbf{x}_1, \dots , \mathbf{x}_N\}\) 집합에 대하여 입력 토큰 \(\mathbf{x}_n\)을 제한 \(a _{nm} \geq 0, \sum_{m=1}^{N}a _{nm} = 1\)을 만족하는 가중치 계수(attention score) \(a _{nm}\)에 대하여 다음과 같은 선형 결합으로 변환한다.

\[ \mathbf{y}_n = \sum_{m=1}^{N}a _{nm}\mathbf{x}_m \]

변환된 토큰 집합 \(\{\mathbf{y}_1, \dots , \mathbf{y}_N\}\)은 새로운 임베딩 공간에서 맥락적 의미가 가미된 의미를 갖는다. 특정 출력 벡터 \(\mathbf{y}_n\)의 값은 입력 벡터 \(\mathbf{x}_n\)뿐만 아니라 모든 벡터 \(\mathbf{x}_1,\dots ,\mathbf{x}_N\)에 의존된다.

bank 가 river 와 swam 에 더 강하게 의존되어 의미를 결정하듯이 어텐션 메커니즘으로 수정된 표현 \(\mathbf{y}_n\)을 판정할 때 중요한 입력 \(\mathbf{x}_m\)에 대한 의존성이 강해진다. 강한 의존성은 높은 어텐션 스코어 \(a _{nm}\)로 표현된다. 반면, 중요하지 않은 토큰에 대해서는 어텐션 스코어가 \(0\)에 가까워진다.

어텐션 스코어가 음이 아니도록 제한하는 이유는 어떤 계수가 무한정 커지고, 그것이 음의 계수에 의하여 보상되도록 학습될 수도 있기 때문이다. 또한, 출력이 특정 입력에 더 큰 어텐션을 줄 경우, 이것에 대한 대가로 다른 입력이 더 작은 어텐션을 갖게 되는 상대성이 존재해야 한다(총합 \(1\) 의 제한). %이 제한이 없으면 한 어텐션이 커져도, 그것에 상대성이 존재하지 않는다.

전통적인 모델 구조와 달리 어텐션이 입력 데이터에 따라 결정되는 동적 가중치를 갖는다는 것은 이 어텐션 스코어가 입력 토큰들의 맥락에 따라 달라진다는 것이다. 이제 입력 데이터에 대한 의존적 가중치(동적 가중치) \(a _{nm}\) 을 결정하는 방법론을 세워야 한다.

가령, 넷플릭스에서 어떤 영화를 볼지 결정하는 문제를 생각해보자. 한 가지 방법은 각각의 영화의 특징(영화 장르, 출연 배우, 감독, 영화 길이, 평점 등) 목록을 나열하고, 자신의 선호도와 가장 매칭되는 영화를 찾는 것이다. 이렇게 영화의 특징을 Key 벡터, 영화의 원본 파일을 Value 벡터, 영화 특징에 매칭시킬 자신의 선호도를 Query 벡터로 인코딩할 수 있다. 이는 사용자가 자신의 Query와 가장 매칭되는 Key를 갖고 있는 영화에 가장 어텐드하는 것과 같다.

가장 매칭되는 영화 파일의 원본 Value 벡터를 그대로 반환하는 방법(하드 어텐션)은 미분이 불가능하고 학습할 수 없다. 따라서 트랜스포머는 Query와 Key가 매칭되는 정도 그 자체를 Value 벡터의 가중치로 삼고 그 가중합을 최종 출력 벡터로 정의한다(소프트 어텐션). 즉, 영화 A, B, C의 특성과 사용자 선호도를 매칭한 결과가 0.2, 0.7, 0.1이 나왔다면, 영화 B 의 비디오 파일만 제공하는 게 아니라 영화의 비디오 파일에 각각 0.2, 0.7, 0.1을 곱하고 이들을 합해서 최종 영화 파일을 제공한다.

셀프 어텐션은 입력 벡터 \(\mathbf{x}_n\)의 출력 \(\mathbf{y}_n\)을 만들기 위해 Query 벡터로 \(\mathbf{x}_n\)을 사용하고, 입력 벡터 집합 \(\mathbf{x}_1, \dots , \mathbf{x}_N\)들을 Key 벡터와 Value 벡터로 사용한다. Query 벡터 \(\mathbf{x}_n\)이 Key 벡터 \(\mathbf{x}_m\)들에 각각 얼마나 어텐드하는지(\(a _{nm}\)) 측정하기 위해 이들의 유사도를 측정하고, 이 유사도를 각각의 Value 벡터에 곱하고 이들을 모두 더하여 최종 출력 벡터 \(\mathbf{y}_n\)을 만든다.

어텐션 스코어(동적 가중치) 측정

Key 벡터와 Query 벡터의 유사도는 점곱 \(\mathbf{x}_n ^{\top}\mathbf{x}_m\)으로 측정하고, 제한을 지키기 위하여 어텐션 스코어 \(a _{nm}\)\(\operatorname{softmax}\)로 정규화하여 최종 동적 가중치가 다음과 같이 정의된다.

\[ a _{nm} = \dfrac{\exp (\mathbf{x}_n ^{\top}\mathbf{x}_m)}{\sum_{m'=1}^{N}\exp (\mathbf{x}_n ^{\top}\mathbf{x}_{m'})} \]

Key, Query 벡터의 유사도인 어텐션 스코어를 측정하기 위하여 점곱을 사용는 이유는, 점곱이 표준내적공간에서의 내적이고, 내적은 두 벡터의 L2-norm과 각도를 반영하기 때문이다. Query 벡터 \(\mathbf{q}\)와 Key 벡터 \(\mathbf{k}\)의 점곱은 L2-norm \(\left\| \cdot \right\|\)과 두 벡터의 각도 \(\theta\)에 대하여 \(\mathbf{q} \cdot \mathbf{k} = \left\| \mathbf{q} \right\|\left\| \mathbf{k} \right\|\cos (\theta )\)와 같이 정의된다.

두 벡터가 같은 방향(\(\theta =0 \degree\))을 가르킬수록 \(\cos (0 \degree) = 1\)이 되어 점곱이 커지며, 유사도가 높다고 판정된다. 두 벡터가 직교(\(\theta =90 \degree\))할수록 \(\cos (90 \degree) = 0\)이 되어 점곱이 \(0\)에 수렴하고, 두 벡터가 관련이 없다고 판정된다. 두 벡터가 반대 방향(\(\theta =180 \degree\))을 가르킬수록 \(\cos (180 \degree) = -1\)이 되어 유사도가 낮다고 판정된다.

이때, Key 벡터의 차원 \(d_k\)가 커지면 점곱의 크기가 커진다. 이 큰 값이 \(\operatorname{softmax}\) 함수에 입력되면 극단적으로 \(0\)이나 \(1\)에 가까운 값이 나온다. 이러면 기울기가 \(0\)에 가까워지고 기울기 소실 문제가 발생한다. 따라서 점곱을 \(\sqrt[]{d_k}\)로 나눠서 어텐션 스코어의 분산이 폭주하는 것을 완화해야 한다.

왜 굳이 \(\sqrt[]{d_k}\)로 나눌까? Query 벡터와 Key 벡터의 각 원소가 평균 \(0\), 표준편차 \(1\)인 확률변수라고 가정할 때, 이들의 내적 결과는 다음과 같이 \(d_k\)개의 확률변수의 합이고, 이 합의 분산은 \(d_k\)가 된다. 따라서 이것을 \(\sqrt[]{d_k}\)로 나눠주면 다음과 같이 분산이 \(1\)이 되어 안정된다.

\[\begin{align*} \operatorname{Var}\left( \sum_{i}^{}q_ik_i\right) &= \sum_{i}^{}\operatorname{Var}(q_ik_i) = d_k \\ \operatorname{Var}\left( \frac{\sum_{i}^{}q_ik_i}{\sqrt[]{d_k}}\right) &= \frac{\sum_{i}^{}\operatorname{Var}(q_ik_i)}{d_k} = \frac{d_k}{d_k} = 1 \\ \end{align*}\]

이 방식을 점곱에 스케일링을 해준다고 해서 SDPA(Scaled Dot-Product Attention)라고 한다. 어텐션 스코어를 계산하는 다양한 함수가 개발되었지만, SDPA 가 표준이 되었다. 가령, Additive Attention은 쿼리와 키를 합산한 후 피드포워드 신경망을 통과시켜 어텐션 스코어를 계산한다. 그러나 SDPA 는 단순 행렬곱 연산만 필요하므로 훨씬 빠르다.

학습 파라미터

결국 셀프 어텐션은 행렬 \(\mathbf{L}\)의 모든 원소의 \(\exp\)를 취하고, 각 행의 합이 \(1\)이 되도록 정규화하는 연산자 \(\operatorname{Softmax}[\mathbf{L}]\)에 대하여 \(N \times D\) 데이터 행렬 \(\mathbf{X}\), 행이 \(\mathbf{y}_m\)\(N \times D\) 출력 행렬 \(\mathbf{Y}\)에 대하여 다음과 같이 주어진다.

\[ \mathbf{Y} = \overbrace{\operatorname{Softmax}[\mathbf{X}\mathbf{X}^{\top}]}^{\text{attention}} \mathbf{X} \]

그러나 이 모델은 아직 고정되어 있고 데이터로부터 학습할 능력이 없다. 그러므로 Query, Key, Value 행렬 \(\mathbf{X}\)에 다음과 같은 학습가능한 가중치 행렬 \(\mathbf{W}^{\text{(q)}}, \mathbf{W}^{\text{(k)}}, \mathbf{W}^{\text{(v)}}\)를 부여할 수 있다. 이로써 \(N \times N\) 차원 \(\mathbf{Q}\mathbf{K}^{\top}\)\(N \times D\) 차원 행렬 \(\mathbf{Y}\)에 대하여 다음을 얻는다.

\[ \mathbf{Y} = \overbrace{\operatorname{Softmax}[\mathbf{Q}\mathbf{K}^{\top}]}^{\text{attention}} \mathbf{V} \quad \text{s.t.}\enspace \mathbf{Q} = \mathbf{X}\mathbf{W}^{\text{(q)}} ,\mathbf{K} = \mathbf{X}\mathbf{W}^{\text{(k)}} , \mathbf{V} = \mathbf{X}\mathbf{W}^{\text{(v)}} \]

\(\mathbf{Q}, \mathbf{K}, \mathbf{V}\)를 만드는 가중치 행렬 \(\mathbf{W}^{\text{(q)}}, \mathbf{W}^{\text{(k)}}, \mathbf{W}^{\text{(v)}}\)는 입력 벡터를 각각 Query 공간, Key 공간, Value 공간으로 사영(projection)시키는 선형 변환이다. 각 사영 행렬은 원래 임베딩 공간을 서로 다른 의미론적 부분공간으로 변환해준다. 이 사영 행렬들이 역전파를 통해 일반적인 신경망 가중치처럼 학습되며, 트랜스포머 모델에서 고정되어 있는 파라미터이다.

3가지 의미론적 부분 공간인 Query 공간, Key 공간, Value 공간의 의미는 이렇다. Query 공간은 현재 토큰의 "어떤 정보를 찾아야 할까?"의 의미를 최적화하여 표현하는 공간이다. 가령, "나는 학교에 갔다"에서 "갔다"라는 토큰의 Query 벡터는 "어디로 갔는지"에 대한 정보를 찾아야 하는 의미를 갖고 있을 것이다. 이를 위해 \(\mathbf{W}^{\text{(q)}}\)는 해당 토큰으로 잘 질문하는 방법을 학습한다.

Key 공간은 현재 토큰이 가진 핵심 특징과 정보를 압축한 표현 공간이다. 이로써 Query 벡터에게 "나는 이런 특징을 가지고 있어"를 최적화하여 설명해준다. 가령, "학교에"라는 토큰의 Key 벡터는 장소 관련 특징을 강하게 표현할 것이다. 이를 위해 \(\mathbf{W}^{\text{(k)}}\)는 해당 토큰의 핵심 정보를 잘 대답하는 법을 학습한다.

Value 공간은 실제로 전달하면 유용한 정보를 최적화하여 표현하는 공간이다. 어텐션 스코어가 계산되면 "어떤 토큰에 더 주목할지"가 결정되고, 그 토큰의 Value 벡터에 어텐션 스코어가 곱해져서 최종 출력 표현을 만든다. 이를 위해 \(\mathbf{W}^{\text{(v)}}\)는 해당 토큰에서 제공하면 더욱 유용한 정보를 제공하는 법을 학습한다.

입력이 달라지면 \(\mathbf{Q}, \mathbf{K}, \mathbf{V}\)가 모두 달라지고, 따라서 어텐션 스코어가 달라진다. 전통적 신경망은 "학교"라는 토큰을 항상 동일한 가중치 행렬과 곱하여 임베딩한다. "걔, 마약하고 학교 들어 갔어"든 "학생은 학교에 간다"든 상관없이 "학교"는 같은 임베딩이 된다. 그러나 어텐션은 "학교"라는 토큰를 처리할 때, 시퀸스 내 토큰들의 맥락이 반영된 임베딩이 된다.

결국, 본질적으로 어텐션 학습은 최종 손실을 줄이기 위해 단지 최적의 \(\mathbf{Q}, \mathbf{K}, \mathbf{V}\) 사영 행렬을 찾는 과정이다.

Multi-Head Attention

트랜스포머는 단일 \(\mathbf{Q}, \mathbf{K}, \mathbf{V}\)를 만드는 단일 사영 행렬 집합 \(\mathbf{W}^{\text{(q)}}, \mathbf{W}^{\text{(k)}}, \mathbf{W}^{\text{(v)}}\)을 갖지 않고, 여러 사영 행렬 집합으로 여러 \(\mathbf{Q}, \mathbf{K}, \mathbf{V}\)를 만든다. 이를 멀티 헤드 어텐션이라고 한다. \(h=1,\dots ,H\)에 대한 \(H\)개의 어텐션 헤드를 정의할 수 있고, 이 결과 헤드들을 단일 행렬로 연결하고, 이 행렬을 가중치 행렬 \(\mathbf{W}^{\text{(o)}}\)로 선형 결합하여 다음과 같은 출력을 생성한다.

\[\begin{align*} \mathbf{H}_h = \operatorname{Attention}(\mathbf{Q}_h, \mathbf{K}_{h}, \mathbf{V}_{h}) \quad &\text{s.t.} \enspace \mathbf{Q}_{h} = \mathbf{X}\mathbf{W}_{h} ^{\text{(q)}}, \mathbf{K}_{h} = \mathbf{X}\mathbf{W}_{h} ^{\text{(k)}}, \mathbf{V}_{h} = \mathbf{X}\mathbf{W}_{h} ^{\text{(v)}} \\ \operatorname{MHA}(\mathbf{X}) &= \operatorname{Concat}[\mathbf{H}_1, \dots , \mathbf{H}_{H}] \mathbf{W}^{\text{(o)}} \\ \end{align*}\]

단일 어텐션 헤드를 사용할 경우 한 어텐션이 여러 패턴의 효과의 평균을 취하게 된다. 어텐션 헤드를 여러개 두어야 한 시퀸스의 여러 의미 패턴을 포착할 수 있다. 가령, 사람이 문법을 검증하거나, 의미를 이해하거나, 예의있게 쓰여진 글인지 검증하려고 글을 읽는 것과 같다. % 자연어에서 한 패턴은 시제 관련, 다른 패턴은 어휘(단어의 의미) 관련 의미를 가질 수 있다.

그런데 어떻게 각 헤드들이 겹치지 않게 서로 다른 문장의 의미의 측면에 집중하게 될까? 가령, 문장에 존재하는 모든 의미 특성이 20개인데, 어텐션 헤드를 2천개 두면 어떻게 될까? 멀티 헤드 어텐션에서 각 헤드가 자동으로 서로 다른 역할을 나누어 맡도록 명시적으로 설계되어 있지는 않다. 각 헤드는 단지 서로 다른 \(\mathbf{W}^{\text{(q)}}, \mathbf{W}^{\text{(k)}}, \mathbf{W}^{\text{(v)}}\)파라미터로 독립적으로 초기화되고, 역전파를 통해 손실 함수를 줄이도록 학습될 뿐이다. 헤드들이 서로 다른 의미 측면에 집중하게 되는 것은 손실을 줄이려는 학습 과정에서 자연스럽게 나타나며, 보장되지 않는다. 실제로 많은 헤드를 두면 비슷한 패턴을 학습할 수도 있다. 따라서 실제 트랜스포머 모델들은 8개에서 16개 정도의 헤드를 사용한다.

Transformer Layer

이러한 멀티 헤드 셀프 어텐션이 트랜스포머의 핵심 구조의 원소이다. 이때, 신경망을 깊게 만들기 위하여 이 셀프 어텐션 레이어를 다층으로 쌓야 한다. 이를 위해 기울기 소실 문제를 해결하기 위한 레지듀얼 연결(Residual Connection)을 도입한다. 일반적인 신경망은 \(y = F(x)\)를 학습하지만, 레지듀얼 연결은 \(y = F(x) + x\)와 같이 정의된다. 이 연결에 의하여 역전파 시 기울기가 \(\frac{\partial y}{\partial x} = \frac{\partial F(x)}{\partial x} + 1\)와 같이 계산된다. 이 \(+1\)항 때문에 \(F(x)\)의 기울기가 \(0\)에 수렴해도, 기울기가 최소 \(1\)이상으로 보존되며, 기울기 소실이 방지된다.

레지듀얼 연결이 출력에 입력을 더하여, 출력을 오염시키는 것으로 보인다. 그러나 핵심 아이디어는 전체를 학습하는 대신 차이만 학습하는 것이다. 기존에 \(H(x)\)를 처음부터 끝까지 학습해야 했다면, 레지듀얼 연결 \(H(x) = F(x) + x\)\(F(x)\)는 입력 \(x\)와 원하는 출력 \(H(x)\) 의 차이만 학습하면 된다.

또한, 학습 안정성을 위하여 LN(Layer Normalization)도 필요하다. LN을 적용하는 시점에 따라 다음과 같이 post-norm과 pre-norm으로 나뉜다.

\[\begin{align*} \mathbf{Z} &= \text{LayerNorm}[\operatorname{MHA}(\mathbf{X}) + \mathbf{X}] \\ \mathbf{Z} &= \operatorname{MHA}\left( \text{LayerNorm}[\mathbf{X}] \right) + \mathbf{X} \end{align*}\]

딥러닝의 문제는 앞전 레이어의 가중치를 업데이트 할 때마다, 뒷 레이어가 받는 입력 분포가 바뀐다는 것이다. 가령, 레이어 1 의 가중치를 업데이트하면 입력의 평균과 분산이 \(0, 1\) 이었던 것이 \(5, 100\) 이라는 분포로 바뀐다. 그러면 레이어 2 는 계속 변하는 데이터 분포에 적응해야 해서 학습이 불안정해진다. 따라서 불안정한 입력 데이터를 일정한 분포(평균/분산 \(0,1\))로 정규화해 주어야 한다. LN은 다음과 같이 샘플 단위로 정규화를 하기 때문에 자연어 분야처럼 입력 데이터 크기가 가변일 때 유용하다.

  • 샘플1: [특징1, 특징2, 특징3] → 정규화
  • 샘플2: [특징1, 특징2] → 정규화

트랜스포머 원 논문은 포스트놈 방식을 제안했지만, LN을 먼저 적용하여 입력 데이터를 정규화해준 다음 어텐션 메커니즘을 구하는 것이 학습 안정성이 더 높아서 현재는 프리놈 방식이 표준이 되었다.

FFN(Feed-Forward Network) 레이어

\[\begin{align*} & \mathbf{Z} = \operatorname{LayerNorm}\left(\operatorname{Concat}\left[\mathbf{H}_1, \dotsc, \mathbf{H}_H\right] \mathbf{W}^{\text{(o)}} + \mathbf{X}\right) \\ \text{s.t.} \enspace \mathbf{H}_h = \operatorname{Softmax}&\left(\frac{\mathbf{Q}_h \mathbf{K}_h^\top}{\sqrt{d_k}}\right)\mathbf{V}_h,\ \mathbf{Q}_h = \mathbf{X}\mathbf{W}_h^{\text{(q)}},\ \mathbf{K}_h = \mathbf{X}\mathbf{W}_h^{\text{(k)}},\ \mathbf{V}_h = \mathbf{X}\mathbf{W}_h^{\text{(v)}} \\ \end{align*}\]

결국 어텐션 메커니즘은 다양한 관점(MHA)에서 선형 변환(행렬곱 \(\mathbf{W}^{\text{(q)}}, \mathbf{W}^{\text{(k)}}, \mathbf{W}^{\text{(v)}}, \mathbf{W}^{\text{(o)}}\)), 입력 잔류(ResNet), 분포 정규화(LN)까지 거쳐 Value 벡터들의 선형 결합을 생성하며, 여기에 비선형성이 부여된 적은 없다. 따라서 어텐션 레이어의 출력은 입력들의 선형 결합으로 제한되고, 어텐션 레이어의 표현력도 제한된다. 그러므로 표현력을 향상하기 위해 출력에 \(\text{MLP} [\cdot ]\)로 후처리를 해야 한다. 이 신경망(가령, \(\operatorname{ReLU}\)를 갖는 2층 fc 신경망)을 \(\mathbf{Z}\)의 행들인 각 출력 벡터들에 적용한다.

이를 FFN 레이어라고 한다. FFN 레이어에서는 보통 입력되는 임베딩 벡터가 512차원이면 2048차원으로 확장하고, \(\operatorname{ReLU}\) 비선형을 가한 뒤 다시 512차원으로 압축해서 출력한다. 이 경우 FFN 배수 \(4\) 가 적용되었다고 한다. UAT가 충분히 큰 단일 은닉층으로 임의의 함수를 모델이 근사할 수 있다는 것을 보장하므로 이 FFN 레이어의 존재와 차원을 확장하는 행위가 정당화된다. 이 신경망에도 레지듀얼 연결과 LN을 다음과 같이 적용하여 학습을 안정화시킬 수 있다.

\[ \tilde{\mathbf{X}} = \text{LayerNorm}[\text{MLP} [\mathbf{Z}] + \mathbf{Z}] \]

이제 최종적으로 트랜스포머 레이어를 위와 같이 정의할 수 있다. 일반적인 트랜스포머 모델은 이 트랜스포머 레이어를 여러개 쌓는다. 이 레이어를 여러번 반복할수록 맥락의 의미가 점점 더 고수준으로 추상화되고 더욱 고차원적인 개념의 의미가 각 토큰들에 반영된다. 이로써 토큰 임베딩이 더욱 풍부한 맥락 의미를 가진 임베딩이 된다.

이 트랜스포머 모델은 어떤 데이터든 시퀀스 형태로 표현하여 입력하면, 어텐션 메커니즘이 그 안의 중요한 관계를 자동으로 학습한다. 따라서 당초 설계 목표였던 자연어 뿐만 아니라 비전과 음성 분야에서도 사용된다.

Positional Encoding

포지션 인코딩은 입력 데이터 행렬 \(\mathbf{X}\)의 데이터 토큰 \(\mathbf{x}_n\)들의 순서를 인코딩하는 임베딩 \(\mathbf{r}_n\)이다. 어텐션 메커니즘이 토큰 순서에 독립적이므로 포지션 인코딩이 부여되지 않으면 가령, 다음 문장들을 구분할 수 없다. "The food was bad, not good at all." "The food was good, not bad at all."

지금까지 설계한 어텐션 레이어의 강력한 성질을 유지해야 하므로, 데이터의 토큰 순서가 신경망 안에서 표현되도록 하는 게 아니라 순서 그 자체를 포지션 인코딩 벡터 \(\mathbf{r}_n\)으로 인코딩하고 각 입력 포지션의 입력 토큰 임베딩 \(\mathbf{x}_n\)에 결합시켜야 한다. 따라서 주어진 포지션 인코딩 \(\mathbf{r}_n\)을 데이터 토큰 \(\mathbf{x}_n\)\(\tilde{\mathbf{x}}_n = \mathbf{x}_n + \mathbf{r}_n\)와 같이 부여한다.

이 방식이 포지션 정보를 단순히 토큰 벡터 위에 더해버려서 입력 벡터들의 내용을 오염시키는 것 같지만, 이것은 실제로 잘 작동한다. 서로 상관관계가 없이 선택된 벡터들은 고차원 공간에서 직교에 가까워지는 경향을 갖기 때문에 신경망이 토큰 원본 정보와 포지션 정보를 비교적 분리적하여 처리할 수 있기 때문이다.

포지션 인코딩으로써 트랜스포머 원 논문은 삼각함수에 의한 포지션 인코딩을 제안했지만, 경우에 따라 학습가능한 임베딩으로 포지션 인코딩을 설정하면 더 성능이 좋을 수도 있다.

Transformer Encoder/Decoder/Encoder+Decoder

트랜스포머 레이어는 인코더, 디코더, 인코더+디코더 구조로 응용된다. 디코더 모델에는 GPT가 해당되고, 분포 \(p(\mathbf{x}_n|\mathbf{x}_1,\dots ,\mathbf{x}_{n-1})\)를 학습한 auto regressive 모델을 구축하는 것이 목표이다. 디코더 모델은 \(n-1\)개 토큰을 입력받고 \(n\)번째 토큰을 예측하며 예측 분포와 실제 분포의 차이를 최소화하도록 학습된다. 이 모델은 자연어 데이터 그 자체를 뒷부분을 가려서(Masked Self-Attention) 라벨로 사용할 수 있기 때문에 자기 지도로 학습되며, 이 때문에 방대한 텍스트를 학습한 LLM으로 이어졌다.

인코더 모델에는 BERT가 해당되고, 분포 \(p(\mathbf{x}_i|\mathbf{x}_{\setminus i})\)를 학습한다. BERT의 입력 시퀸스의 첫 토큰은 항상 스페셜 토큰 <class>가 삽입되며, 마스킹된 입력 토큰이 무엇인지 맞추도록 학습된다. GPT가 왼쪽 단어만 보고 다음 단어를 예측한다면, BERT는 좌우 문맥을 이해하여 마스킹된 중간 단어를 예측한다. <class> 토큰도 셀프 어텐션으로 모든 토큰과 상호작용하지만 자신의 언어적 의미가 없기에 편향없이 모든 토큰 정보가 수집되고, 레이어를 거치면서 결국 문장 전체의 의미가 집약된다. 이후 SFT를 할 때 이 토큰의 출력으로 문장 분류, 감정 분석 등의 하위 문제를 해결한다.

인코더+디코더 모델은 당초 어텐션이 개발된 목적인 seq2seq 모델이다. 기존 RNN 2개로 구성된 seq2seq 모델에서 그 연결다리만 어텐션으로 교체한 것이 아니라, 인코더도 트랜스포머 인코더로, 디코더도 트랜스포머 디코더로 교체하여 RNN 없이 순수 어텐션만으로 모델이 구성된다. 이때 인코더와 디코더는 셀프어텐션으로 구성되지만, 그 연결다리 어텐션은 크로스 어텐션으로써 Key, Value 벡터는 인코더 출력 벡터로, Query 벡터는 디코더 출력 벡터로 사용한다. 이로써 이 모델은 입력 \(\mathbf{x}_1,\dots ,\mathbf{x}_{n}\)에 대한 출력 \(\mathbf{y}_1,\dots ,\mathbf{y}_{m}\)을 예측하는 분포 \(p(\mathbf{y}_m|\mathbf{y}_1,\dots ,\mathbf{y}_{m-1}, \mathbf{x})\)를 학습한다.