写点什么

语义检索效果差?深度学习 rerank VS 统计 rerank 选哪个

作者:Zilliz
  • 2025-01-17
    上海
  • 本文字数:11663 字

    阅读完需:约 38 分钟

语义检索效果差?深度学习rerank VS 统计rerank选哪个

前段时间我开发了一个用白话文搜索语义相近的古诗词的应用(详见: 《朋友圈装腔指南:如何用向量数据库把大白话变成古诗词》),但是有时候搜索结果却不让人满意,排名靠前的结果和查询的语义没啥关系,靠后的结果反而和查询更相似。比如,我用白话文“今天的雨好大”搜索,前三个结果是:


今日云景好,水绿秋山明。


今日风日好,明日恐不如。


雨落不上天,水覆难再收。


前两个都和雨没有关系,第三个勉强沾边。


为啥语义更相近的句子,反而排名靠后呢?主要有两个原因,一个是“不理解”,另一个是“难精确”。


“不理解”和嵌入模型有关。我使用的嵌入模型可能训练语料中古诗词较少,导致它不能很好地“理解”古诗词的语义。


“难精确”指的是不论你的度量方法使用的是余弦相似度(Cosine),还是欧几里得距离(L2),都不能保证语义最相似的结果一定排在第一。这些方法都是简化的模型,句子的语义内涵很难只用中学数学知识就能准确计算,只能说在整体趋势上,得分越高的结果语义和查询越接近。这就好像深圳入冬后,我们预测温度在 10-20°C 之间,这样的预测整体来说是正确的,但是具体到每一天的温度就不一定准确了,可能有那么一两天,温度升到了 25°C。


这样的预测相当于语义搜索中的初步搜索,叫做“粗排”。想要优化搜索结果,重新排名,还需要“重排”,也就是 rerank。


除此之外,还有一种情况下也需要重排,那就是混合搜索。我在 《外行如何速成专家?Embedding之BM25、splade稀疏向量解读》 这篇文章中介绍了稀疏向量,稠密向量和稀疏向量各有优势,怎么各取所长呢?可以先分别搜索(也就是混合搜索),再用搜索结果综合起来,而重排就是一种综合多种搜索结果的方法。


这两种重排有所区别,第一种是基于深度学习的重排,第二种是基于统计的重排。第二种原理更简单,我们先来了解第二种。[^1]

基于统计的重排

基于统计的重排用于混合搜索,它可以把多种搜索结果综合起来,重新排序。除了前面介绍的稠密向量和稀疏向量,还可以综合文本向量和图片向量。


怎么综合呢?有两种方法,一种是 WeightedRanker ——分数加权平均算法,通过设置权重计算得分,后面简称权重策略。另一种是 RRFRanker(Reciprocal Rank Fusion)——逆序排名融合算法,通过排名的倒数来计算得分,后面简称 RRF 策略。

权重策略

权重策略就是设置权重。权重值范围从 0 到 1,数值越大表示重要性越大。计算方法很简单,初始得分乘以权重,就是最终得分。^2



打个比方,假设某班级考了语文和数学两门课,统计出学生每门科目的分数和排名。学生就相当于向量数据库中的文档,学生这两门课的分数,就相当于文档在不同搜索结果中的得分。


假设学生的成绩如下表所示:



在权重策略下,综合得分公式为:


根据公式计算出学生们的综合分数,排名如下:


RRF 策略

RRF 策略的计算方式稍微复杂一点:



公式中的 rank 是初始分数的排名,k 是平滑参数。从公式中可以看出,排名越靠前,rank 的值越小,综合得分越高。同时, k 的值越大,排名对分数的影响越小。


我们使用 RRF 策略重新计算分数和排名。参数 k 一般为 60,为方便演示,这里设为 10,公式变成:



RRF 策略根据排名计算分数,所以我们先列出数学和语文的排名。


数学成绩排名:



语文成绩排名:



接下来使用 RRF 策略计算综合得分,重新排名:



比较两个排名可以发现,在权重策略下,数学的权重较大,偏科学生 S1 虽然语文只有 50 分,也能因为数学 100 分而排在第一名。而 RRF 策略注重的是各科的排名,而不是分数,所以 S1 的数学虽然排名第一,但是语文排名第 10,综合排名下降到第三。


学生 S7 正好相反,在权重策略下,即使他语文得了 85 的高分,但是权重只占 30%,而高权重的数学只得了 70 分,所以综合排名靠后,排在第六名。在 RRF 策略下,他的数学和语文排名分别是第六名和第二名,语文的高排名拉高了综合排名,上升到了第一名。


