GenQ

在我们的论文 BEIR: 信息检索模型零样本评估的异构基准 中,我们提出了一种方法,用于调整模型以适应 非对称语义搜索,而无需使用没有标记训练数据的语料库。

背景

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

例如

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 bi-encoder。

查询生成

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

Bi-Encoder 训练

使用生成的查询,我们可以使用 MultipleNegativesRankingLoss 训练 bi-encoder。

完整示例

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

我们使用以下维基百科文章中的文本段落:汇编语言、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