深夜的美食街上,老饕老王想找一道“苹果清甜中带着一点香蕉醇香”的菜。他没有挨家挨户翻菜单,而是闭上眼睛想象:每道菜都可以抽象成一张“食材用量表”——苹果 3 份、香蕉 1 份、盐 0.5 份……他自己心里那团渴望,其实也是一张“心愿用料表”。两张表越接近,这道菜就越可能合胃口。 向量空间模型(Vector Space Model,VSM)做的正是这件事。它把每篇文档变成一张“配料表”(文档向量),把你的查询也变成一张“配料表”(查询向量),然后在高维空间里比较两个向量的夹角:夹角越小,说明文档与查询的“口味”越一致,相关度越高。这个诞生于上世纪六七十年代的经典模型,统治了搜索引擎超过二十年。本篇用“点菜找菜”这条线索,带你拆解 VSM 的每一张配方卡:文档如何变成向量、词频和逆文档频率各管什么、余弦相似度怎么算,以及它今天为什么仍是轻量检索与教学场景的“出厂配置”。

岗位关联

掌握向量空间模型,等于拿到信息检索的“出厂设置”:既能理解搜索排序的原理与局限,也能在工程中用最轻量的方案快速落地检索需求,并为理解 BM25 与神经检索打下地基。

目录
  1. 可视化演示
  2. 核心思想:一切从口味空间说起
  3. 文档表示:先把菜谱变成配料清单
  4. TF 词频:这道菜下了多少料
  5. IDF 权重:这味料有多特别
  6. 余弦相似度:两道菜的默契度
  7. TF-IDF 组合:合出最终权重
  8. 工程与局限:后厨的苦与天花板
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示系统处理流水线、实时性能指标曲线及多方案对比分析,包含数据流转、吞吐延迟监控与方案评估。

本节配有交互动效(进入视口后自动加载,约 3KB)。

系统可视化 处理流程:输入→处理→模型→输出 性能监控:实时指标 P=L×T

核心思想:一切从口味空间说起

老王逛美食街的经验告诉我们一个道理:找菜的本质不是“逐字逐句读菜单”,而是把菜和心愿都抽象成可比较的“配方表”。向量空间模型的创始人 Gerard Salton 在 1960 年代把这个直觉变成了数学:文档是一张配方表,查询也是一张配方表,剩下的工作就是比较两张表有多接近。

具体来说,VSM 只做三件事。第一,把文档映射成一个向量;第二,把查询映射成相同空间里的另一个向量;第三,计算两个向量的夹角相关性,夹角越小,相关度越高。这个“空间”的每个维度都由词典中的一个词充当坐标轴,向量在每个维度上的取值,就是该词在这篇文档中的权重。

于是文档 $d$ 被写成下面的形式:

回到老王的故事:只要美食街每个档口都贴一张数字配方,再用同一套规则把心愿也画成配方,剩下的比较就能交给“夹角”了。接下来六节,就是把这张配方卡一步步拆开看。

d⃗=(w1,d,w2,d,…,wn,d)\vec{d} = (w_{1,d}, w_{2,d}, \dots, w_{n,d})
这个式子是说:一篇文档不再是一串文字,而是一串数字。每个数字代表“词典里第 i 个词在这篇文档里有多重要”,所有数字排在一起,就构成了文档在高维空间中的坐标。
  1. 向量整体 $\vec{d}$带箭头的 $d$ 表示这是“文档 d”对应的多维向量,而不是单个数字。
    d⃗=(w1,d,w2,d,…,wn,d)\vec{d} = (w_{1,d}, w_{2,d}, \dots, w_{n,d})
  2. 权重分量 $w_{i,d}$下标 $i$ 指向词典中第 $i$ 个词,$w_{i,d}$ 就是这个词在文档 $d$ 中的权重。
    wi,dw_{i,d}
  3. 维度个数 $n$$n$ 等于词典大小,通常达到数万甚至数十万,决定了向量空间有多“高维”。
    n=∣V∣n = |V|

文档表示:先把菜谱变成配料清单

