使用 Maximum Marginal Relevance 实现搜索结果多样化

作者:来自 Elastic Peter Straßer

使用 Elasticsearch 和 Python 实现 Maximum Marginal Relevance (MMR)算法。这个博客包含用于向量搜索重排的代码示例。

Elasticsearch 拥有大量新功能,能帮助你为你的使用场景构建最佳搜索解决方案。浏览我们的示例 notebooks 了解更多内容,开始免费云试用,或在本地机器上试用 Elastic。


当你在电商目录中搜索 "pants" 时,你真的想看到 10 条相同的黑色七分裤吗?可能不是。你更可能希望看到展示不同款式、颜色和类型裤子的多样化选择。这正是 Maximum Marginal Relevance (MMR)发挥作用的地方 ------ 一种在搜索结果中平衡相关性和多样性的强大技术。

在这篇博客中,我们将探讨如何使用 Elasticsearch 实现 MMR,以创建更加多样且实用的搜索结果,并以一个时尚商品目录作为示例。

问题:当相关性不再足够

传统搜索系统只优化一个目标:相关性。它们寻找最符合查询的内容,并按相似度得分进行排序。这在很多场景下效果很好,但可能会导致结果冗余。

比如在一个时尚目录中搜索 "pants",纯粹基于相关性的搜索可能会返回:

  • Black capris (score: 0.682)
  • Black capris from another brand (score: 0.681)
  • More black capris (score: 0.680)
  • Even more black capris (score: 0.680)
  • ...you get the idea

虽然这些结果与 "pants" 的确高度相关,但对用户想要浏览不同选择来说,并没有太大帮助。我们需要的是:在保持相关性的同时,引入多样性

引入最大边际相关性(Maximum Marginal Relevance - MMR)

MMR 是一种优雅地解决上述问题的算法,它在两个相互竞争的目标之间取得平衡:

  • 相关性:项目与查询匹配的程度

  • 多样性:项目之间彼此的差异程度

该算法以迭代方式工作:每次选择那些既与查询高度相关,又与已选项目有明显差异的结果。

这能确保每一个新增结果都带来新的信息 ,而不是重复内容

MMR 如何运作

MMR 算法遵循一个简单但有效的流程:

  1. 从得分最高的项目开始
  2. 对每个剩余项目,计算一个 MMR 分数,结合:它与查询的相关性,以及它与已选项目的差异性
  3. 选择 MMR 分数最高的项目
  4. 重复此过程,直到获得足够的结果

关键在于 MMR 的评分公式:

ini 复制代码
`MMR Score = λ × relevance - (1 - λ) × max_similarity_to_selected`AI写代码

λ 参数控制这种权衡,其中 λ = 1.0 表示纯相关性(无多样性),而 λ = 0.0 表示纯多样性(忽略相关性)。

MMR 并不规定你如何计算相关性 ------ 它只需要一个分数。这个分数可以来自 BM-25、一个学习排序器,或任何你喜欢的自定义指标。由于 BM-25 依赖于保存在 postings 列表中的每个词项的统计信息,而这些信息在客户端不可用,因此我们将在本文中使用向量相似度作为我们的相关性函数。这样我们可以通过点积优雅地计算相关性。

MMR 的实现

我们来看如何使用 Elasticsearch 和多模态嵌入实现一个图像搜索系统中的 MMR。为了展示 MMR 的效果,我们将使用 paramaggarwal/fashion-product-images-dataset 数据集。

本文将只关注检索和重排序部分,但你可以在我们的 search-labs GitHub 仓库 里找到一个完整的端到端示例

首先,我们需要使用向量相似度搜索相似的项目:

