在 Elasticsearch 5.x 之前的版本所采用的是 tf-idf 来计算相关度, 而在 5.x 版本开始所采用的是 bm25 来计算相关度。
bm25 是在 tf-idf 的基础上增加了两个参数来控制词频不会因为数量的激增而飘高.
相关度是由TF-IDF和一组参数的组合运算得出的结果,用于评估一个词在文档中的近似匹配程度。
TF(Term frequency): 词频, 用于评估词
在文档中出现的次数, 次数越高分值越高.
(关闭词频: index_options: docs)
IDF(Inverse document frequency): 倒排文档频率, 用于评估包含词
的文档数量,数量越多词
的分值越低.
FLN(Field-length norm): 文本长度归一化(规范化), 用于评估不同字段的长度, 字段文本越短分值越高.
(关闭字段长度规范化: norms: {"enabled": false})联合参数:
coord(The Coordination Factor): 用于配合bool复合条件查询, 具体介绍不知道.
boost: 该参数用于调整字段权重.
Python版BM25实现
def bm25(doc_count, doc_freq):
# idf: 逆向文档频率: 包含词的文档数量越多, 词的权重就越低.
idf = log(1 + (doc_count - doc_freq + 0.5) / (doc_freq + 0.5), e)
idf = round(idf, 7)
# tf: 词频: 词在文档中出现的次数越高, 分值越高.
freq = 2.0
# 新特性: 该参数控制词频饱和(非线性上升速度)的规范化
k1 = 1.2
# 新特性: 该参数的用意是抵消字段越短,权重越高;
# 他将所有字段的长度做一个平均长度然后在做词频相关度计算。
b = 0.75
avg_field_length = 3.0
field_length = 4.0
tf = (freq * (k1 + 1)) / \
(freq + k1 * (1 - b + b * field_length / avg_field_length))
tf = round(tf, 7)
# 相关度: 词频分值 * 权重分值
score = round(tf * idf, 7)
return tf, idf, score
参考
- [x] 相关度评分背后的理论
- [x] BM25 The Next Generation of Lucene Relevance
- [x] 可插拔的相似度算法
- [x] BM25
网友评论