Elasticsearch:实用 BM25 - 第 1 部分:分片如何影响 Elasticsearch 中的相关性评分

这篇具有很好参考价值的文章主要介绍了Elasticsearch:实用 BM25 - 第 1 部分:分片如何影响 Elasticsearch 中的相关性评分。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

作者:Shane Connelly 

Elasticsearch:实用 BM25 - 第 1 部分:分片如何影响 Elasticsearch 中的相关性评分

背景

在 Elasticsearch 5.0 中,我们切换到 Okapi BM25 作为我们的默认相似度算法,这是用于对与查询相关的结果进行评分的算法。 在本博客中,我不会过多地介绍 BM25 与替代措施,但如果你想了解 BM25 的理论依据,你可以继续观看 Elastic{ON} 2016 的 BM25 Demystified 演示文稿。相反,我 我将为你介绍(并希望揭开神秘面纱)BM25 的实际用法,包括介绍可用的参数以及影响评分的因素。

请记住,此博客主要与那些对文本文档进行评分的人有关。 也就是说,它真正专注于帮助我们的搜索用户。 如果你正在索引日志或指标并返回按某些明确的元数据/数字顺序(如时间戳)排序的结果,则此博客可能主要用于满足好奇心。

了解分片如何影响评分

因为我希望你在家里也能跟进,所以我们需要解决的第一件事就是了解超过 1 个分片如何影响评分,因为默认情况下 Elasticsearch 每个索引使用 5 个主分片(请注意这个在最新的版本里有变化)。 让我们从创建一个名为 people 的索引开始。 我在此处提供的设置将是默认设置(因此无需定义),但为了演示目的,我无论如何都会这样做。 我将在这里使用我的名字的变体(“Shane Connelly”),但如果你在家跟随,请随时将其替换为你选择的名字。

PUT people
{
  "settings": {
    "number_of_shards": 5,
    "index": {
      "similarity": {
        "default": {
          "type": "BM25"
        }
      }
    }
  }
}

现在让我们添加一个文档,然后搜索它。 首先,我们只添加我的名字:

PUT /people/_doc/1
{
  "title": "Shane"
}

GET /people/_search?filter_path=**.hits
{
  "query": {
    "match": {
      "title": "Shane"
    }
  }
}

上面搜索的结果为:

{
  "hits": {
    "hits": [
      {
        "_index": "people",
        "_id": "1",
        "_score": 0.2876821,
        "_source": {
          "title": "Shane"
        }
      }
    ]
  }
}

此时你得到 1 个命中,分数为 0.2876821。 我们稍后会深入探讨这个评分是如何得出的,但让我们先看看当我们添加更多带有我全名不同变体的文档时会发生什么。

PUT /people/_doc/2
{
  "title": "Shane C"
}

PUT /people/_doc/3
{
  "title": "Shane Connelly"
}

PUT /people/_doc/4
{
  "title": "Shane P Connelly"
}

现在再次进行相同的搜索:

GET /people/_search?filter_path=**.hits
{
  "query": {
    "match": {
      "title": "Shane"
    }
  }
}

上面搜索的结果为:

{
  "hits": {
    "hits": [
      {
        "_index": "people",
        "_id": "3",
        "_score": 0.2876821,
        "_source": {
          "title": "Shane Connelly"
        }
      },
      {
        "_index": "people",
        "_id": "4",
        "_score": 0.2876821,
        "_source": {
          "title": "Shane P Connelly"
        }
      },
      {
        "_index": "people",
        "_id": "2",
        "_score": 0.2876821,
        "_source": {
          "title": "Shane C"
        }
      },
      {
        "_index": "people",
        "_id": "1",
        "_score": 0.2876821,
        "_source": {
          "title": "Shane"
        }
      }
    ]
  }
}

此时,你确实应该有 4 个命中,但如果你看分数,你可能会摸不着头脑。 文档 1,2,3,4 的得分均为 0.2876821。我们通过如下的方式来查看各个分片的文档情况:

GET /_cat/shards/people?v

上面述命令返回的结果为:

index  shard prirep state      docs store ip        node
people 0     p      STARTED       1 4.7kb 127.0.0.1 liuxgm.local
people 0     r      UNASSIGNED                      
people 1     p      STARTED       1 4.7kb 127.0.0.1 liuxgm.local
people 1     r      UNASSIGNED                      
people 2     p      STARTED       0  247b 127.0.0.1 liuxgm.local
people 2     r      UNASSIGNED                      
people 3     p      STARTED       1 4.6kb 127.0.0.1 liuxgm.local
people 3     r      UNASSIGNED                      
people 4     p      STARTED       1 4.6kb 127.0.0.1 liuxgm.local
people 4     r      UNASSIGNED                      

从上面显示的结果中,我们可以看出来,每个分片含有一个文档。其中的一个分片没有文档。

我们删除之前的所有文档,并再次写入各个文档:

DELETE people

PUT people
{
  "settings": {
    "number_of_shards": 5,
    "index": {
      "similarity": {
        "default": {
          "type": "BM25"
        }
      }
    }
  }
}