老王记菜谱有个习惯:只记“苹果 3 个、香蕉 1 根、盐半勺”,从不记“先放盐还是后放糖”。因为决定味道的是配料和用量,而不是下锅顺序。VSM 的“词袋模型”(Bag of Words)就是这个思路——把文档拆成一袋子词,无视顺序和语法,只统计每个词出现了几次。

在工程上,这一步要先做预处理:分词把句子切成词,去停用词丢掉“的、了、在”这类高频无意义词,必要时再做词干还原。然后构建词典,词典里的每一个词就是向量空间里的一个坐标轴。最后逐篇统计次数,把文档变成计数向量:

词袋向量有一个鲜明的性格:稀疏。一篇文档通常只用到词典里一小部分词,绝大多数分量为 0——就像一盘菜不可能用上超市里所有食材。稀疏高维是 VSM 后续一切工程技巧(倒排索引、稀疏存储)的出发点。

dj=(c1j,c2j,…,cmj),cij=count(ti,dj)d_j = (c_{1j}, c_{2j}, \dots, c_{mj}), \quad c_{ij} = \text{count}(t_i, d_j)
这个式子把“文档”翻译成“计数向量”:第 $j$ 篇文档的向量里,第 $i$ 个分量就是词典第 $i$ 个词在这篇文档里出现的次数。比如“苹果 3 次、香蕉 1 次”,其他词 0 次。
  1. 文档下标 $j$用 $d_j$ 表示语料库里的第 $j$ 篇文档。
    djd_j
  2. 计数分量 $c_{ij}$$c_{ij}$ 是词 $t_i$ 在文档 $d_j$ 中的出现次数——这就是最原始的“配料用量”。
    cij=count(ti,dj)c_{ij} = \text{count}(t_i, d_j)
  3. 维度个数 $m$$m$ 是词典总词数,因此每篇文档向量都有 $m$ 个分量。
    m=∣V∣m = |V|

TF 词频:这道菜下了多少料

同样一道苹果派,老王想知道苹果味到底有多浓。单纯看“苹果出现了几次”不够公平:一份 300 克的大份苹果塔和一份 100 克的小份苹果塔,苹果的绝对次数差了好几倍,但口味浓度可能完全一样。词频(Term Frequency,TF)解决的就是这个“浓度”问题。

TF 的经典做法是长度归一化:用词在文档中的出现次数,除以文档的总词数。这样一来,长文档天然“次数多”的偏差就被抵消了,得到的是一个 0 到 1 之间的相对浓度:

工程上还有进一步改良:对次数做子线性缩放(如 $1 + \log c$),让疯狂重复的词不至于无限霸榜——就像盐放得再多,菜也不会因此“更有营养”。但 TF 只解决了“下料足不足”,还没回答“料够不够特别”,这正是下一节 IDF 登场的原因。

tft,d=ct,d∑k=1nck,dtf_{t,d} = \frac{c_{t,d}}{\sum_{k=1}^{n} c_{k,d}}
这个式子计算“词 t 在文档 d 中的浓度”:分子是词 t 出现的次数,分母是文档所有词出现的总次数,两者相除得到一个比例。100 克小份里的“苹果 3 次”和 300 克大份里的“苹果 9 次”,比值相同,浓度就相同。
  1. 分子 $c_{t,d}$词 $t$ 在当前文档中出现的原始次数。
    ct,d=count(t,d)c_{t,d} = \text{count}(t, d)
  2. 分母 $\sum_{k=1}^{n} c_{k,d}$把文档里所有词的次数加起来,等于文档总词数。
    ∑k=1nck,d=len(d)\sum_{k=1}^{n} c_{k,d} = \text{len}(d)
  3. 比值 $tf_{t,d}$次数占比,取值在 0 到 1 之间,表示词在文档中的相对浓度。
    tft,d∈[0,1]tf_{t,d} \in [0, 1]

IDF 权重:这味料有多特别

老王点菜有一条铁律:说“来点咸的”等于没说,因为每道菜都有盐;可要是说“要松露味”,整条美食街瞬间只剩一个档口够格。词的“信息量”恰恰藏在这种稀有度里。逆文档频率(Inverse Document Frequency,IDF)就是度量“稀有度”的尺子。

