# Relevance scoring in Manticore : part I

本文是系列文章的第一篇，我们将讨论Manticore Search中相关性评分的工作原理。我们从相关性的基础开始：词频和特异性。

### 简单的评分介绍


像Sphinx/Manticore Search这样的搜索引擎会从文档中提取文本，将其拆分为标记，并允许在该集合中搜索标记/单词的集合。
在最简单的场景中，这个集合包含标记/单词（我们称之为索引字典），以及找到它们的文档列表和它们所在的文档字段。
搜索首先确定输入单词之一是否存在于集合中，并提取文档列表，之后将其与其他单词列表合并，以编译包含所有输入单词的文档列表。
如果我们有多个符合此标准的文档，下一步是区分它们。这些文档中哪些对于给定的输入更相关？
一个简单且初步的区分方法是计算每个输入单词在文档中的出现次数。出现次数越多意味着单词越相关？这取决于具体情况。
某些单词可能在文档中出现多次——我们可以认为该单词对文档很重要，但该单词也可能出现在集合中的许多其他文档中——这引发了一个问题，即该单词是否只是一个常见单词，其重要性应被降低。
如果我们计算单词在文档中的出现次数（**频率**），我们希望消除这些常见单词可能对计数产生的影响。为此，我们添加一个计数器，统计包含该单词的文档数量——这就是“**词频**”——以及另一个计数器，告诉我们该单词在多少文档中出现（相对于总数）——它的倒数称为逆文档频率（**IDF**），是衡量一个术语特异性的指标。
这两个指标共同构成了**TF-IDF**，它告诉我们一个单词在集合中相对于文档的重要性。基于IDF，我们还可以计算另一种广泛使用的排名函数——**BM25**。
  
  
### BM25和TF-IDF


这些因素在Manticore Search中是如何实现并使用的？
首先，有几种内置的排名器（评分公式）可以直接使用。但最重要的是表达式排名器，它允许访问这些因素并创建自定义公式。
我们之前提到过BM25排名函数，它在Manticore的默认排名器（proximity_bm25）中包含，并且也可以作为排名表达式中的文档级因素使用。
我们不会深入讨论BM25的细节，因为已有大量学术论文涉及，但我们将专注于Manticore的实现。
需要指出的是，bm25因子的名称有些不准确，因为它不是传统的BM25实现，而是一个等效的估计值`BM25(K1=1.2,B=0)`——在某些论文中称为BM15。
你仍然可以使用经典的BM25，甚至通过`bm25a(k1,b)`排名函数调整k1和b参数。
更高级的版本是`bm25f(k1, b, {field=weight, …})`，它还允许为字段设置权重。请注意，这与常规的field_weights（稍后会讨论）不同，并且需要index_field_lengths选项。
在字段级别，可以通过多种方式访问TF-IDF：`**tf_idf**`是字段中每个匹配关键词出现的TF-IDF值的总和。此外，`**sum_idf**`是每个匹配关键词的TF-IDF值的总和（不乘以出现次数），而`**max_idf**`和`**min_idf**`则分别提供找到的TF-IDF值的最大值和最小值。
IDF的计算可以通过[OPTION](https://docs.manticoresearch.com/latest/html/sphinxql_reference/select_syntax.html#option)子句的`**idf**`进行控制。在最初的实现（Sphinx 2.1之前）中，IDF值是归一化的——这意味着常见单词（出现在超过50%文档中的单词）会受到惩罚（idf='normalized'）。IDF值的范围在`[-log(N),log(N)]`之间。在这种模式下，匹配“常见单词 + 不太常见的单词”会得到比仅匹配不太常见单词的IDF总和更低。为了解决这个问题（如果需要的话），新增了另一种模式（idf='plain'），其中IDF值没有惩罚，范围在`[0,log(N)]`之间。此外，IDF值除以查询关键词数量，使TF-IDF总和落在`[0,1]`范围内。
这在布尔查询中带来了问题，当搜索“**found-word**”与“**found-word OR not-found-word**”时，由于除法操作，相同的结果集会得到不同的权重。
为了解决这个问题，`idf`接收了另一组设置，允许控制是否应用除法。默认的`idf`设置仍为`normalized,tfidf_normalized`，以保持兼容性，但`idf='plain,tfidf_unnormalized'`在一般情况下应提供更好的结果。
  
  
### 下一步是什么？


到目前为止，我们可以基于**频率**和**特异性**创建评分，但这仅告诉我们单词存在于文档中，而没有说明单词是否彼此相邻或简单地分散在文本中。这导致我们需要在集合中添加另一个因素：**文本中单词的位置**。
拥有位置信息可以让我们知道输入单词是否匹配文档的精确字段，是否原样找到，或者它们彼此之间的距离如何，或者它们距离文本开头有多近（因为我们可以认为靠近开头甚至在开头的单词比在文档末尾的单词更相关）。
由于文档可能有多个字段，字段的重要性也可能不同。例如，如果我们有'title'和'body'列，'title'中的匹配项被视为更重要，应获得更高的评分。但更多关于这一点的内容将在未来文章中讨论。
