稀疏检索与稠密检索:定义、区别与应用场景
在信息检索(Information Retrieval, IR)领域,稀疏检索和稠密检索是两种主流的表示与匹配方法。它们分别使用不同的方式将文本(如查询和文档)映射到向量空间,并通过相似度计算来实现检索任务。
本文将从以下几个方面对稀疏和稠密检索进行对比分析:
- 定义
- 区别
- 功能点与算法
- 适用场景
- 示例
📌 一、定义
✅ 稀疏检索(Sparse Retrieval)
稀疏检索是一种基于传统词频统计模型的方法,通常使用像 TF-IDF 或 BM25 这样的特征表示。每个文档或查询被表示为一个高维但稀疏的向量,其中大多数元素为零,只有少数词汇项具有非零值。
特点:
- 高维度
- 向量中大部分为0
- 基于关键词频率和倒排索引
✅ 稠密检索(Dense Retrieval)
稠密检索是一种基于深度学习的方法,使用神经网络模型(如 BERT)将文本编码为低维密集向量(dense vector)。这些向量捕捉语义信息,适合做语义相似度匹配。
特点:
- 低维度
- 向量元素基本不为0
- 捕捉语义而非字面匹配
🔁 二、主要区别
特性 | 稀疏检索 | 稠密检索 |
---|---|---|
向量形式 | 高维稀疏向量 | 低维密集向量 |
表示方法 | TF-IDF、BM25 | 比较早的BERT、DPR、Sentence-BERT,最近的BGE、GTE系列 |
依赖结构 | 倒排索引 | 向量数据库(FAISS、ANN) |
匹配机制 | 关键词匹配 | 语义相似度(余弦、点积) |
可解释性 | 高 | 低 |
训练需求 | 不需要训练 | 需要大量数据和训练 |
⚙️ 三、功能点与算法
1. 稀疏检索常用算法
🧩 BM25(Best Matching 25)
from rank_bm25 import BM25Okapi
tokenized_corpus = [
["hello", "world"],
["hello", "there"]
]
bm25 = BM25Okapi(tokenized_corpus)
query = ["hello"]
doc_scores = bm25.get_scores(query)
print(doc_scores) # 输出每篇文档的相关性得分
🧩 TF-IDF + 余弦相似度
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
corpus = [
"The quick brown fox jumps over the lazy dog",
"Never jump over the lazy dog quickly"
]
vectorizer = TfidfVectorizer()
tfidf_matrix = vectorizer.fit_transform(corpus)
cosine_sim = cosine_similarity(tfidf_matrix[0:1], tfidf_matrix)
print(cosine_sim) # 输出相似度矩阵
2. 稠密检索常用算法
🧩 DPR(Dense Passage Retriever)
DPR 使用两个 BERT 编码器分别编码查询和文档,然后在嵌入空间中进行近似最近邻搜索。
from transformers import DPRQuestionEncoder, DPRContextEncoder, DPRReader
question_encoder = DPRQuestionEncoder.from_pretrained("facebook/dpr-question_encoder-single-nq-base")
context_encoder = DPRContextEncoder.from_pretrained("facebook/dpr-ctx_encoder-single-nq-base")
question = "What is the capital of France?"
context = "Paris is the capital city of France."
question_embedding = question_encoder(question).pooler_output
context_embedding = context_encoder(context).pooler_output
🧩 Sentence-BERT(SBERT)
from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
model = SentenceTransformer('bert-base-nli-mean-tokens')
sentences = ["The cat sits on the mat", "A cat is sitting on the mat", "The dog barks"]
sentence_embeddings = model.encode(sentences)
similarity = cosine_similarity([sentence_embeddings[0]], sentence_embeddings[1:])
print(similarity) # 相似度得分
🎯 四、适合场景
场景 | 推荐方法 | 原因说明 |
---|---|---|
小规模数据集 | 稀疏检索 | 实现简单,无需训练,资源消耗低 |
对可解释性要求高 | 稀疏检索 | 能看到哪些词贡献了分数,便于调试 |
大规模语义匹配任务 | 稠密检索 | 更好的泛化能力,理解同义词和上下文 |
用户意图模糊或表达多样性强 | 稠密检索 | 能处理 paraphrase 和复杂语义 |
实时性要求极高 | 稀疏检索 | 查询速度快,倒排索引效率高 |
支持多语言或跨语言检索 | 稠密检索 | 多语言预训练模型支持跨语言语义匹配 |
📘 五、实际应用举例
✅ 示例 1:搜索引擎中的网页排序
- 稀疏检索:Google 早期版本使用类似 BM25 的算法。
- 稠密检索:现代搜索引擎结合 BERT 等模型提升语义理解。
✅ 示例 2:问答系统(QA)
- 稀疏检索:用于快速筛选候选答案段落。
- 稠密检索:用于精确匹配问题与文档语义。
✅ 示例 3:推荐系统
- 稀疏检索:基于用户历史行为标签匹配商品。
- 稠密检索:使用用户画像和物品嵌入向量进行语义匹配。
📊 六、总结对比图(Markdown 图表)
维度 | 稀疏检索 | 稠密检索 |
---|---|---|
表示方式 | 高维稀疏词袋向量 | 低维密集语义向量 |
检索速度 | 快 | 较慢(需 ANN 加速) |
可解释性 | 高 | 低 |
训练成本 | 无 | 高(需大量标注数据) |
语义理解能力 | 有限(依赖关键词重合) | 强(理解上下文和同义词) |
📚 七、缺点
检索方式 | 缺点 | 举例 |
---|---|---|
稀疏检索 | 不关注顺序,忽略了语义 | 我给你买礼物和你给我买礼物完全被判定为相同,但实际不同 |
稠密检索 | 文本转成向量,包含了上下文以及语义 | |
融合检索 | 稀疏和稠密结合 |
🧠 结语
稀疏检索和稠密检索各有优劣,在不同场景下各展所长。随着技术的发展,越来越多的系统采用**混合检索(Hybrid Retrieval)**策略,结合两者的优势,以达到更高效、更准确的信息检索效果。
是否考虑将两者融合?这是未来信息检索的重要方向之一。