先定义文档频率 $df_t$:整个语料库中“包含词 $t$”的文档篇数。$df_t$ 越大,说明词越常见、越没有区分度。IDF 用总文档数除以它再取对数:

工程上为了防止某个词从未出现导致除零,常在分母加 1(如 $\log \frac{N}{df_t + 1}$)。至此,老王手里的配方卡有了两列信息:下料浓度(TF)和佐料稀缺度(IDF)。但怎么把两列信息合起来判断“方向一致”,还得靠余弦相似度。

idft=log⁡Ndftidf_t = \log \frac{N}{df_t}
这个式子计算“词 t 的稀有奖励”:$N$ 是语料中文档总数,$df_t$ 是包含词 t 的文档数。比值越大,词越稀有,IDF 越高;反之,“的、了”几乎出现在所有文档里,比值接近 1,IDF 趋近 0,权重自动被压低。
  1. 文档频率 $df_t$数一数有多少篇文档包含了词 $t$——注意是“篇数”,不是“出现次数”。
    dft=∣{d:t∈d}∣df_t = |\{d : t \in d\}|
  2. 文档总数 $N$语料里所有文档的篇数,是衡量“全”的基准。
    NN
  3. 稀有度比值 $\frac{N}{df_t}$比值越大,词越稀有;最小为 1(词出现在所有文档),最大为 $N$(词只出现在一篇文档)。
    Ndft∈[1,N]\frac{N}{df_t} \in [1, N]
  4. 对数 $\log$把差距压缩,防止极端稀有词的权重爆炸,同时让中间地带更平滑。
    idft=log⁡Ndftidf_t = \log \frac{N}{df_t}

余弦相似度:两道菜的默契度

有了配方,老王开始比较:他直接忽略“分量”看“方向”。一份苹果:香蕉 = 2:1 的大盘沙拉,和一份同样配比的迷你沙拉,对他来说就是同一种味道——方向一致,只是量不同。余弦相似度衡量的正是这种“方向一致性”,它对向量长度不敏感。

计算余弦相似度,需要两个向量做点积,再各自除以模长。点积衡量两向量在相同维度上的重合程度(查询里出现的词,文档里有没有、权重高不高);模长相当于向量的“总长度”。公式如下:

这解释了为什么 VSM 不用欧氏距离:两份文档一份是另一份的三倍长但配比完全相同,余弦给满分,欧氏距离却判它们“很远”。老王要的是“味道合不合”,不是“分量大不大”,所以余弦才是他的知己。

cos⁡(q⃗,d⃗)=q⃗⋅d⃗∥q⃗∥⋅∥d⃗∥=∑i=1nqidi∑i=1nqi2⋅∑i=1ndi2\cos(\vec{q}, \vec{d}) = \frac{\vec{q} \cdot \vec{d}}{\|\vec{q}\| \cdot \|\vec{d}\|}= \frac{\sum_{i=1}^{n} q_i d_i}{\sqrt{\sum_{i=1}^{n} q_i^2} \cdot \sqrt{\sum_{i=1}^{n} d_i^2}}
这个式子是全篇的灵魂:分子是查询与文档向量的点积,分母是两个向量模长的乘积。点积除以模长积之后,向量的绝对长度被“归一化”了,剩下的就是方向夹角的余弦值。值越接近 1,方向越一致,相关性越高。
  1. 点积 $\vec{q} \cdot \vec{d}$把查询和文档在同一个词上的权重相乘,再对所有词求和——重合的词越多、权重越高,得分越大。
    q⃗⋅d⃗=∑i=1nqidi\vec{q} \cdot \vec{d} = \sum_{i=1}^{n} q_i d_i
  2. 模长 $\|\vec{q}\|$查询向量的长度,等于各分量平方和再开根号。
    ∥q⃗∥=∑i=1nqi2\|\vec{q}\| = \sqrt{\sum_{i=1}^{n} q_i^2}
  3. 分母 $\|\vec{q}\| \cdot \|\vec{d}\|$两个模长相乘,起到归一化作用,把不同长度的向量拉回同一尺度。
    ∥q⃗∥⋅∥d⃗∥=∑i=1nqi2⋅∑i=1ndi2\|\vec{q}\| \cdot \|\vec{d}\| = \sqrt{\sum_{i=1}^{n} q_i^2} \cdot \sqrt{\sum_{i=1}^{n} d_i^2}
  4. 结果范围余弦值落在 $[-1, 1]$;检索场景权重非负,实际通常落在 $[0, 1]$。
    cos⁡(q⃗,d⃗)∈[−1,1]\cos(\vec{q}, \vec{d}) \in [-1, 1]

