임베딩 양자화: 더 빠르고 저렴한 검색을 위한 이진 및 스칼라 기법
TL;DR: Hugging Face는 이진 및 스칼라(int8) 임베딩 양자화를 도입했으며, 각각 임베딩을 32배 또는 4배 압축하고, 메모리와 저장 비용을 크게 줄이며, 검색 속도를 최대 45배 가속화하면서 원래 성능의 96%–99%를 유지합니다.
임베딩이 중요한 이유와 확장 방식
임베딩은 텍스트, 이미지, 오디오 및 기타 데이터를 고차원 벡터로 변환하여 유사도 검색, 추천, 클러스터링 및 많은 하위 NLP 작업을 가능하게 합니다. 최신 모델은 종종 1024차원 float32 벡터를 출력하며, 차원당 4바이트가 필요합니다. 250 M개의 이러한 벡터를 저장하면 약 1 TB의 RAM을 차지하여 매달 수천 달러에 달하는 클라우드 비용이 발생합니다. 블로그에서는 여러 인기 모델에 대한 비용을 정량화하여, 1024차원 모델이 AWS x2gd 인스턴스에서 월 $3,600 이 넘을 수 있음을 보여줍니다.
양자화 vs. 차원 축소
전통적인 확장 방법은 차원 축소(예: PCA) 또는 Matryoshka Representation Learning (MRL)을 사용하여 차원을 잘라내지만 성능에 영향을 줄 수 있습니다. 임베딩 양자화는 모델이 임베딩을 생성한 후 각 차원의 정밀도를 낮춤으로써, 더 저렴한 검색을 위한 보완적인 경로를 제공합니다.
이진 양자화
이진 양자화는 각 float32 값을 0을 기준으로 임계값을 적용하여 단일 비트로 변환합니다. 이는 저장 용량을 32배 감소시킵니다(예: 1024차원 벡터가 1024 비트가 되어 128 바이트로 압축). 검색은 해밍 거리를 사용하며, 이는 단 두 개의 CPU 사이클만으로 계산될 수 있어 엄청난 속도 향상을 제공합니다.
Sentence‑Transformers에서 구현
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("mixedbread-ai/mxbai-embed-large-v1")
# Direct binary encoding
binary_embeddings = model.encode(
["I am driving to the lake.", "It is a beautiful day."],
precision="binary",
)
결과 binary_embeddings는 형태가 (2, 128), int8 dtype이며, 원래 float32 임베딩의 8 192 바이트에 비해 256 바이트만 차지합니다.
벡터 데이터베이스 지원
Faiss, USearch, Vespa AI, Milvus, Qdrant 및 Weaviate에서 이진 인덱스를 사용할 수 있어 기존 파이프라인을 바로 교체할 수 있습니다.
스칼라(int8) 양자화
스칼라 양자화는 각 차원의 연속 float32 범위를 256개의 이산 int8 레벨(‑128~127)로 매핑합니다. 이는 이진보다 더 세밀한 granularity를 유지하면서 저장 용량을 4배 감소시킵니다. 차원별 최소/최대 범위를 계산하기 위해 대규모 임베딩 세트에 대한 보정이 필요합니다.
Sentence‑Transformers에서 구현
from sentence_transformers import SentenceTransformer, quantize_embeddings
from datasets import load_dataset
model = SentenceTransformer("mixedbread-ai/mxbai-embed-large-v1")
corpus = load_dataset("nq_open", split="train[:1000]")["question"]
calibration_embeddings = model.encode(corpus)
embeddings = model.encode(["I am driving to the lake.", "It is a beautiful day."])
int8_embeddings = quantize_embeddings(
embeddings,
precision="int8",
calibration_embeddings=calibration_embeddings,
)
int8_embeddings는 원래 1024차원 형태를 유지하지만 단 2 048 바이트만 사용합니다.
벡터 데이터베이스 지원
스칼라 양자화는 Faiss(IndexHNSWSQ), USearch, Vespa AI, OpenSearch, ElasticSearch, Milvus(IVF_SQ8) 및 Qdrant에서 (직접 또는 간접적으로) 지원됩니다.
이진 및 스칼라 양자화 결합
두 단계 파이프라인을 사용하면 두 접근법의 장점을 모두 얻을 수 있습니다:
- 고품질 모델(e.g.,
mxbai-embed-large-v1)로 쿼리를 인코딩합니다. - 쿼리를 이진으로 양자화하고 이진 인덱스를 검색합니다(≈5 GB, 41 M 위키피디아 구절).
- 디스크에 저장된 int8 인덱스에서 상위 k 후보를 로드합니다(≈48 GB).
- 원본
float32쿼리를 사용해 int8 임베딩에 대해 후보들을 재점수화합니다. - 최종 상위 k 결과를 반환합니다.
이 접근법은 메모리를 ~5 GB, 디스크를 ~52 GB로 줄이며, 전체 정밀도 검색에 필요한 ~200 GB와 비교됩니다.
실험 결과
검색 성능
| 모델 | 차원 | 스토리지 (250 M) | MTEB 검색 NDCG@10 | Float32 대비 % |
|---|---|---|---|---|
mxbai-embed-large-v1 (float32) |
1024 | 953.67 GB $3 623/월 | 54.39 | 100 % |
mxbai-embed-large-v1 (int8) |
1024 | 238.41 GB $905/월 | 52.79 | 97 % |
mxbai-embed-large-v1 (binary) |
1024 | 29.80 GB $113/월 | 52.46 | 96.45 % |
all-MiniLM-L6-v2 (binary) |
384 | 11.18 GB $42/월 | 39.07 | 93.79 % |
주요 관찰:
- Int8 양자화는 종종 성능의 >94 %를 유지하면서 저장 용량을 4배 줄입니다.
- 이진 양자화는 대규모 차원 모델에서 ~96 %를 유지하며, 일부 작은 모델(e.g.,
all-MiniLM-L6-v2)에서는 int8보다 성능이 좋을 수도 있습니다. - 성능은 모델에 따라 다르며, 보정 데이터 품질 및 차원 붕괴가 결과에 영향을 줄 수 있습니다.
재점수화 영향
- 이진 재점수화(원본 float 쿼리로 상위 k 이진 결과를 재정렬)로 성능이 기준선의 92.5 %에서 96.5 %로 상승합니다.
- Int8의 경우,
rescore_multiplier를 늘리면(재점수화 전에 더 많은 후보를 검색) 유지율이 향상되어 배수 4–5에서 약 99 %에 도달합니다.
검색 속도
GCP a2-highgpu-4g CPU 전용 정확 검색에서:
| 양자화 | 최소 가속 | 평균 가속 | 최대 가속 |
|---|---|---|---|
| float32 | 1× | 1× | 1× |
| int8 | 2.99× | 3.66× | 4.8× |
| binary | 15.05× | 24.76× | 45.8× |
따라서 이진 양자화는 수십 배 수준의 지연 감소를 제공합니다.
트레이드오프 요약
| 지표 | float32 | int8/uint8 | binary/ubinary |
|---|---|---|---|
| 메모리 및 인덱스 크기 | 1× | 4× 작음 | 32× 작음 |
| 검색 속도 | 1× | 최대 4× 빠름 | 최대 45× 빠름 |
| 성능 유지 | 100 % | ~99 % | ~96 % |
데모 및 실용 스크립트
실시간 데모(link)는 5 GB RAM과 52 GB 디스크를 사용해 41 M 위키피디아 구절에 대한 검색을 보여주며, 위에서 언급한 가속을 달성합니다. 블로그에서는 실행 준비가 된 스크립트를 세 가지 카테고리로 제공합니다:
- 추천 검색 – 이진 검색과 int8 재점수화를 결합합니다.
- 사용법 – 양자화된 임베딩으로
semantic_search_faiss또는semantic_search_usearch를 호출하는 방법을 보여줍니다. - 벤치마크 – 각 양자화 모드의 속도와 정확도를 측정합니다.
향후 방향
- 더 높은 압축을 위해 서브‑int8 양자화(예: 4‑bit 또는 2‑bit 버킷)를 탐색합니다.
- 양자화를 Matryoshka Representation Learning과 결합하여 먼저 차원을 축소한 뒤 양자화하면, 품질 손실을 최소화하면서 32×–256× 가속을 달성할 수 있습니다.
- 이진 + int8 단계 후에 3단계 교차 인코더 재랭커를 통합하여 낮은 지연과 비용으로 최첨단 검색을 구현합니다.
Citation
@article{shakir2024quantization,
author = {Aamir Shakir and Tom Aarsen and Sean Lee},
title = {Binary and Scalar Embedding Quantization for Significantly Faster & Cheaper Retrieval},
journal = {Hugging Face Blog},
year = {2024},
note = {https://huggingface.co/blog/embedding-quantization}
}