外行速成专家:BM25与Splade稀疏向量解读
在上一篇文章中,我们聊了文本如何变成稠密向量,并且还能很好地表达语义。但有个问题——当遇到嵌入模型“专业领域”之外的文本时,效果就大打折扣了。 打个比方:你身体不舒服去看医生,医生能准确理解你的描述,判断病因、做出诊断。但如果你突然问“人工智能如何影响汽车行业?”,医生大概会觉得你不仅身体不舒服,脑
在上一篇文章中,我们聊了文本如何变成稠密向量,并且还能很好地表达语义。但有个问题——当遇到嵌入模型“专业领域”之外的文本时,效果就大打折扣了。

打个比方:你身体不舒服去看医生,医生能准确理解你的描述,判断病因、做出诊断。但如果你突然问“人工智能如何影响汽车行业?”,医生大概会觉得你不仅身体不舒服,脑子也需要治一治——他不擅长这个领域。想得到答案,你应该去找人工智能或汽车领域的专家。当然,还有一个选择:找一位聪明的门外汉,让他“冒充”专家。
01. 聪明的门外汉——BM25
稠密向量的维度较低,通常几百到上千,每个维度几乎都不为零。与之相对,稀疏向量的维度大得多,几万甚至十万起步,但大部分维度都是零,只有少数非零。稀疏向量又分为两种:统计得到的稀疏向量和学习得到的稀疏向量。先聊第一种,它的代表就是 BM25。
BM25 就像那位聪明的门外汉:你问他领域外的知识,他不懂语义,但会抓住问题中的关键词——比如“人工智能”和“汽车”——然后翻遍文档,把跟这些词最相关的信息给你找出来。
那么,这位门外汉具体是怎么操作的呢?
首先,他会搜集成百上千篇相关文档,快速翻一遍,看看里面都有哪些专业术语。怎么判断哪些词是术语呢?聪明如他,靠的是词频:“的”“是”“了”这种高频词肯定不是术语,反倒是出现频率低的词,更像是行话。这就好比你的两个微信群:工作群消息少,但每条都很重要,你会置顶;吃喝玩乐群整天刷屏,但错过也无所谓,你甚至会开免打扰。不同群的权重不同,门外汉也会给不同的词赋予不同的权重。他为文档中的每个词建一个词汇表,根据出现频率赋予权重——频率越低,权重越大,越可能是专业术语。
然后,他要找出哪些文档跟“人工智能”“汽车”这两个术语最相关。怎么做?对照词汇表,数每篇文档里这两个词出现几次,次数越多,相关性越大。
当然,这只是极简版解释,真实的 BM25 算法要复杂很多。公式一多读者就跑,所以下面只简单说一下原理。
首先,BM25 对文档集合做分词处理,得到一张词汇表。词汇表中的单词(准确说是 token)数量,就是稀疏向量的维度。然后,对查询也做分词处理。比如查询是“人工智能如何影响汽车行业?”,分词得到“人工智能”“影响”“汽车行业”三个词。
接下来,计算文档集合中每个词的逆文档频率(IDF),以及查询中某个词在指定文档中的词频(TF)。
IDF(Inverse Document Frequency)这个名字很绕口。说白了,它就是用来衡量一个词在文档集合中间出现的次数——出现越少,数值越大。门外汉用这个来给低频专业术语赋予更大的权重。
其中:
- \(IDF(w)\) 是单词 \(w\) 的逆文档频率。
- \(N\) 是文档总数。
- \(df(w)\) 是包含查询词 \(w\) 的文档数量。
- \(\epsilon\) 是一个平滑因子,避免分母为零。
TF(Term Frequency)表示查询中的某个词在指定文档中间出现的频率,频率越大数值越大,意味着查询和这篇文档的相关性更高。
其中:
- \(TF(w, d)\) 是查询词 \(w\) 在文档 \(d\) 中的词频。
- \(q\) 是查询。
- \(d\) 是语料库中的某个文档。
- \(t_i\) 是查询中的第 \(i\) 个 token。
- \(f(w, d)\) 是词 \(w\) 在文档 \(d\) 中间出现的次数。
- \(k_1\) 是一个调节参数,控制词频的影响,通常在 1.2 到 2 之间。
- \(b\) 是一个调节参数,控制文档长度对词频的影响,通常取 0.75。
- \(|d|\) 是文档的长度(分词后的 token 数量)。
- \(a vgdl\) 是语料库所有文档的平均长度。
最后,根据 IDF 和 TF 计算 BM25 分数,用来表示查询与指定文档的相关程度。
02. BM25 代码实践
好了,纸上谈兵到此为止,下面用代码实际操练一番。先做点准备工作:
Milvus 版本:>=2.4.0
安装依赖:
!pip install pymilvus==2.4.7 "pymilvus[modle]" torch
假设下面这个字符串列表就是我们的文档集合,每个字符串是一篇文档:
docs = [
"机器学习正在改变我们的生活方式。",
"深度学习在图像识别中表现出色。",
"自然语言处理是计算机科学的重要领域。",
"自动驾驶依赖于先进的算法。",
"AI可以帮助医生诊断疾病。",
"金融领域广泛应用数据分析技术。",
"生产效率可以通过自动化技术提高。",
"机器智能的未来充满潜力。",
"大数据支持是机器智能发展的关键。",
"量子隧穿效应使得电子能够穿过经典力学认为无法穿过的势垒,这在半导体器件中有着重要的应用。"
]
使用 BM25 对第一个文档“机器学习正在改变我们的生活方式。”做分词处理:
from pymilvus.model.sparse.bm25.tokenizers import build_default_analyzer
from pymilvus.model.sparse import BM25EmbeddingFunction
# 使用支持中文的分析器
analyzer = build_default_analyzer(language="zh")
# 分析器对文本做分词处理
tokens1 = analyzer(docs[0])
print(tokens1)
分词结果:
['机器', '学习', '改变', '生活', '方式']
接下来对整个文档集合做分词处理,并计算文档集合的 IDF 等参数:
# 创建BM25EmbeddingFunction实例,传入分词器,以及其他参数
bm25_ef = BM25EmbeddingFunction(analyzer)
# 计算文档集合的参数
bm25_ef.fit(docs)
# 保存训练好的参数到磁盘以加快后续处理
bm25_ef.sa ve("bm25_params.json")
我们看看参数都有哪些内容:
import json
file_path = "bm25_params.json"
with open(file_path, 'r', encoding='utf-8') as file:
bm25_params = json.load(file)
print(bm25_params)
corpus_size 是文档数量,a vgdl、idf_value 等参数都在前面的公式中间出现过。
{'version': 'v1', 'corpus_size': 10, 'a vgdl': 5.4, 'idf_word': ['机器', '学习', '改变', '生活', '方式', '深度', '图像识别', '中', '表现出色', '自然语言', '计算机科学', '领域', '自动', '驾驶', '依赖于', '先进', '算法', 'AI', '医生', '诊断', '疾病', '金融', '广泛应用', '数据分析', '技术', '生产', '效率', '自动化', '提高', '智能', '未来', '充满', '潜力', '大', '数据', '支持', '发展', '关键', '量子', '隧穿', '效应', '电子', '穿过', '经典力学', '势垒', '半导体器件'], 'idf_value': [0.7621400520468966, 1.2237754316221157, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.2237754316221157, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.2237754316221157, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.2237754316221157, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.2237754316221157, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.845826690498331, 1.845826690498331], 'k1': 1.5, 'b': 0.75, 'epsilon': 0.25}
idf_word 就是 BM25 对文档集合的分词结果,也就是前面提到的词汇表。词汇表中的单词数量,就是稀疏向量的维度。
# BM25词汇表中的单词数量
print(f"BM25词汇表中的单词数量:{len(bm25_params['idf_word'])}")
# BM25稀疏向量的维度
print(f"BM25稀疏向量维度:{bm25_ef.dim}")
返回结果:
BM25词汇表中的单词数量:46
BM25稀疏向量维度:46
需要的参数都算好了,接下来就可以生成文档集合的稀疏向量了。文档集合中有 10 篇文档(10 个字符串),而稀疏向量的维度是 46,所以文档集合的稀疏向量是一个 10 行 46 列的矩阵。每一行代表一篇文档的稀疏向量。
# 生成文档集合的稀疏向量
sparse_vectors_bm25 = bm25_ef.encode_documents(docs)
# 打印文档集合的稀疏向量
print(sparse_vectors_bm25)
输出结果:
(0, 0) 1.0344827586206897
(0, 1) 1.0344827586206897
(0, 2) 1.0344827586206897
(0, 3) 1.0344827586206897
(0, 4) 1.0344827586206897
: :
(9, 7) 0.7228915662650603
(9, 38) 0.7228915662650603
(9, 39) 0.7228915662650603
(9, 40) 0.7228915662650603
(9, 41) 0.7228915662650603
(9, 42) 1.1214953271028039
(9, 43) 0.7228915662650603
(9, 44) 0.7228915662650603
(9, 45) 0.7228915662650603
来看第一个文档“机器学习正在改变我们的生活方式。”的稀疏向量:
# 第一个文档的稀疏向量
print(list(sparse_vectors_bm25)[0])
结果为:
(0, 0) 1.0344827586206897
(0, 1) 1.0344827586206897
(0, 2) 1.0344827586206897
(0, 3) 1.0344827586206897
(0, 4) 1.0344827586206897
发现了吧?第一个文档的稀疏向量只有 5 个非零元素——因为它的分词结果就是 5 个单词,一一对应。而且每个元素的值都相同,说明它们的 IDF 和 TF 都是一样的。
第一个文档的分词结果:
['机器', '学习', '改变', '生活', '方式']
文档集合处理好了,我们再给一个查询句子,就可以执行搜索了。
query = ["自动驾驶如何影响汽车行业?"]
# 把查询文本向量化
query_sparse_vectors_bm25 = bm25_ef.encode_queries(query)
# 打印稀疏向量
print(query_sparse_vectors_bm25)
# 查询的分词结果
print(analyzer(query[0]))
查看查询的稀疏向量和分词结果:
(0, 12) 1.845826690498331
(0, 13) 1.845826690498331
['自动', '驾驶', '影响', '汽车行业']
你可能会问:查询分词得到 4 个单词,但它的稀疏向量怎么只有 2 维?因为这 4 个词中,只有“自动”和“驾驶”在词汇表里,“影响”和“汽车行业”不存在,后两个词的 BM25 分数为 0。哎,毕竟是门外汉啊。
03. 刚入门的新人——splade
如果说稠密向量是精通特定领域的专家,统计得到的稀疏向量 BM25 是聪明的门外汉,那么学习得到的稀疏向量 splade 就是刚入门的新人。他理解领域内专业术语的语义,还能举一反三,增加更多语义相近的词一起查找。不过,毕竟是新人,还是通过数专业术语出现的次数来找到最相关的文档。
splade 的具体工作原理是这样的:
首先,splade 对句子分词,通过嵌入模型 BERT(BERT 相关内容详见《孙悟空 + 红楼梦 - 西游记 = ?一文搞懂什么是向量嵌入》)得到每个单词的向量。向量能表达语义,所以 splade 能够“举一反三”,找到更多语义相似的单词。
比如,对于“人工智能如何影响汽车行业”这个句子,分词得到“人工智能”和“汽车”,以及和“人工智能”相似的“AI”等词。splade 也有一张词汇表,不过它不像 BM25 那样需要根据文档集合统计,而是预置的——来源于 BERT。
接下来,splade 生成这些单词的稀疏向量。它会计算每个单词出现在词汇表中每个位置的概率。单词和词汇表中某个位置的词在语义上越接近,计算得到的概率越大。这个概率就是单词的权重。
以“人工智能”为例:假设词汇表中第 5 个词也是“人工智能”,两个词完全一样,计算得到的概率很高,比如 40%。而词汇表第 8 个词是“机器学习”,两者比较相似,概率是 20%。其他词和“人工智能”语义相差较远,概率很小,忽略不计。最后,“人工智能”的权重就是 40% + 20% = 60%。
再用同样的方法计算出“AI”和“汽车”的权重,得到稀疏向量:
sparse_vector = {"人工智能": 0.6, "AI": 0.5, "汽车": 0.1}
04. splade 代码实践
老规矩,用代码验证上面的内容。这次换成英文文档集合:
# 使用英文
docs_en = [
"Machine learning is changing our way of life.",
"Deep learning performs exceptionally well in image recognition.",
"Natural language processing is an important field in computer science.",
"Autonomous driving relies on advanced algorithms.",
"AI can help doctors diagnose diseases.",
"Data analysis technology is widely applied in the financial field.",
"Production efficiency can be improved through automation technology.",
"The future of machine intelligence is full of potential.",
"Big data support is key to the development of machine intelligence.",
"The quantum tunneling effect allows electrons to pass through potential barriers that classical mechanics consider impassable, which has important applications in semiconductor devices."
]
生成文档集合的稀疏向量:
from pymilvus.model.sparse import SpladeEmbeddingFunction
query_en = ["How does artificial intelligence affect the automotive industry?"]
model_name = "na ver/splade-cocondenser-selfdistil"
# 实例化splade嵌入模型
splade_ef = SpladeEmbeddingFunction(
model_name = model_name,
device="cpu"
)
# 生成文档集合的稀疏向量
sparse_vectors_splade = splade_ef.encode_documents(docs_en)
print(sparse_vectors_splade)
和 BM25 一样,我们同样得到一个稀疏向量矩阵:
(0, 1012) 0.053256504237651825
(0, 2003) 0.22995686531066895
(0, 2047) 0.08765587955713272
: :
(9, 27630) 0.2794925272464752
(9, 28688) 0.02786295674741268
(9, 28991) 0.12241243571043015
splade 的词汇表是预先准备好的,词汇表中的单词数量同样是稀疏向量的维度。
# splade词汇表中的单词数量
from transformers import AutoModelForMaskedLM, AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained(model_name)
print(f"splade词汇表中的单词数量:{tokenizer.vocab_size}")
print(f"splade稀疏向量维度:{splade_ef.dim}")
二者相同:
splade词汇表中的单词数量:30522
splade稀疏向量维度:30522
再来看看查询的分词结果及其稀疏向量:
# 查看查询的分词
tokens = tokenizer.tokenize(query_en[0])
print(f"“{query_en[0]}” 的分词结果:\n{tokens}")
print(f"tokens数量:{len(tokens)}")
# 生成查询的稀疏向量
query_sparse_vectors_splade = splade_ef.encode_queries(query_en)
print(query_sparse_vectors_splade)
结果如下:
“How does artificial intelligence affect the automotive industry?” 的分词结果:
['how', 'does', 'artificial', 'intelligence', 'affect', 'the', 'automotive', 'industry', '?']
tokens数量:9
(0, 2054) 0.139632448554039
(0, 2079) 0.08572433888912201
(0, 2106) 0.22006677091121674
(0, 2126) 0.038961488753557205
(0, 2129) 0.6875206232070923
(0, 2138) 0.5343469381332397
(0, 2194) 0.32417890429496765
(0, 2224) 0.011731390841305256
(0, 2339) 0.33811360597610474
: :
(0, 26060) 0.0731586366891861
比较分词数量和稀疏向量的维度,有没有发现不对劲?没错,分词数量和稀疏向量的维度不一样。这就是 splade 和 BM25 的重要区别——splade 能够“举一反三”,在最初 9 个分词的基础上,又增加了其他语义相近的单词。
那么,查询现在一共有多少个单词?或者说,它的稀疏向量有多少个非零元素?
# 获取稀疏向量的非零索引
nonzero_indices = query_sparse_vectors_splade.indices[query_sparse_vectors_splade.indptr[0]:query_sparse_vectors_splade.indptr[1]]
# 构建稀疏词权重列表
sparse_token_weights = [
(splade_ef.model.tokenizer.decode(col), query_sparse_vectors_splade[0, col])
for col in nonzero_indices
]
# 按权重降序排序
sparse_token_weights = sorted(sparse_token_weights, key=lambda item: item[1], reverse=True)
# 查询句只有9个tokens,splade通过举一反三,生成的稀疏向量维度增加到了98个。
print(f"splade 稀疏向量非零元素数量:{len(sparse_token_weights)}")
一共有 98 个:
splade 稀疏向量非零元素数量:98
具体是哪些单词?打印出来看看:
# 比如,和“artificial intelligence”语义相近的 “ai”,和“automotive”语义相近的“car”。
for token in sparse_token_weights:
print(token)
splade 增加了大量语义相近的单词,比如和“artificial intelligence”语义相近的“ai”,和“automotive”语义相近的“car”和“vehicle”。
('artificial', 2.588431)
('intelligence', 2.3582284)
('car', 1.590975)
('automotive', 1.4835068)
('vehicle', 0.798108)
('ai', 0.676852)
: :
05. 搜索实践
我们已经了解了两种稀疏向量的特点和生成方法,下面就在实际搜索中体会它们的区别吧。
需要用 Milvus 创建集合、导入数据、创建索引、加载数据,然后搜索。这个过程在《朋友圈装腔指南:如何用向量数据库把大白话变成古诗词》中有详细介绍,这里就不多啰嗦了。
创建集合:
from pymilvus import MilvusClient, DataType
import 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 = MilvusClient.create_schema(
auto_id=True,
enable_dynamic_field=True,
# 设置分区数量,默认为16
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="text", datatype=DataType.VARCHAR, max_length=256)
# bm25稀疏向量
schema.add_field(field_name="sparse_vectors_bm25", datatype=DataType.SPARSE_FLOAT_VECTOR)
# splade稀疏向量
schema.add_field(field_name="sparse_vectors_splade", 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} 创建成功")
# 示例
collection_name = "docs"
uri="http://localhost:19530"
milvus_client = MilvusClient(uri=uri)
create_collection(collection_name)
导入数据:
# 准备数据
entities = [
{
# 文本字段
"text": docs[i],
"text_en": docs_en[i],
# bm25稀疏向量字段
"sparse_vectors_bm25": list(sparse_vectors_bm25)[i].reshape(1, -1),
# splade稀疏向量字段
"sparse_vectors_splade": list(sparse_vectors_splade)[i].reshape(1, -1),
}
for i in range(len(docs))
]
# 导入数据
milvus_client.insert(collection_name=collection_name, data=entities)
创建索引:
# 创建索引参数
index_params = milvus_client.prepare_index_params()
# 为稀疏向量bm25创建索引参数
index_params.add_index(
index_name="sparse_vectors_bm25",
field_name="sparse_vectors_bm25",
# SPARSE_INVERTED_INDEX是传统的倒排索引,SPARSE_WAND使用Weak-AND算法来减少搜索过程中的完整IP距离计算
index_type="SPARSE_INVERTED_INDEX",
# 目前仅支持IP
metric_type="IP",
# 创建索引时,排除向量值最小的20%的向量。对于稀疏向量来说,向量值越大,说明在该维度上的重要性越大。范围[0,1]。
params={"drop_ratio_build": 0.2}
)
# 为稀疏向量splade创建索引参数
index_params.add_index(
index_name="sparse_vectors_splade",
field_name="sparse_vectors_splade",
# SPARSE_INVERTED_INDEX是传统的倒排索引,SPARSE_WAND使用Weak-AND算法来减少搜索过程中的完整IP距离计算
index_type="SPARSE_INVERTED_INDEX",
# 目前仅支持IP
metric_type="IP",
# 创建索引时,排除向量值最小的20%的向量。对于稀疏向量来说,向量值越大,说明在该维度上的重要性越大。范围[0,1]。
params={"drop_ratio_build": 0.2}
)
# 创建索引
milvus_client.create_index(
collection_name=collection_name,
index_params=index_params
)
查看索引是否创建成功:
# 查看索引信息
def show_index_info(collection_name: str) -> None:
"""
显示指定集合中某个索引的详细信息。
参数:
collection_name (str): 集合的名称。
返回:
None: 该函数仅打印索引信息,不返回任何值。
"""
# 查看集合的所有索引
indexes = milvus_client.list_indexes(
collection_name=collection_name
)
print(f"已经创建的索引:{indexes}")
print()
# 查看索引信息
if indexes:
for index in indexes:
index_details = milvus_client.describe_index(
collection_name=collection_name,
# 指定索引名称,这里假设使用第一个索引
index_name=index
)
print(f"索引 {index} 详情:{index_details}")
print()
else:
print(f"集合 {collection_name} 中没有创建索引。")
# 示例
show_index_info(collection_name)
如果创建成功,你会看到下面的输出:
已经创建的索引:['sparse_vectors_bm25', 'sparse_vectors_splade']
索引 sparse_vectors_bm25 详情:{'drop_ratio_build': '0.2', 'index_type': 'SPARSE_INVERTED_INDEX', 'metric_type': 'IP', 'field_name': 'sparse_vectors_bm25', 'index_name': 'sparse_vectors_bm25', 'total_rows': 0, 'indexed_rows': 0, 'pending_index_rows': 0, 'state': 'Finished'}
索引 sparse_vectors_splade 详情:{'drop_ratio_build': '0.2', 'index_type': 'SPARSE_INVERTED_INDEX', 'metric_type': 'IP', 'field_name': 'sparse_vectors_splade', 'index_name': 'sparse_vectors_splade', 'total_rows': 0, 'indexed_rows': 0, 'pending_index_rows': 0, 'state': 'Finished'}
加载集合:
# 加载集合
print(f"正在加载集合:{collection_name}")
milvus_client.load_collection(collection_name=collection_name)
# 验证加载状态
print(milvus_client.get_load_state(collection_name=collection_name))
如果加载成功,会显示:
正在加载集合:docs
{'state': }
加载完成,下面就是重头戏——搜索。
定义搜索函数:
# 定义稀疏向量搜索参数
search_params_sparse_vectors = {
"metric_type": "IP",
"params": {"drop_ratio_search": 0.2},
}
# 执行向量搜索
def vector_search(
query_vectors,
field_name,
search_params,
output_fields,
):
# 向量搜索
res = milvus_client.search(
collection_name=collection_name,
# 指定查询向量。
data=query_vectors,
# 指定要搜索的向量字段
anns_field=field_name,
# 设置搜索参数
search_params=search_params,
output_fields=output_fields
)
return res
再定义一个打印结果的函数,方便查看:
# 打印向量搜索结果
def print_vector_results(res):
for hits in res:
for hit in hits:
entity = hit.get("entity")
print(f"text: {entity['text']}")
print(f"distance: {hit['distance']:.3f}")
print("-"*50)
print(f"数量:{len(hits)}")
首先,使用 BM25 搜索。
# 使用稀疏向量BM25搜索
query1 = ["人工智能如何影响汽车行业?"]
query_sparse_vectors_bm25 = bm25_ef.encode_queries(query1)
field_name = "sparse_vectors_bm25"
output_fields = ["text"]
# 指定搜索的分区,或者过滤搜索
res_sparse_vectors_bm25 = vector_search(query_sparse_vectors_bm25, field_name, search_params_sparse_vectors, output_fields)
print_vector_results(res_sparse_vectors_bm25)
但是并没有搜索到任何结果:
数量:0
为什么呢?查看一下 query1 的分词结果:
# 查看query1的分词结果
print(analyzer(query1[0]))
分词结果只有“人工智能”一个词吗?实际上:
['人工智能', '影响', '汽车行业']
BM25 的词汇表中虽然有“智能”这个词,但并不包含“人工智能”“影响”和“汽车行业”这些词,所以没有任何结果返回。
我们把“人工智能”换成“机器智能”,就可以搜到了。
# 使用稀疏向量BM25搜索
query2 = ["机器智能如何影响汽车行业?"]
query_sparse_vectors_bm25 = bm25_ef.encode_queries(query2)
field_name = "sparse_vectors_bm25"
output_fields = ["text"]
# 指定搜索的分区,或者过滤搜索
res_sparse_vectors_bm25 = vector_search(query_sparse_vectors_bm25, field_name, search_params_sparse_vectors, output_fields)
print_vector_results(res_sparse_vectors_bm25)
而且,这次还搜到了包含“机器学习”的句子。
text: 机器智能的未来充满潜力。
distance: 2.054
--------------------------------------------------
text: 大数据支持是机器智能发展的关键。
distance: 1.752
--------------------------------------------------
text: 机器学习正在改变我们的生活方式。
distance: 0.788
--------------------------------------------------
数量:3
这是因为分词时“机器智能”被分成了“机器”和“智能”两个词,所以能匹配到更多句子。
# 查看query2的分词结果
print(analyzer(query2[0]))
分词结果:
['机器', '智能', '影响', '汽车行业']
接下来,用 splade 搜索,看看和 BM25 的结果有什么不同。
先定义一个打印结果的函数。
# 打印向量搜索结果
def print_vector_results_en(res):
for hits in res:
for hit in hits:
entity = hit.get("entity")
print(f"text_en: {entity['text_en']}")
print(f"distance: {hit['distance']:.3f}")
print("-"*50)
print(f"数量:{len(hits)}")
然后使用 splade 搜索。
query1_en = ["How does artificial intelligence affect the automotive industry?"]
query_sparse_vectors_splade = splade_ef.encode_queries(query1_en)
field_name = "sparse_vectors_splade"
output_fields = ["text_en"]
res_sparse_vectors_splade = vector_search(query_sparse_vectors_splade, field_name, search_params_sparse_vectors, output_fields)
print_vector_results_en(res_sparse_vectors_splade)
比较 BM25 和 splade 的搜索结果,区别很明显。splade 的文档集合中并不包含“artificial intelligence”这个词,但由于它具有“举一反三”的能力,仍然搜到了包含“AI”“machine intelligence”以及“Autonomous”的句子,返回了更多结果(实际上返回了所有文档)。
text_en: The future of machine intelligence is full of potential.
distance: 10.020
--------------------------------------------------
text_en: Big data support is key to the development of machine intelligence.
distance: 8.232
--------------------------------------------------
text_en: AI can help doctors diagnose diseases.
distance: 7.291
--------------------------------------------------
text_en: Autonomous driving relies on advanced algorithms.
distance: 7.213
--------------------------------------------------
text_en: Production efficiency can be improved through automation technology.
distance: 6.999
--------------------------------------------------
text_en: Machine learning is changing our way of life.
distance: 6.863
--------------------------------------------------
text_en: Data analysis technology is widely applied in the financial field.
distance: 5.064
--------------------------------------------------
text_en: The quantum tunneling effect allows electrons to pass through potential barriers that classical mechanics consider impassable, which has important applications in semiconductor devices.
distance: 3.695
--------------------------------------------------
text_en: Deep learning performs exceptionally well in image recognition.
distance: 3.464
--------------------------------------------------
text_en: Natural language processing is an important field in computer science.
distance: 3.044
--------------------------------------------------
数量:10
如果把查询中的“artificial intelligence”换成“machine intelligence”,同样会返回所有结果,但权重有所不同。
text_en: The future of machine intelligence is full of potential.
distance: 15.128
--------------------------------------------------
text_en: Big data support is key to the development of machine intelligence.
distance: 12.945
--------------------------------------------------
text_en: Machine learning is changing our way of life.
distance: 12.763
--------------------------------------------------
text_en: Production efficiency can be improved through automation technology.
distance: 7.446
--------------------------------------------------
text_en: AI can help doctors diagnose diseases.
distance: 6.055
--------------------------------------------------
text_en: Autonomous driving relies on advanced algorithms.
distance: 5.309
--------------------------------------------------
text_en: Data analysis technology is widely applied in the financial field.
distance: 4.857
--------------------------------------------------
text_en: The quantum tunneling effect allows electrons to pass through potential barriers that classical mechanics consider impassable, which has important applications in semiconductor devices.
distance: 3.356
--------------------------------------------------
text_en: Deep learning performs exceptionally well in image recognition.
distance: 3.317
--------------------------------------------------
text_en: Natural language processing is an important field in computer science.
distance: 2.688
--------------------------------------------------
数量:10 你是一名 AI 行业编辑,请围绕下面这条热点输出一份资讯解读:
热点:外行速成专家:BM25与Splade稀疏向量解读要求:
1. 先用一句话解释这条热点在讲什么
2. 再总结它为什么重要
3. 说明会影响哪些 AI 产品或内容方向
4. 最后给出 3 个适合资讯站使用的标题
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
相关热点先来看看Remaker AI这款工具。它的定位非常清晰——专注于解决图像处理中的常见难题:水印、文字、多余元素,以及低分辨率图像的修复与放大。无论是设计师、社交媒体运营人员,还是普通用户,只要遇到需要“清理”图片的场景,它都能轻松应对。下面直接了解它的适用人群和实际能力。 需求人群 Remaker
文心大模型覆盖文化传媒、艺术创作、教育科研、金融保险、医疗健康等需文字与创意的场景,集成文本生成、文生图、智能对话、信息抽取、文本纠错、古诗创作、文案续写等十余种文字处理能力。
今天我们来聊一款非常实用的浏览器工具——Ask AI Browser。如果你经常在Google上搜索问题,又希望随时与AI对话,或者在浏览各类网站时想直接向AI提问,那么这款工具可能会为你的日常浏览体验带来显著提升。 目标用户群体 简单来说,它主要面向以下几类用户:在Google上搜索问题时,希望无
说起来,联通云盘这事儿,其实就是中国联通在云存储这条赛道上的一次重要布局。目标很明确:为个人和家庭用户解决海量数据存储的刚需。具体能干啥呢?个人云、家庭云、微信 通讯录 相册备份、多端文件共享……说白了,就是从存储到共享的一条龙服务。 联通云盘官网网页版登录入口网址:https: pan wo c
- 日榜
- 周榜
- 月榜
热点快看