TF-IDF 组合:合出最终权重

TF 回答“下料足不足”,IDF 回答“料够不够特别”,只用任何一个都会偏科。只看 TF,“盐、水”这类每道菜都有的原料必然霸榜;只看 IDF,全文只出现一次的错别字可能稀有到反常,却毫无意义。VSM 的标准做法是把两者乘起来,合出每个词在文档中的最终权重:

对老王来说,苹果这道主料既在下料表里分量足(TF 高),又在整条街的菜单里不算泛滥(IDF 中高),于是权重被放大;而“盐”因为家家都有,即使下料不少也被压制。一张 TF-IDF 权重向量,就是一份去粗取精的“独门配方”。

wt,d=tft,d×idft=ct,d∑kck,d×log⁡Ndftw_{t,d} = tf_{t,d} \times idf_t= \frac{c_{t,d}}{\sum_{k} c_{k,d}} \times \log \frac{N}{df_t}
这个式子把“浓度”和“稀缺度”相乘:一个词想获得高权重,必须同时在“这篇文章里出现得多”(TF 高)和“在整个语料里很少见”(IDF 高)。常见的“的、了”虽然 TF 可能不低,但 IDF 趋近 0,乘积自动归零;真正的主题词则两项都高,脱颖而出。
  1. TF 部分 $tf_{t,d}$词在本文档中的相对浓度,解决“这篇文章有多强调这个词”。
    tft,d=ct,d∑kck,dtf_{t,d} = \frac{c_{t,d}}{\sum_{k} c_{k,d}}
  2. IDF 部分 $idf_t$词的全局稀有度,解决“这个词在全语料里有多能区分文档”。
    idft=log⁡Ndftidf_t = \log \frac{N}{df_t}
  3. 乘积 $w_{t,d}$两值相乘,只有“既多又特别”的词才能拿到大权重。
    wt,d=tft,d×idftw_{t,d} = tf_{t,d} \times idf_t

工程与局限:后厨的苦与天花板

如果美食街有三百个档口,老王不会挨家精算夹角——他会先让跑堂的筛出“哪些档口确实用过苹果或香蕉”,再对候选们细致比较。搜索引擎的工程实现也是如此:先用“倒排索引”粗筛,再用 VSM 精算。

倒排索引是一张“反着查”的表:从词出发,直接找到包含它的文档列表。查询“苹果 香蕉”时,取两个词的文档列表求交集,得到候选集合;再对候选逐篇算余弦相似度并排序打分:

但 VSM 的天花板也很明显:词袋模型不懂语义、不读词序——“苹果咬了牛顿”和“牛顿咬了苹果”在它眼里完全相同,同义词也无法互相认出。正因如此,它才被加入饱和与长度归一化的 BM25、以及具备语义能力的神经检索模型超越。不过,无监督、可解释、零训练成本这些优点,让它至今仍是教学与轻量场景的标配,也是理解现代搜索的起点。

score(q,d)=∑t∈qwt,q⋅wt,d\text{score}(q, d) = \sum_{t \in q} w_{t,q} \cdot w_{t,d}
这个式子给出最终的检索打分:遍历查询中的每个词,把该词在查询里的权重和在文档里的权重相乘并累加。查询与文档共享的词越多、权重越大,得分越高。它是余弦相似度的分子部分,工程实现时通常先算它,再除以模长完成归一化。
  1. 求和符号 $\sum_{t \in q}$对查询中出现的每个词逐一处理,累加贡献。
    ∑t∈q\sum_{t \in q}
  2. 查询权重 $w_{t,q}$词 $t$ 在查询向量里的 TF-IDF 权重,代表用户有多强调它。
    wt,qw_{t,q}
  3. 文档权重 $w_{t,d}$词 $t$ 在文档向量里的 TF-IDF 权重,两者相乘得到该词的匹配贡献。
    wt,q⋅wt,dw_{t,q} \cdot w_{t,d}

