비밀번호

커뮤니티2

  • 구름많음속초23.0구름조금북춘천19.0구름조금철원19.9맑음동두천20.3맑음파주19.3구름조금대관령15.5구름많음춘천19.1구름조금백령도16.6맑음북강릉23.5구름조금강릉24.3구름조금동해21.6맑음서울19.6맑음인천17.4구름조금원주19.6구름조금울릉도17.1맑음수원19.3맑음영월19.3맑음충주19.8맑음서산18.7구름조금울진17.2맑음청주20.3맑음대전21.1맑음추풍령19.5맑음안동19.3맑음상주21.7맑음포항21.5맑음군산19.2맑음대구21.5맑음전주20.2맑음울산20.5맑음창원21.4맑음광주20.8맑음부산18.4맑음통영19.7맑음목포18.7맑음여수18.8맑음흑산도20.1맑음완도21.7맑음고창20.2맑음순천20.4맑음홍성19.8맑음서청주19.6맑음제주19.6맑음고산18.0맑음성산21.8맑음서귀포19.9맑음진주21.0맑음강화17.9구름조금양평18.8맑음이천20.9구름많음인제19.0구름많음홍천19.6구름조금태백18.5구름조금정선군21.5구름조금제천19.2맑음보은19.9맑음천안20.7맑음보령18.3맑음부여20.8맑음금산20.8맑음세종20.4맑음부안20.6맑음임실19.6맑음정읍20.9맑음남원20.0맑음장수19.6맑음고창군20.9맑음영광군20.7맑음김해시22.2맑음순창군20.7맑음북창원22.2맑음양산시21.7맑음보성군21.0맑음강진군22.8맑음장흥21.7맑음해남20.8맑음고흥21.5맑음의령군21.6맑음함양군22.5맑음광양시21.4맑음진도군19.7구름조금봉화18.9맑음영주19.7맑음문경20.7맑음청송군20.3맑음영덕21.1맑음의성20.9맑음구미22.5맑음영천21.6맑음경주시21.8맑음거창20.9맑음합천22.1맑음밀양21.7맑음산청22.2맑음거제21.1맑음남해21.1맑음북부산21.6
  • 2024.05.09(목)

데이터 엔지니어링데이터 엔지니어링

[ML/DL] Transformer - Rotary Encoding

이번글은 이전 Relative Positional Embedding의 단점을 보완하고, 최근 LLM모델에서 많이 사용되는 Rotary Positional Encoding (RoPE) 에 대해서 리뷰해보려 합니다.

 

이전에 소개했던 Absolute Positional Encoding, Relative Postional Embedding과 Encoding과 Embedding의 차이를 다시 짚어보면, 

Encoding은 모델 학습중에 변하지 않는 값이며, Embedding은 모델이 학습을 통해 변하는 파라미터이다.

 

Absolute Positional Encoding은 sinusodial 함수를 통해 토큰의 순서에 대한 정보를 전달한다. 그러나 이러한 방식은 토큰간의 거리에 대한 정보를 포함하고 있지 않기에 기준이 되는 토큰에서 가까운 토큰과 먼 토큰에 대해서 동일하게 본다.

 

Relative Positional Embedding은 Absolute Positional Encoding에서의 단점인 토큰간의 거리에 대한 정보를 추가하고 학습시에 순서에 대한 정보가 변경되는 Embedding 방법을 사용하였다. 그러나, 이러한 방식은 모델의 학습시 계산량이 늘어나며 비효율적 (Computationally Inefficient)하고, 모델을 사용하여 추론을 할 때에 Positional Embedding이 계속 바뀌어서 추론시에 적합하지 않다는 의견이 있다.

 

이번에 소개할 Rotary Positional Encoding은 위의 두가지 방법의 단점을 보완한 방법으로 RoFormer라는 모델에서 처음 소개되어 현재는 Llama2, PaLM등에서 많이 사용된다. Roformer: Enhanced Transformer with Rotary Position Embedding - https://arxiv.org/abs/2104.09864

 

Rotary Encoding은 삼각함수에서의 Rotation Matix를 이용한다.

Screenshot 2024-02-21 at 3.02.47 PM.png

 

