混合搜索的好处
#showdev #python #machinelearning #nlp

语义搜索是基于自然语言处理(NLP)最新进展的新类别。传统搜索系统使用关键字查找数据。语义搜索对自然语言有了解,并确定具有相同含义的结果,不一定是相同的关键字。

虽然语义搜索增加了惊人的功能,但稀疏关键字索引仍然可以增加值。在某些情况下,找到确切匹配很重要,或者我们只希望快速索引快速进行数据集的初始扫描。

两种方法都有其优点。如果我们将它们结合在一起以构建统一的hybrid搜索功能怎么办?我们可以两全其美吗?

本文将探讨混合搜索的好处。

安装依赖项

安装txtai和所有依赖项。

# Install txtai
pip install txtai pytrec_eval rank-bm25 elasticsearch

引入语义,关键字和混合搜索

在潜入基准之前,让我们简要讨论语义和关键字搜索的工作原理。

语义搜索使用大型语言模型将输入量化为数字数组。类似的概念将具有相似的值。向量通常存储在矢量数据库中,该数据库是一个专门用于存储这些数值和查找匹配的系统。向量搜索将输入查询转换为向量,然后运行搜索以找到最佳的概念结果。

关键字搜索将文本标记为每个文档的令牌列表。这些令牌汇总到每个文档的令牌频率中,并以期限稀疏阵列存储。在搜索时间,查询被令牌化,并将查询的令牌与数据集中的令牌进行了比较。这是一个字面的过程。关键字搜索就像字符串匹配一样,它没有概念上的理解,它匹配字符和字节。

混合搜索结合了语义和关键字索引的分数。鉴于语义搜索分数通常为0-1,并且关键字搜索分数是无限的,因此需要一种方法来结合结果。

TXTAI支持的两种方法是:

TXTAI中的默认方法是凸组合,我们将使用它。

评估性能

现在是时候对结果进行基准测试了。对于这些测试,我们将使用Beir数据集。我们还将使用TXTAI项目中的benchmarks script。此基准测试脚本具有与Beir DataSet合作的方法。

我们将为简洁选择Beir源的子集。对于每个来源,我们将基准为bm25索引,​​embeddings索引和hybrid或组合索引。

import os

# Get benchmarks script
os.system("wget https://raw.githubusercontent.com/neuml/txtai/master/examples/benchmarks.py")

# Create output directory
os.makedirs("beir", exist_ok=True)

# Download subset of BEIR datasets
datasets = ["nfcorpus", "fiqa", "arguana", "scidocs", "scifact"]
for dataset in datasets:
  url = f"https://public.ukp.informatik.tu-darmstadt.de/thakur/BEIR/datasets/{dataset}.zip"
  os.system(f"wget {url}")
  os.system(f"mv {dataset}.zip beir")
  os.system(f"unzip -d beir beir/{dataset}.zip")

  # Remove existing benchmark data
if os.path.exists("benchmarks.json"):
  os.remove("benchmarks.json")

现在让我们运行基准。

# Remove existing benchmark data
if os.path.exists("benchmarks.json"):
  os.remove("benchmarks.json")

# Runs benchmark evaluation
def evaluate(method):
  for dataset in datasets:
    command = f"python benchmarks.py beir {dataset} {method}"
    print(command)
    os.system(command)

# Calculate benchmarks
for method in ["bm25", "embed", "hybrid"]:
  evaluate(method)
import json
import pandas as pd

def benchmarks():
  # Read JSON lines data
  with open("benchmarks.json") as f:
    data = f.read()

  df = pd.read_json(data, lines=True).sort_values(by=["source", "ndcg_cut_10"], ascending=[True, False])
  return df[["source", "method", "ndcg_cut_10", "map_cut_10", "recall_10", "P_10", "index", "search", "memory"]].reset_index(drop=True)

# Load benchmarks dataframe
df = benchmarks()
df[df.source == "nfcorpus"].reset_index(drop=True)
来源 方法 ndcg_cut_10 map_cut_10 recome_10 p_10 索引 搜索 记忆
nfcorpus 混合动力 0.34531 0.13369 0.17437 0.25480 29.46 3.57 2900
nfcorpus 嵌入 0.30917 0.10810 0.15327 0.23591 33.64 3.33 2876
nfcorpus BM25 0.30639 0.11728 0.14891 0.21734 2.72 0.96 652
df[df.source == "fiqa"].reset_index(drop=True)
来源 方法 ndcg_cut_10 map_cut_10 recome_10 p_10 索引 搜索 记忆
fiqa 混合动力 0.36642 0.28846 0.43799 0.10340 233.90 68.42 3073
fiqa 嵌入 0.36071 0.28450 0.43188 0.10216 212.30 58.83 2924
fiqa BM25 0.23559 0.17619 0.29855 0.06559 19.78 12.84 76
df[df.source == "arguana"].reset_index(drop=True)
来源 方法 ndcg_cut_10 map_cut_10 recome_10 p_10 索引 搜索 记忆
arguana 混合动力 0.48467 0.40101 0.75320 0.07532 37.80 21.22 2924
arguana 嵌入 0.47781 0.38781 0.76671 0.07667 34.11 10.21 2910
arguana BM25 0.45713 0.37118 0.73471 0.07347 3.39 10.95 663
df[df.source == "scidocs"].reset_index(drop=True)
来源 方法 ndcg_cut_10 map_cut_10 recome_10 p_10 索引 搜索 记忆
Scidocs 嵌入 0.21718 0.12982 0.23217 0.1146 127.63 4.41 2929
Scidocs 混合动力 0.21104 0.12450 0.22938 0.1134 138.00 6.43 2999
Scidocs BM25 0.15063 0.08756 0.15637 0.0772 13.07 1.42 722
df[df.source == "scifact"].reset_index(drop=True)
来源 方法 ndcg_cut_10 map_cut_10 recome_10 p_10 索引 搜索 记忆
scifact 混合动力 0.71305 0.66773 0.83722 0.09367 39.51 2.35 2918
scifact BM25 0.66324 0.61764 0.78761 0.08700 4.40 0.93 658
scifact 嵌入 0.65149 0.60193 0.78972 0.08867 35.15 1.48 2889

上面的部分显示了每个源和方法的指标。

表标头列出了source (dataset)index methodNDCG@10/MAP@10/RECALL@10/RECALL@10/P@10精度指标,index time(s)search time(s)memory usage(MB)。表由NDCG@10降序排序。

查看结果,我们可以看到hybrid搜索通常比单独的embeddingsbm25更好。在某些情况下,与SCIDOC一样,组合的性能较差。但是在总体上,得分更好。这对于整个Beir数据集都是正确的。对于某些来源,bm25表现最好,有些embeddings,但总体而言,hybrid的总分表现最好。

混合搜索不是免费的,它较慢,因为它具有额外的逻辑来结合结果。对于单个查询,结果通常可以忽略不计。

包起来

本笔记本涵盖了使用混合方法提高搜索准确性的方法。我们评估了Beir数据集子集的性能,以显示在许多情况下混合搜索如何提高整体准确性。

也可以使用此方法作为specified in this link来评估自定义数据集。本笔记本和关联的基准测试脚本可以重复使用以评估哪种方法最适合您的数据。