AI 应用场景

企业知识库的轻量检索

阶段:检索与排序

解决的问题:中小团队没有 GPU、没有标注数据,用 SQL 的 LIKE 模糊查询只能做关键词匹配、无法按相关度排序;引入深度模型又周期太长。VSM 无需训练、当天可上线,用 TF-IDF + 余弦相似度就能把“匹配”升级为“按相关性排序”。

具体案例:某 SaaS 公司的工单系统沉淀了上万条历史工单。工程师把工单文本分词后用 TF-IDF 向量化,用户提交新问题时同样向量化,余弦相似度取 Top 5 推荐相似工单,客服效率提升明显。推荐逻辑与本文 Python 演示代码一致,只是用在线倒排索引做了候选粗筛。

新模型评估的基线对照

阶段:模型评估

解决的问题:评估一个神经检索模型时,需要知道“不学习也能达到多少分”,否则无法判断模型的提升到底来自语义理解还是数据泄露。VSM 是天然的无监督基线。

具体案例:研究员构建对话检索系统时,先用 VSM 跑出 MRR@10 基线,再对比双塔编码器的表现。如果神经模型只比 VSM 高几个点,就要反思训练数据或模型结构是否存在问题。

文本分类的特征工程

阶段:特征表达

解决的问题:传统机器学习模型无法直接吃原始文本,需要把文本变成数值特征。TF-IDF 向量可解释、与词表一一对应,配合线性模型就是高效的轻量分类方案。

具体案例:垃圾邮件分类中,团队将每封邮件转成 TF-IDF 向量,再训练逻辑回归分类器,几分钟完成训练即可上线拦截——这与神经分类器形成“成本-效果”的梯度互补。

Python 演示

python68 行
import mathimport refrom collections import Counter  def tokenize(text):    """按单词切分并转小写(中文场景替换为分词器即可)"""    return re.findall(r'\w+', text.lower())  class VectorSpaceModel:    """最小可用的向量空间模型:TF-IDF 加权 + 余弦相似度"""     def __init__(self, docs):        self.docs = [tokenize(d) for d in docs]        self.doc_freq = Counter()        for tokens in self.docs:            for term in set(tokens):                self.doc_freq[term] += 1        self.doc_count = len(self.docs)     def idf(self, term):        """IDF:文档总数除以含该词的文档数,再取对数"""        return math.log(self.doc_count / (1 + self.doc_freq[term]))     def tf(self, term, tokens):        """TF:词在文档中出现的次数占比"""        return tokens.count(term) / len(tokens)     def weight(self, tokens):        """把文档或查询转成 TF-IDF 权重向量(字典)"""        vec = {}        for term in set(tokens):            vec[term] = self.tf(term, tokens) * self.idf(term)        return vec     def cosine(self, v1, v2):        """余弦相似度:点积除以两个向量的模长乘积"""        if not v1 or not v2:            return 0.0        dot = sum(w * v2.get(t, 0.0) for t, w in v1.items())        norm1 = math.sqrt(sum(w * w for w in v1.values()))        norm2 = math.sqrt(sum(w * w for w in v2.values()))        return dot / (norm1 * norm2) if norm1 and norm2 else 0.0     def search(self, query, top_k=3):        """对查询打分,返回最相关的 top_k 个文档"""        q_vec = self.weight(tokenize(query))        scored = []        for i, tokens in enumerate(self.docs):            score = self.cosine(q_vec, self.weight(tokens))            scored.append((score, i))        scored.sort(reverse=True)        return scored[:top_k]  if __name__ == '__main__':    corpus = [        "apple banana apple orange",        "banana orange banana orange",        "apple apple apple banana",        "the fox jumps over the lazy dog",    ]    vsm = VectorSpaceModel(corpus)    query = "apple banana"    print("查询:", query)    for score, idx in vsm.search(query):        print("文档 %d 评分: %.3f" % (idx, score))
目的:用不到百行代码实现一个可运行的向量空间模型——先算 TF-IDF 权重向量,再用余弦相似度为查询检索最相关的文档。
  1. self.doc_freq[term] += 1统计每个词出现在几篇文档中,得到 df
  2. math.log(self.doc_count / (1 + self.doc_freq[term]))计算 IDF,分母加 1 平滑防止除零
  3. tokens.count(term) / len(tokens)归一化 TF:出现次数除以文档总词数
  4. for term in set(tokens)先对词去重,保证每个词只算一次权重
  5. sum(w * v2.get(t, 0.0) for t, w in v1.items())点积:相同词权重相乘再累加
  6. math.sqrt(sum(w * w for w in v1.values()))计算向量模长,供分母归一化
  7. return dot / (norm1 * norm2)余弦相似度:点积除以双模长积
  8. scored.sort(reverse=True)按相似度降序排列,取前 top_k 作为检索结果

