欢迎光临
我们一直在努力

LlamaIndex 系列【18】关键词检索(Keyword Search):TF-IDF 算法

文章目录

  • 1. 算法介绍
  • 2. 整体流程
    • 2.1 📦 阶段一:离线预处理
    • 2.2 🔍 阶段二:在线实时检索
  • 3. 核心概念
    • 3.1 系统词汇表
    • 3.2 稀疏向量
    • 3.3 文档-词项矩阵
  • 4. 打分算法迭代演进
    • 4.1 版本一:简单命中计数打分
    • 4.2 版本二:TF 原始词频打分
    • 4.3 版本三:TF‑IDF(词频‑逆文档频率)
      • 步骤 1:计算 DF(文档频率)
      • 步骤 2:权重反转
      • 步骤 3:对数平滑得到标准 IDF
      • 步骤 4:TF‑IDF 加权计算
    • 5. TF-IDF 致命短板

1. 算法介绍

关键词检索(Keyword Search)属于信息检索技术的基础方法之一,是一种通过输入关键字获取文档信息的查询方式。

这种技术几十年来一直驱动着数据库和搜索引擎的检索。它的简单性和高效性,使其成为现代 RAG 系统检索的核心组成部分。

基本思路:统计文档与查询重叠词数量,重叠越多原始分数越高,但不理解语义,只看字面词共现。

示例,当前有三个做菜相关的文档:

  • Doc1:做川味水煮牛肉,首选牛里脊,搭配豆芽莴笋打底。
  • Doc2:这家川味菜馆的水煮牛肉支持外卖,可以在家点单食用。
  • Doc3:这家川味老店生意火爆,很多食客会在家点麻辣火锅。

用户输入提问:

怎么自制川味水煮牛肉?

输入会进行关键词拆分为:怎么、自制、川味、水煮牛肉,根据关键词三个文档都会被召回:

文档文档真实语义命中关键词字面命中数量
Doc1 讲解自制水煮牛肉做法,匹配用户意图 川味、水煮牛肉 2
Doc2 介绍餐馆外卖服务,并非做菜教程 川味、水煮牛肉 2
Doc3 介绍自制麻辣火锅,与水煮牛肉无关 川味 1

其中 Doc1、Doc2 字面命中数量一致,但语义相关性天差地别,简单的命中计数无法区分真实相关性。

2. 整体流程