通过比较两种策略的排名结果,我们发现了这样的规律,如果你更看重搜索结果的得分,就使用权重策略,你还可以通过调整权重来调整得分;如果你更看重搜索结果的排名,就使用 RRF 策略。

基于深度学习的重排

和基于统计的重排相比,基于深度学习的重排更加复杂,通常被称为 Cross-encoder Reranker,交叉编码重排,后面简称“重排模型”。


粗排和重排模型有什么区别呢?粗排搜索速度更快,重排模型准确性更高。


为什么粗排搜索速快?粗排使用的是双塔模型(Dual-Encoder),“双塔”指的是它有两个独立的编码器,分别把查询和文档向量化,然后通过计算向量之间的相似度(比如余弦相似度 Cosine)搜索结果并且排序。双塔模型的优势在于搜索效率高,因为可以提前计算文档向量,搜索时只需要向量化查询即可。而重排模型则是在搜索时现场编码。就好比两个饭店,一个使用预制菜,一个现场热炒,上菜速度肯定不一样。


重排模型的优势则是准确性高。它把查询和文档组成数据对后输入给编码器编码,然后给它们的相似程度打分,针对性强。这就相当于公司招聘人才,粗排是根据专业、学历和工作年限等几个指标快速筛选简历,挑选出多位候选者。重排则是通过面试详细了解候选者做过什么项目,遇到了什么挑战,解决了什么难题,然后判断他有多适合应聘的岗位(文档与查询有多相似)。



图片来源:自制


所以,重排模型适合那些对回答准确性要求高的场景,比如专业知识库或者客服系统。不适合追求高响应速度和低成本的场景,比如网页搜索、电商,这种场景建议使用基于统计的重排。


你还可以把粗排和重排模型结合起来。比如,先通过粗排筛选出 10 个候选结果,再用重排模型重新排名。既可以提高搜索速度,也能保证准确度。

代码实践

版本说明:


  • Milvus 版本:2.5.0

  • pymilvus:2.5.0


接下来我们通过代码实践一下,看看这些重排方法实际效果到底如何。


我们会使用“敏捷的狐狸跳过懒惰的狗。”作为查询,从下面 10 个句子中搜索出语义相似的句子。你可以先猜一猜,粗排、基于统计的重排以及基于深度学习的重排,哪个效果最好。


文档:


[        {"content": "灵活的狐跳过了懒散的犬。"},        {"content": "一只敏捷的狐在公园里跳过了那只懒犬。"},        {"content": "那只懈怠的犬正在大树下睡觉。"},        {"content": "在公园里,那只棕色的狐狸正在跳。"},        {"content": "犬跃过了狐。"},        {"content": "树下有一个小池塘。"},        {"content": "动物如狗和狐狸生活在公园里。"},        {"content": "池塘靠近公园里的大树。"},        {"content": "懒狗跳过了狐狸。"},        {"content": "那只灵巧的狐狸轻松地跨过了那只懒散的狗。"},        {"content": "狐迅速地跳过了那只不活跃的犬。"}]
复制代码


首先创建集合。我们为集合设置稠密向量“dense_vector”和稀疏向量“sparse_vector”两个字段,分别储存稠密向量和稀疏向量,用于混合搜索。


from pymilvus import MilvusClient, DataTypeimport time
def create_collection(collection_name): # 检查同名集合是否存在,如果存在则删除 if milvus_client.has_collection(collection_name): print(f"集合 {collection_name} 已经存在") try: # 删除同名集合 milvus_client.drop_collection(collection_name) print(f"删除集合:{collection_name}") except Exception as e: print(f"删除集合时出现错误: {e}") # 创建集合模式 schema = milvus_client.create_schema( auto_id=True, enable_dynamic_field=True, num_partitions=16, description="" ) # 添加字段到schema schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True, max_length=256) schema.add_field(field_name="content", datatype=DataType.VARCHAR, max_length=256) # 添加稠密向量字段 schema.add_field(field_name="dense_vector", datatype=DataType.FLOAT_VECTOR, dim=1024) # 添加稀疏向量字段 schema.add_field(field_name="sparse_vector", datatype=DataType.SPARSE_FLOAT_VECTOR) # 创建集合 try: milvus_client.create_collection( collection_name=collection_name, schema=schema, shards_num=2 ) print(f"创建集合:{collection_name}") except Exception as e: print(f"创建集合的过程中出现了错误: {e}") # 等待集合创建成功 while not milvus_client.has_collection(collection_name): # 获取集合的详细信息 time.sleep(1) if milvus_client.has_collection(collection_name): print(f"集合 {collection_name} 创建成功")
复制代码


