检索 & 重排序
在 语义搜索 中,我们展示了如何使用 SentenceTransformer 计算查询、句子和段落的嵌入,以及如何将其用于语义搜索。对于复杂的搜索任务,例如问答检索,通过使用检索 & 重排序可以显著提高搜索效果。
检索 & 重排序 Pipeline
以下信息检索 / 问答检索的 Pipeline 工作效果非常好。本文提供了所有组件并对其进行了解释
给定一个搜索查询,我们首先使用检索系统来检索大量的潜在命中结果列表,例如 100 个,这些结果可能与查询相关。对于检索,我们可以使用词汇搜索,例如使用像 Elasticsearch 这样的向量引擎,或者我们可以使用带有 SentenceTransformer
(也称为 bi-encoder)的密集检索。但是,检索系统可能会检索到与搜索查询不太相关的文档。因此,在第二阶段,我们使用基于 CrossEncoder
的重排序器,该重排序器对给定搜索查询的所有候选结果的相关性进行评分。输出将是我们呈现给用户的命中结果排名列表。
检索:Bi-Encoder
为了检索候选集,我们可以使用词汇搜索(例如 Elasticsearch),或者我们可以使用 Sentence Transformers 中实现的 bi-encoder。
词汇搜索在您的文档集合中查找查询词的字面匹配项。它不会识别同义词、首字母缩写词或拼写变体。相比之下,语义搜索(或密集检索)将搜索查询编码到向量空间中,并检索在向量空间中接近的文档嵌入。
语义搜索克服了词汇搜索的缺点,可以识别同义词和首字母缩写词。请查看 语义搜索文章,了解实现语义搜索的不同选项。
重排序器:Cross-Encoder
检索器必须对数百万条条目的大型文档集合有效。但是,它可能会返回不相关的候选结果。基于 Cross-Encoder 的重排序器可以大大提高用户的最终结果。查询和可能的文档同时传递到 Transformer 网络,然后网络输出 0 到 1 之间的单个分数,指示文档与给定查询的相关程度。
Cross-Encoder 的优势在于更高的性能,因为它们在查询和文档之间执行注意力机制。对成千上万或数百万个(查询,文档)对进行评分会相当慢。因此,我们使用检索器创建一个例如 100 个可能的候选结果的集合,然后由 Cross-Encoder 对其进行重排序。
示例脚本
retrieve_rerank_simple_wikipedia.ipynb [ Colab 版本 ]:此脚本使用较小的 Simple English Wikipedia 作为文档集合,以提供用户问题/搜索查询的答案。首先,我们将所有 Wikipedia 文章拆分为段落,并使用 bi-encoder 对其进行编码。如果输入新的查询/问题,则由相同的 bi-encoder 对其进行编码,并检索具有最高余弦相似度的段落(请参阅 语义搜索)。接下来,由 Cross-Encoder 重排序器对检索到的候选结果进行评分,并将来自 Cross-Encoder 的得分最高的 5 个段落呈现给用户。
in_document_search_crossencoder.py: 如果您只有一小部分段落,我们不会进行检索阶段。例如,如果您想在单个文档中执行搜索,则就是这种情况。在此示例中,我们采用关于欧洲的 Wikipedia 文章并将其拆分为段落。然后,使用 Cross-Encoder 重排序器对搜索查询/问题和所有段落进行评分。返回与查询最相关的段落。
预训练 Bi-Encoders(检索)
bi-encoder 为您的段落和搜索查询独立生成嵌入。您可以像这样使用它
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("multi-qa-mpnet-base-dot-v1")
docs = [
"My first paragraph. That contains information",
"Python is a programming language.",
]
document_embeddings = model.encode(docs)
query = "What is Python?"
query_embedding = model.encode(query)
有关如何比较嵌入的更多详细信息,请参阅 语义搜索。
我们提供基于以下内容的预训练模型
MS MARCO: 来自 Bing 搜索引擎的 50 万个真实用户查询。请参阅 MS MARCO 模型
预训练 Cross-Encoders(重排序器)
有关预训练 Cross Encoder 模型,请参阅:MS MARCO Cross-Encoders