GenQ

在我们的论文 BEIR: A Heterogeneous Benchmark for Zero-shot Evaluation of Information Retrieval Models 中,我们提出了一种方法,可以在没有标注训练数据的情况下,针对语料库调整模型以进行非对称语义搜索

背景

非对称语义搜索中,用户提供一个(短)查询,例如一些关键词或一个问题。我们希望检索提供答案的较长文本段落。

例如

query: What is Python?
passage to retrieve: Python is an interpreted, high-level and general-purpose programming language. Python's design philosophy emphasizes code readability with its notable use of significant whitespace. Its language constructs and object-oriented approach aim to help programmers write clear, logical code for small and large-scale projects.

我们在这里展示了如何在有足够训练数据(查询与相关段落)的情况下训练此类模型:训练 MS MARCO 数据集

在本教程中,我们将展示如何在没有训练数据可用的情况下训练此类模型,即如果您没有数千个标注的查询与相关段落对。

概述

我们使用合成查询生成来实现我们的目标。我们从文档集合中的段落开始,并为这些段落创建用户可能询问/搜索的可能查询。

Query Generation

例如,我们有以下文本段落

 Python is an interpreted, high-level and general-purpose programming language. Python's design philosophy emphasizes code readability with its notable use of significant whitespace. Its language constructs and object-oriented approach aim to help programmers write clear, logical code for small and large-scale projects.

我们将此段落传递给一个经过特殊训练的 T5 模型,该模型为我们生成可能的查询。对于上述段落,它可能会生成以下查询:

  • 什么是 python

  • python 定义

  • 什么语言使用空白字符

然后我们使用这些生成的查询来创建我们的训练集

(What is python, Python is an interpreted...)
(definition python, Python is an interpreted...)
(what language uses whitespaces, Python is an interpreted...)

并用它来训练我们的 SentenceTransformer 双编码器。

查询生成

BeIR 中,我们提供了可用于查询生成的不同模型。在此示例中,我们使用了由 docTTTTTquery 训练的 T5 模型。

from transformers import T5Tokenizer, T5ForConditionalGeneration
import torch

tokenizer = T5Tokenizer.from_pretrained("BeIR/query-gen-msmarco-t5-large-v1")
model = T5ForConditionalGeneration.from_pretrained("BeIR/query-gen-msmarco-t5-large-v1")
model.eval()

para = "Python is an interpreted, high-level and general-purpose programming language. Python's design philosophy emphasizes code readability with its notable use of significant whitespace. Its language constructs and object-oriented approach aim to help programmers write clear, logical code for small and large-scale projects."

input_ids = tokenizer.encode(para, return_tensors="pt")
with torch.no_grad():
    outputs = model.generate(
        input_ids=input_ids,
        max_length=64,
        do_sample=True,
        top_p=0.95,
        num_return_sequences=3,
    )

print("Paragraph:")
print(para)

print("\nGenerated Queries:")
for i in range(len(outputs)):
    query = tokenizer.decode(outputs[i], skip_special_tokens=True)
    print(f"{i + 1}: {query}")

在上述代码中,我们使用了Top-p(核)采样,它会从一组可能的词中随机选择一个词。因此,模型每次都会生成不同的查询。

Bi-Encoder 训练

有了生成的查询,我们就可以使用 MultipleNegativesRankingLoss 来训练一个双编码器。

完整示例

我们训练了一个语义搜索模型,用于搜索关于编程文章与技术的维基百科文章。

我们使用了以下维基百科文章中的文本段落:Assembly language, C, C#, C++, Go, Java, JavaScript, Keras, Laravel, MATLAB, Matplotlib, MongoDB, MySQL, Natural Language Toolkit, NumPy, pandas (software), Perl, PHP, PostgreSQL, Python, PyTorch, R, React, Rust, Scala, scikit-learn, SciPy, Swift, TensorFlow, Vue.js