然后,定义把文档向量化的函数。我们使用 bge_m3 生成稠密向量和稀疏向量。


from tqdm import tqdmimport torchfrom pymilvus.model.hybrid import BGEM3EmbeddingFunction
# 定义全局变量bge_m3_ef = None
# 定义初始化嵌入模型实例的函数def initialize_embedding_model() -> None: global bge_m3_ef # 检查是否有可用的CUDA设备 device = "cuda:0" if torch.cuda.is_available() else "cpu" # 根据设备选择是否使用fp16 use_fp16 = device.startswith("cuda") # 创建嵌入模型实例 bge_m3_ef = BGEM3EmbeddingFunction( model_name="BAAI/bge-m3", device=device, use_fp16=use_fp16 )
# 向量化查询def vectorize_query(query: list) -> dict: global bge_m3_ef if bge_m3_ef is None: raise ValueError("嵌入模型未初始化,请先调用 initialize_embedding_model 函数。") # 把输入的文本向量化 vectors = bge_m3_ef.encode_queries(query) return vectors
# 向量化文档def vectorize_docs(docs: list) -> dict: global bge_m3_ef if bge_m3_ef is None: raise ValueError("嵌入模型未初始化,请先调用 initialize_embedding_model 函数。") # 把输入的文本向量化 return bge_m3_ef.encode_documents(docs)
# 初始化嵌入模型实例initialize_embedding_model()
复制代码


接下来,生成向量并且导入向量数据库。


import json
def vectorize_and_import_data( input_file_path: str, field_name: str, batch_size: int = 1000) -> None: # 读取 json 文件,把指定字段的值向量化 with open(input_file_path, 'r', encoding='utf-8') as file: data_list = json.load(file) # 提取该json文件中的所有指定字段的值 docs = [data[field_name] for data in data_list] # 向量化docs,获取稠密向量和稀疏向量 dense_vectors = vectorize_docs(docs)['dense'] sparse_vectors = vectorize_docs(docs)['sparse']
for data, dense_vector, sparse_vector in zip(data_list, dense_vectors, sparse_vectors): data['dense_vector'] = dense_vector.tolist() csr_matrix = sparse_vector.tocsr() sparse_dict = {int(idx): float(val) for idx, val in zip(csr_matrix.indices, csr_matrix.data)} data['sparse_vector'] = sparse_dict print(f"正在将数据插入集合:{collection_name}") total_count = len(data_list) with tqdm(total=total_count, desc="插入数据") as pbar: # 每次插入 batch_size 条数据 for i in range(0, total_count, batch_size): batch_data = data_list[i:i + batch_size] res = milvus_client.insert( collection_name=collection_name, data=batch_data ) pbar.update(len(batch_data))
input_file_path = "docs_rank.json"field_name = "content"vectorize_and_import_data(input_file_path, field_name, embed_model)
复制代码


数据入库后,为它们创建索引。因为数据库中同时包含了两个向量,所以使用混合搜索,需要分别创建稠密向量和稀疏向量的索引。


index_params = milvus_client.prepare_index_params()
# 创建密集向量索引参数index_params.add_index( index_name="IVF_FLAT", field_name="dense_vector", index_type="IVF_FLAT", metric_type="COSINE", params={"nlist": 128})
# 创建稀疏向量索引参数index_params.add_index( index_name="sparse", field_name="sparse_vector", index_type="SPARSE_INVERTED_INDEX", # 目前仅支持IP metric_type="IP", params={"drop_ratio_build": 0.2})
# 创建索引milvus_client.create_index( collection_name=collection_name, index_params=index_params )
# 查看创建的索引print(milvus_client.list_indexes(collection_name))
复制代码


加载集合。


print(f"正在加载集合:{collection_name}")milvus_client.load_collection(collection_name=collection_name)
# 验证加载状态print(milvus_client.get_load_state(collection_name=collection_name))
复制代码


为了实现混合搜索,还需要定义混合搜索函数。


