阶段5 | NLP传统 · 第25课/共30课

📖 第25课:关键词提取

🎯 课程目标

关键词提取从文本中自动识别最能代表文本主题的词语,是文本摘要、信息检索等任务的基石。

📐 核心原理

三大方法对比

💡 TextRank本质:和Google的PageRank同源——给图中的节点打分,连接多的节点得分高。关键词图中,与很多词共现的词更重要。

🔬 三种关键词提取方法

TF-IDF/TextRank/手动TextRank

import jieba import jieba.analyse from collections import Counter import math text = "自然语言处理是人工智能的重要分支。深度学习技术推动了自然语言处理的快速发展。词向量表示和预训练语言模型成为NLP的核心技术。文本分类、情感分析、机器翻译等任务取得了显著进展。大规模预训练模型如BERT和GPT改变了NLP的研究范式。" # 方法1: TF-IDF关键词提取 tfidf_keywords = jieba.analyse.extract_tags(text, topK=10, withWeight=True) print("=== TF-IDF关键词 ===") for word, weight in tfidf_keywords: print(f" {word}: {weight:.4f}") # 方法2: TextRank关键词提取 textrank_keywords = jieba.analyse.textrank(text, topK=10, withWeight=True) print("\n=== TextRank关键词 ===") for word, weight in textrank_keywords: print(f" {word}: {weight:.4f}") # 方法3: 手动实现TextRank import numpy as np def manual_textrank(words, window=4, d=0.85, iterations=30): word_set = list(set(words)) n = len(word_set) word2idx = {w: i for i, w in enumerate(word_set)} # 构建共现图 graph = np.zeros((n, n)) for i in range(len(words)): for j in range(max(0, i-window), min(len(words), i+window+1)): if i != j: a, b = word2idx[words[i]], word2idx[words[j]] graph[a][b] += 1 # PageRank迭代 scores = np.ones(n) / n for _ in range(iterations): new_scores = (1 - d) / n + d * graph.T @ scores / (graph.sum(axis=0, keepdims=True) + 1e-8) scores = new_scores ranked = [(word_set[i], scores[i]) for i in range(n)] ranked.sort(key=lambda x: -x[1]) return ranked words = jieba.lcut(text) keywords = manual_textrank(words, window=4) print("\n=== 手动TextRank ===") for word, score in keywords[:10]: print(f" {word}: {score:.6f}")
=== TF-IDF关键词 === NLP: 0.6131 自然语言: 0.5351 模型: 0.3491 训练: 0.3410 机器翻译: 0.3152 BERT: 0.3065 GPT: 0.3065 范式: 0.2838 处理: 0.2775 人工智能: 0.2425 === TextRank关键词 === 训练: 1.0000 研究: 0.8726 技术: 0.7444 模型: 0.6980 分析: 0.6421 处理: 0.6278 文本: 0.6226 分类: 0.6189 分支: 0.6168 推动: 0.6040 [STDERR] Building prefix dict from the default dictionary ... Loading model from cache /tmp/jieba.cache Loading model cost 0.828 seconds. Prefix dict has been built successfully. Traceback (most recent call last): File "<string>", line 47, in <module> File "<string>", line 39, in manual_textrank ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 1 is different from 44)

⚠️ 部分验证:代码实机运行结果如上

🔧 RAKE算法实现

RAKE关键词提取

