Vector Quantization

우리가 평소에 자주 사용하는 zip 파일이나 고해상도 이미지 및 음원들의 일부는 무손실 압축을 사용한다. 손실 없이 압축해야만 정보가 보존되기 때문이다. 통계적으로 데이터의 중복을 활용하여 압축하는 등의 방법을 사용한다.
반대로 손실 압축은 말 그대로 일부 정보를 버려서 압축한다. TurboQuant에서 사용하는 데이터 압축 방식은 벡터 양자화로 손실 압축이다. 양자화는 높은 정밀도의 데이터를 낮은 정밀도로 매핑하는 것을 말한다.
이미지 데이터
우리는 접하는 다양한 종류의 정보들은 사용하고자 하는 목적에 따라서 정보가 가지고 있는 정보량이 과잉일수도, 부족할 수도 있다. 이미지를 표현하는 방법을 생각해보자. 해상도가 높으려면 많은 픽셀이 필요하고, 풍부한 색상을 표현하려면 넓은 색영역을 지원하는 방법이 필요하다. 둘 다 많은 데이터를 필요로 한다. 같은 이미지를 저해상도, 좁은 색영역으로 표현하면 사진의 품질이 다소 아쉬워지지만, 용량을 줄일 수 있다. 이미지 데이터는 반드시 높은 해상도, 넓은 색영역에서 표현되어야할까? 그렇지 않다.
이미지가 사용되는 목적은 다양한다. 누군가는 이미지 데이터를 이미지 감상에 사용한다. 누군가는 이미지 속 어떤 사물을 식별하는 용도로 사용할 것이다. 어떤 사람은 이미지에 담간 어떤 메시지만 충분한 경우도 있을 것이다. 이 경우에는 흑백 사진이어도 상관 없을 수도 있다. 한정된 공간에 많은 이미지를 저장하고 싶은 사람은 적은 용량의 이미지를 선호할 것이다. 결국 이미지 데이터의 품질과 그에 따른 크기는 목적에 따라 결정된다고 말할 수 있다.
AI 모델과 데이터

AI에서 사용되는 데이터들에는 가중치(weight)과 컨텍스트(context window, KV cache)가 있다. 이외에도 다양하지만, 예시로써는 충분하다. AI에서 데이터들은 추론하기에 충분한 정도의 최소한의 크기로 존재해야한다. 그래야 한정된 자원으로 최대한 큰 모델로 깊은 추론을 수행할 수 있다.
데이터 크기는 추론 성능을 유지할 수 있을 정도면 된다. 그 선까지 압축하기 위해서 transformer 기반 모델들에서는 벡터 양자화 방식을 사용하고, 여러 변종이 존재한다.
TurboQuant는 어떤 것이 다를까?
벡터 양자화같은 생각은 연구자라면 누구나 할 수 있는 생각이다. 한정된 자원으로 더 많은 일을 하기 위한 방법 혹은 알고리즘. 떠올리기 쉬운 주제다. TurboQuant 이전에도 많은 연구자들이 이미 추론 성능을 최대한 유지하면서도 추론에 필요한 데이터를 최소한으로 유지하기 위한 여러 방법들을 제시해왔다. 하지만 TurboQuant가 달성한 것은 압축 전과 (거의) 동일한 수준의 추론성능을 보이면서도 매우 높은 효율의 압축률이다.

단순히 압축만 한건 아니다. 이 속에 숨겨져 있는 논리를 한 번 살펴보자.
Codebook를 골라보자
벡터 양자화를 쉽게 이해하기 위해서 다음 예시를 가져왔다. 물컵 그림이다.

물컵 그림을 표현하기 위해 74개의 색상을 사용한 상태이다. 색상을 적게 사용해서 표현한다면 74개의 색상을 저장할 필요가 없으므로 이미지를 효율적으로 표현할 수 있을 것이다. 그래서 2개의 색상으로 물컵을 표현했다. 대충 물컵인지 알 수 있는 이미지가 생성되었다. 다만 물컵의 깊이 표현이나 컵이 질감 표현이 사라져서 아쉬운 품질이 된 것을 확인할 수 있다.