# 混合搜索from pymilvus import AnnSearchRequest, WeightedRanker, RRFRanker
def perform_hybrid_search( collection_name: str, query: list, ranker, output_fields: list, limit_dense: int = 20, limit_sparse: int = 20, limit_hybrid: int = 10 ) -> dict: # 获取查询的稠密向量和稀疏向量 query_vector = vectorize_query(query) query_dense_vector = [query_vector['dense'][0].tolist()] query_sparse_vector = [query_vector['sparse'][[0]].tocsr()] # 创建稠密向量的搜索参数 dense_search_params = { # 查询向量 "data": query_dense_vector, "anns_field": "dense_vector", "param": { "metric_type": "COSINE", "params": { "nprobe": 16, "radius": 0.1, "range_filter": 1 } }, "limit": limit_dense } # 创建稠密向量的搜索请求 dense_req = AnnSearchRequest(**dense_search_params) # 创建稀疏向量的搜索参数 sparse_search_params = { "data": query_sparse_vector, "anns_field": "sparse_vector", "param": { "metric_type": "IP", "params": {"drop_ratio_search": 0.2} }, "limit": limit_sparse } # 创建稀疏向量的搜索请求 sparse_req = AnnSearchRequest(**sparse_search_params) # 执行混合搜索 start_time = time.time() res = milvus_client.hybrid_search( collection_name=collection_name, reqs=[dense_req, sparse_req], ranker = ranker, limit=limit_hybrid, output_fields=output_fields ) end_time = time.time() total_time = end_time - start_time print(f"搜索时间:{total_time:.3f}") return res
复制代码


最后再定义一个打印函数,方便查看搜索结果。


def print_vector_results(res):       for hits in res:        for hit in hits:            entity = hit.get("entity")            print(f"content: {entity['content']}")            print(f"distance: {hit['distance']:.4f}")            print("-"*50)        print(f"数量:{len(hits)}")
复制代码

对比搜索结果

准备工作就绪,先分别看下稠密向量和稀疏向量的搜索结果。在混合搜索的权重策略下,调整权重,一个设置 1,另一个设置为 0,就可以只查看一种搜索结果。


query = ["敏捷的狐狸跳过懒惰的狗。"]ranker=WeightedRanker(1, 0)output_fields = ["content"]limit_dense = 10limit_sparse = 10limit_hybrid = 10
res_dense = perform_hybrid_search(collection_name, query, ranker, output_fields, limit_dense, limit_sparse, limit_hybrid)print_vector_results(res_dense)
复制代码


稠密向量的搜索结果勉强及格,正确答案分别排在第一、第三、第四和第五。让人不满意的是,语义和查询完全相反的句子,却排在了第二和第六,而且前 6 个搜索结果的得分相差很小,区别不明显。


另外,留意一下搜索时间是 0.012 秒,后面要和基于深度学习的重排做比较。


搜索时间:0.012content: 灵活的狐跳过了懒散的犬。distance: 0.9552--------------------------------------------------content: 懒狗跳过了狐狸。distance: 0.9444--------------------------------------------------content: 一只敏捷的狐在公园里跳过了那只懒犬。distance: 0.9373--------------------------------------------------content: 那只灵巧的狐狸轻松地跨过了那只懒散的狗。distance: 0.9366--------------------------------------------------content: 狐迅速地跳过了那只不活跃的犬。distance: 0.9194--------------------------------------------------content: 犬跃过了狐。distance: 0.9025--------------------------------------------------content: 在公园里,那只棕色的狐狸正在跳。distance: 0.8456--------------------------------------------------content: 动物如狗和狐狸生活在公园里。distance: 0.8303--------------------------------------------------content: 那只懈怠的犬正在大树下睡觉。distance: 0.7702--------------------------------------------------content: 树下有一个小池塘。distance: 0.7174--------------------------------------------------数量:10
复制代码


调整权重,再来看看稀疏向量的结果。


ranker=WeightedRanker(0, 1)res_sparse = perform_hybrid_search(collection_name, query, ranker, output_fields, limit_dense, limit_sparse, limit_hybrid)print_vector_results(res_sparse)
复制代码


稀疏向量的搜索结果就更差了,正确答案分别排在第二、第三、第六和第七。这是因为我特意用语义相近但是文本不同的词做了替换,比如用“犬”代替“狗”,“懈怠”代替“懒”,导致它们较难命中查询中的词,得分较低。如果你想了解稀疏向量是如何参与搜索并且计算得分的,可以看看 《外行如何速成专家?Embedding之BM25、splade稀疏向量解读》 这篇文章。


搜索时间是 0.014 秒,和稠密向量相当。


