Appearance
相关性算分模型
要理解 Elasticsearch(ES)的相关性算分模型,我们需要从「如何量化“查询与文档的匹配程度”」这个核心问题出发,逐步拆解其底层逻辑和进化路径。
一、相关性算分的核心矛盾
用户的需求是:让“最符合查询意图”的文档排在最前面。但“符合意图”是抽象的,需要转化为可计算的统计特征或语义特征。
ES 中的相关性算分模型,本质是通过以下两类特征来量化匹配度:
- 词的统计特征:比如“词在文档中出现的次数”(TF)、“词在语料库中的稀有性”(IDF)—— 解决精确关键词匹配问题;
- 语义特征:比如“查询与文档的向量相似度”—— 解决语义理解问题(比如“猫”和“小猫”的语义关联)。
二、经典关键词匹配模型:从 TF-IDF 到 BM25
早期的相关性算分基于关键词的统计规律,最基础的是 TF-IDF,而 ES 默认的算分器是 BM25(TF-IDF 的优化版)。
1. TF-IDF:词频-逆文档频率
TF-IDF 是相关性算分的“启蒙模型”,核心逻辑是:
一个词对文档的重要性 = 词在文档中的频率(TF) × 词在语料中的稀有性(IDF)。
(1)TF(Term Frequency,词频)
表示某个词在当前文档中出现的次数。公式通常做归一化处理(避免长文档的“词频膨胀”):
$$ TF(t, d) = \frac{\text{词 t 在文档 d 中的出现次数}}{\text{文档 d 的总词数}} $$
或更常用的对数衰减(避免词频过高时的边际效益递减):
$$ TF(t, d) = \log(1 + \text{词 t 在文档 d 中的出现次数}) $$
比如:查询“猫”,文档 A 含“猫”5 次(总词数 1000),文档 B 含“猫”1 次(总词数 100)。
- 原始 TF:A=5,B=1 → A 更高;
- 归一化 TF:A=5/1000=0.005,B=1/100=0.01 → B 更高(因为“猫”在 B 中的密度更大)。
(2)IDF(Inverse Document Frequency,逆文档频率)
表示某个词在整个语料库中的稀有性—— 词越稀有,IDF 越高,对相关性的贡献越大。公式:
$$ IDF(t) = \log\left( \frac{\text{总文档数}}{\text{包含词 t 的文档数} + 1} \right) $$
加 1 是为了避免分母为 0(比如某个词未出现在任何文档中)。
比如:语料库有 1000 篇文档,“的”出现在 990 篇中,“量子计算机”出现在 10 篇中。
- IDF(的) = log(1000/(990+1)) ≈ 0.004 → 几乎无贡献;
- IDF(量子计算机) = log(1000/(10+1)) ≈ 2.39 → 贡献很大。
(3)TF-IDF 总分计算
查询的总得分是每个查询词的 TF-IDF 之和。例如:
查询“猫 可爱”,文档 d 的得分 = TF(猫,d)×IDF(猫) + TF(可爱,d)×IDF(可爱)。
2. BM25:TF-IDF 的优化版(ES 默认算分器)
TF-IDF 有两个明显缺陷:
- TF 无饱和:词频过高时,得分会无限制增长(比如“猫”出现 100 次的文档,得分远高于出现 10 次的,但实际相关性差异很小);
- 文档长度未合理惩罚:长文档更容易包含更多查询词,导致得分虚高(比如一篇 10000 字的文档含“猫”10 次,可能不如一篇 100 字含“猫”5 次的文档相关)。
BM25(Best Matching 25)是概率检索模型,解决了上述问题,成为 ES 的默认算分器。
(1)BM25 公式(简化版)
对于查询 ( q = {t_1, t_2, ..., t_n} ),文档 ( d ) 的得分是每个查询词的贡献之和:
$$ Score(d, q) = \sum_{t \in q} IDF(t) \times \frac{TF(t,d) \times (k_1 + 1)}{TF(t,d) + k_1 \times \left(1 - b + b \times \frac{|d|}{\text{avgdl}}\right)} $$
其中关键参数:
- ( k_1 ):控制 TF 的饱和速度(默认 1.2)—— ( k_1 ) 越大,TF 增长越慢(饱和越晚);
- ( b ):控制文档长度的影响(默认 0.75)—— ( b=1 ) 完全惩罚长文档,( b=0 ) 不考虑文档长度;
- ( |d| ):文档 ( d ) 的长度;
- ( \text{avgdl} ):语料库中文档的平均长度。
(2)BM25 的核心优化逻辑
我们用一个例子拆解公式的作用:
假设:
- 语料库总文档数 = 1000,avgdl = 100;
- 查询词 ( t = \text{“猫”} ),IDF(t) = log(1000/100 +1) ≈ 2.398;
- 文档 A:长度 50,TF(t)=3;
- 文档 B:长度 200,TF(t)=5;
- 参数:( k_1=1.2 ),( b=0.75 )。
计算文档 A 的贡献:
分母 = 3 + 1.2 × (1 - 0.75 + 0.75 × 50/100) = 3 + 1.2 × 0.625 = 3.75;
分子 = 3 × (1.2 + 1) = 6.6;
TF 修正项 = 6.6 / 3.75 = 1.76;
总贡献 = 1.76 × 2.398 ≈ 4.22。
计算文档 B 的贡献:
分母 = 5 + 1.2 × (1 - 0.75 + 0.75 × 200/100) = 5 + 1.2 × 1.75 = 7.1;
分子 = 5 × (1.2 + 1) = 11;
TF 修正项 = 11 / 7.1 ≈ 1.55;
总贡献 = 1.55 × 2.398 ≈ 3.72。
结论:文档 A 的得分更高—— 尽管文档 B 的 TF 更大,但 BM25 通过文档长度惩罚(文档 B 更长)和TF 饱和(TF 增长到一定程度后,贡献递减),修正了 TF-IDF 的缺陷。
(3)BM25 的概率解释
BM25 基于二元独立模型(BIM),核心假设是:
“文档与查询相关的概率” 可以通过“查询词在相关文档与不相关文档中的出现概率比”来计算。
具体来说,每个查询词 ( t ) 的贡献对应:
$$ \log\left( \frac{P(t|相关)}{1-P(t|相关)} \div \frac{P(t|不相关)}{1-P(t|不相关)} \right) $$
其中 ( P(t|相关) ) 是“词 ( t ) 出现在相关文档中的概率”,( P(t|不相关) ) 是“词 ( t ) 出现在不相关文档中的概率”。
BM25 的公式是这个概率模型的工程近似,通过 ( k_1 ) 和 ( b ) 调整模型对实际数据的拟合度。
三、语义匹配模型:向量搜索(Vector Search)
随着 NLP 技术的发展,ES 从 7.0 开始支持向量搜索,解决了关键词匹配无法处理的语义关联问题(比如“如何用苹果手机拍夜景”和“苹果手机夜景拍摄技巧”的语义相似,但关键词不完全重叠)。
1. 向量搜索的核心逻辑
向量搜索的本质是将文本转化为高维向量(通过预训练模型,如 BERT、Sentence-BERT),然后用向量相似度量化查询与文档的语义匹配度。
关键步骤:
- 文本向量化:将查询和文档都转换为固定长度的向量(比如 768 维);
- 向量索引:用近似最近邻(ANN)算法(如 HNSW、IVF)构建向量索引,加速检索;
- 相似度计算:用相似度度量(如余弦相似度)计算查询向量与文档向量的距离,距离越近,语义越相似。
2. 常见的向量相似度度量
ES 支持以下三种主要的相似度计算方式(适用于 dense_vector 字段):
(1)余弦相似度(Cosine Similarity)
衡量两个向量的夹角(不考虑向量长度),取值范围 [-1, 1],越接近 1 越相似。公式:
$$ \cos(\theta) = \frac{A \cdot B}{||A|| \times ||B||} $$
其中 ( A \cdot B ) 是向量点积,( ||A|| ) 是向量 A 的 L2 范数(模长)。
适用场景:文本语义匹配(如搜索“猫”时,“小猫”的向量夹角很小)。
(2)欧氏距离(Euclidean Distance)
衡量两个向量在空间中的直线距离,取值范围 [0, ∞),越小越相似。公式:
$$ \text{Euclidean}(A,B) = \sqrt{\sum_{i=1}^n (A_i - B_i)^2} $$
适用场景:数值型数据的相似性(如推荐系统中的用户画像匹配)。
(3)内积(Dot Product)
当向量被归一化到单位长度时,内积等价于余弦相似度。公式:
$$ \text{Dot}(A,B) = \sum_{i=1}^n A_i \times B_i $$
适用场景:需要快速计算的场景(内积的计算速度比余弦相似度快)。
3. ES 中的向量搜索示例
假设我们有一个 dense_vector 字段 embedding,存储文档的向量表示。查询时,用 knn 子句指定向量搜索:
json
{
"knn": {
"field": "embedding",
"query_vector": [0.1, 0.2, ..., 0.768], // 查询的向量表示
"k": 10, // 返回 Top 10 相似文档
"num_candidates": 100 // 候选文档数(影响召回率)
}
}四、混合算分模型:结合关键词与语义匹配
关键词匹配(BM25)擅长精确匹配(如“苹果手机 15”),向量搜索擅长语义匹配(如“如何用苹果手机拍夜景”)。ES 支持混合搜索(Hybrid Search),将两者的得分结合,提升整体相关性。
1. 混合算分的常见方式
(1)线性加权
将 BM25 得分和向量相似度得分按权重相加:
$$ \text{FinalScore} = \alpha \times BM25Score + (1-\alpha) \times VectorScore $$
其中 ( \alpha ) 是权重参数(如 ( \alpha=0.7 ) 表示更侧重关键词匹配)。
(2)Reciprocal Rank Fusion(RRF)
根据文档在两个模型中的排名计算最终得分,避免得分范围差异的影响:
$$ \text{FinalScore} = \sum_{i=1}^k \frac{1}{r_i + c} $$
其中 ( r_i ) 是文档在第 ( i ) 个模型中的排名,( c ) 是常数(如 60)。
2. ES 中的混合搜索示例
用 search API 结合 query(BM25)和 knn(向量搜索):
json
{
"query": {
"match": {
"content": "如何用苹果手机拍夜景"
}
},
"knn": {
"field": "embedding",
"query_vector": [0.1, 0.2, ..., 0.768],
"k": 10,
"num_candidates": 100
},
"rank": {
"rrf": { // 用 RRF 融合得分
"window_size": 50,
"rank_constant": 60
}
}
}五、总结:相关性算分的进化路径
ES 的相关性算分模型,本质是从“关键词统计”到“语义理解”的升级,核心目标是更精准地匹配用户意图:
| 模型 | 核心逻辑 | 适用场景 |
|---|---|---|
| TF-IDF | 词频 × 逆文档频率 | 简单关键词匹配 |
| BM25 | 优化 TF 饱和与文档长度惩罚的概率模型 | 大多数精确匹配场景(ES 默认) |
| 向量搜索 | 向量空间中的语义相似度 | 语义匹配、长文本搜索 |
| 混合模型 | 结合关键词与语义得分 | 复杂意图的精准匹配 |
关键结论:
- 相关性算分的本质是量化“查询与文档的匹配程度”,不同模型的差异在于“如何定义匹配”;
- BM25 是 ES 的“基石”,解决了大多数精确匹配问题;
- 向量搜索是未来的趋势,解决了语义理解的痛点;
- 混合模型是平衡精确与语义匹配的最佳实践。
希望这个讲解能帮你理解 ES 相关性算分的底层逻辑!如果有具体场景的问题,欢迎继续探讨。
