숫자를 인식하는 임베딩 (Number-aware embeddings)
요약
기존 임베딩 모델들이 숫자의 크기나 순서를 제대로 인식하지 못하는 문제를 해결하기 위해, 숫자를 로그 자릿수(log magnitude)로 인코딩하는 새로운 아키텍처를 제안합니다. 정규 표현식과 128개의 빈(bins)을 활용한 미세 조정을 통해, ModernBERT 및 BGE 모델 대비 숫자 정렬 성능을 대폭 향상시켰습니다.
핵심 포인트
- 기존 MLM 기반 임베딩 모델은 토크나이저와 손실 함수 구조상 숫자의 크기 차이를 반영하지 못하는 한계가 있음
- 숫자를 로그 자릿수로 변환하고 128개의 빈(bins)에 부드럽게 인코딩하는 커스텀 아키텍처를 도입하여 이를 완화함
- H100 GPU 6시간 학습 결과, 문장 삼중항 정렬 성능에서 ModernBERT(38%)와 BGE-base-v1.5(34%)를 크게 상회하는 59%를 기록함
- 숫자가 포함된 HTML 테이블 등 구조화된 정량적 데이터 추출 작업에서 뛰어난 성능을 보임
"500마력 자동차", "1,200마력 자동차", "73마력 자동차"의 임베딩 간 코사인 유사도 (cosine sim)를 살펴보면, 임베딩 모델들이 숫자의 순서에 대한 감각이 전혀 없다는 것을 곧 알게 될 것입니다. (저는 Qwen과 ModernBERT 기반의 임베딩을 테스트했습니다.)
이는 주로 MLM (Masked Language Modeling) 사전 학습 (pre-training) 단계에서, 토크나이저 (tokenizer)와 로그 가능도 손실 (log likelihood loss)이 자릿수 (Order Of Magnitude) 예측보다 정확한 예측에 과도하게 보상을 주기 때문에 발생합니다.
저는 숫자에 대해 기본 토크나이저/예측 헤드 (prediction head)를 오버라이딩(overriding)하고, 수정된 아키텍처를 3억 개의 토큰(그 중 약 4백만 개의 숫자 포함)으로 MLM 미세 조정 (fine-tuning)함으로써 이를 완화하려고 시도했습니다.
그리고 효과가 있었습니다. 아이디어는 숫자 패턴을 정규 표현식 (regex)으로 추출하고, 이를 로그 자릿수 (log magnitude)로 표현하는 것입니다. 각 숫자는 128개의 빈 (bins)으로 부드럽게 인코딩되며 (인접한 빈 사이의 선형 보간 사용), 이 128개의 각 빈에 대해 임베딩 사전 (embedding dict) 항목이 할당됩니다. 디코딩 (decoding)도 거의 유사하게 작동합니다. 저는 128개의 출력 빈과 부드러운 CE (Cross-Entropy) 손실을 사용하는 분류-회귀 (classification-regression) 헤드를 사용했습니다.
MLM 사전 학습된 모델을 임베딩 모델로 만드는 것이 가장 흥미로운 부분이었습니다. JEPA를 시도했으나 실패했고, 그래서 인코더/디코더 (encoder/decoder) 설정을 사용했는데 잘 작동했습니다.
6시간의 H100 학습 결과: 저의 커스텀 벤치마크에서 (이 문장은 완전히 위험 신호(red flag) 같네요, 그렇죠?), 이 모델은 문장 삼중항 (triplets of sentences)을 59%의 확률로 정확하게 정렬할 수 있었습니다. 이는 ModernBERT (mean-pooling)의 38% 및 BGE-base-v1.5 (CLS)의 34%와 비교됩니다.
또한 숫자가 많은 HTML 테이블에서 구조화된/정량적 데이터를 추출하는 데에도 상당히 뛰어납니다.
(다소 학습이 덜 된) 모델은 여기에서 확인할 수 있습니다: https://huggingface.co/edereynal/financial_bert
전체 엔지니어링 과정에 관심이 있다면 블로그 포스트를 확인해 주세요. 기술적으로 꽤 밀도가 높지만, 흥미롭다고 생각합니다: https://www.eloidereynal.com/p/i-spent-1-year-trying-to-predict
AI 자동 생성 콘텐츠
본 콘텐츠는 Reddit AI Engineering의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기