Eric TechBlog
AI

BM25

用淺顯易懂的方式理解 BM25、詞頻、IDF、文件長度正規化,以及 k1、b 這些重要變數。

當你在搜尋系統中輸入一個關鍵字,例如:

  • elasticsearch
  • apple watch
  • 前端效能優化

系統通常不只是找出「有沒有包含這些詞」的文件而已,還要回答另一個更重要的問題:

「哪一篇應該排在最前面?」

BM25 就是一種常見的「相關性排序演算法」,它的目標是替每一份文件計算一個分數,分數越高,代表這份文件越可能符合使用者的搜尋意圖。在現代搜尋系統裡,它也常和 Embeddings 一起使用。

放在這個系列裡看,BM25 是在 Chunking 之後最值得先理解的第一階段檢索方法之一。因為當 chunk 已經設計好之後,你第一個會遇到的問題通常是:要怎麼快速、便宜而且可解釋地把候選內容抓出來?BM25 往往就是那個起點。

你可以把 BM25 想成:

它不是只看關鍵字有沒有出現,而是綜合判斷:

  1. 這個詞在文件裡出現幾次
  2. 這個詞是不是很常見
  3. 相對於整個文集,被評分的那篇文件是否篇幅偏長(避免長文只因字多、詞碰巧多出現幾次就佔優勢)
  4. 同一個詞每多出現一次,對分數的加分是否應越來越少(遞減效益),而不是「出現幾次就線性加幾倍分」

用更白話一點說:「重要的詞在這篇出現得夠多,但又不是只因為文章很長才出現很多次,這樣的文件更值得排前面。」

BM25 在做什麼?

假設使用者搜尋:

distributed systems

搜尋引擎會對每篇文件做評估:

  • 文件 A:有提到 distributedsystems
  • 文件 B:只提到一次 systems
  • 文件 C:雖然提到很多次,但整篇文件非常長

BM25 會替每篇文件算出一個分數,最後依照分數排序。

1. 詞頻(Term Frequency)

第一個很直覺的因素是:搜尋詞在這份文件中出現幾次?

如果某個詞在文件中出現越多次,通常代表這篇文件和這個主題越有關。

例如搜尋 database:

  • 文件 A:出現 1 次
  • 文件 B:出現 7 次

通常文件 B 比較可能跟 database 有關。

但是,這裡有一個問題:出現 7 次,真的就一定比出現 1 次好 7 倍嗎?

BM25 的答案是:不一定。

因為當某個詞已經出現很多次之後,再多出現幾次,對相關性的幫助會越來越小。這種概念叫做 遞減效益(diminishing returns)

也就是說:

  • 從 1 次增加到 2 次,幫助很明顯
  • 從 10 次增加到 11 次,幫助就沒那麼大

這就是 BM25 很重要的一點:它承認「詞出現多次是好事」,但不會讓分數無限暴衝。

2. 逆文件頻率(IDF)

第二個因素是:這個詞在整個文件集合中常不常見?

這就是 IDF,Inverse Document Frequency。

你可以把它理解成:

  • 如果一個詞在幾乎每篇文件都出現,那它沒什麼鑑別力
  • 如果一個詞只出現在少數文件,那它更有辨識度

例如:

  • the
  • is
  • and

這些字幾乎到處都有,所以對搜尋排序幫助很小。

但如果搜尋詞是:

  • kubernetes
  • vector database
  • bm25

這種詞通常更能幫助系統判斷哪些文件真的相關。

所以 BM25 會讓:

  • 常見詞的權重變低
  • 稀有詞的權重變高

可以把 IDF 想成:「這個詞有多能幫我把真正相關的文件找出來?」

3. 文件長度正規化

第三個因素是:文件很長,是否只是因為字很多,所以剛好把搜尋詞提到比較多次?

這很重要。

假設有兩份文件都在講 search engine:

  • 文件 A:300 字,關鍵詞出現 5 次
  • 文件 B:3000 字,關鍵詞出現 5 次

直覺上,文件 A 的關鍵詞密度更高,看起來更聚焦。

文件 B 雖然也出現 5 次,但可能只是因為它很長,所以剛好提到了這些詞。

BM25 會把「文件長度」納入考量,避免長文件天然佔便宜。

注意,這不是說長文件一定比較差,而是說 BM25 會防止「只是因為篇幅長」就得到不公平的高分。

Okapi BM25 公式

對單一文件 D 與查詢 Q(由多個詞項組成),BM25 分數是每個查詢詞貢獻的加總。常見的 Okapi BM25(與 Lucene、Elasticsearch 等實作相近)寫成:

score(D,Q)=qQIDF(q)f(q,D)(k1+1)f(q,D)+k1(1b+bDavgdl)\operatorname{score}(D,Q) = \sum_{q \in Q} \operatorname{IDF}(q) \cdot \frac{f(q,D) \cdot (k_1 + 1)}{f(q,D) + k_1 \cdot \left(1 - b + b \cdot \frac{\lvert D \rvert}{\mathrm{avgdl}}\right)}

各符號代表:

