导读:本期聚焦于芒果创作的《TF-IDF和TextRank哪个更适合中文关键词提取?原理与代码实战对比》,敬请观看详情。关键词提取是文本挖掘的基础任务,面对TF-IDF和TextRank两种主流算法,选哪个往往让人犹豫。本文从底层原理讲起,先拆解TF-IDF的词频与逆文档频率计算逻辑,再分析TextRank借鉴PageRank思想的图排序机制,随后用Python代码分别实现两种算法,处理中文分词、停用词过滤等细节问题,最后从语料依赖、单文档场景、长文本短文本等维度做横向对比,给出明确的选择建议,帮你快速搭建一套可落地的关键词提取方案。

关键词提取是自然语言处理中最基础也最实用的任务之一,无论是新闻摘要、搜索引擎索引,还是舆情监控和内容标签化,都离不开它。目前业内最常用的两种经典算法就是TF-IDF和TextRank,前者依赖统计特征,后者基于图排序思想,两者的适用场景差异很大。这篇文章会详细拆解两者的原理,给出完整的Python实现代码,并在多个维度上做横向对比,帮你搞清楚什么场景该用哪个。

TF-IDF和TextRank哪个更适合中文关键词提取?原理与代码实战对比

TF-IDF的原理与实现

TF-IDF(Term Frequency-Inverse Document Frequency)的核心思想非常直观:一个词在某篇文档中出现得越频繁,并且在整个语料库的其他文档中越少出现,它就越可能是这篇文档的关键词。它由两个因子相乘得到:TF表示词在当前文档中的频率,IDF衡量词的区分能力。计算公式为:TF-IDF = TF × IDF,其中IDF通常取 log(N/DF),N是文档总数,DF是包含该词的文档数。如果一个词在所有文档中都出现(比如“的”“我们”这类高频虚词),DF接近N,IDF趋近于0,权重自然被压低。

这个算法的优点是计算简单、可解释性强,权重数值可以直接用来排序。但它有一个明显的硬性前提:必须有一个规模合理的语料库来计算IDF。如果语料库太小,IDF的估计会严重失真;如果处理的是单篇文档,TF-IDF会退化成纯粹的词频统计,效果大打折扣。此外,TF-IDF完全不考虑词与词之间的语义关系,纯粹依赖统计。

下面用Python手动实现TF-IDF关键词提取,中文场景需要先做分词和停用词过滤:

import math
import jieba

# 示例语料库:多个文档
documents = [
    "人工智能技术正在改变搜索引擎的工作方式",
    "深度学习模型在图像识别领域取得了突破性进展",
    "搜索引擎通过机器学习优化排序算法",
    "自然语言处理是人工智能的重要分支",
    "图像识别与自然语言处理都属于机器学习范畴"
]

# 停用词表(实际项目中建议加载完整停用词文件)
stopwords = {"的", "是", "在", "与", "和", "都", "通过", "正在", "取得", "了"}

def tokenize(text):
    # 分词并过滤停用词和单字词
    return [w for w in jieba.lcut(text) if w not in stopwords and len(w) > 1]

# 构建语料库的文档频率
tokenized_docs = [tokenize(doc) for doc in documents]
N = len(tokenized_docs)

def tfidf_extract(doc_tokens, topk=5):
    tf = {}
    for w in doc_tokens:
        tf[w] = tf.get(w, 0) + 1
    scores = {}
    for word, freq in tf.items():
        # 计算包含该词的文档数
        df = sum(1 for dt in tokenized_docs if word in dt)
        idf = math.log(N / df) + 1  # 加1平滑,避免idf为0
        scores[word] = (freq / len(doc_tokens)) * idf
    return sorted(scores.items(), key=lambda x: x[1], reverse=True)[:topk]

print(tfidf_extract(tokenize(documents[2])))

代码中IDF部分加了1做平滑,这是工程上的常见技巧,可以避免某些词的IDF恰好为0导致权重归零。实际项目中也可以直接使用scikit-learn的TfidfVectorizer,它内置了平滑参数和多种归一化方式,处理大规模语料时效率更高。

TextRank的原理与实现

TextRank的思想来源于Google的PageRank算法。它把文本看作一张图:每个词是图上的一个节点,词与词之间存在某种关系(通常是共现关系,即在一个固定大小的滑动窗口内同时出现)就连一条边。每个节点的得分由指向它的节点投票决定,得分为这些节点自身得分与转移概率的加权和,再乘一个阻尼系数d(通常取0.85)。迭代公式为:WS(Vi) = (1-d) + d × Σ (WS(Vj)/Out(Vj)),反复迭代直到收敛。