import jieba from collections import Counter import math # RAKE算法实现 class RAKE: def __init__(self, stop_words=None): if stop_words is None: self.stop_words = {'的', '了', '在', '是', '我', '有', '和', '就', '不', '人', '都', '一', '一个', '上', '也', '很', '到', '说', '要', '去', '你', '会', '着', '没有', '看', '好', '自己', '这'} else: self.stop_words = stop_words def extract_keywords(self, text, topn=10): words = jieba.lcut(text) # 分割为候选关键词 candidates = [] current = [] for word in words: if word in self.stop_words or len(word.strip()) == 0: if current: candidates.append(current) current = [] else: current.append(word) if current: candidates.append(current) # 计算词频和共现度 word_freq = Counter() word_degree = Counter() for phrase in candidates: degree = len(phrase) - 1 for word in phrase: word_freq[word] += 1 word_degree[word] += degree # 计算 score = degree / frequency word_score = {} for word in word_freq: word_score[word] = (word_degree[word] + word_freq[word]) / word_freq[word] # 短语得分 phrase_scores = {} for phrase in candidates: score = sum(word_score.get(w, 0) for w in phrase) phrase_scores[' '.join(phrase)] = score ranked = sorted(phrase_scores.items(), key=lambda x: -x[1]) return ranked[:topn] rake = RAKE() text = "自然语言处理是人工智能的重要分支。深度学习推动了自然语言处理的发展。预训练语言模型改变了NLP的研究范式。词向量表示技术是深度学习在NLP中的基础应用。" keywords = rake.extract_keywords(text, topn=10) print("=== RAKE关键词提取 ===") for phrase, score in keywords: print(f" {phrase}: {score:.4f}")
=== RAKE关键词提取 === 发展 。 预 训练 语言 模型 改变: 47.7500 研究 范式 。 词 向量 表示 技术: 47.7500 重要 分支 。 深度 学习 推动: 31.7500 基础 应用 。: 11.7500 深度 学习: 8.0000 自然语言 处理: 4.0000 NLP 中: 3.5000 NLP: 1.5000 人工智能: 1.0000

✅ 验证通过:代码实机运行结果如上

📝 练习

动手练习

  1. 实现YAKE!算法(无监督、无需训练语料的关键词提取)
  2. 对比五种关键词提取方法在新闻文本上的效果
  3. 用关键词提取结果作为搜索索引,构建简单检索系统
🔑

🏆 成就解锁:关键词猎手

掌握了多种关键词提取算法,能自动识别文本的核心概念。

🧪 扩展:关键词提取评估

评估方法

关键词提取的应用

  1. 搜索引擎:用关键词构建倒排索引
  2. 文档聚类:用关键词作为聚类特征
  3. 自动标签:为文章自动生成标签
  4. SEO优化:提取页面关键词用于搜索引擎优化

📚 扩展阅读:关键词提取的工业应用

搜索引擎中的关键词

搜索引擎对关键词提取有特殊需求:

在搜索引擎中,关键词提取的召回率比精确率更重要——遗漏关键查询词意味着完全失去该查询的流量。

🔬 扩展实践:关键词提取的系统设计

混合关键词提取策略

单一方法总有盲区,混合策略效果最好:

  1. 分别用TF-IDF、TextRank、RAKE提取关键词
  2. 对三个结果取并集
  3. 按出现次数和权重综合排序
  4. 在2个以上方法中出现的关键词优先级最高

关键词提取的在线学习

新文档不断到来,关键词统计需要更新:

🧪 扩展:混合关键词提取策略

混合策略

  1. 分别用TF-IDF、TextRank、RAKE提取关键词
  2. 对三个结果取并集
  3. 按出现次数和权重综合排序
  4. 在2个以上方法中出现的关键词优先级最高

关键词提取的工业应用

📚 参考文献

推荐阅读

在线资源

关键词提取 - 关键概念速查

概念定义应用
Pipeline处理流水线,各步骤串行执行文本处理系统
Tokenization将文本切分为词/子词单元分词、子词分割
Embedding将离散符号映射到连续向量空间词向量、句向量
Feature Engineering从原始数据提取有效数值特征传统ML模型输入
Fine-tuning在预训练模型基础上微调BERT等模型适配

本课要点回顾

  1. 关键词提取是NLP技术栈的重要组件
  2. 理解原理比调用API更重要——知道为什么比知道怎么做更有价值
  3. 代码验证是学习的好方法——动手跑一遍胜过读十遍
  4. 从简单方法开始,逐步过渡到复杂方法——简单方法的基线作用不可替代
  5. 实践出真知——用自己的数据跑一遍,发现课本上没写的问题