符號意義
qq查詢中的一個詞項
f(q,D)f(q, D)qq 在文件 DD 中的出現次數(詞頻)
D\lvert D \rvert文件 DD 的長度(實務上常以詞數衡量)
avgdl\mathrm{avgdl}整個文集的平均文件長度
k1k_1bb可調參數(下一節說明)

IDF 常採用 Robertson/Sparck Jones 形式(加 0.5 平滑、外層再加 1 後取自然對數),例如:

IDF(q)=ln(Nnq+0.5nq+0.5+1)\operatorname{IDF}(q) = \ln\left( \frac{N - n_q + 0.5}{n_q + 0.5} + 1 \right)

其中 NN 為文集文件總數,nqn_q 為「至少出現過一次詞 qq」的文件數。不同系統可能對 IDF 做微調,但核心都是:越稀有的詞,IDF 越大

把兩式合起來看:分子裡的 (k1+1)(k_1 + 1) 與分母裡含 f(q,D)f(q,D)k1k_1 的那一項,正是前面說的「詞頻有上限、不會線性暴衝」;分母裡含 D/avgdl\lvert D \rvert / \mathrm{avgdl}bb 的部分,則對應「依文件長度做正規化」。

BM25 公式中的兩個重要參數:k1k_1bb

上一節公式裡的 k1k_1bb,是實務上最常動到的兩個旋鈕:

  • k1k_1
  • bb

你不一定要死背整條式子,但一定要知道它們在控制什麼。

k1k_1:控制詞頻成長的飽和速度

k1k_1 主要影響的是:詞頻增加時,分數成長得多快、以及多快開始趨緩。

你可以理解成:

  • k1k_1 較大:詞頻增加的效果維持比較久
  • k1k_1 較小:詞頻增加很快就進入飽和

也就是說:

  • 如果 k1k_1 大,文件中多出現幾次關鍵詞,還能繼續帶來明顯加分
  • 如果 k1k_1 小,出現幾次之後,再多也不太加分了

可以把它想成一個「TF 敏感度旋鈕」。

bb:控制文件長度正規化的強度

bb 主要影響的是:系統要多在意文件長度差異。

它通常介於 0 到 1 之間。

  • b=0b = 0:完全不考慮文件長度
  • b=1b = 1:完整考慮文件長度
  • 常見設定是 0.75

你可以這樣理解:

  • bb 越高:長文件會被更明顯地正規化
  • bb 越低:長度差異影響越小

可以把它想成一個「長度公平性旋鈕」。

公式到底在算什麼?

把上一節的式子對照成具體步驟,就是:

  1. 對查詢中的每個詞逐一評分
  2. 看這個詞在文件中出現幾次
  3. 看這個詞在整個資料庫中稀不稀有
  4. 相對於文集平均長度,這篇文件是否偏長(長度正規化)
  5. 把每個詞的分數加總起來

所以你不用把 BM25 當成一個很神祕的公式。

它本質上只是想回答:

  • 這個詞重要嗎?
  • 這篇文章真的常提到它嗎?
  • 還是只是因為文章很長?
  • 提到很多次,是不是已經多到沒有額外意義?

最後給一個簡單例子

假設使用者搜尋:

bm25 tutorial

現在有兩篇文章:

文件 A

  • 長度中等
  • bm25 出現 4 次
  • tutorial 出現 3 次

文件 B

  • 非常長
  • bm25 出現 5 次
  • tutorial 出現 3 次

哪篇比較可能排前面?

很多人第一眼會覺得文件 B 勝出,因為它出現次數比較多。

但 BM25 不會這麼單純。

它會進一步想:

  • 文件 B 只是因為比較長,所以多出現 1 次嗎?
  • bm25 這個詞是不是很有辨識度?
  • 4 次和 5 次之間的差距,真的有那麼大嗎?

最後,文件 A 很可能因為內容更集中,而得到更有競爭力的分數。

若只記核心觀念,下面四句就夠:

  1. 詞出現越多通常越相關,但加分不會無限增加(飽和)。
  2. 越少見的詞,通常越有判斷價值(IDF)。
  3. 長文件不應只因篇幅大就佔便宜(長度正規化)。
  4. 整體是在平衡「詞頻、稀有度、文件長度」。

結論

BM25 經典之處在於簡單務實。在現在 LLM 肆虐的時代,RAG 是我們做個人化 AI Assistant 重要的環節。為了效率,我們可以先透過 BM25 做第一階段 lexical retrieval,過濾掉一些不重要的文件,再搭配 Embeddings 補足語意檢索能力,或用 RRF 把不同檢索器的結果融合,最後把關聯高的文件交給 LLM 做進一步處理,必要時再加上 Re-ranking 精修排序。這樣不僅可以降低成本,也可以減少 LLM 的幻覺,提高回答的準確性。

如果把整個系列當成一條 pipeline 來看,BM25 回答的是「怎麼先把可能相關的內容找出來」,而下一篇 Embeddings 則會回答「當使用者沒有講出一模一樣的字詞時,系統怎麼靠語意去找到相關內容」。

參考資料

Last updated on

On this page