드디어 이해한 Transformer Positional Encoding/Embedding

2021. 10. 7. 21:39coding

반응형

이해하려고 노력할 때마다 항상 sin, cos의 폭격에 정신 못 차렸다.

하지만 귀여운 커피 캐릭터와 함께 드디어 이해가 좀 간다......

 

https://www.youtube.com/watch?v=1biZfFLPRSY&feature=youtu.be 

 

일단 트랜스포머에 positional encoding이 필요한 이유!

트랜스포머는 RNN, LSTM과 달리 recurrent하지 않음. input의 모든 토큰이 parallel하게 처리됨. 따라서 어순 정보가 추가적으로 필요함.

 

이 어순 정보를 positional encoding에 담아 전달할 건데, 이 positional encoding은 각 토큰의 word embedding과 더해짐. 더해져서 똑같은 단어라도 첫 번째 위치에 왔을 때랑, 다섯 번째 위치에 왔을 때 벡터 값을 약간 다르게 하는 거!!!

 

그래서 생각해볼 수 있는 간단한 후보가 몇 개 있다

1. 그냥 1,2,3,4를 배정하자 

첫 번째 토큰은 1, 두 번째 토큰은 2, ... 이런 식으로.

이 방식은 input 길이가 길어질수록 positional encoding의 값이 급격히 커질 수 있다는 단점이 있다. 이 값이 너무 커지면 word embedding과 더해졌을 때 어순 정보만 지배적이게 되어서 의미 정보는 퇴색될 수 있다. 값을 좀 줄이자!

 

2. 그렇다면 우리의 친구 normalization을 해볼 수 있다.

첫 번째 토큰은 0, 마지막 토큰은 1로 두고 그 사이를 0.xx로 만드는 거다. 

예를 들어 'I love you'는 [0, 0.5, 1], 'I want to eat ice-cream now'는 [0, 0.1, 0.2..., 1] 뭐 이런 식으로.

하지만!! 이 방식은 같은 두 번째 토큰이라도 input의 길이에 따라 값이 달라질 수 있다는 단점과 input의 길이에 따라 바로 옆에 있는 토큰들끼리의 차가 달라진 다는 단점이 있다. 

 

우리가 해결해야할 문제는 

- 의미가 퇴색되지 않게 positional encoding 값이 너무 크면 안 되고

 - n번째 토큰이면 항상 같은 positional encoding을 내놔야 한다는 것이다

 

이걸 sin, cos 함수를 통해 모두 만족할 수 있다. 

일단 sin, cos은 -1이랑 1 사이에서만 반복되는 주기함수니까 값이 너무 커지지 않는 조건은 바로 만족한다. 

그런데 또 주기함수니까 예를 들어 1번째 토큰이랑 5번째 토큰이랑 9번째 토큰이랑 모두 같은 positional encoding 값을 가질 수도 있다!!! 

 

여기서 우리가 착각하지 말아야 할 것이 각 토큰의 positional encoding은 하나의 값(스칼라)이 아니라 벡터라는 점이다.. word embedding의 차원과 같은 차원의 벡터.. 그래야 더하니까...

 

이 벡터를 채우기 위해 우리는 하나의 sin, cos 함수만 사용하는 것이 아니라 다양한 frequency의 sin, cos을 사용한다.

그래서 예를 들어 1번째 토큰이랑 5번째 토큰이랑 9번째 토큰이랑 모두 positional encoding 벡터의 1번째 차원의 값은 같을 수도 있지만 다른 차원에서 값이 다르니까 괜찮다.  그리고 당연히 우리의 2번째 조건도 만족한다. 

 

이 영상을 보고 깨달은 점... 

난 왜 지금까지 각 토큰의 positional encoding이 벡터라는 사실을 망각하고 있었을까? sin, cos 수식에 쫄아서 뇌가 멈췄던 게 분명하다 .. 

반응형