이제 물컵을 그림으로 표현할 때 32개의 색상을 사용해보자. 74개의 색상을 사용할 때와 별반 다르지 않다. 물컵 깊이 표현이 살짝 단순해진 정도? 하지만 컵의 질감이나 물 표현은 거의 비슷하다고 할 수 있다. 하지만 색상은 절반 밖에 사용하지 않은 것이다.
어떤 색상으로 데이터를 표현할 것인가에서, 색상에 해당하는 것이 바로 코드북(codebook)이다. 내가 정해놓은 도구들로 표현하는것이다. 개념을 확장하여, 평면 상의 점을 생각해보자. 평면에 여러 점들이 찍혀 있다. 점들의 개수, 점들 사이의 거리가 여기에 포함된 정보다. 극단적인 예시로, 100개의 점이 있고 10개의 점들끼리 가까이 모여 있어서 10개의 그룹을 이루고 있다고 생각해보면, 우리는 이 100개의 점을 10개의 점으로 표현할 수 있다. 우리가 원하는 것이 점이 모여있는 구역을 나누는 작업이라고 한다면 10개의 점으로 표현해버리는 것이 이 평면을 이해하는데 매우 적합할 것이다.
여러 예시로 머리를 적셔 다음에 이어질 논리들을 맞이할 준비를 해보자. 이번에는 거대한 회전목마를 생각해보자. 다만 목마들이 없는, 평평한 돌아가는 원형판으로 생각해보자. 여기에 우리는 나뭇가지 100개를 무작위로 뿌려놓을 것이다. 회전판을 돌려도 나뭇가지들은 움직이지 않는다. 회전판을 돌려놓고 잠시 후 회전판을 멈추고, 나뭇가지들의 모양을 관찰해본다. 이 후 다시 반복한다. 우리가 바라보는 방향이 바뀌었기 때문에 매번 다른 형태로 보일 것이다. 하지만 나뭇가지들의 길이와 서로 놓여져 있는 모습이 바뀌었나? 아니다. 나뭇가지들은 원형판 위에 그대로 있을뿐이고, 우리가 판을 회전시켜서 다른 방향에서 바라본 것이다.
고차원 벡터를 위한 전용 아이템
AI 모델에서 사용하는 데이터들은 고차원 벡터 데이터다. 이제 이 벡터들이 갖고 있는 정보들을 압축하기 위해 벡터 양자화를 할 것이다. 앞선 예시들을 머리에 담아두고 벡터를 바라보면 나뭇가지로 보일 것이다…. 여러가지 색을 가지고 있는 나뭇가지 (색상 정보를 포함한 평면 상의 나뭇가지는 3차원으로 생각하면 될 것이다). 이 벡터들이 우선 2차원에 놓여 있다 생각하고 좌표 축을 회전시켜보자. 회전판을 돌리는 것이다. 원래의 벡터들의 크기와 방향, 서로와의 위치등은 보존될 것이고 벡터를 표현하기 위한 기저인 좌표계만 움직여서 벡터의 표현들이 바뀌었다. 정보들은 그대로 있고, 정보들의 표현하는 방법이 바뀌었다.