搜索时间:0.014content: 懒狗跳过了狐狸。distance: 0.5801--------------------------------------------------content: 那只灵巧的狐狸轻松地跨过了那只懒散的狗。distance: 0.5586--------------------------------------------------content: 一只敏捷的狐在公园里跳过了那只懒犬。distance: 0.5553--------------------------------------------------content: 在公园里,那只棕色的狐狸正在跳。distance: 0.5502--------------------------------------------------content: 动物如狗和狐狸生活在公园里。distance: 0.5476--------------------------------------------------content: 灵活的狐跳过了懒散的犬。distance: 0.5441--------------------------------------------------content: 狐迅速地跳过了那只不活跃的犬。distance: 0.5336--------------------------------------------------content: 犬跃过了狐。distance: 0.5192--------------------------------------------------content: 那只懈怠的犬正在大树下睡觉。distance: 0.5006--------------------------------------------------content: 树下有一个小池塘。distance: 0.0000--------------------------------------------------数量:10
复制代码


接下来是重点了,我们分别使用权重策略和 RRF 策略,看看重排后的结果如何。


先来看看权重策略中,权重是如何影响综合得分的。我们给稠密向量设置更高的权重——0.8,稀疏向量的权重则设置为 0.2。


ranker=WeightedRanker(0.8, 0.2)res_Weighted = perform_hybrid_search(collection_name, query, ranker, output_fields, limit_dense, limit_sparse, limit_hybrid)print_vector_results(res_Weighted)
复制代码


综合排名第一的结果“灵活的狐跳过了懒散的犬。”,在稠密向量中的得分是 0.9552,排名也是第一,与第二名相差 0.108。


它在稀疏向量中的得分是 0.5441,排名第六。虽然排名低,但是得分与第一名只差 0.036 分,而且权重只占 0.2,对综合得分仍然是第一。因为稠密向量的权重高,综合排名基本和稠密向量的排名一致。


搜索时间是 0.022 秒。


搜索时间:0.022content: 灵活的狐跳过了懒散的犬。distance: 0.8730--------------------------------------------------content: 懒狗跳过了狐狸。distance: 0.8716--------------------------------------------------content: 那只灵巧的狐狸轻松地跨过了那只懒散的狗。distance: 0.8610--------------------------------------------------content: 一只敏捷的狐在公园里跳过了那只懒犬。distance: 0.8609--------------------------------------------------content: 狐迅速地跳过了那只不活跃的犬。distance: 0.8423--------------------------------------------------content: 犬跃过了狐。distance: 0.8259--------------------------------------------------content: 在公园里,那只棕色的狐狸正在跳。distance: 0.7865--------------------------------------------------content: 动物如狗和狐狸生活在公园里。distance: 0.7738--------------------------------------------------content: 那只懈怠的犬正在大树下睡觉。distance: 0.7163--------------------------------------------------content: 树下有一个小池塘。distance: 0.5739--------------------------------------------------数量:10
复制代码


接下来,我们来看看权重策略下的第一名,在 RRF 策略中表现如何。


ranker = RRFRanker(k=10)res_rrf = perform_hybrid_search(collection_name, query, ranker, output_fields, limit_dense, limit_sparse, limit_hybrid)print_vector_results(res_rrf)
复制代码


“灵活的狐跳过了懒散的犬。”在 RRF 策略中的排名从第一下滑到了第四。因为这次注重的是排名,它在稠密向量中虽然排名第一,但是在稀疏向量中的排名只有第六,拉低了综合排名。


排名第一是“懒狗跳过了狐狸。”,因为它在两个搜索结果中的排名都很高,分别是第二和第一。


搜索时间是 0.022 秒,和权重策略的搜索时间差不多。


搜索时间:0.022content: 懒狗跳过了狐狸。distance: 0.1742--------------------------------------------------content: 那只灵巧的狐狸轻松地跨过了那只懒散的狗。distance: 0.1548--------------------------------------------------content: 一只敏捷的狐在公园里跳过了那只懒犬。distance: 0.1538--------------------------------------------------content: 灵活的狐跳过了懒散的犬。distance: 0.1534--------------------------------------------------content: 在公园里,那只棕色的狐狸正在跳。distance: 0.1303--------------------------------------------------content: 狐迅速地跳过了那只不活跃的犬。distance: 0.1255--------------------------------------------------content: 动物如狗和狐狸生活在公园里。distance: 0.1222--------------------------------------------------content: 犬跃过了狐。distance: 0.1181--------------------------------------------------content: 那只懈怠的犬正在大树下睡觉。distance: 0.1053--------------------------------------------------content: 树下有一个小池塘。distance: 0.0500--------------------------------------------------数量:10
复制代码


