该方法基于如下论文:
[2202.08904] SGPT: GPT Sentence Embeddings for Semantic Search (arxiv.org)
该方法用于基于上下文信息对使用BM2.5算法获得的检索结果进行重排序。
预训练在计算机视觉领域早已应用,NLP近些年随着BERT的出现也进入了预训练模型时代。
预训练模型优势:
学习上下文独立的静态词嵌入,应用到下游任务时需要重新训练,例如word2vec。
通过一个预训练的编码器能够输出上下文相关的词向量,解决一词多义的问题。这一类预训练编码器输出的向量称之为「上下文相关的词嵌入」。如GPT、BERT。
由于本文中提到的方法以GPT作为预训练模型,因此将着重介绍。
GPT是“Generative Pre-Training”的简称,从名字上就可以看出其是一个生成式的预训练模型。与ELMo不同的是,其采用多层Transformer Decoder作为特征抽取器,多项研究也表明,Transformer的特征抽取能力是强于LSTM的。
Prompt是一种为下游任务设计的”模板“,它可以帮助预训练模型回忆起自己在预训练时学习到的内容。pre-train、prompt、predict带来了nlp的第二次巨变。
比如,在该问题中我们可以选用这样的prompt:”我们的目的是找到与查询相关的文档,查询{query}最相关的文档是{doc}“。
如何设计和选择prompt会影响最终的性能表现。
作者在本文中提出了两种计算query和doc相关度的方法,Bi-Encorder和CrossEncoder。这两种方法都是基于GPT预训练模型。
在Cross-Encoder中,query和doc一起作为输入,模型输出可以衡量这种组合中语义的合理性。优点是可以充分利用大规模语料库中的语义信息,缺点在于对于不同doc,query需要重复被编码。
P(q)对于所有文档而言是一个常数,因此可以不考虑,而P(d)我们认为在语料库中近似相似,因此可以通过P(q|d)计算概率。
在实际使用时,作者使用prompt来计算P(q|d),即求解:
其中qi代表query的token,pi代表prompt的token。
最后使用,其中out_i代表query token所对应的输出,因为对于所有文档而言,query是相等长度的,因此无需进行归一化。
∑ l o g ( s o f t m a x ( o u t i ) ) \sum{log(softmax(out_i))} ∑log(softmax(outi))
该值一定是负数,其越接近0,代表query和doc相关度越高。
在bi-Encoder中,query和doc被分别输入,然后计算embedding编码的余弦相似度。这种方法query只需编码一次,但是分别编码的query和doc不能充分利用大规模语料库的信息。
在Bert模型中,句子的编码常常使用[cls]符对应位置的编码来替代,这是因为Bert可以看到双向信息,即便[cls]在句子开始处,只要设置恰当的训练任务就可以编码语义信息。然而GPT模型只能看到单向的信息,因此常见的做法是使用最后一个token的编码和编码整个句子的信息。
然而,和单个token的编码相比,平均池化(mean-pooling)通常会有更好的表现,在本文中作者针对GPT模型提出了一种加权池化的方法。
其中hi代表第i个token的隐藏层输出。从上述公式中可以看出,越靠后的token权重越大。作者指出,由于GPT只能单向编码,因此越靠后的token蕴含越多的语义信息。
目前想到的解决方法包括:
1、使用bert代替GPT,但不期待其效果理想,因为GPT是为文本生成任务设计的语言模型,而bert用于文本分类和fill mask的任务,对于Cross-Encoder需要表征query和doc搭配的合理性,显然用于文本生成的GPT更胜一筹。
2、将中文翻译成英文,然后作为模型输入。
Prompt的设计会极大的影响最终效果。对于一个Prompt可能出现在A任务上的性能好,但在B任务上表现极差的情况。比较直观的策略是设计几个不同的Prompt然后对结果进行平均。