Combiner BM25 et vecteurs sans régler dix poids : le rang suffit.
La fusion de rang réciproque combine deux listes classées en additionnant l’inverse
du rang de chaque document : un résultat bien placé dans l’un ou l’autre récupérateur
remonte naturellement, sans qu’il faille normaliser les scores. L’unique constante k
est bien plus facile à appréhender qu’un mélange pondéré de scores lexicaux et cosinus,
par nature incomparables.
Mieux vaut fusionner deux classements imparfaits que sur-optimiser un seul.
# fusion de rang réciproque: fusionne N classements par leur rang, pas leur score
from collections import defaultdict
def rrf(rankings, k=60):
scores = defaultdict(float)
for ranking in rankings:
for rank, doc_id in enumerate(ranking):
scores[doc_id] += 1 / (k + rank + 1)
return sorted(scores, key=scores.get, reverse=True)
En pratique, la voie lexicale repère les identifiants exacts et les termes rares que le plongement laisse passer, tandis que la voie vectorielle rattrape les paraphrases. Fusionnées, les deux voies compensent leurs angles morts respectifs : une solution par défaut robuste avant de se tourner vers un reranker entraîné.
| Récupérateur | Repère | Manque |
|---|---|---|
| Lexical (BM25) | Identifiants exacts et termes rares | Paraphrases |
| Vectoriel | Paraphrases | Identifiants exacts et termes rares que le plongement laisse passer |