GenQ

在我们的论文 BEIR: 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

  • definition 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。

完整示例

我们训练一个语义搜索模型,以搜索关于编程文章和技术的 Wikipedia 文章。

我们使用以下 Wikipedia 文章中的文本段落: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