다항식 오토인코더, 트랜스포머 임베딩 압축에서 PCA 능가
트랜스포머 임베딩 압축 시 기존 선형 방식인 PCA가 놓치는 비선형적 특성을 포착하기 위해 '다항식 오토인코더(Poly-AE)' 기법이 제안되었습니다. 복잡한 학습 과정 없이 단순한 수학적 계산만으로 적용할 수 있으며, 동일한 메모리 예산에서 기존 PCA 대비 검색 품질(NDCG)을 최대 4.4%p 가까이 끌어올렸습니다. 이는 정보 검색 시스템에서 저장 공간을 획기적으로 줄이면서도 성능 저하를 최소화할 수 있는 매우 실용적인 접근법입니다.
02 블로그
(양자화를 제외하고) 임베딩을 압축하는 가장 직접적인 방법은 코퍼스(말뭉치)에 PCA(주성분 분석)를 적용하고 상위 d개의 고유 벡터를 유지하는 것입니다. 이 방법은 잘 작동하지만 PCA는 선형 투영(Linear projection)이며, 구(Sphere) 위의 신경망 임베딩은 구조적으로 비선형적입니다. 즉, 트랜스포머에서 잘 알려진 '원뿔 효과(Cone effect)'가 나타납니다. 분산의 일부는 선형 디코더가 도달할 수 없는 비선형 꼬리 영역에 존재합니다. 이 글은 이러한 비선형 꼬리의 일부를 포착하기 위해 PCA 위에 폐쇄형(Closed-form) 2차 디코더를 추가하는 방법에 대한 것입니다. 인코더는 일반적인 PCA로 유지됩니다. 디코더는 2차 다항식 리프트(Polynomial lift)와 릿지 최소제곱법(Ridge OLS, L2 정규화가 적용된 일반 선형 회귀)을 사용하며, 이 역시 폐쇄형으로 계산됩니다. SGD, 에포크, 하이퍼파라미터 탐색이 전혀 필요 없습니다. 코퍼스 통계량에 대해 단 한 번의 np.linalg.solve 연산만 수행하면 됩니다.
이 구조 자체는 제가 새로 만든 것이 아닙니다. "PCA 인코더 + 2차 디코더 + 최소제곱법 적합"은 동적 시스템(Dynamical-systems) 문헌에서 '2차 다양체(Quadratic manifold)'라는 이름으로 등장합니다 (Jain 2017, Geelen-Willcox 2022/2023, Schwerdtner-Peherstorfer 2024+ 등 참고, §9에서 자세히 다룹니다). 저는 실험을 진행하고 이 구조가 새롭다고 생각한 후에야 우연히 이 논문들을 발견했습니다. 다항식 리프트 기법은 현대 머신러닝 대화에서 자주 언급되지 않으며, 이 글은 인접 학문의 유용한 기법이 검색(Retrieval) 분야로 어떻게 넘어왔는지에 대한 기록입니다.
구체적인 결과는 다음과 같습니다. BEIR/FiQA 데이터셋, mxbai-embed-large-v1 (1024차원) 모델 기준으로 벡터당 512바이트의 예산을 사용했습니다. 평가 지표는 NDCG@10 (상위 10개의 정규화 할인 누적 이득, 표준 검색 순위 품질 측정값, [0, 1] 범위, 높을수록 좋음)입니다:
- raw 1024d (4096 bytes): NDCG@10 0.4525 (—)
- PCA top-256: 0.4168 (-3.58 p.p.)
- poly-AE 256d: 0.4441 (-0.85 p.p.)
- matryoshka top-256: 0.4039 (-4.86 p.p.)
PCA만으로도 벡터당 메모리를 4배 압축하면서 NDCG를 -3.58 p.p. 수준으로 유지합니다. 그러나 PCA 위에 2차 디코더를 얹은 방식(poly-AE)은 여기에 추가로 +2.73 p.p.를 끌어올립니다. 동일한 바이트 예산으로 원본(Raw)과의 성능 격차를 거의 전부 메꾼 셈입니다. 또 다른 친숙한 베이스라인인 Matryoshka는 표에 포함시켰으나 (여기서는 PCA보다 성능 하락이 더 큽니다. 이는 알려진 부가적인 관찰 사항일 뿐, 이 글의 핵심 주장은 아닙니다. §3 각주 및 §4 참고). 이 측정은 4개 모델(nomic-v1.5, mxbai-large, bge-base, e5-base)에서 진행되었습니다. PCA 대비 Poly-AE의 성능 향상은 d=128일 때 +1 ~ +4.4 p.p., d=256일 때 +0.03 ~ +2.7 p.p.입니다. 전체 표는 §3에 있습니다.
전체 구현은 약 150줄의 NumPy 코드와 MIT 라이선스를 사용하며, 저장소(github.com/IvanPleshkov/poly-autoencoder)에서 확인할 수 있습니다. 동일한 저장소의 beir_eval.py가 BEIR 평가 스크립트입니다. M 시리즈 맥북에서 3040분이면 재현 가능합니다 (코퍼스 인코딩에 1015분, d=256일 때 Ridge 계산에 약 15분 소요).
목차: §1 비교 대상 §2 실험 설정 §3 핵심 결과표 §4 2차 디코더가 도움이 되는 이유 §5 선형 투영이 실패하는 이유 §6 방법론 §7 소규모 코퍼스에 대한 주의사항 §8 잔차 압축 §9 방법론의 출처 §10 한계점 §11 다음으로 시도해 볼 것
- 비교 대상 모든 측정은 다음 4가지 라인을 통해 비교됩니다:
- raw: 압축이 없는 전체 임베딩입니다. 품질의 상한선이며 벡터당 가장 많은 바이트를 차지합니다. 공정한 상한선을 제공하는 '비싼' 베이스라인입니다.
- matryoshka:
embedding[:d]에 L2 정규화를 적용한 형태입니다. Matryoshka 손실 함수로 학습된 모델(우리 테스트 샘플에서는 nomic, mxbai)에서 이는 유효한 Matryoshka 벡터입니다. 반면 Matryoshka 학습이 되지 않은 모델(bge-base, e5-base)에서는 MRL이 아닌 모델을 단순히 자르면 어떻게 되는지를 보여줍니다. 이는 bge 패밀리, e5 및 사용자 지정 미세 조정(Feature-tuned) 임베딩 사용자들이 실제로 겪는 시나리오입니다. - PCA: 코퍼스 공분산(Covariance)의 상위 d개 고유 벡터입니다. 벡터는 d차원의 PCA 좌표 공간에 존재하게 됩니다.
- poly-AE: 우리가 제안하는 방법입니다. PCA를 사용하여 p ∈ ℝ^d로 인코딩한 다음, 2차 다항식을 사용하여 전체 D차원의 V̂로 디코딩하며, 이 V̂를 기반으로 검색을 수행합니다. 고정된 d 값에 대해 위 4가지 방법은 모두 벡터당 2d바이트(fp16 좌표 기준)의 메모리를 저장합니다.
- 실험 설정 BEIR은 표준 검색 데이터셋 모음(SciFact, FiQA, NFCorpus, TREC-COVID 등)입니다. 평가 지표는 NDCG@10입니다. 코퍼스와 쿼리(검색어)는 선택한 모델로 인코딩되고, 코사인 유사도를 통해 상위 10개가 검색된 뒤 레이블이 지정된 qrels(관련성 평가 데이터)와 비교하여 NDCG를 계산합니다. PCA와 poly-AE는 전랜덕티브(Transductive) 방식으로 학습됩니다. 즉, 통계량이 코퍼스 자체에서 계산됩니다.