PUT /people/_doc/2?routing=1
{
  "title": "Shane C"
}

PUT /people/_doc/3
{
  "title": "Shane Connelly"
}

PUT /people/_doc/4?routing=1
{
  "title": "Shane P Connelly"
}

PUT /people/_doc/1
{
  "title": "Shane"
}

在上面,我们有意识地通过 routing 把有些文档写入到同一个分片中。我们运行如下的命令来进行查看:

GET /_cat/shards/people?v

上面的命令显示:

index  shard prirep state      docs store ip        node
people 0     p      STARTED       1 4.7kb 127.0.0.1 liuxgm.local
people 0     r      UNASSIGNED                      
people 1     p      STARTED       0  247b 127.0.0.1 liuxgm.local
people 1     r      UNASSIGNED                      
people 2     p      STARTED       0  247b 127.0.0.1 liuxgm.local
people 2     r      UNASSIGNED                      
people 3     p      STARTED       0  247b 127.0.0.1 liuxgm.local
people 3     r      UNASSIGNED                      
people 4     p      STARTED       3 9.7kb 127.0.0.1 liuxgm.local
people 4     r      UNASSIGNED                      

如上所示,这次,我们看到有一个分片含有 3 个文档,有一个分片含有一个文档。其它的三个分片不含有任何的文档。我们再次进行同样的搜索:

GET /people/_search?filter_path=**.hits
{
  "query": {
    "match": {
      "title": "Shane"
    }
  }
}

上面的命令返回的结果为:

{
  "hits": {
    "hits": [
      {
        "_index": "people",
        "_id": "3",
        "_score": 0.2876821,
        "_source": {
          "title": "Shane Connelly"
        }
      },
      {
        "_index": "people",
        "_id": "1",
        "_score": 0.16786805,
        "_source": {
          "title": "Shane"
        }
      },
      {
        "_index": "people",
        "_id": "2",
        "_score": 0.13353139,
        "_routing": "1",
        "_source": {
          "title": "Shane C"
        }
      },
      {
        "_index": "people",
        "_id": "4",
        "_score": 0.110856235,
        "_routing": "1",
        "_source": {
          "title": "Shane P Connelly"
        }
      }
    ]
  }
}

这通常会让新用户望而却步。 文档 2 和 3 非常相似 —— 它们都有 2 个词并且都匹配“ shane”,但是文档 2 的分数要低得多。 您可能会开始假设 “C” 的评分与 “Connelly” 的评分有所不同,但实际上这与文档如何落入分片有关。

提醒一下,Elasticsearch 将文档写入到不同的分片(shards)之中,每个碎片保存数据的一个子集。 这意味着术语 “shane” 的总出现次数在这些不同的分片中是不同的,这就是最终导致这种情况下分数差异的原因。 默认情况下,Elasticsearch 以每个分片为基础计算分数。

人们开始只将几个文档加载到他们的索引中并问 “为什么文档 A 的分数比文档 B 高/低”,有时答案是用户的分片与文档的比例相对较高,因此分数是倾斜的跨越不同的分片。 有几种方法可以跨分片获得更一致的分数:

1)加载到索引中的文档越多,分片的术语统计数据就越规范化。 如果文档足够多,你可能不会注意到术语统计数据的细微差异,因此不会注意到每个分片中的得分。

2)你可以使用较低的分片数来减少术语频率的统计偏差。 例如,如果我们在索引设置中将 number_of_shards 设置为 1,我们就会得到非常不同的分数。 我们会看到文档 1 的得分为 0.13245322,文档 2 和 3 的得分各为 0.105360515,文档 4 的得分为 0.0874691。 拥有不同数量的主分片需要权衡取舍,这在我们的定量集群大小网络研讨会中进行了讨论。

{
  "hits": {
    "hits": [
      {
        "_index": "people",
        "_id": "1",
        "_score": 0.13245323,
        "_source": {
          "title": "Shane"
        }
      },
      {
        "_index": "people",
        "_id": "2",
        "_score": 0.10536051,
        "_source": {
          "title": "Shane C"
        }
      },
      {
        "_index": "people",
        "_id": "3",
        "_score": 0.10536051,
        "_source": {
          "title": "Shane Connelly"
        }
      },
      {
        "_index": "people",
        "_id": "4",
        "_score": 0.0874691,
        "_source": {
          "title": "Shane P Connelly"
        }
      }
    ]
  }
}

3)你可以将 ?search_type=dfs_query_then_fetch 添加到请求中,它首先收集分布式术语频率(DFS = 分布式频率搜索),然后使用这些计算分数。 事实上,这会返回与只有 1 个分片相同的分数。 看看使用和不使用 “search_type” 参数的结果有何不同:

GET /people/_doc/_search?search_type=dfs_query_then_fetch
{
    "query": {
        "match": {
             "title": "Shane"
         }
      }
}

这与设置 number_of_shards=1 相同。 然后你可能会问,“好吧,如果这会产生更准确的分数,为什么默认情况下不打开它?” 答案是它在处理过程中增加了一次额外的往返以收集所有统计数据,对于某些用例(评分准确性不如速度重要),这种往返是不必要的。 此外,如果分片中有足够的数据,统计数据可以变得非常接近,从而也不需要往返。 如果你有足够的数据, search_type=dfs_query_then_fetch 只有在分片之间的数据继续分布不均时才最需要,就像一些自定义路由的情况一样。        

