BM25
用淺顯易懂的方式理解 BM25、詞頻、IDF、文件長度正規化,以及 k1、b 這些重要變數。
當你在搜尋系統中輸入一個關鍵字,例如:
elasticsearchapple watch前端效能優化
系統通常不只是找出「有沒有包含這些詞」的文件而已,還要回答另一個更重要的問題:
「哪一篇應該排在最前面?」
BM25 就是一種常見的「相關性排序演算法」,它的目標是替每一份文件計算一個分數,分數越高,代表這份文件越可能符合使用者的搜尋意圖。在現代搜尋系統裡,它也常和 Embeddings 一起使用。
放在這個系列裡看,BM25 是在 Chunking 之後最值得先理解的第一階段檢索方法之一。因為當 chunk 已經設計好之後,你第一個會遇到的問題通常是:要怎麼快速、便宜而且可解釋地把候選內容抓出來?BM25 往往就是那個起點。
你可以把 BM25 想成:
它不是只看關鍵字有沒有出現,而是綜合判斷:
- 這個詞在文件裡出現幾次
- 這個詞是不是很常見
- 相對於整個文集,被評分的那篇文件是否篇幅偏長(避免長文只因字多、詞碰巧多出現幾次就佔優勢)
- 同一個詞每多出現一次,對分數的加分是否應越來越少(遞減效益),而不是「出現幾次就線性加幾倍分」
用更白話一點說:「重要的詞在這篇出現得夠多,但又不是只因為文章很長才出現很多次,這樣的文件更值得排前面。」
BM25 在做什麼?
假設使用者搜尋:
distributed systems
搜尋引擎會對每篇文件做評估:
- 文件 A:有提到
distributed和systems - 文件 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 等實作相近)寫成:
各符號代表:
| 符號 | 意義 |
|---|---|
| 查詢中的一個詞項 | |
| 詞 在文件 中的出現次數(詞頻) | |
| 文件 的長度(實務上常以詞數衡量) | |
| 整個文集的平均文件長度 | |
| 、 | 可調參數(下一節說明) |
IDF 常採用 Robertson/Sparck Jones 形式(加 0.5 平滑、外層再加 1 後取自然對數),例如:
其中 為文集文件總數, 為「至少出現過一次詞 」的文件數。不同系統可能對 IDF 做微調,但核心都是:越稀有的詞,IDF 越大。
把兩式合起來看:分子裡的 與分母裡含 、 的那一項,正是前面說的「詞頻有上限、不會線性暴衝」;分母裡含 與 的部分,則對應「依文件長度做正規化」。
BM25 公式中的兩個重要參數: 與
上一節公式裡的 與 ,是實務上最常動到的兩個旋鈕:
你不一定要死背整條式子,但一定要知道它們在控制什麼。
:控制詞頻成長的飽和速度
主要影響的是:詞頻增加時,分數成長得多快、以及多快開始趨緩。
你可以理解成:
- 較大:詞頻增加的效果維持比較久
- 較小:詞頻增加很快就進入飽和
也就是說:
- 如果 大,文件中多出現幾次關鍵詞,還能繼續帶來明顯加分
- 如果 小,出現幾次之後,再多也不太加分了
可以把它想成一個「TF 敏感度旋鈕」。
:控制文件長度正規化的強度
主要影響的是:系統要多在意文件長度差異。
它通常介於 0 到 1 之間。
- :完全不考慮文件長度
- :完整考慮文件長度
- 常見設定是 0.75
你可以這樣理解:
- 越高:長文件會被更明顯地正規化
- 越低:長度差異影響越小
可以把它想成一個「長度公平性旋鈕」。
公式到底在算什麼?
把上一節的式子對照成具體步驟,就是:
- 對查詢中的每個詞逐一評分
- 看這個詞在文件中出現幾次
- 看這個詞在整個資料庫中稀不稀有
- 相對於文集平均長度,這篇文件是否偏長(長度正規化)
- 把每個詞的分數加總起來
所以你不用把 BM25 當成一個很神祕的公式。
它本質上只是想回答:
- 這個詞重要嗎?
- 這篇文章真的常提到它嗎?
- 還是只是因為文章很長?
- 提到很多次,是不是已經多到沒有額外意義?
最後給一個簡單例子
假設使用者搜尋:
bm25 tutorial
現在有兩篇文章:
文件 A
- 長度中等
- bm25 出現 4 次
- tutorial 出現 3 次
文件 B
- 非常長
- bm25 出現 5 次
- tutorial 出現 3 次
哪篇比較可能排前面?
很多人第一眼會覺得文件 B 勝出,因為它出現次數比較多。
但 BM25 不會這麼單純。
它會進一步想:
- 文件 B 只是因為比較長,所以多出現 1 次嗎?
- bm25 這個詞是不是很有辨識度?
- 4 次和 5 次之間的差距,真的有那麼大嗎?
最後,文件 A 很可能因為內容更集中,而得到更有競爭力的分數。
若只記核心觀念,下面四句就夠:
- 詞出現越多通常越相關,但加分不會無限增加(飽和)。
- 越少見的詞,通常越有判斷價值(IDF)。
- 長文件不應只因篇幅大就佔便宜(長度正規化)。
- 整體是在平衡「詞頻、稀有度、文件長度」。
結論
BM25 經典之處在於簡單務實。在現在 LLM 肆虐的時代,RAG 是我們做個人化 AI Assistant 重要的環節。為了效率,我們可以先透過 BM25 做第一階段 lexical retrieval,過濾掉一些不重要的文件,再搭配 Embeddings 補足語意檢索能力,或用 RRF 把不同檢索器的結果融合,最後把關聯高的文件交給 LLM 做進一步處理,必要時再加上 Re-ranking 精修排序。這樣不僅可以降低成本,也可以減少 LLM 的幻覺,提高回答的準確性。
如果把整個系列當成一條 pipeline 來看,BM25 回答的是「怎麼先把可能相關的內容找出來」,而下一篇 Embeddings 則會回答「當使用者沒有講出一模一樣的字詞時,系統怎麼靠語意去找到相關內容」。
參考資料
Last updated on