TF‑IDF 的完整链路分为 知识库离线构建流程 和 用户在线检索流程 两大阶段:

  • 离线阶段(预处理):对全部文档分词 → 构建全局词表 → 统计 TF / DF → 计算 IDF,生成 TF‑IDF 稀疏向量库
  • 在线阶段(实时查询):用户输入 Query → 分词 → 使用离线保存的 IDF 表计算 Query 的 TF‑IDF 稀疏向量 → 积分排序 → 返回 Top‑K 文档
  • 2.1 📦 阶段一:离线预处理

    在这里插入图片描述

    一次性执行,知识库更新时重新跑:

  • 原始文档输入:收集知识库全部非结构化文本。
  • 文本清洗:去除标点、特殊符号、过滤无意义停用词(的、是、怎么)。
  • 分词:将连续句子切割成独立词语列表。
  • 构建全局词汇表:合并所有文档词语,去重,给每个词分配唯一固定下标,保证所有向量维度对齐。
  • 计算 TF(词频 Term Frequency):针对每一篇文档,统计每个词汇在本文档内出现多少次。
  • 计算 DF(文档频率 Document Frequency):统计整个知识库中,包含该词语的文档一共有多少篇。
  • 计算 IDF(逆文档频率 Inverse Document Frequency)

    I

    D

    F

    (

    w

    o

    r

    d

    )

    =

    log

    (

    N

    D

    F

    (

    w

    o

    r

    d

    )

    )

    IDF(word)=\\log\\left(\\frac{N}{DF(word)}\\right)

    IDF(word)=log(DF(word)N)

    N

    N

    N = 知识库文档总数;

    D

    F

    DF

    DF 越大(词语越通用),

    I

    D

    F

    IDF

    IDF 分值越低。

  • 生成 TF‑IDF 加权向量

    T

    F

    I

    D

    F

    =

    T

    F

    ×

    I

    D

    F

    TF‑IDF = TF × IDF

    TFIDF=TF×IDF 每个词语最终权重 = 局部词频 × 全局稀有度权重

  • 持久化存储:保存所有文档 TF‑IDF 稀疏向量,以及全局 IDF 字典,供线上查询复用。
  • 2.2 🔍 阶段二:在线实时检索

    在这里插入图片描述

    每次用户提问执行:

  • 用户输入自然语言 Query。
  • 对 Query 使用和文档完全一致的清洗、分词规则。
  • 统计 Query 内每个词汇的局部词频 TF。
  • 读取离线预计算的全局 IDF 字典,得到查询词语的加权分值。
  • 通过倒排索引快速筛选出包含目标关键词的候选文档;对候选文档累加词语的 TF‑IDF权重作为最终相关性得分。
  • 按相关性分数降序排序,截取前 K 个文档作为检索结果返回。
  • 3. 核心概念

    3.1 系统词汇表

    系统词汇表:整个知识库提前固定好的、不变化的全局词语清单,它给每一个词语分配唯一固定下标,用来统一所有文档向量的维度。

    把全部文档里所有不重复的词收集、去重,整理成一份全局词列表,这份列表就是系统词汇表。

    上面的 Doc1、Doc2、Doc3 三个做菜文档,收集去重后的系统词汇表(固定顺序,全局唯一):

    下标词语
    0 川味
    1 水煮牛肉
    2 牛里脊
    3 豆芽
    4 莴笋
    5 菜馆
    6 外卖
    7 麻辣火锅

    3.2 稀疏向量

    为了让知识库能够被检索,每个文档都会生成一个稀疏向量。

    这些词频会被存储在一个向量中,这个向量为系统词汇表中的每个词都分配一个固定位置,向量中的每个数字,表示该词语在文本里出现的次数。

    上面那套词汇表规则中,每个文档词频对应的向量为:

    • Doc1:[1, 1, 1, 1, 1, 0, 0, 0]
    • Doc2:[1, 1, 0, 0, 0, 1, 1, 0]
    • Doc3:[1, 0, 0, 0, 0, 0, 0, 1]

    向量的维度很高,可能有数万个位置,由于绝大多数位置存放的值都是 0 ,这类向量叫做稀疏向量(Sparse Vectors)。

    和稠密向量(Dense Vector)对比:

    对比项TF‑IDF 向量(稀疏)Embedding嵌入向量(稠密)
    生成方式 分词+统计公式,无神经网络 大模型/预训练Encoder推理输出
    向量维度 等于词表大小(上万~几十万维) 固定小维度(512/768/1024)
    向量特征 大量0,稀疏 数值连续非0,稠密
    语义能力 仅字面匹配,不理解语义 承载语义,支持同义模糊匹配
    相似度计算 余弦/点积 余弦相似度
    检索定位 稀疏检索(关键词召回) 稠密检索(语义召回)

    3.3 文档-词项矩阵

    每一篇文档生成稀疏向量后,全部向量组合形成二维网格结构,这个表格叫文档-词项矩阵(Document-Term Matrix)。

    结构定义:

    • 行:词项(系统词汇表中)
    • 列:单篇文档

    关于单元格的取值,可以有多种形式,比如:

    • One‑Hot 形式:1 代表词语在该文档出现,0 代表未出现,只标记存在与否,不关心词汇出现多少次。
    • TF(词频)形式:单元格填入该词在文档中的实际出现次数。数值越大,说明这个词在当前文档里反复出现,主题关联性更强。

    上面的 Doc1、Doc2、Doc3 词项‑文档矩阵(One‑Hot 形式):

    词项\\文档Doc1Doc2Doc3
    川味 1 1 1
    水煮牛肉 1 1 0
    牛里脊 1 0 0
    豆芽 1 0 0
    莴笋 1 0 0
    菜馆 0 1 0
    外卖 0 1 0
    麻辣火锅 0 0 1

    有了这个矩阵之后,我们就把非结构化的自然语言文本,转换成了计算机可以直接运算的数值化结构化数据。

    可以很方便地从一个词查找包含该词的所有文档,一般也叫倒排索引。因为通常我们是从文档出发,思考它包含哪些词(正向索引),这里是给定一个词语,列出所有包含这个词的文档。

    词语对应文档列表
    川味 Doc1,Doc2,Doc3
    水煮牛肉 Doc1,Doc2
    牛里脊 Doc1
    豆芽 Doc1
    莴笋 Doc1
    菜馆 Doc2
    外卖 Doc2
    麻辣火锅 Doc3

    4. 打分算法迭代演进

    至此,文档与查询语句各自都拥有对应的稀疏向量,检索器接收查询语句后,接下来便可对全部文档执行打分与排序操作。

    三代矩阵对比总结:

    • One‑Hot 矩阵:仅标记是否出现,无权重差异
    • TF 词频矩阵:仅统计文档内部频次,无法抑制通用词汇
    • TF‑IDF 矩阵:全局加权,稀有业务词汇获得高分,无区分度的高频词权重归零

    4.1 版本一:简单命中计数打分

    最基础的打分规则:每命中一个关键词,文档获得对应积分,关键词只要出现一次即得 1 分,重复出现不会额外加分,后续可基于累计分值完成相关性排序。

    在 2.5 章节中的示例,查询文本:自制川味水煮牛肉?,提取全部关键词:自制、川味、水煮牛肉,命中文档:

    词语对应文档列表
    自制 无匹配文档
    川味 Doc1,Doc2,Doc3
    水煮牛肉 Doc1,Doc2

    每命中 1 个关键词得 1 分,这样就会得到一个得分排序:

    • Doc1:川味 + 水煮牛肉 = 2 分
    • Doc2:川味 + 水煮牛肉 = 2 分
    • Doc3:川味 = 1 分

    这种基础打分机制存在短板:它仅判断关键词是否存在于文档中,不会统计关键词在文本内的出现次数。但现实场景里,同一个关键词反复出现,往往代表这份文档和用户查询的相关性更强,该简单算法无法捕捉这层信号。

    4.2 版本二:TF 原始词频打分

    一种简易优化方案:文档中每出现一次关键词,就累加一次分值。

    假设三篇文档内部词汇出现频次如下:

    关键词Doc1词频Doc2词频Doc3词频
    自制 2 0 0
    川味 3 1 2
    水煮牛肉 3 1 0
    TF总分 8 2 2

    打分计算过程:

    • Doc1:自制(2) + 川味(3) + 水煮牛肉(3) = 8 分
    • Doc2:自制(0) + 川味(1) + 水煮牛肉(1) = 2 分
    • Doc3:自制(0) + 川味(2) + 水煮牛肉(0) = 2 分

    TF 词频只统计单个文档内部词语出现多少次,但它存在一个明显缺陷:无法区分词语本身的珍贵程度。有些高频通用词(如 自制、的)哪怕多次出现,对判断文档主题几乎没有区分价值;而小众专属词汇,才是判断相关性的核心线索。

    4.3 版本三:TF‑IDF(词频‑逆文档频率)

    TF-IDF 的全称是 Term Frequency-Inverse Document Frequency,中文叫词频 – 逆文档频率。它的核心思想很简单:如果一个词在某篇文章里出现很多次,但在其他文章里很少出现,那这个词对这篇文章就很重要 。‌‌

    这个技术由两部分组成:

    • TF(词频)‌:衡量一个词在当前文档中出现的频率,出现越多越重要。
    • IDF(逆文档频率)‌:衡量一个词在整个文档集合中的稀有程度,越稀有的词权重越高。‌‌

    IDF 这个概念最早由英国学者 Karen Spärck Jones 在 1972 年提出,后来与 TF 结合形成了现在广泛使用的 TF-IDF 算法 。‌‌是一种用于评估词语在文档中重要程度的统计方法‌,广泛应用于搜索引擎、文本分类和关键词提取等场景 。‌‌

    IDF 的完整计算分为 4 个关键步骤,最终生成 TF‑IDF 加权词项‑文档矩阵。

    步骤 1:计算 DF(文档频率)

    文档频率

    D

    F

    DF

    DF 代表:整个文档库中,包含该词的文档占全部文档的比例。

    计算公式:

    D

    F

    (

    w

    o

    r

    d

    )

    =

    包含该词的文档数量

    文档库总文档数

    DF(word) = \\frac{\\text{包含该词的文档数量}}{\\text{文档库总文档数}}

    DF(word)=文档库总文档数包含该词的文档数量

    D

    F

    DF

    DF 值越大,代表这个词汇在语料中越普遍,区分文档差异的价值越低。

    以本次案例为例,文档总数

    N

    =

    3

    N=3

    N=3

    • 词「川味」出现在 3 篇文档:

      D

      F

      =

      3

      3

      =

      1.0

      DF=\\dfrac{3}{3}=1.0

      DF=33=1.0

    • 词「水煮牛肉」出现在 2 篇文档:

      D

      F

      =

      2

      3

      0.67

      DF=\\dfrac{2}{3}\\approx0.67

      DF=320.67

    • 词「牛里脊」仅出现在 1 篇文档:

      D

      F

      =

      1

      3

      0.33

      DF=\\dfrac{1}{3}\\approx0.33

      DF=310.33

    步骤 2:权重反转

    DF 的数值逻辑和我们想要的打分逻辑是相反的:

    • DF 大(到处都出现)→ 我们希望权重低
    • DF 小(很少出现)→ 我们希望权重高

    对 DF 取倒数,就是把分数逻辑翻转过来:

    中间权重

    =

    1

    D

    F

    (

    w

    o

    r

    d

    )

    =

    总文档数量

    包含该词的文档数量

    \\text{中间权重} = \\frac{1}{DF(word)}=\\frac{\\text{总文档数量}}{\\text{包含该词的文档数量}}

    中间权重=DF(word)1=包含该词的文档数量总文档数量

    代入案例演算:

  • 川味:

    D

    F

    =

    1.0

    DF=1.0

    DF=1.0,中间权重

    1

    1.0

    =

    1

    \\displaystyle \\frac{1}{1.0}=1

    1.01=1

  • 水煮牛肉:

    D

    F

    0.67

    DF≈0.67

    DF0.67,中间权重

    1

    0.67

    1.5

    \\displaystyle \\frac{1}{0.67}≈1.5

    0.6711.5

  • 牛里脊:

    D

    F

    0.33

    DF≈0.33

    DF0.33,中间权重

    1

    0.33

    3

    \\displaystyle \\frac{1}{0.33}≈3

    0.3313

  • 词项DF中间权重

    1

    D

    F

    \\boldsymbol{\\dfrac{1}{DF}}

    DF1变化效果

    川味 1.0 1 高频通用词,分值压低
    水煮牛肉 0.67 1.5 中等稀有度,中等分值
    牛里脊 0.33 3 稀有专属词,获得更高分值

    直接取倒数会造成数值差距过大:稀有词权重爆炸放大。如果文档库很大(例如10000篇文档),只出现 1 次的词,中间权重直接等于 10000,分值会严重失衡,打分结果失真。

    因此需要下一步:对数平滑压缩数值范围。

    步骤 3:对数平滑得到标准 IDF

    引入对数函数压缩权重区间,得到工程上标准的逆文档频率 IDF:

    I

    D

    F

    (

    w

    o

    r

    d

    )

    =

    log

    (

    总文档数

    包含该词的文档数

    )

    IDF(word)=\\log\\left(\\frac{\\text{总文档数}}{\\text{包含该词的文档数}}\\right)

    IDF(word)=log(包含该词的文档数总文档数)

    案例计算:

  • 川味:

    log

    (

    1

    )

    =

    0

    \\log(1)=0

    log(1)=0

  • 水煮牛肉:

    log

    (

    1.5

    )

    0.41

    \\log(1.5)≈0.41

    log(1.5)0.41

  • 牛里脊:

    log

    (

    3

    )

    1.10

    \\log(3)≈1.10

    log(3)1.10

  • 对数不会改变大小关系:稀有词依然分数更高,只是把巨大的差值压缩到一个合理的小数区间。全局高频词最终权重归零,不再干扰检索打分。

    词项命中文档数DF

    N

    命中数

    \\boldsymbol{\\dfrac{N}{命中数}}

    命中数N(倒数反转)IDF(对数平滑)

    川味 3 1.0

    1

    1

    1

    0

    0

    0

    水煮牛肉 2 0.67

    1.5

    1.5

    1.5

    0.41

    0.41

    0.41

    牛里脊 1 0.33

    3

    3

    3

    1.10

    1.10

    1.10

    步骤 4:TF‑IDF 加权计算

    T

    F

    I

    D

    F

    TF‑IDF

    TFIDF 的计算公式:

    T

    F

    I

    D

    F

    (

    w

    o

    r

    d

    ,

    d

    o

    c

    )

    =

    T

    F

    (

    w

    o

    r

    d

    ,

    d

    o

    c

    )

    ×

    I

    D

    F

    (

    w

    o

    r

    d

    )

    \\boldsymbol{TF‑IDF(word,doc) = TF(word,doc) \\times IDF(word)}

    TFIDF(word,doc)=TF(word,doc)×IDF(word)

    其中:

    • T

      F

      (

      w

      o

      r

      d

      ,

      d

      o

      c

      )

      TF(word,doc)

      TF(word,doc):词在单篇文档内部的出现次数,代表词汇对这一篇文档的局部重要性

    • I

      D

      F

      (

      w

      o

      r

      d

      )

      IDF(word)

      IDF(word):词汇在整个文档库的全局权重,代表词汇本身的珍贵程度

    • T

      F

      I

      D

      F

      TF‑IDF

      TFIDF:二者相乘,得到该词汇在这篇文档里的最终加权得分

    假设 TF 原始词项‑文档矩阵:

    词项Doc1(TF)Doc2(TF)Doc3(TF)
    川味 3 1 2
    水煮牛肉 3 1 0
    牛里脊 2 0 0

    逐单元格手动演算:

  • Doc1 – 水煮牛肉:

    T

    F

    =

    3

    ,

     

    I

    D

    F

    =

    0.41
      


      

    3

    ×

    0.41

    =

    1.23

    TF=3,\\ IDF=0.41 \\implies 3 \\times 0.41 = \\boldsymbol{1.23}

    TF=3, IDF=0.413×0.41=1.23

  • Doc1 – 牛里脊:

    T

    F

    =

    2

    ,

     

    I

    D

    F

    =

    1.10
      


      

    2

    ×

    1.10

    =

    2.20

    TF=2,\\ IDF=1.10 \\implies 2 \\times 1.10 = \\boldsymbol{2.20}

    TF=2, IDF=1.102×1.10=2.20

  • Doc1 – 川味:

    T

    F

    =

    3

    ,

     

    I

    D

    F

    =

    0
      


      

    3

    ×

    0

    =

    0

    TF=3,\\ IDF=0 \\implies 3 \\times 0 = \\boldsymbol{0}

    TF=3, IDF=03×0=0(通用词权重清零)

  • 最终生成TF‑IDF 加权词项‑文档矩阵:

    词项 \\ 文档Doc1Doc2Doc3
    川味 0 0 0
    水煮牛肉 1.23 0.41 0
    牛里脊 2.20 0 0

    当用户输入查询语句时,我们对查询文本执行完全相同的分词、TF‑IDF计算,生成查询向量;再将查询向量和矩阵中每一列的文档向量计算相似度,按照相似度从高到低完成文档排序,最终返回检索结果。

    5. TF-IDF 致命短板

    TF-IDF 是传统稀疏检索的经典基线方案,依靠词频与全局词权重实现文档相关性打分,解决了基础命中打分、简易词频打分的核心缺陷。

    但在实际检索场景中,原始 TF-IDF 算法存在两处致命短板,无法适配真实业务的检索需求:

    • 词频无上限,分数容易虚高:关键词无限堆砌即可拉高得分,低质量刷词文档排名靠前,排序失真。
    • 未做文档长度归一化:篇幅更长的文档天然拥有更多命中机会,打分对短而精炼的优质文档不公平。

    正因 TF‑IDF 存在上述缺陷,工业界进一步演化出 BM25 算法,作为生产环境稀疏检索的标准实现。

    赞(0)
    未经允许不得转载:171主机测评 » LlamaIndex 系列【18】关键词检索(Keyword Search):TF-IDF 算法
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址