第 四 章

关键词提取

提其纲领,振其裘领

一、关键词与应用

关键词(Keywords)是最能代表一篇文档主题的少量词语。自动提取关键词是许多系统的基石:

  • 搜索与检索:用关键词建立倒排索引、做文档召回;
  • 内容运营:自动打标签、生成新闻热榜、相关文章推荐;
  • 文本摘要与问答:先抓关键词,再围绕关键词组织答案;
  • 舆情监控:监控品牌、事件关键词的热度与情感变化。

关键词方法分两大流派:无监督的 TF-IDF、TextRank(无需标注,拿来即用)和有监督的关键词序列标注(精度高但需要标注语料)。本章聚焦两个最经典的无监督算法。

二、TF-IDF 原理

TF-IDF 由两部分相乘构成:

词频 TF(Term Frequency)

一个词在当前文档出现得越多,越可能与主题相关:

TF(t, d) = 词 t 在文档 d 中出现的次数 / 文档 d 的总词数

逆文档频率 IDF(Inverse Document Frequency)

但「的、是、在」这类词处处出现,并没有区分度。IDF 对普遍常见的词降权,只在少数文档出现的词反而权重高:

IDF(t) = log( 文档总数 N / 包含词 t 的文档数 DF(t) )

最终:

TF-IDF(t, d) = TF(t, d) × IDF(t)
物以稀为贵——在本文频繁出现,又在他文难得一见,这个词才是「关键」。

工程实现中常对 IDF 做平滑,避免词从未出现导致除零:

IDF(t) = log( (N + 1) / (DF(t) + 1) ) + 1

TF-IDF 的局限:不考虑词序与语义,「不喜欢」和「喜欢」会被同等对待;对短文本统计不稳;高频但确有实义的领域通用词可能被误伤(可用自定义 IDF 表修正)。

三、用 Python 实现 TF-IDF

方法一:直接调用 jieba 内置的 TF-IDF(自带一份 IDF 语料库):

python · jieba 关键词import jieba.analyse

doc = """自然语言处理是人工智能的重要分支。中文分词、关键词提取、
文本向量化是自然语言处理的基础技术。问答机器人则综合运用了
语义分析与情感分析技术,为用户提供智能问答服务。"""

for word, weight in jieba.analyse.extract_tags(doc, topK=8, withWeight=True):
    print(f"{word}: {weight:.4f}")
# 自然语言处理 0.62 / 问答机器人 0.41 / 关键词 0.33 / ...

方法二:用 scikit-learn 对一批文档计算完整 TF-IDF 矩阵(第五章还会用到):

python · sklearnfrom sklearn.feature_extraction.text import TfidfVectorizer
import jieba

docs = ["自然语言处理 是 人工智能 的 分支",
        "问答机器人 运用 语义分析 与 情感分析",
        "中文分词 是 自然语言处理 的 基础"]

# 用 jieba 分词后用空格连接,再交给 sklearn
tok_docs = [" ".join(jieba.lcut(d)) for d in docs]

vec = TfidfVectorizer(stop_words=["的", "是"])
matrix = vec.fit_transform(tok_docs)

print(vec.get_feature_names_out())   # 词表
print(matrix.shape)                  # (3 篇文档, 词表大小)
print(matrix.toarray())              # 每篇文档的 TF-IDF 向量

四、TextRank 算法

TextRank 源自网页排序算法 PageRank,核心思想是「投票」:一个词被越多重要的词共现,它自己也越重要。

  1. 分词与过滤:切词后只保留名词、动词等实词;
  2. 构建词图:滑动窗口(如大小为 5)内共同出现的词之间连一条无向边;
  3. 迭代投票:每个节点把分数均分给邻居,反复迭代直至收敛,公式为 WS(Vᵢ) = (1-d) + d × Σ 邻居的加权贡献,阻尼系数 d 通常取 0.85;
  4. 排序输出:得分最高的若干词即关键词,相邻关键词还可拼接成关键短语。
python · jieba 的 TextRankfrom jieba.analyse import textrank

for word, weight in textrank(doc, topK=8, withWeight=True):
    print(word, round(weight, 4))

与 TF-IDF 相比:

TF-IDFTextRank
所需语料需要多篇文档统计 DF单篇文档即可
依据词频的全局稀有度词在词图中的共现关系
适用大规模语料批量处理单文档、长文摘要前处理
代价快需构建图并迭代,略慢

五、主题模型 LDA 简介

当目标不是为单篇文档抽词,而是发现整个语料库隐含的若干主题时,可以使用 LDA(Latent Dirichlet Allocation)主题模型。

它假设每篇文档是多个主题的混合,每个主题又是一组词的概率分布。例如从大量新闻中可自动学出:主题 A「比赛、球队、冠军、球员」,主题 B「股市、利率、基金、上涨」。

python · gensim LDA(示意)from gensim.corpora import Dictionary
from gensim.models import LdaModel

texts = [["比赛", "球队", "冠军"],
         ["股市", "基金", "上涨"]]
dictionary = Dictionary(texts)
corpus = [dictionary.doc2bow(t) for t in texts]

lda = LdaModel(corpus, id2word=dictionary, num_topics=2, passes=10)
print(lda.print_topics())
LDA 需要设置主题数 K,可用困惑度(Perplexity)或主题一致性(Coherence)来选择;短文本(如微博)可先做词聚合或改用 BTM 模型。

六、交互演示:亲手算 TF-IDF

在下方输入多篇文档(文档之间用空行分隔),点击计算,再用下拉框切换查看每篇文档的 TF-IDF 关键词。注意观察:在多篇文档中反复出现的词,分数会被 IDF 压低。

TF-IDF 关键词实验台多篇文档 · 空行分隔

试试把某个词加入所有文档(例如都写上「自然语言处理」),再看它在结果中的排名变化——这就是 IDF 在起作用。