IMG_0047.JPG


위의 예시에서, [x,y]에 해당하는 벡터가  θ (세타)값에 따라 원을 따라 로테이션 하는 것을 볼 수 있다 

 

아래 그림은 Radius가 1인 원에서의 cos(thetha)와 sin(thetha)를 시각화 한 것이다.

Screenshot 2024-02-21 at 3.42.39 PM.png

Rotation Matrix에 대해서 이해 했다면, 간단한 예시를 들어 Rotary Encoding을 이해해보자.

 

Token이 임베딩 레이어를 들어가서 나온 결과가 [b, seq, 2]로, 각 토큰이 2개의 벡터값으로 임베딩이 됬다는 가정으로 확인해보자.

 

Vaswani의 트랜스포머 모델의 Q, K, V는 행렬인데, 이를 백터화 하여 표현하자면 아래와 같다.

Screenshot 2024-02-21 at 3.28.56 PM.png

 

q의 m번째 순서는 f_q를 통해 나타나는 값, 이며 k, v도 동일한 의미이다.

 

따라서, q_m은 [1, 2]의 값을 가진다.

만약 문장의 길이가 5라면, 

Q는 [5, 2]의 크기를 가진 텐서가 된다.

 

벡터와 매트릭스의 표현을 주의하여 보면, RoFormer에 적용된 f_q는 아래와 같다.

Screenshot 2024-02-21 at 3.32.46 PM.png

위의 수식에서 m은 해당 토큰의 순서이다.

예를 들어, [ i, like, the, transformer] 라는 4개의 토큰이 있다면, 

i = 1, like = 2, the = 3, transformer = 4 라는 m값을 가진다.

 

thetha는 아래와 같이 정해진 값을 따른다.

Screenshot 2024-02-21 at 3.35.24 PM.png

 

여기서 i는 d/2이며, d 는 벡터의 dimension이다.

 

간단한 예제에서는 각 토큰이 2-d로 표현 되었기에 d=2가 되고, i = 1 하나의 값만 가진다.

따라서 Θ = {1}값 하나이다.

 

이에 따라 각 m에 해당하는 토큰들의 값을 로테이션을 해준다고 보면 된다.

 

여기에서 생기는 의문점은, 위와 같이 Position에 대한 값이 Encoding이 되었는데, 어떻게 Relative Position에 대한 정보를 주느냐? 라는 의문이 생길수 있다.

 

이는 아래 그림을 통해 알아 볼 수 있다.

 

https://www.youtube.com/watch?v=o29P0Kpobz0

 

위의 그림과 같이, 3개의 문장이 있다.

[dog]

[the dog]

[the pig chased the dog]

 

이 문장에서 우리는 dog라는 단어에 포커스를 맞추면, 단어가 출현하는 순서에 따라 fig.1의 dog의 백터값이 변화한다.

 

여기서 가장 중요한것은 fig.4인데, pig와 dog의 거리는 2를 보여준다. 

[the pig chased the dog]

[once upon a time, the pig chased the dog]

그러나, 각 pig와 dog가 문장에서 출현하는 위치는 다르다

1번문장의 pig는 m=2, dog = 5

2번 문장의 pig는 m=6, dog=9

각 문장에서 해당 단어가 가지는 로테이션은 다르지만, 동일한 거리의 차이로 인해 두 단어의 각도의 차이는 동일하다.

이 부분이 단어간의 거리에 대한 정보를 포함한다고 보는 점이다.

 

다시 수식을 보면, 

 

Screenshot 2024-02-21 at 3.57.46 PM.png

f_q를 구할때 단순 Thetha가 아닌 포지션인 m을 곱한 값을 통해 rotation matrix를 만든다

[cos(mθ) -sin(mθ) ]

[ sin(mθ)  cos(mθ)]

 

 

어떠한 방식으로 Rotary Encoding이 생성되는지 이해 했다면, 이번에는 2-D 이상의 값으로 생각해보자.

여기서 발생하는 문제는, 3차원으로보게 된다면, Rotation matrix는 더이상 단순하지가 않다..

 

Screenshot 2024-02-21 at 4.01.30 PM.png

 