常见误区

误区我以为 TF 越大,词对相关性的贡献就越大,所以文档里重复最多的词,应该就是最能代表这篇文档的词。

正解重复最多不代表最有区分度——“的、了、我们”在每篇中文文档里都高频出现,却几乎不携带主题信息。IDF 正是为压制这类词而存在:一个词在越多的文档中出现,它的权重就越低。只有 TF 与 IDF 相乘,才能同时保证“下料足”且“料特别”,缺一不可。

为何常见:初学时先接触 TF,很容易把“出现多”直接等同于“重要”,忽略了文档频率这个全局视角。

误区我以为向量越相似,它们在空间里的“直线距离”就越近,欧氏距离和余弦相似度是一回事。

正解两者衡量的维度完全不同。余弦只看方向夹角,对向量长度不敏感;欧氏距离看的是绝对坐标差。一份文档的长文本副本与原文配比完全一致,余弦给满分,欧氏距离却判它们很远。VSM 权衡的是“口味方向”而不是“分量大小”,所以选择余弦。

为何常见:中学几何用坐标系理解距离的直觉根深蒂固,容易把“空间里离得近”直接等同于“文本相似”。

误区既然 IDF 越大说明词越稀有,那查询里只放生僻词、不放常见词,检索效果一定最好。

正解权重是 TF 与 IDF 的乘积。一个稀有词如果只在文档里出现一次,TF 很小,乘积不一定高;完全生僻的词还可能来自错别字或专名,反而误导检索。而且用户的真实查询大多是常见词,刻意回避常见词等于丢弃大多数有效信号。

为何常见:IDF“惩罚常见词”的效果令人印象深刻,让人误以为常见词毫无价值,忽略了它与 TF 的合作关系。

误区我听说它能算出“苹果和 iPhone 相似”,以为 VSM 懂得词义,甚至能理解同义词。

正解VSM 是纯词袋统计:不看词序、不读搭配、不懂语义。词典里两个不同的词是完全独立的维度,“苹果”和"iPhone"在 VSM 眼里没有任何直接联系。它捕捉的只是统计层面的共现规律,而非意义本身。

为何常见:“相似度”三个字容易让人联想到语义相似,但这里的相似度只是文本用词重叠程度的数学表达,与“含义相近”是两回事。

面试题

Q1. 向量空间模型中,一篇文档最终被表示成什么?

单选题 · easy

  • A.词项的权重向量← 正确答案
  • B.一段压缩的二进制
  • C.一棵句法分析树
  • D.一张关系数据表

答案:A。VSM 的核心就是“文档向量化”:把文档映射成词典维度上的权重向量,每个分量对应一个词的权重。二进制、句法树、关系表都不是 VSM 的表示形式,它们分别属于压缩、句法分析与数据库的范畴。

Q2. 在标准向量空间模型中,余弦相似度的取值范围是多少?

单选题 · easy

  • A.恒为 0 到 1
  • B.恒为 -1 到 1← 正确答案
  • C.恒为 0 到正无穷
  • D.恒为负无穷到正无穷

答案:B。余弦值在数学上恒落于 [-1, 1]。在信息检索中因为权重非负,实际值多在 [0, 1],但“恒为 0 到 1”是把文本场景的特殊性当成了普遍定义,B 才是通用答案。

Q3. 当查询向量与文档向量夹角为 0° 时,其余弦相似度等于多少?

