本文约2700字,建议阅读5分钟
本文解读双编码器和交叉编码器。
在信息检索领域(即从海量数据中查找相关信息),双编码器和交叉编码器是两种至关重要的工具。它们各自拥有独特的工作机制、优势和局限性。章的第二篇,本文将深入探讨这两种核心技术。双编码器:高效的大规模检索
双编码器分别处理文档和搜索查询。可以将其类比为两个人独立工作:一人负责概括文档,另一人则专注于搜索查询,两者之间互不交流。“双”字体现了查询和文档的独立编码过程。用户查询和文档向量嵌入使用相同的嵌入模型计算,但两者完全隔离。双编码器尤其适用于需要大规模实时检索的场景,例如搜索引擎或大型知识库。
双编码器的关键特性
优势
局限性
交叉编码器:精准的相关性评估
交叉编码器将搜索查询和每个文档一同进行比对,如同一个人仔细地逐一比较两份文本。这种方法通常能更准确地评估相关性,使交叉编码器在需要高精度语义匹配的任务中极具价值。交叉编码器将两个文本片段(例如,用户查询和文档)同时作为输入。它不分别生成向量表示,而是输出 0 到 1 之间的值,表示输入对的相似度。交叉编码器在高精度至关重要的任务中尤其重要,例如在最终文档重排序阶段,或在语义匹配的准确性至关重要时。
交叉编码器的关键方面
优势
局限性
如何选择
使用的代码示例
假设有四个句子 A、B、C 和 D,需要比较所有可能的配对:- 交叉编码器需要编码所有可能的配对,共需编码六次(AB、AC、AD、BC、BD、CD)。
假设有 100,000 个句子,需要比较所有可能的配对:- 交叉编码器将编码 4,999,950,000 对(根据组合公式:n! / (r!(n-r)!),其中 n=100,000 且 r=2)。因此,交叉编码器的扩展性较差,在大规模数据集上计算成本过高。
使用交叉编码器进行语义相似度检测的实际应用:尽管双编码器也可以完成此任务,但交叉编码器在牺牲一定处理速度的情况下能提供更高的准确性。以下演示将使用微软的预训练模型 MS MARCO,通过两个句子对进行说明。模型输出一个分数,分数越高表示句子之间的语义相似度越高。
from sentence_transformers import CrossEncoder
model = CrossEncoder('cross-encoder/ms-marco-TinyBERT-L-2-v2', max_length=512)
sentence_pairs = [
('How many people live in Berlin?', 'Berlin had a population of 3,520,031 registered inhabitants in an area of 891.82 square kilometers.'),
('How many people live in Berlin?', 'Berlin is well known for its museums.')
]
scores = model.predict(sentence_pairs)
print(scores)
下面的代码片段演示了如何使用双编码器进行语义相似性搜索。模型将查询和语料库编码成嵌入向量,然后执行相似性搜索以找到最相关的段落。结果显示前 k 个匹配项(此处 k=25),每个匹配项包含语料库 ID 和相似度分数: from sentence_transformers import SentenceTransformer, util
bi_encoder = SentenceTransformer('multi-qa-MiniLM-L6-cos-v1')
bi_encoder.max_seq_length = 256
corpus_embeddings = bi_encoder.encode(chunks, convert_to_tensor=True, show_progress_bar=True)
query = "what is rlhf?"
query_embedding = bi_encoder.encode(query, convert_to_tensor=True).cuda()
top_k = 25
hits = util.semantic_search(query_embedding, corpus_embeddings, top_k=top_k)[0]
print(hits)
使用高召回率但低精度的双编码器获取最相似的文本块后,可以通过第二阶段使用交叉编码器模型对结果进行重排序,利用其更高的准确性来优化结果。 from sentence_transformers import CrossEncoder
cross_encoder = CrossEncoder('cross-encoder/ms-marco-MiniLM-L-6-v2')
cross_inp = [[query, chunks[hit['corpus_id']]] for hit in hits]
cross_scores = cross_encoder.predict(cross_inp)
print(cross_scores)
代码使用交叉编码器模型对双编码器识别的查询-文本块对重新评分。交叉编码器提供更准确的相似度分数,从而实现更精细的排序。这种两阶段方法结合了双编码器在初始检索阶段的高效性和交叉编码器在最终排序阶段的高精度,为语义搜索任务提供了一种均衡的解决方案。总结
双编码器和交叉编码器在现代信息检索中都扮演着至关重要的角色。双编码器提供速度和效率,是进行大规模初始搜索的理想选择。交叉编码器提供精度和深度,非常适合优化结果和处理复杂查询。理解它们的优势和局限性有助于构建能够同时处理广泛和细致信息需求的高效搜索系统。数据派THU作为数据科学类公众号,背靠清华大学大数据研究中心,分享前沿数据科学与大数据技术创新研究动态、持续传播数据科学知识,努力建设数据人才聚集平台、打造中国大数据最强集团军。
新浪微博:@数据派THU
微信视频号:数据派THU
今日头条:数据派THU