评分
全文评分函数
评分文档
在搜索时,文档会根据其与查询的相关性进行评分。评分是介于 0.0 和 1.0 之间的一个浮点数,其中 1.0 是最高分。评分作为搜索结果的一部分返回,可用于对结果进行排序。
Redis Stack 附带了一些非常基本的评分函数来评估文档相关性。它们都基于文档评分和词频。这与使用 可排序字段 的能力无关。通过向搜索查询添加 SCORER {scorer_name}
参数来指定评分函数。
如果您更喜欢自定义评分函数,可以使用扩展 API添加更多函数。
以下是 Redis Stack 中可用的预捆绑评分函数列表,以及它们的工作原理的简要说明。每个函数都按注册名称提及,该名称可以作为 FT.SEARCH
中的 SCORER
参数传递。
TFIDF(默认)
带有几个额外功能的基本TF-IDF 评分
-
对于每个结果中的每个术语,将计算该术语的 TF-IDF 分数到该文档。频率基于预先确定的字段权重进行加权,每个术语的频率都根据每个文档中最高的术语频率进行归一化。
-
查询术语的总 TF-IDF 乘以在
FT.ADD
上给出的推定文档分数。 -
根据“松弛”或搜索术语之间的累积距离为每个结果分配一个惩罚。完全匹配不会受到任何惩罚,但搜索术语相距较远的匹配项的分数会大幅降低。对于连续术语的每个二元组,确定它们之间的最小距离。惩罚是距离平方和的平方根;例如,
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
中的松弛度应用惩罚。
FT.SEARCH myIndex "foo" SCORER BM25
DISMAX
一个简单的评分器,用于汇总匹配术语的频率。在并集子句的情况下,它将给出这些匹配项的最大值。不应用任何其他惩罚或因素。
它不是Solr 的 DISMAX 算法的一对一实现,但它在广义上遵循它。
FT.SEARCH myIndex "foo" SCORER DISMAX
DOCSCORE
一个评分函数,它只返回文档的推定分数,而不对其应用任何计算。由于可以更新文档分数,因此如果您想使用外部分数而无需进一步操作,这将很有用。
FT.SEARCH myIndex "foo" SCORER DOCSCORE
HAMMING
对文档有效负载和查询有效负载之间的逆汉明距离进行评分。由于最近邻域是关注对象,因此使用逆汉明距离(1/(1+d)
),以便距离为 0 时给出 1 的完美分数,并且是最高排名。
仅在以下情况下有效
- 文档具有有效负载。
- 查询具有有效负载。
- 两者长度完全相同。
有效负载是二进制安全的,并且具有长度为 64 位的倍数的有效负载会产生稍快的结果。
示例
127.0.0.1:6379> FT.CREATE idx SCHEMA foo TEXT
OK
127.0.0.1:6379> FT.ADD idx 1 1 PAYLOAD "aaaabbbb" FIELDS foo hello
OK
127.0.0.1:6379> FT.ADD idx 2 1 PAYLOAD "aaaacccc" FIELDS foo bar
OK
127.0.0.1:6379> FT.SEARCH idx "*" PAYLOAD "aaaabbbc" SCORER HAMMING WITHSCORES
1) (integer) 2
2) "1"
3) "0.5" // hamming distance of 1 --> 1/(1+1) == 0.5
4) 1) "foo"
2) "hello"
5) "2"
6) "0.25" // hamming distance of 3 --> 1/(1+3) == 0.25
7) 1) "foo"
2) "bar"