文档评分
全文评分函数
搜索时,文档根据其与查询的相关性进行评分。评分是一个介于 0.0 和 1.0 之间的浮点数,其中 1.0 是最高分。评分作为搜索结果的一部分返回,可用于对结果进行排序。
Redis 开源版提供了一些非常基本的评分函数来评估文档相关性。它们都基于文档评分和词频。这与是否可以使用可排序字段无关。通过在搜索查询中添加 SCORER {scorer_name}
参数来指定评分函数。
如果您喜欢自定义评分函数,可以使用扩展 API 添加更多函数。
以下是 Redis 中预置的评分函数列表及其工作原理的简要说明。每个函数都按注册名称提及,可以在 FT.SEARCH
中作为 SCORER
参数传递。
TFIDF (默认)
基础 TF-IDF 评分,带有一些额外功能
-
对于每个结果中的每个词项,计算该词项对该文档的 TF-IDF 分数。频率根据预设的字段权重进行加权,并且每个词项的频率由每个文档中的最高词项频率进行归一化。
-
查询词项的总 TF-IDF 乘以通过
SCORE_FIELD
在FT.CREATE
上给出的推定文档分数。 -
根据搜索词项之间的“slop”或累积距离,对每个结果分配惩罚。精确匹配不会受到惩罚,但搜索词项距离较远的匹配会显著降低分数。对于连续词项的每个二元组,确定它们之间的最小距离。惩罚是距离平方和的平方根;例如,
1/sqrt(d(t2-t1)^2 + d(t3-t2)^2 + ...)
。
假设文档 D 中有 N 个词项,T1...Tn
,结果分数可以用此 Python 函数描述
def get_score(terms, doc):
# the sum of tf-idf
score = 0
# the distance penalty for all terms
dist_penalty = 0
for i, term in enumerate(terms):
# tf normalized by maximum frequency
tf = doc.freq(term) / doc.max_freq
# idf is global for the index, and not calculated each time in real life
idf = log2(1 + total_docs / docs_with_term(term))
score += tf*idf
# sum up the distance penalty
if i > 0:
dist_penalty += min_distance(term, terms[i-1])**2
# multiply the score by the document score
score *= doc.score
# divide the score by the root of the cumulative distance
if len(terms) > 1:
score /= sqrt(dist_penalty)
return score
TFIDF.DOCNORM
与默认的 TFIDF
评分器相同,但有一个重要区别
词项频率按文档长度归一化,文档长度表示为词项总数。长度是加权的,因此如果文档包含两个词项,一个位于权重为 1 的字段中,一个位于权重为 5 的字段中,则总频率为 6,而不是 2。
FT.SEARCH myIndex "foo" SCORER TFIDF.DOCNORM
BM25
基本 TFIDF
评分器的一个变体,更多信息请参阅此维基百科文章。
每个文档的相关性分数乘以推定文档分数,并像 TFIDF
中一样基于 slop 应用惩罚。
FT.SEARCH myIndex "foo" SCORER BM25
DISMAX
一个简单的评分器,它总结匹配词项的频率。在 union 子句的情况下,它将给出这些匹配的最大值。不应用其他惩罚或因素。
它不是 Solr 的 DISMAX 算法 的一对一实现,但它大体遵循其原则。
FT.SEARCH myIndex "foo" SCORER DISMAX
DOCSCORE
一个仅返回文档推定分数而不对其进行任何计算的评分函数。由于文档分数可以更新,如果您想使用外部分数并且不再进行其他处理,这会很有用。
FT.SEARCH myIndex "foo" SCORER DOCSCORE
HAMMING
通过计算文档负载与查询负载之间的逆 Hamming 距离进行评分。由于关注的是最近邻居,因此使用逆 Hamming 距离 (1/(1+d)
),以便距离为 0 时获得满分 1,并且是最高排名。
这仅在以下情况下有效
- 文档有负载(payload)。
- 查询有负载(payload)。
- 两者的长度完全相同。
负载(payload)是二进制安全的,并且长度为 64 位倍数的负载会产生稍快的결果。
示例
> HSET key:1 foo hello payload aaaabbbb
(integer) 2
> HSET key:2 foo bar payload aaaacccc
(integer) 2
> FT.CREATE idx ON HASH PREFIX 1 key: PAYLOAD_FIELD payload SCHEMA foo TEXT
"OK"
> FT.SEARCH idx "*" PAYLOAD "aaaabbbc" SCORER HAMMING WITHSCORES
1) "2"
2) "key:1"
3) "0.5"
4) 1) "foo"
2) "hello"
5) "key:2"
6) "0.25"
7) 1) "foo"
2) "bar"