3차원만 해도 수식이 복잡해지는데, 4차원, 등등 더욱 고차원으로 올라갈수록 input을 로테이션하기 위한 매트릭스는 더 복잡해진다. 더욱이, 대부분의 LLM에서 사용하는 차원수는, 1024가 넘어간다.

 

Screenshot 2024-02-21 at 4.04.56 PM.png

Llama의 경우 4096의 d 를 가졌다.

 

다행인점은 대부분의 모델들의 차원이 짝수개를 이룬다는 것이다. (even number) 대부분은 2의 제곱 형태로 증가한다.

 

이러한 문제를 해결하기 위해서, Roformer에서 고안한 방법은 고차원의 벡터를 2개씩 decompose하여 2개의 백터에 대해서 로테이션을 진행하는 방법이다.

Screenshot 2024-02-21 at 4.09.21 PM.png

 

Screenshot 2024-02-21 at 4.10.15 PM.png

 

위와 같이 정형화된 형식으로 Rotary Encoding 을 만들면 이렇게 만들수 있다.

Screenshot 2024-02-21 at 4.13.12 PM.png

 

인풋으로 들어오는 문장에서 단어의 최대 길이만큼 (context_window)의 R이라는 Rotary 텐서를 생성후에 

Q, K, V 값을 연산한다.

 

이를 적용한 Attention Block은 아래와 같이 쓸수 있다.

Screenshot 2024-02-21 at 4.15.40 PM.png

 

자세한 코드는 아래주소에서 찾아볼수 있다

https://github.com/bkitano/llama-from-scratch/blob/main/llama.ipynb 

 

이러한 방식으로 Rotary Encoding을 구현 할 수 있으나, Roformer에서 이런 R을 만드는 general form은 연산시 효율이 좋지 않아 다른 방법을 제안해 주었다.

 

Screenshot 2024-02-21 at 4.18.35 PM.png

 


연산의 효율을 올리기 위해서는 Roformer의 식을 다시 볼 필요가 있다.

 

Screenshot 2024-02-21 at 4.19.28 PM.png

 

Roformer에서 사용하는 방법은 복소수 (Complex Number)를 사용하여, 오일러 공식을 사용하는 방법이다.

 

위에서 들었던 간단한 예제를 보면, 2-D의 벡터는 Complex Number로 볼수 있다.

예를 들면, [1, 2]라는 Real Number를 Complex Number로 보게 되면, 1+2i (i = imaginary number)로 표현된다.

오일러 공식은 아래와 같다

Screenshot 2024-02-21 at 4.33.41 PM.png

undefined

 

 

특히 오일러 공식은 Rotation과 벡터의 변환 및 연산을 간략화 할 수 있다.

 

따라서 complex number를 사용하여 벡터의 로테이션을 진행해보면 다음과 같은 시각화 결과를 얻을수 있다.


Screenshot 2024-02-21 at 4.47.08 PM.png

 

위의 시각화는 아래의 코드를 통해 얻을수 있다.

Screenshot 2024-02-21 at 4.48.59 PM.png

 

Complex  Number를 사용함으로써 행렬곱이 아닌 [ (a + bi) * (sin(thetha) + cos(thetha)i ] 처럼 간략화 될수 있다.

 


Dimension관련해서 연산하는 방법이 이해가 됬다면, 이번에는 sequence length = 3인 문장에 대해서 로테이션을 진행해보자.

 

PNG image 3.png

 

 

중요한점은 이러한 Complex Number를 생성할때 Cartesian coordinates와 상응하는 polar coordinates를 생성해주는것이 중요하다. pytorch 에서는 polar라는 메소드를 사용 할 수 있다.

 

위의 매소드를 사용할때에는 abs값을 1. 로 사용한다.

 

이러한 점을 사용하면, wq를 구하는 것을 간략화 할수 있다.

PNG image 4.png

 

이러한 방법으로 Rotary Encoding을 구현할수 있으며, 정확한 코드는 Llama 코드에서 확인해볼수 있다.

https://github.com/facebookresearch/llama/blob/main/llama/model.py

 

 

전체댓글0

검색결과는 총 12건 입니다.    글쓰기
1