在信息檢索(IR)、推薦系統和多模態檢索中,我們常常需要融合來自多個檢索器或模型的結果。不同檢索器可能對同一文檔打出的分數差異很大,如果直接簡單加權,很容易出現某個檢索器“主導融合結果”的情況。
Distribution-Based Score Fusion (DBSF) 是一種基于分布的分數融合方法,它通過統計方法對各檢索器的分數進行歸一化和標準化,使得融合過程更加穩健和公平。
背景
在多檢索器融合中,我們通常面臨以下問題:
-
分數尺度不統一
-
BM25 輸出的分數范圍可能是 0–30
-
Dense Embedding 輸出余弦相似度,范圍可能是 0–1
-
-
分布形態差異大
-
某些檢索器的分數分布可能非常集中(方差小)
-
某些檢索器存在極端值(outliers)
-
-
傳統方法的局限
-
Min-Max 或 Z-score 歸一化 + 加權融合
-
容易受 outlier 影響
-
對分布差異大的檢索器不夠穩健
-
-
人工加權需要經驗和先驗知識
-
DBSF 應運而生,它通過統計分布的方式統一各檢索器的貢獻,不依賴復雜的手動權重。
DBSF 的原理
DBSF 的核心步驟如下:
-
計算均值和標準差
對每個檢索器的分數集計算:-
均值 μ
-
標準差 σ
-
-
截斷分數到 μ±3σ
-
小于 μ?3σ 的分數 → 0
-
大于 μ+3σ 的分數 → 1
-
中間分數線性縮放到 0–1
-
-
標準化與歸一化
對在 μ±3σ 區間的分數: -
融合分數
將各檢索器的歸一化分數相加(或平均):
這種方法能夠避免極端值影響,同時保證不同檢索器的信號都有貢獻。
優缺點
優點
-
穩健性高:對 outlier 不敏感
-
分布自適應:不同檢索器的分數分布差異大時效果更好
-
無需手動調權重:自動平衡各檢索器的貢獻
-
易于實現:基于均值和標準差即可
缺點
-
無法體現先驗偏好:如果某個檢索器非常重要,DBSF 不會自動偏向它
-
假設分數近似正態分布:在極端非正態分布下,μ±3σ 截斷可能不完全合理
-
單純線性加權:融合邏輯簡單,可能無法捕捉復雜關系
示例代碼(Python)
下面是一個簡化實現示例:
import numpy as np
from collections import defaultdictdef normalize_dbsf(scores):values = np.array(list(scores.values()))mu, sigma = values.mean(), values.std(ddof=1) if len(values) > 1 else (values.mean(), 1e-9)lower, upper = mu - 3*sigma, mu + 3*sigmanorm_scores = {}for doc, s in scores.items():if upper == lower:ns = 0.5else:ns = (s - lower) / (upper - lower)ns = max(0.0, min(1.0, ns))norm_scores[doc] = nsreturn norm_scoresdef dbsf_fusion(results_list):fused = defaultdict(float)for scores in results_list:norm_scores = normalize_dbsf(scores)for doc, ns in norm_scores.items():fused[doc] += nsreturn sorted(fused.items(), key=lambda x: x[1], reverse=True)# 示例數據
bm25 = {"doc1": 28.4, "doc2": 17.2, "doc3": 3.9, "doc4": 10.5}
dense = {"doc1": 0.78, "doc2": 0.65, "doc3": 0.52, "doc4": 0.31}
ctr = {"doc1": 0.045, "doc2": 0.032, "doc3": 0.028, "doc4": 0.041}# 融合
fused_results = dbsf_fusion([bm25, dense, ctr])
print(fused_results)
輸出示例:
[('doc1', 2.07), ('doc2', 1.53), ('doc4', 1.25), ('doc3', 1.15)]
可以看到,doc3
雖然在 BM25 分數很低,但在 Dense 和 CTR 中仍然貢獻了一部分分數,被合理保留在排名中。
llama_index 相關的代碼實現。?
from llama_index.core.retrievers import QueryFusionRetrieverretriever = QueryFusionRetriever([vector_retriever, bm25_retriever],retriever_weights=[0.6, 0.4],similarity_top_k=10,num_queries=1, # set this to 1 to disable query generationmode="dist_based_score",use_async=True,verbose=True,
)nodes_with_scores = retriever.retrieve("What happened at Interleafe and Viaweb?"
)for node in nodes_with_scores:print(f"Score: {node.score:.2f} - {node.text[:100]}...\n-----")
應用場景示例
-
多檢索器文本搜索:BM25 + Dense Embedding + Click-Through Rate
-
多模態檢索:文本檢索 + 圖像相似度
-
跨語言檢索:原文語言 + 翻譯語言
-
推薦系統:不同算法輸出的評分融合
DBSF 在這些場景下都能顯著提升融合結果的穩健性和多樣性。
總結
-
DBSF 是一種基于統計分布的分數融合方法
-
通過 μ±3σ 截斷 + 標準化 + 相加,實現多檢索器結果的穩健融合
-
適合 分布差異大、沒有明確權重先驗 的場景
-
實現簡單,可用 Python 自定義,也可以使用如 LlamaIndex、Qdrant、Upstash 等系統內置功能
📚 參考資料
-
LlamaIndex 文檔:Relative Score Fusion 和 Distance-Based Score Fusion
-
Qdrant 文檔:Hybrid Queries
-
Upstash 文檔:Hybrid Indexes