Zettelkasten

BM25는 TF 포화 함수와 길이 정규화로 TF-IDF의 한계를 해결한다

·수정 2026.05.20·수정 2

요약

  • BM25(Okapi BM25)는 TF, IDF, 문서 길이 정규화를 확률론적으로 결합한 랭킹 함수
  • TF-IDF가 단어 빈도를 선형 누적하는 반면, BM25는 포화 함수로 누적을 제한하고 길이 정규화로 긴 문서의 점수 부풀림을 보정
  • 1990년대 Okapi 시스템에서 개발됐고 지금도 Elasticsearch/OpenSearch의 기본 랭킹 알고리즘

본문

기본 정의

쿼리 QQ의 각 단어 qiq_i에 대해 문서 DD의 점수를 합산:

score(D,Q)=i=1nIDF(qi)f(qi,D)(k1+1)f(qi,D)+k1(1b+bDavgdl)\text{score}(D, Q) = \sum_{i=1}^{n} \text{IDF}(q_i) \cdot \frac{f(q_i, D) \cdot (k_1 + 1)}{f(q_i, D) + k_1 \cdot \left(1 - b + b \cdot \dfrac{|D|}{\text{avgdl}}\right)}

  • f(qi,D)f(q_i, D): 단어 qiq_i가 문서 DD에 등장한 횟수
  • D|D|: 문서 길이, avgdl\text{avgdl}: 코퍼스 평균 문서 길이
  • k1k_1: TF 포화 속도 (보통 1.22.01.2 \sim 2.0, 기본 1.21.2)
  • bb: 길이 정규화 강도 (010 \sim 1, 기본 0.750.75)

세 가지 구성 요소

1. Term Frequency — 포화 함수

핵심 인사이트는 "용어 빈도와 관련성의 관계는 선형이 아니라 포화해야 한다". 첫 몇 번의 등장은 강한 관련성 증거지만, 그 이후로는 한계 효용이 급감해야 함.

길이 정규화를 제외한 TF 항만 보면:

TF-component(f)=f(k1+1)f+k1\text{TF-component}(f) = \frac{f \cdot (k_1 + 1)}{f + k_1}

ff \to \infty일 때 점근선 k1+1k_1 + 1에 수렴한다. TF-IDF의 단순 누적과 결정적으로 다른 지점.

2. Inverse Document Frequency — 확률적 IDF

전체 문서 NN개 중 단어 qq가 등장하는 문서 수 n(q)n(q)로 계산. 흔한 단어는 IDF 낮음, 드문 단어는 높음.

IDF(q)=log ⁣(Nn(q)+0.5n(q)+0.5+1)\text{IDF}(q) = \log\!\left(\frac{N - n(q) + 0.5}{n(q) + 0.5} + 1\right)

원래 BM25 IDF는 log-odds ratio에서 유도된 형태라 TF-IDF의 단순 log(N/n)\log(N/n)보다 확률론적으로 정당화됨. +0.5+0.5 smoothing은 0-division 방지. 절반 이상 문서에 등장하는 단어는 IDF가 음수가 될 수 있어서 Lucene 구현은 log 안에 +1+1을 더해 음수 방지.

3. Document Length Normalization

긴 문서가 단순히 길다는 이유로 점수가 부풀려지는 걸 방지. TF 분모의 k1k_1에 곱해지는 항이 길이 보정자다:

1b+bDavgdl1 - b + b \cdot \frac{|D|}{\text{avgdl}}

  • b=0b = 0: 길이 보정 없음 (긴 문서가 유리)
  • b=1b = 1: 완전 보정 (분모가 D/avgdl|D|/\text{avgdl}에 정비례)
  • b=0.75b = 0.75: Lucene 기본값, 부분 보정

문서가 평균보다 길면 (D>avgdl|D| > \text{avgdl}) 분모가 커져 점수가 깎이고, 짧으면 가산점.

TF-IDF와의 차이

TF-IDF BM25
TF 누적 선형 포화 함수 (점근선 k1+1k_1 + 1)
길이 보정 없음 (또는 단순 정규화) bD/avgdlb \cdot \lvert D \rvert / \text{avgdl}
IDF 유도 휴리스틱 (log(N/n)\log(N/n)) log-odds ratio 기반 확률론
파라미터 없음 k1,bk_1, b로 튜닝 가능

TF-IDF는 긴 문서/반복 많은 문서에 과도하게 유리한 반면, BM25는 두 측면을 모두 통제. 같은 bag-of-words 모델 계열이지만 BM25는 확률적 정당화가 있는 정교한 버전.

왜 지금도 표준인가

  • 계산 효율: 인덱스 구축 후 O(쿼리 단어 수)로 평가
  • zero-shot: 학습 데이터 없이 작동, 도메인 어휘에 강함
  • 정확 매칭에 강함: 약어, 코드, 식별자 같은 토큰을 임베딩보다 잘 잡음
  • 인프라 성숙도가 높음 (Elasticsearch, Solr, Lucene, SQLite FTS5 모두 내장)

GitHub 코드 검색이 100B+ 문서 규모에서 벡터 검색이 아니라 BM25를 선택한 사례가 대표적.

한계

  • 의미 모름: bag-of-words라 동의어/의역 못 잡음 ("EV battery refill duration" vs "car charging time")
  • 한국어 약함: 형태소 분석기 없는 토크나이저(SQLite FTS5 등)는 한국어 검색 품질이 크게 떨어짐 → mecab/kiwi 같은 분석기 + 동의어 사전 필요
  • 자연어 질의 약함: 짧은 키워드 쿼리에 최적화돼 있어, 문장형 자연어 RAG 쿼리에는 벡터와 결합이 필요

그래서 현대 RAG는 BM25 + 벡터 검색의 하이브리드로 운영하는 게 표준이 됨.

관련 노트

참고