TextRank最大的优势是完全不需要语料库,只利用当前文档自身的结构信息就能算出关键词,这让它特别适合单文档、无预训练语料的场景。而且由于引入了词与词之间的共现关系,它能捕捉到一定的上下文结构信息,比如一个词如果总和多个不同的词共现,它的权重会被多路投票推高。缺点是图构建和迭代计算的开销比TF-IDF大,超长文本上性能会明显下降。

下面是TextRank的手写实现,重点看窗口共现建图和迭代两部分:

import jieba
from collections import defaultdict

def textrank_extract(text, topk=5, window=3, d=0.85, max_iter=200):
    words = [w for w in jieba.lcut(text) if len(w) > 1 and not w.isspace()]
    # 构建共现图
    graph = defaultdict(lambda: defaultdict(int))
    for i, w in enumerate(words):
        for j in range(i + 1, min(i + window, len(words))):
            graph[w][words[j]] += 1
            graph[words[j]][w] += 1

    # 初始化权重
    ws = {w: 1.0 for w in graph}
    out_sum = {w: sum(graph[w].values()) for w in graph}

    # 迭代计算直到收敛
    for _ in range(max_iter):
        change = 0
        for w in graph:
            s = sum(ws[nw] / out_sum[nw] * weight
                    for nw, weight in graph[w].items())
            new_ws = (1 - d) + d * s
            change += abs(new_ws - ws[w])
            ws[w] = new_ws
        if change < 1e-6:
            break

    return sorted(ws.items(), key=lambda x: x[1], reverse=True)[:topk]

text = "自然语言处理技术中,关键词提取是文本挖掘的基础任务。" \
       "关键词提取算法包括TF-IDF和TextRank,前者依赖语料库统计," \
       "后者基于图排序思想,两者在关键词提取场景中各有优势。"
print(textrank_extract(text))

参数window控制共现窗口大小,窗口太小图会过于稀疏,窗口太大则会引入大量噪声边,经验值在2到5之间。阻尼系数d沿用PageRank的经典取值0.85,一般不需要调整。如果不想手写,jieba自带的analyse.textrank函数可以直接调用,内部实现逻辑与上面基本一致。

两者如何选择:多维度对比与实践建议

从语料依赖性来看,TF-IDF必须依赖外部语料库计算IDF,语料库质量直接决定效果上限,而TextRank零语料依赖,单篇文档即可运行。从计算效率看,TF-IDF只需一次词频统计加查表,复杂度接近线性;TextRank需要建图并迭代,复杂度明显更高,处理超长文档时可能成为瓶颈。从效果维度看,长文档上TextRank的图结构信息能发挥作用,效果往往更稳定;短文本由于词太少、图过于稀疏,TextRank容易失效,此时TF-IDF配合高质量语料库反而更可靠。

整理成表格更直观:

对比维度TF-IDFTextRank
语料依赖需要外部语料库无需语料库
计算复杂度低,接近线性较高,需建图迭代
长文本效果依赖语料质量稳定良好
短文本效果语料好则较优图稀疏,效果差
可解释性强,权重有明确含义中等,迭代收敛值

实践中有几条经验值得参考。第一,如果有稳定的大规模领域语料,优先用TF-IDF,并对IDF做定期更新,让它适应语言分布的变化。第二,处理单篇长文档、又没有现成语料时,直接上TextRank。第三,工业界的常见做法是两者融合:分别用两种算法各取一批候选词,取交集或加权融合排序,准确率通常比单一算法更高。第四,无论用哪种算法,中文分词质量和停用词表的完备程度对最终效果的影响,往往比算法本身的选择更大,这一步值得投入足够精力。

总结一下,TF-IDF和TextRank没有绝对的优劣,前者是统计派,靠语料说话;后者是结构派,靠文档自身的图结构说话。理解了各自的底层逻辑,再结合手头的数据条件和文本特点做选择,关键词提取这件事就能做到心里有数。如果后续想进一步提升效果,还可以考虑基于预训练模型的KeyBERT等方案,让语义理解能力参与进来,这也是当前关键词提取技术演进的主流方向。

TF-IDFTextRank关键词提取修改时间:2026-09-01 07:41:04

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。