单选题 · easy

  • A.余弦值等于 0
  • B.余弦值等于 1← 正确答案
  • C.余弦值等于 -1
  • D.余弦值无法计算

答案:B。cos(0°) = 1,表示两向量方向完全一致,是最高相关度。0 对应 90°(正交、无关联),-1 对应 180°(方向相反)。此题考察夹角与余弦值的对应关系。

Q4. TF(词频)主要用来刻画文档的哪个属性?

单选题 · mid

  • A.词在本文档中的出现频次← 正确答案
  • B.词在整个语料中的出现频次
  • C.词在查询句中的出现频次
  • D.词在词典中的排列位置

答案:A。TF 衡量的是词在“当前文档”内的浓度。B 是文档频率(df)的范畴,C 属于查询侧的概念,D 与权重毫无关系——词袋世界里根本没有“位置”。

Q5. IDF 公式 log(N/df_t) 中的 df_t 表示什么?

单选题 · mid

  • A.包含词 t 的文档数量← 正确答案
  • B.词 t 在所有文档中的总次数
  • C.语料库中的文档总数
  • D.查询语句中的词项总数

答案:A。df_t 是 document frequency,即“有多少篇文档包含了词 t”(一篇文章里出现多次也只算一次)。B 是总出现次数,C 是 N,D 属于查询侧,都不是 df_t 的定义。

Q6. 为什么“的、了”这类词在 VSM 中权重会被 IDF 压低?

单选题 · easy

  • A.因为它们出现在绝大多数文档中← 正确答案
  • B.因为它们经常出现在标题里
  • C.因为它们的词频通常非常低
  • D.因为它们的长度实在太短了

答案:A。这类词的 df 接近文档总数 N,IDF = log(N/df) 趋近 log 1 = 0,与 TF 相乘后权重自动归零。B、C、D 都不是 IDF 的设计依据,IDF 只关心“出现在多少篇文档里”。

Q7. 下列哪些是向量空间模型的典型特点?(选择两项)

多选题 · mid

  • A.文档被表示为稀疏高维向量← 正确答案
  • B.能理解词序和语法结构
  • C.用向量夹角衡量相关性← 正确答案
  • D.需要大量人工标注来训练

答案:AC。VSM 用词典决定维度,单篇文档只命中少量词,因此向量又高维又稀疏(A 对);相关性由向量夹角即余弦相似度衡量(C 对)。B 错误——词袋模型恰恰忽略顺序和语法;D 错误——VSM 无需训练和标注。

Q8. 为什么 VSM 常用余弦相似度而不是欧氏距离?(选择两项)

多选题 · hard

  • A.余弦对向量长度不敏感← 正确答案
  • B.余弦能识别同义词汇
  • C.余弦只关注方向一致程度← 正确答案
  • D.余弦计算结果必为整数

答案:AC。文档长短不一导致向量模长差异大,欧氏距离会被“长度”带偏;余弦通过除以双模长天然归一化,只关注方向(A、C 对)。识别同义词是语义模型的能力(B 错);余弦值是连续实数而非整数(D 错)。

Q9. 构建一个可用的向量空间模型检索系统,哪些步骤是必需的?(选择两项)

多选题 · hard

  • A.分词并构建词典← 正确答案
  • B.计算每个词的 TF-IDF 权重← 正确答案
  • C.训练深度神经网络编码器
  • D.人工为每篇文档标注标签

答案:AB。VSM 需要词典来确定维度(A),需要 TF-IDF 来确定每个维度上的权重(B)。C 是神经检索路线的做法,D 是监督学习的要求,二者都不是 VSM 的必需步骤。

Q10. 若词 t 出现在语料全部 N 篇文档中,它的 TF-IDF 权重会怎样变化?

单选题 · extreme

  • A.IDF 为 0,TF-IDF 恒为 0← 正确答案
  • B.IDF 为 1,TF-IDF 等于 TF
  • C.IDF 为 N,TF-IDF 大幅提高
  • D.IDF 无法定义直接报错

答案:A。df_t = N 时,IDF = log(N/N) = log 1 = 0,任何 TF 乘以 0 都得 0——这个词在所有文档中都出现,毫无区分度,被自动屏蔽。这也解释了为什么工程上可以直接用停用词表替代这部分计算。