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 (nucleus) 采样,它将从一组可能的词中随机选择一个词。因此,模型每次都会生成不同的查询。

双编码器训练

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

完整示例

我们训练一个语义搜索模型来搜索有关编程文章和技术的维基百科文章。

我们使用以下维基百科文章中的文本段落:汇编语言、C、C#、C++、Go、Java、JavaScript、Keras、Laravel、MATLAB、Matplotlib、MongoDB、MySQL、自然语言工具包、NumPy、pandas (软件)、Perl、PHP、PostgreSQL、Python、PyTorch、R、React、Rust、Scala、scikit-learn、SciPy、Swift、TensorFlow、Vue.js。