python 复制代码
`

1.  def search_similar_images(es, index_name, query_vector, k=10):
2.      """Search for similar images using vector similarity"""
3.      query = {
4.          "knn": {
5.              "field": "image_vector",
6.              "query_vector": query_vector,
7.              "k": k
8.          },
9.          "_source": ["id", "image_url"],
10.          "size": k
11.      }

13.      response = es.search(index=index_name, body=query)
14.      return extract_results(response)

`AI写代码![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

这为我们提供了初始的相关性排序结果。现在,让我们应用 MMR 对它们进行重排序以提升多样性:

ini 复制代码
`

1.  def maximal_marginal_relevance(
2.      query_embedding: List[float],
3.      embedding_list: List[List[float]],
4.      lambda_mult: float = 0.5, # value between 0.0 and 1.0
5.      k: int = 4,
6.  ) -> List[int]:
7.      query_embedding_arr = np.array(query_embedding)

9.      if min(k, len(embedding_list)) <= 0:
10.          return []
11.      if query_embedding_arr.ndim == 1:
12.          query_embedding_arr = np.expand_dims(query_embedding_arr, axis=0)

14.      # calcuate the similarity to the query for all reranking candidates
15.      similarity_to_query = _cosine_similarity(query_embedding_arr, embedding_list)[0]
16.      # start with the most similar item to the query
17.      most_similar = int(np.argmax(similarity_to_query))
18.      idxs = [most_similar]
19.      selected = np.array([embedding_list[most_similar]])

21.      # Iteratively select documents that maximize MMR score
22.      while len(idxs) < min(k, len(embedding_list)):
23.          best_score = -np.inf
24.          idx_to_add = -1

26.  	   # calulate the similarity between all candidate items and all selected items
27.          similarity_to_selected = _cosine_similarity(embedding_list, selected)

29.  	   # look at all candidates 
30.          for i, query_score in enumerate(similarity_to_query):
31.              if i in idxs:
32.                  continue

34.  		 # Find the highest similarity of this item to already selected items
35.              redundant_score = max(similarity_to_selected[i])
36.  		 # Calculate MMR score
37.              equation_score = (lambda_mult * query_score - (1 - lambda_mult) * redundant_score)

39.  		 # select this item if it has the highest MMR score for this run
40.              if equation_score > best_score:
41.                  best_score = equation_score
42.                  idx_to_add = i

44.          # append the item with the highest MMR score for this run to our list  
45.          idxs.append(idx_to_add)
46.          selected = np.append(selected, [embedding_list[idx_to_add]], axis=0)
47.      return idxs

`AI写代码![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

github.com/elastic/ela...

影响:MMR 前后对比

来看一下 MMR 如何改变查询 "裤子" 的搜索结果:

MMR 之前(纯相关性)

注意到重复了吗?我们看到大多数商品都是深色、直筒剪裁。

MMR 之后(λ = 0.5)

重排序后的结果在颜色、品牌、目标人群、风格等多方面展示了多样性。每个结果都带来了新信息,使浏览体验更有价值。

为你的场景调整 MMR

MMR 的优点在于可调节性。通过调整 λ 参数,你可以将算法适配不同场景:

  • 产品发现(λ=0.3-0.5):强调多样性,帮助用户探索更多选项

  • 精准搜索(λ=0.7-0.9):优先相关性,适合用户明确需求时

  • 研究应用(λ=0.5-0.7):平衡相关性和覆盖范围

你甚至可以根据以下情况动态调整 λ:

  • 查询类型(广泛 vs. 具体)

  • 用户行为(浏览 vs. 购买)

  • 结果集特征(高相似度 vs. 低相似度)

性能考虑

虽然 MMR 带来显著价值,但计算成本也不可忽视。算法需要计算候选项与已选项之间的相似度。对于生产系统,建议将重排序深度限制在结果前 k 项,以平衡效果和性能。同时,检索向量会影响性能,因为这需要序列化大量数据。

超越电商:其他应用

虽然我们关注的是时尚产品和传统搜索栏结果列表,MMR 具有广泛应用。当使用检索增强生成(RAG)应用时,查询 "great vacation spots" 如果不多样化,可能只返回希腊海滩相关结果。MMR 则会让结果涵盖多种度假类型,从希腊的海滩度假到冰岛火山徒步。其他应用包括:

  • 新闻聚合:展示来自不同来源和视角的文章

  • 文档搜索:呈现覆盖话题不同方面的文档

  • 推荐系统:推荐多样化的电影、音乐或内容

  • 学术搜索:查找来自不同研究团队和方法的论文

  • 以及更多

总结

最大边际相关性(MMR)将搜索从单纯的相关性竞赛转变为平衡的信息检索系统。通过在 Elasticsearch 中实现 MMR,你可以提供不仅相关且信息丰富、多样化的搜索结果。

关键是找到适合你场景的平衡。初始可以用 λ=0.7 侧重相关性,然后根据用户反馈和行为进行调整。你的用户会更喜欢看到多样且相关的选项,而不是同质化的轻微变体。

有时候,与其选择另一个重复的完美匹配,不如选择第二佳但不同的匹配。那就是搜索中多样性的力量。

原文:Diversifying search results with Maximum Marginal Relevance - Elasticsearch Labs

相关推荐
1.01^10009 小时前
[2-02-02].第03节:环境搭建 - Win10搭建ES集群环境
elasticsearch
张先shen11 小时前
Elasticsearch RESTful API入门:全文搜索实战(Java版)
java·大数据·elasticsearch·搜索引擎·全文检索·restful
Elastic 中国社区官方博客11 小时前
Elasticsearch 字符串包含子字符串:高级查询技巧
大数据·数据库·elasticsearch·搜索引擎·全文检索·lucene
张先shen12 小时前
Elasticsearch RESTful API入门:全文搜索实战
java·大数据·elasticsearch·搜索引擎·全文检索·restful
2201_7567767712 小时前
网络安全初级
大数据·elasticsearch·搜索引擎
张先shen14 小时前
Elasticsearch RESTful API入门:索引的增删改查完全指南
java·大数据·elasticsearch·搜索引擎·架构·全文检索·restful
重生之后端学习15 小时前
day08-Elasticsearch
后端·elasticsearch·spring cloud·中间件·全文检索·jenkins
Elasticsearch16 小时前
全领域的 AI 采用:主要用例和需避免的错误
elasticsearch
oneslide21 小时前
elasticsearch备份恢复
大数据·elasticsearch·搜索引擎