今更聞けないBM25 ― 情報検索の王道スコアリングモデルとは?
検索エンジンや質問応答システムなど、「検索」に関わる技術の中で、**BM25(Best Matching 25)**という名前を聞いたことがある方も多いのではないでしょうか?
でも、正直なところ「TF-IDFと何が違うの?」「数式を見るとよくわからない…」という声もよく聞きます。
この記事では、今更聞けないBM25の基礎から応用まで、優しく丁寧に解説していきます。
🔍 BM25とは?
BM25は、情報検索(IR: Information Retrieval)で文書の関連度をスコアリングするためのモデルです。
クエリ(検索語)と文書(ドキュメント)の類似度を数値で表すことで、検索結果のランキングを決定します。
BM25は、TF-IDF(Term Frequency - Inverse Document Frequency)の改良版と考えることができます。
🧮 BM25の数式(ざっくり理解)
BM25の基本形は以下の通りです:
[
\text{score}(D, Q) = \sum_{q_i \in Q} \text{IDF}(q_i) \cdot \frac{f(q_i, D) \cdot (k_1 + 1)}{f(q_i, D) + k_1 \cdot (1 - b + b \cdot \frac{|D|}{\text{avgdl}})}
]
意味を分解してみましょう:
記号 | 意味 |
---|---|
( q_i ) | クエリ中の単語 |
( f(q_i, D) ) | 文書Dにおける単語 ( q_i ) の出現回数(TF) |
( | D |
( \text{avgdl} ) | 全文書の平均長さ |
( k_1, b ) | ハイパーパラメータ(調整用) |
( \text{IDF}(q_i) ) | 単語の希少性を表す重み(逆文書頻度) |
⚙️ TF-IDFとの違い
項目 | TF-IDF | BM25 |
---|---|---|
文書の長さ補正 | なし | あり(長い文書にペナルティ) |
TFの扱い | 線形(出現回数そのまま) | 非線形(飽和効果を持つ) |
パラメータ調整 | なし | ( k_1, b ) で柔軟に調整可 |
つまり、BM25はより現実的な検索ニーズにマッチする改良型モデルです。
🛠️ パラメータ ( k_1 ) と ( b ) の意味
- ( k_1 ):TFの重みづけ。大きくするほど出現回数の影響が大きくなる。
-
( b ):文書の長さに対する補正の強さ。
- ( b = 1 ):文書長の影響を最大限に考慮(長い文書は不利に)
- ( b = 0 ):文書長は無視
実務では、だいたい ( k_1 = 1.2 \sim 2.0, b = 0.75 ) がよく使われます。
🧠 なぜ「今でも」使われるのか?
- シンプルかつ計算効率が高い
- 多くの検索エンジン(Lucene、Elasticsearch、Whooshなど)に実装済
- 深層学習以前の検索モデルとして今も強力なベースライン
また、最近ではBM25とBERTを組み合わせたハイブリッド検索も盛んに研究されています。
例えば:
- BM25で上位100件をフィルタ
- BERTでその100件を精緻に再ランク
といった活用です。
🤖 PythonでBM25を使ってみよう(簡易例)
from rank_bm25 import BM25Okapi
corpus = [
"東京に行きたい",
"京都の紅葉が美しい",
"大阪でたこ焼きを食べたい"
]
tokenized_corpus = [doc.split() for doc in corpus]
bm25 = BM25Okapi(tokenized_corpus)
query = "京都 紅葉"
tokenized_query = query.split()
scores = bm25.get_scores(tokenized_query)
print(scores)
✍️ まとめ
- BM25は、TF-IDFを改良した現代的なスコアリング手法
- 文書長の補正やTFの非線形扱いが特徴
- 現在でもLucene系の検索エンジンで広く使われている
**「なんとなく聞いたことはあるけど、理解が曖昧だった」**という方にこそ、BM25の基本を押さえておくことは、自然言語処理や情報検索を深く学ぶ上での第一歩です。
Discussion