想象你在老城区一家藏书上百万册的书店里当学徒。顾客站在柜台前说:“我想找讲怎么训练小狗的书。”资深店员阿诚从不逛书架,他翻开一本磨破边角的笔记本——每一页记着一个词,下面抄着这个词在哪几本书里出现过、各出现过几次。这套“先查词、再翻书”的土办法,就是今天要讲的稀疏检索。后来阿诚把笔记本升级了两代:第一代叫 TF-IDF,教会他什么样的词值得记、记得多不等于真的重要;第二代叫 BM25,教会他词频会“饱和”、厚书要“打折”。这两代心法看似朴素,至今仍是各行各业搜索系统、以及大模型外挂知识库(RAG)的底层地基。读完这篇,你不但能看懂它们,还能在自己的检索项目里亲手用起来。
稀疏检索是大模型 RAG 的关键词召回底座。掌握 TF-IDF 与 BM25,你就能在精确匹配场景中做出又快又稳的检索方案,并懂得如何与稠密检索配合。
可视化演示
通过逐步展示快速排序的分区过程,直观理解枢轴选择、元素比较与交换操作,支持自动播放和手动步进切换。
本节配有交互动效(进入视口后自动加载,约 3KB)。
快速排序初始化 待排序数组已就绪,即将开始分区操作 枢轴选择策略:选取最右端元素 T(n) = O(n log n) 点击自动播放或手动步进开始演示
稀疏检索概念
阿诚的笔记本正面是书名,背面是词表。客人问“训练”,他哗啦啦翻到“训练”那一页,上面密密麻麻写着一长串书名。这套“从词反查书”的索引方式,在计算机里有个名字叫倒排索引:与“一页页翻书找词”(正排)相反,它提前建好“词 → 文档列表”的映射,因此书店再大,查询也是瞬间的事。
不过,要建这张表,得先把每本书拆成一个个词装进“袋子”里——这就是词袋模型:丢词语序、丢掉语法,只记录“哪些词出现了、出现了几次”。每本书用一个向量表示,向量每一维对应词典里的一个词。
问题来了:中文分词后词典规模轻松达到几万到几十万,而一本书只包含其中一小部分词。于是这个向量绝大多数位置是 0——“稀疏”二字由此而来。若没有倒排索引,每次查询都要遍历所有书籍算相似度,成本高得吓人;有了索引,查询时直接取文档列表、求交集、排序即可。
阿诚的土笔记本,本质就是一本手写倒排索引。词袋模型、稀疏向量、倒排索引这三件套,构成了 TF-IDF 与 BM25 表演的舞台:
阿诚的笔记本证明了一件事:检索快不快,不取决于书有多少,而取决于索引怎么建。接下来,阿诚要解决一个更棘手的问题——同一本书里,哪个词才是真正带客人找到书的“钥匙”。
- 文档向量每本书变成一个向量 \(\vec{d}\),它的维度数等于词典大小 \(n\),就像给笔记本预留了 \(n\) 个词条位。
- 分量含义第 \(i\) 维 \(w_{t_i}\) 表示词典第 \(i\) 个词在这本书里的权重,可以是次数也可以是加权分。
- 稀疏条件非零分量的个数远小于 \(n\),因为一本书实际用到的词非常有限。
- 空间直觉数万维空间中只有零星几点“亮灯”,其余全黑——这就是稀疏向量独有的特征形态。
TF-IDF原理
阿诚很快发现,光数次数会出大错。“的”在一本书里出现几百次,但客人从不靠“的”找书。真正有用的词必须同时满足两条:在眼前这本书里出现得多(词频高),在整个书店里却很少出现(稀缺)。前者英文叫 TF(Term Frequency),后者叫 IDF(Inverse Document Frequency,逆文档频率)。
在计算机里,TF 就是词在文档中的出现次数,或者归一化后的频率。IDF 用对数公式计算:\(N\) 是语料库文档总数,\(\text{df}(t)\) 是包含词 \(t\) 的文档数。“的”几乎每篇都有,df 接近 N,IDF 趋近 0;而“量子纠缠”只在少数几篇出现,IDF 很大。这正是信息论里的直觉:越稀有的信号,携带的信息量越大。
TF-IDF 把两个信号相乘。一篇文章里“小狗”出现 8 次、全库只有 30 篇提到它,得分就很高;而“的”出现 800 次、全库 1 万篇都有它,得分几乎为零。经典用法有两种:一是提取文档关键词(取 Top 词),二是把查询和文档都转成 TF-IDF 向量,用余弦相似度排序。
阿诚给笔记本改版:每个词条不再只记“在哪本书出现”,还补上了“全店有多少本书也有这个词”。改版成本极低,找书准确率却立竿见影。第一代心法,就此诞生:
阿诚的“数次数”哲学从第一代就定型了:一靠本地频率,二靠全局稀缺。这套思路简单优美,可它还有一个致命伤——阿诚很快会被一本厚得离谱的大百科狠狠上一课。
- 词频项\(f(t,d)\) 是词 \(t\) 在文档 \(d\) 里出现的次数,代表“这本书里这个词多不多”。
- 文档总数\(N\) 是语料库所有文档的数量,对应阿诚笔记本里登记的书的总数。
- 文档频率\(\text{df}(t)\) 是包含词 \(t\) 的文档数量,代表“这个词在整家书店里有多少本”。
- 对数稀缺度\(\log(N/\text{df}(t))\) 越大,词越罕见;大路货的比值接近 1,对数后趋近 0。
- 权重相乘高频且稀缺的词语得分高;高频但常见(如“的”)或稀缺但低频的词都被压制。
BM25改进
阿诚发现 TF-IDF 有两个漏洞。第一:“小狗”在一本书里出现 100 次,难道比出现 10 次有用 10 倍?客人翻两页就明白了,多出的 90 次多半是废话——词频的收益会“饱和”。第二:一本 1000 页的大百科里 30 次“训练”,和一本 100 页的小册子里 30 次,含金量完全不同——长文档天生更容易堆词频,必须按长度“打折”。
BM25 诞生于 90 年代,是 Robertson 等人在概率检索框架下提出的第二代稀疏检索公式。它保留了 IDF 项,但把词频项从直线改成一条饱和曲线,并加入文档长度归一化。公式里出现两个新参数:\(k_1\) 控制饱和速度(词频涨到多少开始“腻”),\(b\) 控制长度惩罚力度(对厚书多狠)。
在 RAG 与搜索引擎里,最常用的是 BM25 的原始形式:对查询里的每个词,先算带平滑的 IDF,再乘上经过饱和与长度归一化处理的词频项,最后把所有词的贡献加起来。这个公式看似吓人,拆开看其实就四块积木:IDF 负责压制大路货,分子保证词频越高分越高,分母让增长曲线封顶,长度因子让厚书不占便宜。
阿诚给笔记本加装了两个旋钮,调了两周后感慨:第二代的稳,体现在“公平”二字——长书不再靠字数欺负短书,一个词刷再多遍,分数也不会无限膨胀:
阿诚合上笔记本,两代心法已在他脑中形成对比图:一条直线冲天,一条曲线封顶。那么问题来了——换了第二代之后,检索效果真的全面碾压吗?
- 带平滑的 IDF\(\text{IDF}(t) = \log\left(1 + \frac{N - \text{df}(t) + 0.5}{\text{df}(t) + 0.5}\right)\),0.5 平滑避免除零,也保证 IDF 非负。
- 词频分子\(f(t,D) \times (k_1+1)\) 保证词频越高分数越高,但增长被下面积的分母限制住。
- 饱和分母\(f + k_1\) 让词频项随着 \(f\) 增大趋近一个上限,这就是“饱和”的数学来源。
- 长度归一化\(|D|/\text{avgdl}\) 是文档相对长度,大于 1 表示它比平均文档长,要被打折。
- 参数封顶当词频 \(f\) 趋于无穷,词频分量收敛到 \(k_1+1\),不会像 TF-IDF 那样无限上涨。
检索效果对比
阿诚把两代笔记本并排测试:同一个书库、同一批查询,看谁排得准。三周下来,结论清晰又有趣。
先说长文档表现。TF-IDF 最容易吃亏:一本 1000 页的烹饪百科里“训练”出现 60 次,得分轻松超过一本 100 页的训犬手册里出现 30 次。可明眼人都知道后者才是客人要的。BM25 的长度归一化直接改写了局面——按相对词频比,短书的“含金量”立刻凸显。再说停用词抑制:两者都靠 IDF 压低“的、了、和”这类高频词,但 BM25 的平滑 IDF 更稳健,不会因为某个词恰好出现在一半文档里而产生剧烈波动。
不过,两代心法共享同一个天花板——只认字面,不认语义。“苹果手机”和“iPhone 新品”互相找不到对方;“车”和“汽车”在词典里是两个毫不相干的维度;用户说“胸口闷”,指南里写“胸闷”,词面失配直接漏召回。这就是稀疏检索的固有边界,也是稠密检索(向量嵌入)存在的理由。
所以选型建议很实用:产品型号、人名、法条编号、代码符号这类精确硬匹配场景,用稀疏检索又快又准还可解释;开放式的同义改写、口语化查询,用稠密检索;通用 RAG 里,两者往往是互补搭档而非竞争对手。数学上,两代算法最本质的分歧就藏在极限里:
阿诚顿悟:心法再老练,也看不见“意思”。那句“苹果手机”始终匹配不上"iPhone",成了他后来加入 RAG 项目时最重要的伏笔。
- 左侧极限BM25 词频分量在词频趋于无穷时收敛到常数 \(k_1+1\),分数有边界。
- 右侧极限TF-IDF 里的词频项 \(f\) 直接线性发散,单靠一个词就能把分数顶到天。
- 对比结论一个“封顶”、一个“没顶”,这就是靠堆词刷分在 BM25 下失效的根本原因。
RAG融合方案
RAG(检索增强生成)通俗说就是给大模型“外挂知识库”:用户提问后,先从文档库捞 Top-K 片段,再把这些片段连同问题一起喂给大模型生成答案。阿诚退休后被一家企业知识问答公司请去当搜索顾问,很快发现:只靠第二代心法还是不够。
标准方案是混合检索:BM25 跑一路关键词候选,稠密检索(向量相似度)跑一路语义候选,两路结果合并后统一排序。但这里藏着一个大坑——BM25 的得分是几十到几百的累计值,稠密检索的余弦相似度在 -1 到 1 之间。两把尺子刻度完全不同,直接相加等于稠密检索被无视。
解决办法分三步:先做分数归一化(MinMax 把两路分数各自压到 0~1),再做加权融合(用权重 \(\alpha\) 调配关键词与语义的占比),最后可选做重排序(用更精细的模型对 Top 候选精排)。也有更省事的替代方案叫 RRF(倒数排名融合),不看分数只看名次,把两路排名取倒数相加。
阿诚把两代笔记本变成一条流水线:关键词保证“找得到”,语义负责“找得对”,大模型负责“答得好”。这套流程如今是 RAG 工程的标配:
阿诚在项目复盘会上说了一句大实话:检索不是选边站队,而是让两代心法各司其职。但也有人追问——BM25 那两个旋钮到底怎么拧才顺手?答案藏在语料里。
- MinMax 归一化把 BM25 原始分数线性压缩到 0~1,消除与向量相似度的量纲差异。
- 融合权重\(\alpha \in [0,1]\) 控制关键词检索的占比,经验值在 0.3~0.5 之间。
- 综合排序语义分支占剩余权重,融合分数降序取 Top-K,作为送入大模型的上下文。
参数调优实践
阿诚带徒弟,先教认识两个旋钮。\(k_1\) 是“词频信任度”:调大等于相信“多出现真的更有用”,词频影响接近线性;调小等于“出现两三次我就信了,再多也不加分”。\(b\) 是“厚书偏见”:调大对长文档惩罚重,调小则一视同仁。两者配合,决定了 BM25 的个性。
经验的默认值是 \(k_1=1.2\sim2.0\)、\(b=0.75\),但这是长文本通用语料调出来的。如果你的语料是短标题、FAQ、商品名,词频普遍偏低,饱和机制几乎不触发,可以调小 \(k_1\);如果文档长度差异悬殊(比如既有 50 字的公告又有 5 万字的白皮书),需要调大 \(b\) 强化长度惩罚。此外还要做语料适配:中文要选对分词器,中英混合要处理大小写与特殊字符。
怎么判断调得好不好?不能凭感觉。用带标注的检索评估集算 Recall@K、MRR、NDCG,或者直接看 RAG 端到端的答案质量。调参时用小步网格搜索:\(k_1\) 在 \([0.5, 3.0]\)、\(b\) 在 \([0, 1]\),步长 0.1~0.25,让评估指标自己说话。调参的本质不是找魔法数字,而是对齐你的语料分布。
阿诚在笔记本最后一页写道:算法是死的,语料是活的。参数不是魔法,是对语料的尊重。把旋钮拧到合适的位置,第二代心法才算真正在你手里落了地:
两个旋钮拧完,阿诚的心法传授也接近尾声。从词袋到倒排索引,从 TF-IDF 到 BM25,再到 RAG 里的混合检索——这套“关键词召回”的地基,你已经有了一幅完整地图。
- 简化分量去掉 IDF 与长度归一化,只看词频饱和部分,方便单独研究 \(k_1\) 的影响。
- k1 的作用\(k_1\) 越大,分母中 \(f\) 的权重越小,曲线越接近直线;\(k_1\) 越小饱和来得越快。
- 边界验证\(f=0\) 时得 0;\(f=k_1\) 时恰好得到封顶值的一半,这是快速理解饱和的好抓手。
- 调参直觉想快速感受版本差异,先固定 \(b\) 只动 \(k_1\),在验证集上对比 Recall@K 曲线。
AI 应用场景
企业知识库的关键词召回
阶段:检索召回(Retrieval)
解决的问题:企业内部知识库充满产品型号、合同编号、法条序号等“精确词”,纯语义检索极易把这些词向量化后混淆。BM25 按字面精确命中、毫秒级响应,且结果可解释——命中了哪些词一目了然,这正是硬匹配场景最需要的特性。
具体案例:某保险公司上线 RAG 问答,用户问“重疾险条款第 12 条赔付比例”,稠密检索召回的是语义相近的健康告知段落;接入 BM25 后精确命中“第 12 条”,与稠密候选按 0.4:0.6 融合,答案准确率提升约 22%。
医疗问答的混合检索
阶段:结果融合与重排序
解决的问题:用户描述症状用的是生活化口语(“胸口闷”),医学指南写的是“胸闷”,词面不匹配导致 BM25 漏召回;而纯稠密检索又容易召回无关段落。双路召回再融合能同时保住术语精确与语义泛化。
具体案例:某在线问诊平台用 BM25 召回指南关键词段落、用向量检索召回同义口语段落,各取 Top 20 后用 RRF 合并、精排取 Top 5 喂给大模型。上线后医生对检索片段的采纳率从 63% 提升到 81%。
电商搜索快速冷启动
阶段:检索召回(Baseline)
解决的问题:新店铺没有用户行为数据,无法训练学习排序模型;TF-IDF 作为零成本基线,按标题词面召回即可快速上线,之后再平滑迭代为 BM25 或向量检索。逻辑简单、好排查,特别适合业务早期快速验证。
具体案例:某跨境电商上架 5 万件新品,先用 TF-IDF 做关键词召回 MVP,上线当天即可搜索;两周后切换 BM25 并将 \(k_1=1.2\)、\(b=0.6\) 适配短标题语料,搜索点击率提升 9%。
Python 演示
import mathimport refrom collections import Counter class TFIDF: """TF-IDF: 词频 x 逆文档频率, 稀疏检索第一代""" def __init__(self, docs): self.tokens_list = [self._tokenize(d) for d in docs] self.N = len(docs) self.df_map = Counter() for tokens in self.tokens_list: for term in set(tokens): self.df_map[term] += 1 def _tokenize(self, text): return re.findall(r'[\w\u4e00-\u9fff]+', text.lower()) def score(self, doc_index, query): tokens = self.tokens_list[doc_index] total = 0.0 for term in set(self._tokenize(query)): tf = tokens.count(term) / len(tokens) idf = math.log(self.N / (self.df_map[term] + 1)) total += tf * idf return total class BM25: """BM25: 在 TF-IDF 上加入词频饱和与长度归一化""" def __init__(self, docs, k1=1.5, b=0.75): self.tokens_list = [self._tokenize(d) for d in docs] self.N = len(docs) self.k1 = k1 self.b = b self.avgdl = sum(len(t) for t in self.tokens_list) / self.N self.df_map = Counter() for tokens in self.tokens_list: for term in set(tokens): self.df_map[term] += 1 def _tokenize(self, text): return re.findall(r'[\w\u4e00-\u9fff]+', text.lower()) def score(self, doc_index, query): tokens = self.tokens_list[doc_index] tf_map = Counter(tokens) dl = len(tokens) total = 0.0 for term in set(self._tokenize(query)): if term not in tf_map: continue freq = tf_map[term] denom = freq + self.k1 * (1 - self.b + self.b * dl / self.avgdl) idf = math.log(1 + (self.N - self.df_map[term] + 0.5) / (self.df_map[term] + 0.5)) total += idf * freq * (self.k1 + 1) / denom return total def rank_all(model, docs, query): scored = [(index, docs[index], model.score(index, query)) for index in range(len(docs))] return sorted(scored, key=lambda item: item[2], reverse=True) if __name__ == "__main__": docs = [ "书店里有很多训练小狗的方法手册", "训练小狗需要耐心和零食奖励", "苹果手机发布了新款旗舰机", "如何挑选新鲜的苹果", "机器学习模型训练需要大量数据", ] query = "训练 小狗" for model, name in [(TFIDF(docs), "TF-IDF"), (BM25(docs), "BM25")]: print("==== %s 排序结果 ====" % name) for index, doc, score in rank_all(model, docs, query): print(" score=%.4f %s" % (score, doc))
self.df_map = Counter()统计每个词出现在多少篇文档中,为 IDF 做准备。idf = math.log(self.N / (self.df_map[term] + 1))TF-IDF 的稀缺度项,加 1 防除零。denom = freq + self.k1 * (1 - self.b + self.b * dl / self.avgdl)BM25 分母中的长度归一化核心。total += idf * freq * (self.k1 + 1) / denom稀缺度、词频、饱和三者相乘的完整 BM25 打分。sorted(scored, key=lambda item: item[2], reverse=True)按分数降序输出,得到最终检索排名。
常见误区
误区“BM25 不是全面升级版吗?那我直接把所有 TF-IDF 的代码换成 BM25 默认参数就完事了,效果肯定更好。”
正解不一定。BM25 的优势来自词频饱和与长度归一化,但这两个特性依赖语料形态。在短标题、词频普遍很低的场景里,饱和机制几乎不触发,两者差距很小;而默认参数是在长文语料上调出来的,用在新闻标题库上,长度归一化反而可能误伤短小精悍的文档。换算法之前,先拿一个小评估集跑一版对比,让数据说话。
为何常见:各类教程都强调 BM25 是 TF-IDF 的“进化版”,容易让人忽略它在新语料上同样需要适配。
误区“一篇文档里'苹果'出现 80 次,另一篇只出现 5 次,那 80 次那篇肯定更相关,排名应该更高。”
正解词频的边际收益是递减的。一个词出现 10 次已足以说明主题,再多往往来自篇幅或刻意堆砌。BM25 设计饱和曲线正是为了纠正这件事——80 次相对 5 次的分数优势远没有 16 倍。TF-IDF 在这点很吃亏,长文档可以靠重复词“刷分”,这也是它和 BM25 最核心的行为差异。
为何常见:“数量多 = 重要”符合直觉,但忽略了长文档天然词频更高这个混淆因素。
误区“既然 IDF 衡量稀缺度,那我选 IDF 最大的词当查询词,检索结果一定最精准。”
正解IDF 大只说明词在语料中罕见,不代表它与查询意图相关。一个拼写错误或生僻型号可能 IDF 极高,但几乎不出现在任何相关文档里,检索结果依然为空或噪声。IDF 的正确用途是压制停用词、放大可区分度,而不是单独充当相关性度量——相关性由词频和稀缺度共同决定。
为何常见:把“区分度”误解成“重要性”,忽略了查询与文档的匹配还需要词频来验证。
误区“既然 BM25 也对文档打了分,那我用 BM25 就能完成语义检索,同义词不用额外处理。”
正解稀疏检索只看词面是否出现。“汽车”和“车辆”在词典里是两个完全独立的维度,互相匹配不上;同义改写、指代消解、语序变化都会导致漏召回。这正是 RAG 中引入稠密检索(向量嵌入)的原因:稀疏负责精确硬匹配,稠密负责语义泛化,两者配合而非互相替代。
为何常见:大模型时代大家对“语义”太熟悉,容易误以为所有打分模型都懂语义,忽略了词袋模型天然丢失语义结构。
面试题
Q1. TF-IDF 中 IDF 的主要作用是什么?
- A.衡量词在单篇文档中的频率
- B.衡量词在整个语料中的稀缺度← 正确答案
- C.衡量文档长度并做归一化
- D.计算查询中关键词的数量
答案:B。IDF 的公式是 \(\log(N/\text{df})\),文档总数除以包含该词的文档数再取对数,衡量的是词在全语料中的稀缺程度。“的”“了”几乎每篇都有,IDF 趋近 0;专有名词 IDF 很大。A 描述的是 TF,C 是 BM25 长度归一化做的事,D 与 IDF 无关。
Q2. 稀疏检索中“稀疏”指的是什么?
- A.向量维度数值很小
- B.向量中绝大部分元素为零← 正确答案
- C.向量中所有元素数值都很大
- D.向量中只能存储正整数值
答案:B。词典规模有数万到数十万维,一篇文档只包含其中少量词,所以向量绝大多数维度是 0,非零维度很少,这就是“稀疏”。维度本身并不小,元素也不都很大,权重更不限于整数(BM25 打分就是小数)。
Q3. BM25 相比 TF-IDF 引入哪两个关键改进?
- A.词向量与自注意力机制
- B.倒排索引与缓存优化
- C.词频饱和与文档长度归一化← 正确答案
- D.停用词过滤与智能分词
答案:C。BM25 把词频项从线性改成饱和曲线(词频再高分数封顶),并加入 \(|D|/\text{avgdl}\) 长度归一化,解决长文档刷词频的问题。词向量与注意力属于深度模型,倒排索引两代算法都要用,停用词过滤只是预处理步骤。
Q4. BM25 中参数 b 的主要作用是什么?
- A.控制词频饱和的快慢速度
- B.控制逆文档频率的平滑程度
- C.控制文档长度的惩罚强度← 正确答案
- D.控制查询词数量的多少范围
答案:C。b 出现在 \(1-b+b\cdot|D|/\text{avgdl}\) 中,决定文档相对长度对分母的影响。b=0 时完全不看长度,b 越大长文档惩罚越强。k1 控制饱和速度,IDF 的平滑由 +0.5 项完成,查询词数量由用户输入决定。
Q5. 其他条件不变,k1 调大后词频对 BM25 分数的影响如何变化?
- A.词频影响越接近线性增长← 正确答案
- B.词频影响会越快趋于饱和
- C.词频影响将不再起作用
- D.词频影响会变为指数增长
答案:A。词频分量 \(f(k_1+1)/(f+k_1)\) 中,k1 越大分母里 f 的系数越小,曲线越平直、越接近线性;k1 越小饱和来得越快。封顶值 \(k_1+1\) 是常数,所以不可能指数增长,更不会失效。
Q6. 混合检索中为什么必须先把两路分数归一化?
- A.因为 BM25 和稠密分数量纲完全不同← 正确答案
- B.因为查询词必须编码成同一向量
- C.因为需要把文档长度统一对齐
- D.因为两路分数全部都是负值
答案:A。BM25 得分是几十到几百的累计分,稠密检索是余弦相似度(约 -1 到 1),直接相加等于稠密检索被淹没。MinMax 归一化把两路都压到 0~1 再加权,融合才有意义。长度对齐是 BM25 内部的事,编码统一属于稠密分支的设计。
Q7. 当词频 f 趋于无穷时,BM25 的词频分量趋近于?
- A.趋近于无穷大的数值
- B.趋近于 k1 加一的常数← 正确答案
- C.趋近于参数 b 的倒数
- D.趋近于零没有任何效果
答案:B。求极限 \(\lim_{f\to\infty} f(k_1+1)/(f+k_1) = k_1+1\)。这就是“饱和”的数学表达:不管词出现几百次,贡献封顶为 \(k_1+1\) 倍 IDF。而 TF-IDF 的词频项线性发散,这正是两者最核心的数学分歧。
Q8. 哪些场景更适合选用稀疏检索?
- A.产品型号的精确匹配场景← 正确答案
- B.法律条文的关键词查询场景← 正确答案
- C.同义改写后的语义查询应用
- D.代码片段与日志检索场景← 正确答案
答案:ABD。稀疏检索擅长字面硬匹配:型号、法条编号、代码符号都是精确词且可解释性强。同义改写、口语化表达是它的短板,应交给稠密检索或混合检索处理,所以 C 应排除。
Q9. 关于 BM25 参数调优,正确的做法是?
- A.文档偏长时适当增大 b 值← 正确答案
- B.直接套默认参数从不评估
- C.调整后用验证集对比指标← 正确答案
- D.把 k1 设为零让词频失效
答案:AC。语料普遍偏长时增大 b 能强化长度惩罚;每次调整必须用 Recall@K、MRR 等评估集指标验证。从不评估无法知道参数好坏;把 k1 设为 0 会使词频分量对所有词恒为 1,词频彻底失去区分度,属于典型错误调参。
Q10. 关于 TF-IDF 与 BM25 的说法,正确的有?
- A.TF-IDF 的词频贡献是线性增长← 正确答案
- B.BM25 对长文档的评分更公平← 正确答案
- C.两者都基于词面匹配原理← 正确答案
- D.BM25 已经完全不受 IDF 影响
答案:ABC。TF-IDF 词频项就是 f,确实线性增长;BM25 用长度归一化避免长文档靠篇幅刷分;两者都在词面层匹配,不懂同义词。BM25 公式里保留了 IDF 项且做了平滑,D 说法错误。