Turboquant의 핵심 개념을 짧은 몇개의 문장으로 표현하면 다음과 같다.
차원 벡터들을 랜덤으로 회전하게 되면 각 벡터들의 좌표 값들은 베타 분포를 따르게 된다. 베타 분포를 따르는 좌표 값들을 양자화하는 방법으로 Lloyd-Max quantizer를 사용하였고, 이를 통해 최적의 MSE를 달성하였다. 내적 오차는 QJL 방법을 사용하여 1비트의 추가만으로 효율적으로 잔차를 처리하였다.
우선 벡터들을 회전시키는 이유는 벡터의 좌표 값들이 베타 분포를 따르게 만들기 위함이다. 베타 분포를 따르게 되면 어떤 점이 좋은 것일까? 우리가 사용하고자 하는 데이터들이 ‘항상’ 어떤 일정 분포를 따르게 되면 여러 장점이 있다.
- 양자화를 위한 칸막이 설치가 편해진다.
칸막이를 설치한다는 것은 분포도를 수직으로 자르는 것과 같다. 수직으로 잘라서 여러 구간으로 표현한다 생각해보자. 100개의 구간. 99개의 칸막이를 설치하고, 각 칸막이 사이사이마다 점을 하나씩 찍는 것이다. 이 구간 안에 구간을 대표하는 점을 축에 찍으면, 그것이 바로 양자화다. 우리는 수많은 데이터들을 데이터가 속한 분포를 이용해서 분포에 따른 구간, 그리고 구간을 대표하는 값으로 양자화하여 표현하였다.
- 데이터의 값과 관계없이 데이터를 다룰 수 있다.
자명한 문장일 수도 있지만, 큰 의미를 갖고 있다. 데이터의 값과 관계없다는 것은 데이터를 보고 무언가를 결정할 필요가 없다는 뜻이다. 데이터의 형식만 정해져 있다면, 데이터가 어떤 값들을 갖는지를 몰라도 우리는 이 데이터들을 계산할 준비를 마칠 수 있다.
여기서 말하는 형식은 데이터의 자릿 수와 같은 데이터의 표현방식일 수도 있지만, 데이터의 분포도 또한 포함된다. 데이터들의 집합이 어떤 속성을 나타내는지 미리 확정적으로 알 수 있다면, 우리는 이 데이터 집합에 대해 해당 집합에 적용시킬 수 있는 것들을 전부 적용시킬 수 있다. 그 데이터들이 어떤 값을 갖냐와 무관하게 말이다.
여기서 이 문장을 다시 보자.
차원 벡터들을 랜덤으로 회전하게 되면 각 벡터들의 좌표 값들은 베타 분포를 따르게 된다.
단순히 회전시켰을 뿐인데, 회전판을 돌렸을 뿐인데 벡터들이 어떤 분포를 따르게 된다는 것이다. 이는 차원 벡터가 고차원 벡터이기 때문이다.

3차원의 예시를 보자. 사실 3차원도 부족하지만, 일단 이렇게라도 보자. 크기와 방향, 그리고 벡터들과의 관계가 고정된 상태로 좌표 축만 돌려본 것이다. 원점에서 출발하는 벡터의 길이는 좌표 에 대해 다음과 같이 표현된다.
차원에서도 마찬가지다.
인 벡터가 있다고 생각해보자. 모든 좌표 값이 같을 때, 2차원에서는,
3차원에서는,
그러면 차원에는 다음과 같다.
여기서 알 수 있듯이 값이 매우 클 경우 축 별 좌표값의 크기가 작아진다는 것을 알 수 있다. 즉, 일정한 크기의 벡터를 고차원에서 이리저리 이동시킬 경우, 축에 놓인 좌표가 아니라면 개별 좌표값은 매우 작은 크기가 된다는 것을 직관적으로 알 수 있다.
다음과 같은 차원 상의 벡터를 생각해보면 매우 간단하다. 이것을 해당 고차원에서 다른 어딘가에 놓는다면, 이를 표현하기 위한 개별 좌표값들은 1보다 훨씬 작은 어떤 값이 될 것이다.

수학적으로 고차원 벡터들을 임의로 배치하였을 때, 좌표값들의 분포가 베타 분포를 따른다는 것 자체를 TurboQuant에서 제시한 것은 아니다. 다만 모델에서 사용하는 데이터들이 고차원 벡터이며, 이 고차원 벡터들을 어떤 분포로 다룬다면 효율적으로 양자화할 수 있다는 것을 이번 연구에서 제시한 것이다. 그림에서처럼 고차원으로 갈 수록 분포도는 매우 좁아지고, 이 좁은 범위에서 양자화를 하게 되면 양자화 효율을 높일 수 있는 것은 물론이며, 항상 같은 분포를 사용할 수 있어 데이터 의존성 없이 가중치과 컨텍스트를 위한 벡터들을 다룰 수 있게 된다.
베타 분포에 적합한 방식인 Lloyd-Max quantizer를 이용하여 벡터들을 양자화하고 나면 이 후에는 내적 연산을 위한 나머지 보정 방식인 QJL이 있다. 나머지를 곱셈을 적게 사용하고 1비트 수준의 덧셈과 뺄셈으로 보정하는 방법이다.
결론
TurboQuant에서 제시하는 방법은 매우 유려하다. 가장 중요한 것은 데이터 종속성 없이 효율적인 양자화 방식을 제안했다는 점이다. 연산 전에 데이터에 대해 미리 알 수 있는 점들이 많다면, 우리는 연산하는 하드웨어에게 더 많은 것을 기대할 수 있다. 연산을 더 효율적으로 할 수 있게 준비시킬 수 있다는 것이다. 더 구체적인 알고리즘이나 하드웨어 최적화 기법은 다음에 분석해보겠다.