好的,现在我们了解了分片如何影响我们的评分(以及如何针对它进行调整)。 接下来,我们将研究 BM25 算法,看看不同的变量是如何发挥作用的。

请继续阅读第二部分 “Elasticsearch:实用 BM25 - 第 2 部分:BM25 算法及其变量”。文章来源地址https://www.toymoban.com/news/detail-493816.html

到了这里,关于Elasticsearch:实用 BM25 - 第 1 部分:分片如何影响 Elasticsearch 中的相关性评分的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用ElasticSearch完成大模型+本地知识库:BM25+Embedding模型+Learned Sparse Encoder 新特性

    本文指出,将BM25,向量检索Embedding模型后近似KNN相结合,可以让搜索引擎既能理解用户查询的字面意义,又能捕捉到查询的深层次语义,从而提供更全面、更精确的搜索结果。这种混合方法在现代搜索引擎中越来越普遍,因为它结合了传统搜索的精确性和基于AI的搜索的语义

    2024年02月03日
    浏览(59)
  • Elasticsearch 主副分片切换过程中对业务写入有影响吗

    🍊🍉🍋 先说下结论,只要集群中的工作节点过半,有候选的master节点,挂掉的节点中不同时包含索引的主分片和副分片,那么ES是可以做到让业务无感知的进行主副分片切换的。 蓝胖子会先讲解下ES集群写入文档的原理,并对异常情况进行分析,最后来模拟集群写入过程中

    2024年04月10日
    浏览(56)
  • BM25检索算法 python

    BM25(Best Matching 25)是一种经典的信息检索算法,是基于 TF-IDF算法的改进版本,旨在解决、TF-IDF算法的一些不足之处。其被广泛应用于信息检索领域的排名函数,用于估计文档D与用户查询Q之间的相关性。它是一种基于概率检索框架的改进,特别是在处理长文档和短查询时表

    2024年04月27日
    浏览(36)
  • Elasticsearch:如何使用集群级别的分片分配过滤(不包括节点)安全地停用节点

    当你想停用 Elasticsearch 中的节点时,通常的过程不是直接销毁节点。 如果你这样做,那么你就有数据丢失的风险,这不是你想要对应该是可靠的数据库做的事情。 这样做的问题是,节点很可能会通过 Elasticsearch 处理的恰当命名的分片分配分配给它们的分片。 Elasticsearch 中的

    2024年02月07日
    浏览(46)
  • 集成多元算法,打造高效字面文本相似度计算与匹配搜索解决方案,助力文本匹配冷启动[BM25、词向量、SimHash、Tfidf、SequenceMatcher]

    搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术细节以及项目实战(含码源) 专栏详细介绍:搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目

    2024年02月05日
    浏览(68)
  • BM20 数组中的逆序对

    描述 解题思路:归并排序 分治:分治即“分而治之”,“分”指的是将一个大而复杂的问题划分成多个性质相同但是规模更小的子问题,子问题继续按照这样划分,直到问题可以被轻易解决;“治”指的是将子问题单独进行处理。经过分治后的子问题,需要将解进行合并才

    2024年02月11日
    浏览(22)
  • Elasticsearch的集群负载均衡与分片分片

    Elasticsearch是一个分布式、实时的搜索和分析引擎,它可以处理大量数据并提供快速、准确的搜索结果。在大规模应用中,Elasticsearch的性能和可用性是关键因素。为了确保高性能和高可用性,Elasticsearch需要实现集群负载均衡和分片分片。 在本文中,我们将深入探讨Elasticsear

    2024年04月25日
    浏览(40)
  • 23.7.25 杭电暑期多校3部分题解

    题目大意 你有一个长度为 n n n 的序列,你每次可以向一个栈内放一个数,如果栈不为空并且栈顶的数大于你放的数,那么你放的数会变成栈顶的数再放入,问当栈的大小为 1 1 1 到 n n n 时分别有几种情况 解题思路 考虑dp, f i , j f_{i,j} f i , j ​ 表示放了 i i i 个数,最大的数

    2024年02月15日
    浏览(36)
  • ElasticSearch 数据分片

    一、ElasticSearch 分片 ElasticSearch集群中有许多个节点(Node),每一个节点实例就是一个实例;数据分布在分片之间。集群的容量和性能主要取决于分片如何在节点上如何分配。将数据分片是为了提高可处理的容量和易于进行水平扩展,为分片做副本是为了提高集群的稳定性和提高

    2024年02月03日
    浏览(40)
  • Elasticsearch 分片策略

    和数据库中的表空间类似,不过分片是为每个索引设置,一个索引可以有多个分片,分片分为主分片和副本分片,主分片和副本分片类似于数据库中的主库和备库。 主分片(shards):可以有一个或多个,但至少会有一个,默认为1。多个主分片类似于分表,可以提高大量数据

    2024年02月05日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包