자연어 처리 분야에서 가장 유명한 논문을 하나 고르라면 많은 사람들이 Attention Is All You Need를 선택할 것입니다. 이제는 자연어 처리를 넘어서 컴퓨터 비전를 비롯한 여러 분야에서도 매우 중요하게 여겨지는 트랜스포머 아키텍처를 제안한 혁명적인 논문입니다. Attention Is All You Need는 매우 중요한 논문인 만큼, 배경지식으로 사용된 여러 개념에 대한 설명을 추가하여 전체 내용을 이해하는 데 부족함이 없도록 노력하였습니다. 그럼에도 너무 길이가 길어질까봐 중간에 생략한 내용이 많은데, 더 공부하다가 필요한 내용이 누락되었다고 생각하면 추가할 예정입니다. 번역을 통해 오히려 이해가 어려워지거나, 원문의 표현을 사용하는 게 원래 의미를 온전히 잘 전달할 것이라고 생각하는 표현은 원문의 표기를 따랐습니다. 오개념이나 오탈자가 있다면 댓글로 지적해주세요. 설명이 부족한 부분에 대해서도 말씀해주시면 본문을 수정하겠습니다.
1. Introduction
순환 신경망(RNN), LSTM, GRU는 언어 모델링, 기계 번역과 같은 여러 NLP 태스크에서 뛰어난 성능을 보이며 SOTA 모델로 자리매김했습니다. 이후 recurrent language modeling과 인코더-디코더 아키텍처에 대한 연구가 계속해서 이어졌습니다.
Recurrent model은 일반적으로 입력 및 출력 시퀀스에서 토큰(symbol)의 위치에 따라 계산을 수행합니다. 이러한 모델은 연산이 이루어지는 동안 token position과 step을 align하여, position $t$의 입력과 이전 타임 스텝의 은닉 상태(hidden state) $h_{t-1}$의 함수인 $h_t$를 생성합니다. 그런데 이런 순차적인 특성은 학습 샘플간의 병렬화를 불가능하게 하여, 메모리 효율 면에서 치명적입니다. 논문이 발표할 당시에는 factorization trick이나 conditional computation과 같은 기법 덕분에 연산 효율이 크게 증가하였지만, sequential computation의 제약은 여전히 남아있었습니다.
Factorization Trick
Factorization trick은 LSTM의 파라미터 개수를 줄이고 학습 속도를 빠르게 하는 기법입니다. 논문에서는 기존 LSTM의 가중치 행렬을 두 개의 작은 행렬의 곱으로 나타내는 factorized LSTM(F-LSTM)과 LSTM 셀을 독립적인 그룹으로 분할하는 group LSTM(G-LSTM)을 제안합니다. 이를 통해 모델 성능을 제한하지 않으면서 RNN 파라미터를 두 배에서 최대 세 배까지 줄일 수 있었습니다.
Conditional Computation
Conditional Computation은 학습 샘플에 따라 신경망의 일부만이 활성화된다는 점에 착안하여, 이론적으로 연산량의 증가 없이 모델 용량을 획기적으로 증가하는 방법입니다. 이를 expert network라고 부르는데, 실제 사용하기에는 여러 문제가 있었습니다. 하지만 이내 계산 효율은 크게 떨어지지 않지만 모델 용량을 1000배 이상 크게 하는 기법인 Sparsely-Gated Mixture-of-Experts(MOE)이 제안되어 연산 효율을 챙기면서 모델 용량도 키울 수 있게 되었습니다.
어텐션 메커니즘은 시퀀스 모델링과 변환(transduction) 모델 등 다양한 태스크에서 필수적인 요소가 되었으며, 입력과 출력 시퀀스에서 거리에 관계없이 종속성(dependancy)를 모델링할 수 있습니다. 하지만 여태까지는 어텐션 메커니즘이 순환 신경망과 함께 사용되었습니다.
논문에서는 순환 신경망을 제거하고 오로지 어텐션 메커니즘만을 사용하여 입력과 출력의 global dependancy를 모델링하는 Transformer 아키텍처를 제안합니다. Transformer는 병렬화를 가능하게 할 뿐만 아니라 적은 훈련으로도 품질이 높은 번역을 생성합니다.
2. Background
순차적인 연산을 줄이기 위한 목표는 합성곱 신경망을 사용하여 병렬적으로 은닉 상태를 계산하는 Extended Neural GPU, ByteNet, ConvS2S의 목표이기도 합니다. 이 모델들에서 임의의 두 입력 및 출력 position에 대한 연산은 두 position의 거리가 멀어질수록, 선형적으로(ConvS2S) 또는 logarithmically(ByteNet)하게 증가합니다. 이는 먼 거리에 있는 토큰끼리의 의존성을 학습하기 어렵게 합니다. 트랜스포머는 이러한 연산이 상수에 비례하게 합니다. 이 과정에서 position에 대한 정보가 일부 손실되지만, Transformer는 멀티 헤드 어텐션을 사용하여 이를 해결하였습니다.
Intra-attention이라고도 불리는 셀프 어텐션은 시퀀스의 표현(representation)을 계산하기 위하여 하나의 시퀀스 내의 서로 다른 토큰들을 연관짓는 어텐션 메커니즘입니다. 셀프 어텐션은 이미 여러 태스크에 성공적으로 적용되었지만, Transformer는 RNN이나 CNN을 전혀 사용하지 않고 어텐션에만 의존하는 최초의 transduction model입니다.
3. Model Architecture
대부분의 뛰어난 성능을 보이는 시퀀스 변환 모델은 인코더-디코더 구조를 갖습니다. 인코더는 입력 시퀀스 $(x_1,\dots,x_n)$을 연속적인 표현 $\mathbf z=(z_1,\dots,z_n)$로 매핑하고, 디코더는 $\mathbf z$를 통해 출력 시퀀스 $(y_1,\dots,y_n)$의 토큰을 매 스텝마다 하나씩 생성합니다. 매 스텝에서 모델은 자기 회귀적(auto-regressive)인데, 이는 이전 스텝에 생성된 토큰을 입력으로 사용하여 다음 스텝의 출력을 생성한다는 의미입니다. Transformer 아키텍처 또한 다음 그림과 같이 셀프 어텐션, point-wise fully connected layer을 쌓은 인코더와 디코더로 이루어집니다.
3.1 Encoder and Decoder Stacks
Encoder
인코더는 $N=6$개의 동일한 레이어를 쌓은 구조를 갖습니다. 각 레이어는 두 개의 서브 레이어(sub-layer)를 갖습니다. 하나는 멀티 헤드 셀프 어텐션 메커니즘이며 나머지는 position-wise fully connected feed-forward network입니다. 각 서브레이어에는 잔차 연결(residual connection)과 레이어 정규화(layer normalization)이 적용되어, 각 서브레이어의 출력은 $\textrm{LayerNorm}(x+\textrm{Sublayer}(x))$이 됩니다. 여기서 $\textrm{Sublayer}(x))$는 서브레이어 자체에 구현된 함수를 의미합니다. 잔차 연결을 적용하기 위해 임베딩 레이어를 포함한 모든 서브레이어는 $d_{\textrm{model}}=512$ 차원의 벡터를 출력으로 합니다.
Decoder
디코더 또한 인코더와 같이 $N=6$개의 동일한 레이어를 쌓은 구조입니다. 디코더는 인코더가 갖는 두 개의 서브레이어 외에 세 번째 서브레이어를 갖는데, 이는 인코더 스택의 출력에 대한 멀티 헤드 어텐션을 수행합니다. 디코더 또한 잔차 연결과 레이어 정규화를 사용합니다. 디코더 스택의 셀프 어텐션 서브레이어에는 특별히 마스킹이 적용되어 있습니다. 마스킹은 position $i$에 대한 예측은 $i$ 번째 미만의 position에 대한 정보에만 의존하도록 하여, 이후 position의 정보를 알 수 없게 합니다.
3.2 Attention
어텐션 함수는 query와 key-value 쌍의 집합을 출력(output)으로 매핑합니다. 여기서 query, key, value와 output은 모두 벡터이며 각 토큰에 대해 생성됩니다. 출력은 value의 가중합이며, 각 value에 대한 가중치는 query와 그에 대응하는 key에 대한 호환성 함수(compatibility function)에 의해 계산됩니다.
3.2.1 Scaled Dot-Product Attention
논문에서는 특별히 Scaled Dot-Product Attention을 도입하였습니다. 입력은 $d_k$ 차원을 갖는 query와 key, $d_v$ 차원을 갖는 value로 이루어집니다. 먼저 각 query와 모든 key의 점곱을 계산하고 각각을 $\sqrt {d_k}$로 나눈 후 소프트맥스를 취하여 각 value에 대한 가중치를 얻습니다.
실제로는 query 집합에 대한 어텐션 함수를 동시에 계산하기 때문에, query, key, value는 행렬 $Q$, $K$, $V$로 패킹됩니다. 따라서 연산을 다음 수식과 같이 나타낼 수 있습니다.
흔히 사용되는 두 가지 어텐션 메커니즘은 additive attention과 dot-product(multiplicative) attention입니다. 논문의 알고리즘은 dot-product attention을 사용하였지만, 추가로 scaling factor $\frac{1}{\sqrt{d_k}}$를 사용합니다. Additive attention은 하나의 히든 레이어를 갖는 피드포워드 신경망을 사용하여 compatibility function을 계산합니다. 두 메커니즘은 이론적으로는 비슷한 연산 복잡도를 갖지만, dot-product attention의 행렬 곱셈을 고도로 최적화할 수 있기 때문에 실제로는 더 빠르고 공간 효율적입니다.
$d_k$가 작을 경우 두 메커니즘은 비슷한 성능을 보이지만, $d_k$가 커질수록 addition attention이 dot-product attention보다 뛰어난 성능을 보입니다. 이는 $d_k$가 클 경우 점곱의 크기가 커지고, 소프트맥스 함수에 의해 절댓값이 큰 값은 극단적으로 작은 그라디언트를 갖게 됩니다. 이러한 효과를 상쇄하기 위해서 논문에서는 scaling factor를 사용하였습니다.
$d_k$가 커지면 왜 dot products 또한 커지는지 알아보겠습니다. $q$와 $k$가 각각 평균이 0이고 분산이 1인 정규분포를 따르는 독립적인 확률 변수라고 하겠습니다. 이 때 dot product $q \cdot k =\sum_{i=1}^{d_k}q_kk_i$는 평균이 0이고 분산이 $d_k$입니다.
먼저 $q$와 $k$는 $\mathbb R^{d_k}$ 차원의 벡터이며 $q_i$와 $k_i$는 독립 확률 변수입니다. 가정에 의해 $E[q_i]=E[k_i]=0$이고, $Var(q_i)=Var(k_i)=1$입니다. 확률 변수의 분산은 다음과 같이 계산됩니다.
여기서 $q$와 $k$는 각각 독립이므로 $E[q\cdot k]$은 다음과 같이 0임을 알 수 있습니다.
그러면 분산의 식이 다음과 같이 나타나는데, $q$와 $k$은 독립이며 $E[q_i^2]=Var(q_i)+(E[q_i])^2=1$이기 때문에 다음과 같이 식을 계산할 수 있습니다.
실제로 다음과 같은 파이썬 코드로 scaling factor가 적용되지 않은 상태에서 dot product를 계산하면 매우 극단적인 값이 소프트맥스 함수의 출력으로 나타나는 것을 확인할 수 있습니다.
import numpy as np
np.random.seed(42)
def softmax(x):
exp_x = np.exp(x - np.max(x))
return exp_x / exp_x.sum(axis=0)
d_k = 512
mean = 0
std_dev = np.sqrt(d_k)
dot_product = np.random.randn(4) * std_dev + mean
print(dot_product) # [11.23935827 -3.128564 14.65551864 34.46223166]
print(softmax(dot_product)) # [8.21172186e-11 4.72633905e-17 2.50065528e-09 9.99999997e-01]
3.2.2 Multi Head Attention
논문에서는 $d_{\textrm{model}}$ 차원을 갖는 key, value, query를 사용하여 하나의 어텐션 함수를 사용하는 대신, 각각을 서로 다른 $h$개의 learned linear projection을 통해 $d_k$, $d_k$, $d_v$ 차원에 투영하면 더 좋은 성능을 보인다는 것을 발견하였습니다. 각각의 투영된 버전의 query, key, value에는 병렬적으로 어텐션 함수가 적용되어, $d_v$ 차원의 출력을 내놓습니다. 각각의 출력은 연결(concatenate)된 후 다시 한번 투영되어 최종적인 값을 가집니다.
멀티헤드 어텐션은 모델이 서로 다른 표현의 부분 공간(representation subspace)에 집중할 수 있게 해줍니다. 즉 각 헤드에서는 서로 다른 관점에서 학습이 수행될 것입니다.
수식에서 projection은 파라미터 행렬이며, $W_i^Q\in\mathbb R^{d_{model}\times d_k}$, $W_i^K\in\mathbb R^{d_{model}\times d_k}$, $W_i^V\in\mathbb R^{d_{model}\times d_v}$, $W^O\in\mathbb R^{hd_v \times d_{model}}$입니다. 논문에서는 $h=8$개의 parallel attention layer(head)를 사용하였습니다. $d_k=d_v=d_{\textrm{model}}/h=64$이며, 각 헤드에서 벡터의 차원이 감소하였기 때문에 전체 연산량은 single head attention과 비슷합니다.
3.2.3 Applications of Attention in our Model
Transformer에서 멀티 헤드 어텐션은 세 가지 방법으로 사용됩니다.
- 인코더-디코더 어텐션 레이어에서 query는 이전 디코더 레이어, memory key와 value는 인코더의 출력을 사용합니다. 이는 디코더의 각 position이 입력 시퀀스의 모든 position에 주의를 기울이게 합니다.
- 인코더의 셀프 어텐션 레이어의 query, key, value는 인코더의 이전 레이어의 출력을 사용합니다. 인코더의 각 position은 인코더의 이전 레이어의 모든 position에 집중합니다.
- 디코더의 셀프 어텐션 레이어도 인코더와 유사하지만, 각 position이 모든 position이 아니라 자기 자신이 위치한 곳의 토큰까지만 집중합니다. Auto regressive가 이루어지기 위해서는 정보가 왼쪽으로 흐르지 못하게 하여야 합니다. 즉 앞으로 생성되어야 할 토큰에 대한 정보는 이전에 미리 확인할 수 없어야 합니다. 따라서 저자는 현재 position 이후의 모든 토큰에 마스킹을 적용하였습니다. 기술적으로는 그 값을
-inf
로 설정하여 소프트맥스를 취한 값이 0이 되도록 하였습니다.
3.3 Position-wise Feed-Forward Networks
Transformer의 인코더와 디코더는 어텐션 서브레이어 이외에 fully connected feed-forward network를 갖습니다. 이는 다음과 같이 두 개의 선헝 변환과 ReLU 함수로 구성됩니다.
각각의 선형 변환은 모두 같은 방식으로 이루어지지만, 파라미터는 레이어마다 모두 다릅니다. 입력과 출력 차원은 $d_\textrm{model}=512$이며, 내부 레이어의 차원은 $d_{ff}=2048$입니다.
이 피드포워드 신경망은 커널 사이즈가 1인 합성곱 신경망을 두 번 적용하는 것으로 이해할 수도 있습니다. $1\times 1$ 컨볼루션은 point-wise convolution이라고도 불리며, 이미지 처리에서 한 번에 하나의 픽셀을 처리함을 의미합니다. 이 연산은 입력 데이터의 깊이 차원(채널) 에 대한 선형 변환입니다. Transformer와 같이 입력 데이터가 1차원 시퀀스인 경우 $1\times 1$ 컨볼루션은 입력의 각 position에 대한 선형 변환, 즉 피드포워드 레이어라고 생각할 수 있습니다.
3.4 Embedding and Softmax
다른 시퀀스 변환 모델과 마찬가지로 Tranformer에서도 learned embeddings를 사용하여 입력과 출력의 토큰을 $d_\textrm{model}$ 차원의 벡터로 변환합니다. 또한 learned linear transformation 과 소프트맥스 함수를 사용하여 디코더의 출력을 다음 토큰의 확률로 변환합니다. Transformer에서 두 개의 임베딩 레이어와 소프트맥스 이전의 선형 변환(pre-softmax linear transformation)에는 같은 가중치 행렬이 사용됩니다. 임베딩 레이어의 가중치에는 $\sqrt{d_\textrm{model}}$이 곱해집니다.
여기서 두 개의 임베딩이란 입력 임베딩과 출력 임베딩을 의미합니다. Using the Output Embedding to Improve Language Models 논문의 연구에 따라 출력을 확률 분포로 투영하는 레이어를 출력 임베딩으로 생각하고, 입력 임베딩 레이어와 가중치를 공유하게 하는 것입니다. 이를 통해 모델의 파라미터를 줄일 수 있을 뿐만 아니라 모델 성능도 개선됩니다.
3.5 Positional Encoding
Transformer 아키텍처는 순환 또는 합성곱 레이어를 포함하지 않기 때문에 모델이 시퀀스의 순서를 학습하기 위해서는 각 토큰의 상대적 또는 절대적인 위치를 알려주는 정보가 별도로 주어져야 합니다. 따라서 입력 임베딩에 positional encoding을 더하여 사용합니다. Positonal encoding은 임베딩과 마찬가지로 $d_\textrm{model}$ 차원을 가집니다.
Positional encodings를 구현하기 위한 방법에는 여러가지가 있는데 그 중 일부는 learned와 fixed 방식입니다. Fixed positional encoding은 학습 과정에서 변경되지 않는 고정된 벡터로 이루어집니다. 반면 Learned positional encoding은 그 자체를 매개변수로 취급하여 모델이 학습 과정에서 가중치를 계속해서 갱신하게 됩니다. 이는 다른 모델 파라미터와 마찬가지로 임의로 초기화되며 역전파를 통하여 학습 과정에서 업데이트됩니다.
논문에서는 서로 다른 주파수를 갖는 sine과 cosine 함수를 fixed positional encoding에 사용합니다.
$pos$는 토큰의 위치를 의미하며 $i$는 positional encoding 차원의 인덱스입니다. 주기함수의 파장은 $2\pi$에서 $10000\cdot 2\pi$의 값을 갖습니다. 저자는 어떤 고정된 오프셋 $k$에 대해서든 $PE_{pos+k}$가 $PE_{pos}$의 선형 함수로 표현될 수 있기 때문에, 이 함수를 사용하여 모델이 상대적인 위치를 잘 학습할 것이라고 생각하였습니다.
여기서 $PE_{pos+k}$가 $PE_{pos}$에 대한 선형 함수르 표현될 수 있는 이유는 삼각함수의 성질과 관련이 있습니다. 먼저 $\sin(A+B)$는 삼각함수의 덧셈정리에 의해 다음과 같이 나타낼 수 있습니다.
같은 원리로 $PE_{(pos+k, 2i)}$ 또한 다음과 같이 나타낼 수 있습니다. 수식에서 $B$는 $pos$자리에 $k$를 대입한 것입니다.
논문에서는 learned positional embedding을 사용한 모델의 실험도 진행하였는데, 두 버전의 성능은 거의 비슷했습니다. 하지만 Transformer에서는 sinusoidal version이 학습 과정에서 보지 못한 길이가 긴 시퀀스에 대해 더 잘 일반화될 것이라고 생각되어 최종적으로 사용되었습니다.
이는 사인과 코사인 함수의 특징과 관계가 있습니다. 정현파(sinusoidal)는 주기를 가지므로 일정한 간격으로 같은 값이 반복됩니다. 모델이 학습에 사용된 데이터의 길이보다 더 긴 데이터를 다루게 되어도, sinusoidal positional encoding은 이전에 본 것과 같은 값을 생성할 것입니다. 따라서 긴 시퀀스에 대한 일반화가 잘 될 것이라고 기대할 수 있습니다.
참고로 positional encoding에서 단순히 토큰의 인덱스를 사용하지 않는 이유는, 시퀀스의 뒷부분에서 그 값이 커져 gradient exploding의 문제가 발생할 수 있기 때문입니다. 이 문제를 해결하기 위한 방법이 바로 값을 정규화하는 것인데, 사인과 코사인 함수는 그 자체로 -1에서 1사이의 값만을 가집니다. 문제는 주기함수의 특성 상 같은 값이 반복될 수 있다는 것인데, 이를 해결하기 위하여 저자는 매 위치에서 정현파의 주기를 다르게 하여 고유한 값을 갖게 하였습니다. $pos$가 10000보다 클 경우, positional encoding의 값이 반복될 수 있지만, 일반적인 데이터의 길이를 생각해보면 이런 일은 발생하지 않을 것이라고 봐도 무방합니다.
Positional encoding과 Word embedding 사이의 연산이 concatenation이 아닌 summing인 이유는 다음과 같을 것입니다. 먼저 concatenation은 벡터의 차원을 두 배로 만들어 더 많은 메모리를 필요로 합니다. 또한 연결된 벡터를 다시 원래의 차원으로 투영하기 위해서는 또 다른 선형 레이어가 필요한데, 이는 학습할 파라미터의 숫자를 늘릴 것입니다. 물론 두 벡터를 단순히 더하면 위치 정보에 손실이 발생할 수 있습니다. 예를 들어 더해진 값이 1일 때, 이 값이 원래 0.3 + 0.7이었는지, 0.5 + 0.5였는지를 알 수 없습니다. 하지만 Transformer가 반드시 원래의 값을 복원할 수 있어야 하는 것은 아닙니다. 핵심은 인코딩된 벡터가 일관성(consistency)를 유지한다는 것인데, 같은 단어가 같은 위치에서 인코딩될 경우 같은 벡터를 갖게 됩니다. 이를 통해 Transformer는 대규모 데이터로부터 단어 간의 관계를 잘 학습할 수 있습니다. 즉 Transformer는 positional encoding과 word embedding을 따로 학습하는 것이 아닌 이를 조합하여 하나의 개체로 인식하고 학습한다고 생각할 수 있습니다.
4. Why Self Attention
이제 셀프 어텐션 레이어와 순환, 또는 합성곱 신경망을 다양한 측면에서 비교해보아야 합니다. 논문에서는 세 가지 측면에서 이들을 비교하였는데, 첫 번째로 각 레이어에 대한 연산 복잡도 입니다. 다른 하나는 병렬화될 수 있는 연산량이며, 이는 최소한으로 요구되는 순차적 연산(sequential operation)으로 측정됩니다. 마지막은 장기 의존성(long-range dependency) 사이의 path length입니다. 장기적 의존성은 시퀀스 변환 모델에서 주요 해결 과제중 하나인데, 장기적 의존성을 갖는 두 토큰 사이의 거리가 짧을수록 좋습니다.
다음 표를 통해 각 레이어를 비교한 결과를 확인할 수 있습니다. 셀프 어텐션 레이어는 복잡도가 $n$인 RNN과 다르게, 모든 position을 어떤 상수에 비례하는 순차적 연산을 통해 연관지을 수 있습니다. 또한 셀프 어텐션 레이어는 $n$이 $d$ 보다 작을 경우 RNN보다 연산 복잡도도 낮은데, 대부분의 경우 시퀀스의 길이가 벡터의 차원보다 작기 때문에 실제로 연산 효율이 더 좋습니다. 연산 효율을 높이기 위해서 어떤 position을 중심으로 크기가 $r$인 window 내에서만 어텐션을 수행하는 restricted self attention을 사용할 수도 있습니다. 이 경우 maximum path length는 $O(n/r)$이 됩니다.
예를 들어 시퀀스 길이가 100이고 window의 크기가 10일 경우, 첫 번째 토큰과 마지막 토큰의 어텐션 함수가 계산되기 위해서는 window를 9번 이동해야 하므로, maximum path length가 10이 됩니다. 같은 원리로 RNN에서는 그 길이가 100이 되고 이는 시퀀스 길이인 $n$에 비례하게 됩니다.
Convolutional layer에서도 비슷하게 커널 크기가 $k < n$일 경우 모든 position이 연결될 수 없습니다. 따라서 contiguous kernel의 경우 $O(n/k)$의 복잡도를 갖고, dilated convolution의 경우 $O(log_k(n))$의 복잡도를 갖습니다. 합성곱 신경망은 일반적으로 순환 신경망보다 연산 비용이 크지만, separable convolution은 연산 복잡도를 $O(k\cdot n \cdot d + n \cdot d^2)$로 크게 줄일 수 있습니다. 하지만 $k=n$이 되어도 연산 비용은 셀프 어텐션 레이어와 point-wise 피드포워드 레이어를 함께 사용한 것과 같습니다. 따라서 셀프 어텐션 레이어는 모든 면에서 효율적이라고 결론지을 수 있습니다.
어텐션의 또 다른 이점은 모델에 해석 가능성을 부여한다는 것입니다. 각 어텐션 헤드가 서로 다른 태스크를 수행하는 방법을 학습할 뿐만 아니라 헤드는 문장의 의미론적, 통사론적 구조를 학습하기도 합니다.
위 그림은 인코더의 셀프 어텐션 레이어가 장기 의존성을 학습했다는 것을 보여줍니다. 서로 다른 색깔은 각 어텐션 헤드를 의미하며, 여러 어텐션 헤드가 동사 making과 먼 거리에 있는 단어와의 관계에 주목했음을 알 수 있습니다.
위 그림에서는 두 개의 어텐션 헤드가 anaphora에 대해 이해하였음을 알 수 있습니다. Anaphora는 어떤 단어가 이전에 언급된 단어를 지칭하는 것을 의미합니다. 여기서 어떤 단어는 흔히 대명사입니다. 위 예시의 왼쪽 그림에서 its가 Law를 가리키고 있음을 알 수 있습니다. 실제로 “법은 완벽하지 않지만, 법의 적용은 공정해야 한다.”라고 해석되는 이 문장에서 it application의 it은 법에 대응합니다.
위 그림에서는 어텐션 헤드가 학습한 내용이 문장 구조와 연관되어 있음을 볼 수 있습니다. 또한 각 헤드가 서로 다른 부분에 집중하여 이런 정보를 학습했음을 알 수 있습니다.
5. Training
5.1 Training Data and Batching
450만 개의 문장쌍으로 이루어진 WMT 2014 English-German 데이터셋으로 모델을 훈련하였습니다. 문장은 약 37000개의 토큰으로 이루어진 어휘사전(vocabulary)을 갖는 byte-pair encoding을 통해 인코딩되었습니다. English-French 번역 태스크에서는 3600만 개의 문장 쌍으로 이루어진 WMT 2014 English-French를 사용하였고 32000개의 word-piece vocabulary를 사용하였습니다. 문장 쌍은 시퀀스 길이에 따라 배치를 이루었습니다.
5.2 Hardward and Schedule
모델은 8개의 NVIDIA P100 GPU를 가진 하나의 기기에서 훈련되었습니다. Base model에서 매 training step당 0.4초가 걸렸고 총 12시간 동안 10만 step을 훈련하였습니다. Big model은 각 training step당 1초가 걸렸으며 3.5일동안 30만 step을 훈련하였습니다.
5.3 Optimizer
학습에는 Adam optimizer를 사용하였고 $\beta_1=0.9$, $\beta_2=0.98$, $\epsilon=10^{-9}$입니다. 여기서 $\beta_1$과 $\beta_2$는 기울기 감쇠와 연관되며 $\epsilon$은 파라미터를 업데이트하는 과정에서 사용하는 공식의 분모가 0이되지 않기 위해 추가합니다.
모델 훈련 동안 learning rate scheduler가 사용되었는데, 이는 다음 공식을 따릅니다.
이는 처음 $\textit{warmup_steps}$ 동안 학습률이 선형적으로 증가하고, 이후 inverse square root에 비례하게 학습률이 감소함을 의미합니다. $\textit{warmup_steps}=4000$을 사용하였습니다. 코드를 통해 실제로 학습률이 어떻게 변화하는지 다음과 같이 확인할 수 있습니다.
import numpy as np
import matplotlib.pyplot as plt
def lrate(d_model, step_num, warmup_steps):
arg1 = step_num**-0.5
arg2 = step_num * warmup_steps**-1.5
return d_model**-0.5 * min(arg1, arg2)
d_model = 512
warmup_steps = 4000
steps = np.arange(1, 20000)
lrate_values = [lrate(d_model, step, warmup_steps) for step in steps]
plt.figure(figsize=(10, 5), dpi=200)
plt.plot(steps, lrate_values, label='Learning Rate', color='black')
plt.xlabel('Step')
plt.ylabel('Learning Rate')
plt.grid(True)
plt.ticklabel_format(style='sci', axis='y', scilimits=(0, 1))
plt.legend()
plt.show()
Residual Dropout
Transformer의 각 서브레이어의 출력은 residual connection에서 원본 입력에 더해지기 전 드롭아웃이 적용된 후 레이어 정규화가 수행됩니다. 드롭아웃은 인코더와 디코더 스택 모두에서 임베딩과 positional encoding을 합한 벡터에도 적용됩니다. Base model에서 $P_{drop}=0.1$입니다.
참고로 현재 Transformer가 구현된 코드에서는 레이어 정규화가 먼저 수행됩니다. 논문에서 레이어 정규화(LN)가 적용된 방식을 Post-LN이라 하고, 아래 코드와 같이 레이어 정규화를 먼저 적용하는 방식을 Pre-LN이라고 합니다. On Layer Normalization in the Transformer Architecture 논문을 통해 Pre-LN 방식이 학습 안정성과 효율을 높인다는 연구 결과로 인해 구현 방식이 변경된 것으로 보입니다.
Label Smoothing
학습 과정에서 $\epsilon_{ls}=0.1$의 label smoothing을 적용하였습니다. 이는 perplexity를 높여 모델의 예측에 대한 confidence를 낮추지만, BLEU 점수는 향상되었습니다.
6. Results
6.1 Machine Translation
WMT 2014 English-to-German 번역 태스크와 WMT 2014 English-to-French 번역 태스크에 대한 실험 결과는 다음과 같습니다. 주목할 점은 Transformer(big) 모델의 경우 앙상블 모델보다 뛰어난 성능을 보이며 base 모델 또한 EN-DE 태스크에서는 앙상블 모델을 포함한 모든 모델보다 나은 성능을 보입니다. 특히 Transformer 모델의 훈련 비용도 기존의 SOTA 모델 보다 훨씬 적은 것을 확인할 수 있습니다.
Base model은 마지막 5개의 체크포인트를 평균한 모델을 사용하였고, big model은 20개의 체크포인트를 사용하였습니다. 각 체크포인트는 10분 간격으로 저장되었습니다. Beam size를 4로 하여 beam search를 수행하였고 length penalty $\alpha=0.6$을 사용하였습니다. 최대 출력 길이는 입력 길이 + 50으로 하였고 가능한 경우 일찍 디코딩을 마치도록 하였습니다.
위 표에서 모델 훈련에 사용된 floating point operation은 학습 시간, 사용된 GPU 개수, 각 GPU에 대해 추정한 single-precision floating-point capacity를 곱하여 계산하였습니다.
6.2 Model Variations
저자는 newstest 2013 데이터셋을 사용하여 English-to-German 번역 태스크를 통해 Transformer의 각 구성 요소에 대한 ablation study를 수행하였습니다. 여기서는 앞에서 언급한 빔 서치는 그대로 사용하였지만, checkpoint averaging은 사용되지 않았습니다.
(A)열을 통해 single head attention 보다는 multi head attention이 나은 성능을 보이지만, 어텐션 헤드가 너무 많으면 오히려 성능이 저하됨을 알 수 있습니다. (B)열에서는 $d_k$의 차원이 작아지면 모델 품질이 저하됨을 알 수 있습니다. (C)와 (D)열을 통해 큰 모델이 더 나은 성능을 보이며 드롭아웃을 통해 과대적합이 방지되는 것을 다시 한번 확인하였습니다. (E)에서는 sinusiodal positional encoding을 learned positional embedding으로 교체한 결과를 보여주는데, 모델 성능에는 거의 차이가 없습니다.
6.3 English Constituency Parsing
저자는 Transformer가 다른 태스크에도 일반적으로 좋은 성능을 보이는지 확인하기 위하여 constituency parsing을 통해 검증하였습니다. 이 태스크는 출력이 문법을 따라야 한다는 구조적 제약이 있고, 출력이 입력보다 길다는 점에서 어려운 과제입니다. 예를 들어 Penn Treebank annotation의 경우 출력은 원본 문장에 파싱된 문법 구조에 대한 정보가 더해지기 때문에 입력에 비해 그 길이가 매우 깁니다. 게다가 RNN을 사용한 sequence-to-sequence 모델은 소규모 데이터를 사용하는 경우 SOTA 성능을 달성할 수 없었습니다.
이 태스크에는 $d_\textrm{model}=1024$ 차원을 갖는 4개의 Transformer 레이어를 갖는 모델이 사용되어, 4만여개의 문장으로 이루어진 Wall Street Journal 데이터셋으로 훈련되었습니다. 또한 1700만 여개의 문장을 사용하여 semi-supervised setting에서 학습된 모델도 사용되었습니다. Inference 단계에서 태스크를 고려하여 최대 출력 크기를 입력 크기보다 300만큼 크게 하였습니다. 빔 사이즈는 21을 $\alpha=0.3$을 사용하였습니다. 실험 결과는 다음과 같습니다. 태스크에 특화한 튜닝이 충분히 수행되지 않았음에도 뛰어난 성능을 보임을 알 수 있습니다.
7. Conclusion
이 논문에서는 어텐션에만 전적으로 의존하는 최초의 문장 변환 모델인 Transformer를 제안하였습니다. Transformer는 대부분의 인코더-디코더 아키텍처에서 사용되는 recurrent layer를 multi-headed self attention으로 대체하였습니다.
저자는 Transformer의 적용 범위를 확장하여 텍스트 뿐만 아니라 다른 모달리티의 입력과 출력을 갖는 문제를 해결하려는 계획을 세웠습니다. 또한 local, restricted attention 메커니즘을 사용하여 이미지, 비디오와 오디오와 같이 규모가 큰 입출력을 처리하는 방식을 연구하고자 합니다. 마지막으로 생성 과정에서 순차적인 연산을 줄이는 것도 또 하나의 연구 과제로 설정하였습니다.
8. Reflection
딥러닝 분야의 랜드마크 논문인 만큼 정말 획기적인 아키텍처를 제안했을 뿐만 아니라 논문 구성과 내용도 정말 잘 쓰여졌다는 생각이 들었습니다. 트랜스포머는 2017년에 제안되어 현재까지도 대부분의 최첨단 모델에서 사용되는 아키텍처입니다. 이 분야가 매우 빠르게 발전하고 있는데도 이를 넘어서는 아키텍처가 새롭게 제안되지 않는다는 것이 놀랍고, 또한 그만큼 시대를 앞선 혁명적인 연구라는 게 다시 한번 느껴졌습니다. 아마 올해 트랜스포머를 넘어설 것이라고 주장하는 Retentive Network(RetNet)이 제안된 것으로 아는데 현재 많이 언급되지 않는 것으로 보아 아직까지는 트랜스포머가 최고의 아키텍처가 아닐까 생각됩니다. 트랜스포머는 BERT, GPT 등 이후에 제안되는 수많은 획기적인 연구의 바탕이 되기도 하였고 HuggingFace가 발표한 라이브러리의 이름으로 사용될 정도로 NLP와 딥러닝에서 큰 입지를 갖고 있습니다.
이 논문을 처음 읽은 것은 올해 봄 쯤인데, 당시에 정리한 내용에 부족함이 많이 있다고 생각되어 다시 한 번 꼼꼼히 읽어보며 리뷰를 작성해보았습니다. 논문을 다시 읽어보니, 논문도 개정되는 게 아닐까 싶을 정도로 새롭게 알게 된 내용이 많았습니다. 같은 글이라도 여러번 볼 필요성이 있다는 사실을 새삼 느꼈습니다. 특히 트랜스포머에 사용된 residual connection, layer normalization, adam optimizer 등을 포함한 여러 개념들에 대해서 추가로 공부하는 과정에서 딥러닝 분야 전반에 걸친 다양한 지식을 얻을 수 있어서 더욱 유익했습니다.
댓글