제가 Transformer 논문 "Attention Is All You Need" 를 읽을때마다 느끼는 점은 self-attention, multi-head attention 모두 좋지만 positional encoding 기법만큼은 직관적으로 이해하기 쉽지 않다는 점입니다. 물론 Transformer 자체에는 입력 시퀀스 위치에 대한 정보가 없으니 positional encoding 이 필요하다는 사실은 당연하나 논문에서는 매우 짧게 cosine / sine 함수로 이루어진 식만 제공합니다.
그렇다면 위의 식은 어떠한 이유로 유도가 되었을까요? 한 번 살펴보도록 하겠습니다.
Positional encoding
Positional encoding 이란 주어진 시퀀스에서 특정한 위치에 대한 유한한 차원의 representation 을 말합니다. 시퀀스 $A=[a_0, a_1, ..., a_{n-1}]$이 주어졌을 때 positional encoding 결과는 시퀀스의 각 원소의 위치와 원소 간의 위치에 대한 정보를 담고있는 텐서가 될 것이고 Transformer 에서는 입력 시퀀스의 각 원소별 임베딩 결과와 positional encoding 결과가 더해져야하므로 positional encoding 결과는 [시퀀스 길이, 임베딩 차원] 크기를 가져야만 합니다. 특히, 이상적인 positional encoding 을 위해서는 1) 각 위치 별로 유일한 벡터 값이고, 2) 서로 다른 길이의 시퀀스에 대해서도 적용이 가능하고, 3) 서로 다른 길이의 시퀀스의 두 인덱스 간 거리는 일정해야합니다. 그렇다면 가장 간단하게 위치를 담고있는 방법부터 생각해보겠습니다.
Simple indexing
Positional encoding 을 가장 간단하게 수행하는 방법으로는 Figure 1처럼 $a_i\rightarrow i$일 것입니다. 즉, 각 위치 인덱스 자체를 positional encoding 으로 사용하겠다는 것이죠. 이 방법은 absolute positional encoding 방법으로 제일 왼쪽을 기준으로한 값입니다. 하지만 이 방법은 시퀀스가 길어지면 그에따라 인덱스도 같이 커지기 때문에 매우 큰 값을 neural networks 입력으로 넣으면 exploding gradients 나 훈련이 매우 불안정해지는 현상이 발생합니다.
Normalize simple indexing
인덱스 자체가 매우 커지는 것이 문제라면 Figure 2처럼 인덱스의 최대값을 나누면 모든 positional encoding 값이 [0,1] 사이에 존재하니 괜찮을 것 같습니다. 하지만 이 경우는 임의의 시퀀스 길이에 대응할 수 없는 것이 시퀀스 길이가 5라면 0.8은 4번째 원소를 의미할 것이고 시퀀스 길이가 20이라면 0.8은 16번째 원소를 의미할 것이므로 길이마다 encoding 의미가 달라지게 됩니다.
Using binary
그렇다면 인덱스 값 자체를 이진수로 표현하는 것은 어떨까요? 이진수는 0과 1로만 구성되니 크기 문제에서도 자유롭고 정규화를 시켜줄 필요도 없습니다. 대신에 인덱스 최대값을 표현할 수 있는 위치당 $d_{model}$ 차원이 필요하겟죠. 하지만 우리는 연속적인 벡터로부터 임의의 위치를 표현하는 값을 얻고 싶은데 이 방법은 순수히 discrete 합니다. 즉, 위치 별로 discrete 한 값을 얻는다 하더라도 그것을 연속적인 함수로부터 얻고 싶고 그래야 중간 위치의 interpolation 또한 쉽게 가능하겠죠. 결과적으로 이진 벡터를 어떤 연속적인 함수로부터의 discretization 결과로서 얻는 방법이 필요합니다.
Continuous binary vector
시퀀스의 각 위치를 표현하는 $d_{model}$ 차원의 encoding 벡터를 이었을 때 그것이 연속적인 함수로 표현되면 좋을 것 같습니다. 위의 이진 벡터를 연속적으로 만들기 위해서는 0과 1을 왔다갔다하는 함수가 필요한데 바로 sine 함수가 있죠. 특히 sine 함수는 [-1, 1] 사이에 값이 위치해 있으므로 이미 정규화 또한 되어 있습니다.
Figure 4와 같이 음량을 조절하는 상상의 dial 들이 존재한다고 가정하고 dial 들은 0과 1을 계속해서 반복합니다. 또한, 512개의 음량 레벨이 존재한다고 했을 때 하나의 큰 dial 이 아니라 8개의 작은 dial 들로부터 음량 레벨을 맞춘다고 생각해보겠습니다. 첫 번째 dial 은 매우 미세하게 한 칸씩 움직이고 두 번째 dial 은 두 칸, 세 번째 dial 은 4 칸 등으로 움직인다고 하면 모든 음량 레벨을 표현할 수 있습니다. (1+2+...+256=512) 즉, 맞추고자 하는 특정 음량을 시퀀스의 위치라 생각하면 해당 위치에 존재하는 $d_{model}$개의 dial 의 0 / 1 을 조절함으로써 표현할 수 있다는 것이죠.
이를 수학적으로 어떻게 표현할 수 있을까요? 첫번째 dial ($d_{model}$의 첫번째 차원) 은 시퀀스를 한 스텝 움직일 때마다 0과 1이 바뀌니 주기가 $\pi/2$, 두번째 dial 은 $\pi/4$, 세번째 dial 은 $\pi/8$ 식으로 될 겁니다. 따라서 다음과 같은 형태로 쓸 수 있을 겁니다.
$sin(\pi i / 2^j)=sin(x_i w_j)$
$x_i$는 시퀀스의 위치 인덱스이고 $j$는 임베딩 차원으로 $d_{model}$까지의 값을 가집니다. ($w_j$는 $j$에 해당하는 주파수를 나타냅니다.) 하지만 문제가 두가지 있습니다. 첫번째 문제는 Figure 5처럼 위 식을 따라 주기가 $\pi/2, \pi/4, \pi/8$에 대한 위치에 따른 3차원 encoding 결과를 나타낸 것으로 시퀀스 인덱스가 계속 움직이면 다시 처음 인덱스로 돌아가는 닫힌 구조로 되어 있습니다. 즉, 처음 인덱스와 멀리 떨어진 인덱스가 동일해진다는 것이죠.
생각해보면 positional encoding 결과가 이진 벡터일 필요는 없습니다. 시퀀스 별 각 위치를 어떠한 벡터로 표현하면 되기 때문에 주기가 굳이 $\pi/2$로부터 파생될 필요가 없고 단지 $j$에 따라서 주파수가 감소하면 됩니다. 따라서 다음과 같이 구성하고 Transformer 에서는 최저 frequency $w_0=1/10000$ 으로 $j$가 증가할 때마다 주파수가 단조적으로 감소합니다.
$sin(x_i w_0^{j/d_{model}})$
두번째 고칠 점은 인덱스 $i$의 positional encoding 벡터가 인덱스 $j$의 positional encoding 벡터의 함수로 표현되게 하고 싶은 positional encoding translation 을 반영하는 것입니다. 특히, Transformer 에서는 self-attention 기법을 통해 각 위치 별 다른 모든 위치에 대한 attention score 를 계산한다는 점에서 각 인덱스 별 positional encoding 벡터가 다른 인덱스 벡터의 선형변환으로 표현할 수 있게 하는 것이 중요합니다.
Use both sine and cosine
Equation 1과 같이 각 위치 별 positoinal encoding 벡터가 쌓인 $PE$ 행렬이 구성되고 다음 $v^i$에 대해 인덱스 벡터간 선형변환을 위해서 $PE(x+\nabla x) = PE(x)\cdot T(\nabla x)$를 만족하는 선형변환 $T$를 구성해야만 합니다.
$v^i=[sin(w_0 x_i), ..., sin(w_{n-1} x_i)]$
이것은 위치 $x$가 실질적으로 sine 함수의 각도로 들어가기 때문에 Equation 2와 같이 cosine / sine 함수의 각도에 따른 rotation 법칙을 사용하면 해결할 수 있습니다.
먼저 각 $v^i$에 대해 sine 함수를 cosine 함수로 대체한 벡터를 구성합니다. 이후에 새로운 $PE$ 행렬을 sine 함수와 cosine 함수를 번갈아가면서 다음과 같이 구성합니다.
$v^i=[cos(w_0 x_i), sin(w_0, x_i), ..., cos(w_{n-1}x_i), sin(w_{n-1}x_i)$
이제 Equation 3과 같이 선형변환을 위한 $T$를 구성할 수 있습니다. Equation 2의 $\theta, \phi$를 각각 인덱스와 인덱스 오프셋이라 생각할 수 있고 예를 들어 $k$번째 dial 에서 $dx$ 만큼 이동시키려면 $\omega_k \cdot dx$ 만큼의 각도이동이 필요합니다. 즉, cosine 함수를 sine 함수와 번갈아가며 사용함으로써 각 인덱스 별 positional encoding 벡터 간의 선형변환이 가능해집니다. 이는 추후 attention layer 에서 선형변환을 통해 key, query 를 구성할 때 도움이 되고 Transformer 에서 사용되었던 positional encoding 행렬 구성이 완료되었습니다.
Wrapup
Positional encoding 특성은 다음과 같습니다.
- 시퀀스 길이 (보통 최대 길이를 지정합니다.), 임베딩 차원] 크기의 텐서로 구성됩니다.
- $PE$ 행렬의 각 행은 sine / cosine 함수에서 각 위치별로 interpolate 된 벡터입니다.
- $PE$ 행렬은 행은 sine / cosine 함수가 번갈아가면서 구성되며 열은 임베딩 차원이 커지면서 주파수가 감소합니다. (파장은 주파수의 역수이므로 증가합니다.)
- 임의의 두 행에 대해서 선형변환이 가능한 행렬이 존재합니다.
홍머스 정리
- 그렇다면 입력 시퀀스 정보를 담은 임베딩과 위치 정보를 담은 임베딩을 이어붙이지 (concatenate) 않고 더하는 이유에 대해서는 아직 명확히 정리된 것은 없음. 일단 더함으로서 메모리 공간 상으로 이득이 있고 최저 주파수가 1/10000 인 상태에서 상대적으로 시퀀스 길이가 짧을 경우 위치 임베딩이 매우 sparse 해질 것이고 이에따라 더하기를 하여도 입력 임베딩의 정보가 손실되지 않을 것이라고 추정됨.
- 또한, 상대적으로 시퀀스 길이가 짧다면 전체 임베딩 차원에서 처음의 몇 개의 차원에 대해서는 위치 임베딩이 집중적으로 사용할 것이기 때문에 더하기 대신 concatenate 비슷하게 구성해야되지 않을까 생각됨.
참조
'Machine Learning Models > Transformer' 카테고리의 다른 글
Vision Transformer (3) - Attention Map (3) | 2021.06.17 |
---|---|
Vision Transformer (2) (0) | 2021.06.16 |
Vision Transformer (1) (3) | 2021.06.16 |
Transformer 구현 (0) | 2021.05.27 |
Transformer (0) | 2021.05.27 |