终于,轮到我们最期待的重排模型上场了。其实,因为返回的搜索结果数量和文档中的句子数量相同,对任何一个搜索结果重排,或者直接对文档重排,效果都是一样的。不过,为了和实际应用中的粗排、重排流程一致,我们还是对粗排结果重排,比如稀疏向量的搜索结果。


首先,我们要以字符串列表的形式,获取稀疏向量的搜索结果,以满足重排模型的输入要求。


# 获取稀疏向量的搜索结果def get_init_res_list(res, field_name):    res_list = []    for hits in res:        for hit in hits:            entity = hit.get("entity")            res_list.append(entity[field_name])    return res_list
# 为了显示重排的效果,我们对搜索结果最差的稀疏向量做重排init_res_list = get_init_res_list(res_sparse, field_name)
复制代码


接下来,定义重排模型。这里使用的是 bge_m3 的重排模型。


from pymilvus.model.reranker import BGERerankFunction
# 定义重排函数bge_rf = BGERerankFunction( model_name="BAAI/bge-reranker-v2-m3", device="cpu")
def perform_reranking(query: str, documents: list, top_k: int = 10) -> list: # 获取重排结果 start_time = time.time() rerank_res = bge_rf( # query参数是字符串 query=query[0], # documents参数是字符串列表 documents=documents, top_k=top_k, ) end_time = time.time() total_time = end_time - start_time print(f"搜索时间:{total_time:.3f}") return rerank_res
top_k = 10rerank_res = perform_reranking(query, init_res_list, top_k)
复制代码


前面我提到过重排模型会花更多的时间,我们先对比下时间。第一次使用重排模型花了 3.2 秒,后面再使用一般用时 0.4 秒,这可能是因为第一次需要加载重排模型到内存中,花的时间较多。所以我们按照用时 0.4 秒计算。


基于统计的重排用时在 0.014-0.022 秒之间,按照最慢的 0.022 秒计算。两者时间相差 18 倍。


重排模型多花了这么多时间,效果怎么样呢?打印搜索结果看看吧。


for hit in rerank_res:    print(f"content: {hit.text}")    print(f"score: {hit.score:.4f}")    print("-"*50)
复制代码


我对重排结果还是比较满意的。四个正确答案排在前四名,而且得分非常接近满分 1 分。而且,它们和其他搜索结果在得分上终于拉开了较大的差距。


content: 灵活的狐跳过了懒散的犬。score: 0.9998--------------------------------------------------content: 狐迅速地跳过了那只不活跃的犬。score: 0.9997--------------------------------------------------content: 那只灵巧的狐狸轻松地跨过了那只懒散的狗。score: 0.9987--------------------------------------------------content: 一只敏捷的狐在公园里跳过了那只懒犬。score: 0.9980--------------------------------------------------content: 犬跃过了狐。score: 0.3730--------------------------------------------------content: 懒狗跳过了狐狸。score: 0.2702--------------------------------------------------content: 在公园里,那只棕色的狐狸正在跳。score: 0.1924--------------------------------------------------content: 动物如狗和狐狸生活在公园里。score: 0.0972--------------------------------------------------content: 那只懈怠的犬正在大树下睡觉。score: 0.0059--------------------------------------------------content: 树下有一个小池塘。score: 0.0000--------------------------------------------------
复制代码

总结

通过对比我们发现,基于统计的重排速度快,准确性一般,适合追求高响应速度和低成本的场景,比如网页搜索、电商。


它有权重和 RRF 两个策略。如果你更看重某种类型的搜索结果,建议使用权重策略。如果你没有明显的偏好,希望在不同搜索结果中,排名都靠前的结果能够胜出,建议使用 RRF 策略。


基于深度学习的重排速度慢,但是准确性高,适合对回答准确性要求高的场景,比如专业知识库或者客服系统。


藏宝图


如果你还想了解更多重排的知识,可以参考下面的文章:



参考


[^1]: 一文玩转 Milvus 新特性之 Hybrid Search


代码获取链接: https://pan.baidu.com/s/10dppfvaRPCX9mJmTa6QGHg?pwd=1234 提取码: 1234

作者介绍

Zilliz 黄金写手:江浩




发布于: 刚刚阅读数: 3
用户头像

Zilliz

关注

Data Infrastructure for AI Made Easy 2021-10-09 加入

还未添加个人简介

评论

发布
暂无评论
语义检索效果差?深度学习rerank VS 统计rerank选哪个_Milvus_Zilliz_InfoQ写作社区