用 Python 实现文本摘要:基于提取式与生成式方法的对比实践
文本摘要实现:基于提取式与生成式方法的对比实践
文本摘要是自然语言处理的核心任务,旨在从长文本中提炼关键信息。主要方法包括提取式(直接从原文选取句子)和生成式(使用模型生成新文本)。下面,我将逐步引导你通过 Python 实现这两种方法,并进行对比实践。实践基于真实数据集(如新闻文本),确保结果可靠。代码使用常用库(如 nltk 和 transformers),需提前安装(运行 pip install nltk transformers torch)。
1. 提取式方法实现
提取式方法基于统计或图算法挑选原文句子。常用算法如 TextRank,其核心公式基于 PageRank: $$WS(V_i) = (1 - d) + d \times \sum_{V_j \in In(V_i)} \frac{w_{ji}}{\sum_{V_k \in Out(V_j)} w_{jk}} WS(V_j)$$ 其中,$WS(V_i)$ 表示句子权重,$d$ 为阻尼因子(通常取 0.85)。
以下 Python 代码使用 nltk 实现 TextRank 摘要:
import nltk
from nltk.corpus import stopwords
from nltk.tokenize import sent_tokenize, word_tokenize
from nltk.cluster.util import cosine_distance
import numpy as np
# 下载必要资源
nltk.download('punkt')
nltk.download('stopwords')
def textrank_summary(text, num_sentences=3):
# 分句和分词
sentences = sent_tokenize(text)
stop_words = stopwords.words('english')
# 构建句子相似度矩阵
similarity_matrix = np.zeros((len(sentences), len(sentences)))
for i in range(len(sentences)):
for j in range(len(sentences)):
if i != j:
words_i = [word.lower() for word in word_tokenize(sentences[i]) if word.lower() not in stop_words]
words_j = [word.lower() for word in word_tokenize(sentences[j]) if word.lower() not in stop_words]
if len(words_i) == 0 or len(words_j) == 0:
similarity_matrix[i][j] = 0
else:
similarity_matrix[i][j] = 1 - cosine_distance(words_i, words_j)
# 计算 TextRank 权重
d = 0.85 # 阻尼因子
max_iter = 100
tolerance = 0.0001
weights = np.ones(len(sentences)) / len(sentences)
for _ in range(max_iter):
prev_weights = np.copy(weights)
for i in range(len(sentences)):
total = 0
for j in range(len(sentences)):
if similarity_matrix[j][i] > 0:
total += similarity_matrix[j][i] * weights[j] / np.sum(similarity_matrix[j])
weights[i] = (1 - d) + d * total
if np.sum(np.abs(weights - prev_weights)) < tolerance:
break
# 选取权重最高的句子
ranked_sentences = [sentences[i] for i in np.argsort(weights)[-num_sentences:]]
return ' '.join(ranked_sentences)
# 示例使用
text = "自然语言处理是人工智能的重要分支。它涉及文本分析、机器翻译等任务。文本摘要是其常见应用之一。"
summary = textrank_summary(text)
print("提取式摘要:", summary)
2. 生成式方法实现
生成式方法使用序列到序列模型生成新文本。常用模型如 T5(Text-to-Text Transfer Transformer),其核心公式为: $$P(y|x) = \prod_{t=1}^{T} P(y_t | y_{<t}, x)$$ 其中,$x$ 是输入文本,$y$ 是输出摘要,$T$ 是摘要长度。
以下 Python 代码使用 Hugging Face transformers 库实现 T5 摘要:
from transformers import pipeline
import torch
# 加载预训练模型(使用小规模模型以节省资源)
summarizer = pipeline("summarization", model="t5-small", tokenizer="t5-small", framework="pt")
def t5_summary(text, max_length=50):
# 生成摘要
summary = summarizer(text, max_length=max_length, min_length=10, do_sample=False)
return summary[0]['summary_text']
# 示例使用
text = "自然语言处理是人工智能的重要分支。它涉及文本分析、机器翻译等任务。文本摘要是其常见应用之一。"
summary = t5_summary(text)
print("生成式摘要:", summary)
3. 对比实践
为公平比较,使用同一文本(如新闻片段)测试两种方法。以下代码执行对比:
# 测试文本(真实新闻示例)
test_text = "OpenAI发布了新一代语言模型GPT-4,该模型在多任务处理上表现优异。GPT-4支持图像和文本输入,能生成更准确的回答。专家认为,这标志着AI技术的重大进步。"
# 运行两种方法
extractive_summary = textrank_summary(test_text, num_sentences=2)
generative_summary = t5_summary(test_text, max_length=30)
# 输出结果
print("原文:", test_text)
print("提取式摘要:", extractive_summary)
print("生成式摘要:", generative_summary)
对比分析:
- 准确性:
- 提取式方法(如 TextRank)直接复制原文句子,保证事实准确性,但可能冗余。例如,测试文本摘要可能为:"OpenAI发布了新一代语言模型GPT-4。专家认为,这标志着AI技术的重大进步。"
- 生成式方法(如 T5)生成新句子,流畅度高,但可能引入错误或遗漏细节。例如,摘要可能为:"GPT-4是OpenAI的新模型,在多任务处理上表现优异,标志着AI进步。"
- 资源需求:
- 提取式方法:计算轻量(时间复杂度 $O(n^2)$,$n$ 为句子数),适合实时应用。
- 生成式方法:需GPU资源(模型参数量大),推理速度慢,不适合低端设备。
- 适用场景:
- 提取式:新闻摘要、报告生成(强调事实性)。
- 生成式:创意写作、社交媒体(强调可读性)。
- 优缺点总结:
方法 优点 缺点 提取式 高准确性、实现简单 缺乏灵活性、冗余风险 生成式 高流畅度、可生成新内容 资源密集、可能失真
4. 实践建议
- 初学者:从提取式方法入手(如 TextRank),易于理解和调试。
- 进阶:尝试生成式方法(如 T5 或 BART),但注意模型微调(使用自定义数据集)。
- 工具推荐:提取式用
spaCy或gensim;生成式用 Hugging Facetransformers。 - 注意事项:生成式方法需处理伦理问题(如偏见);提取式方法在长文本中效果更好。
通过此实践,你可根据需求选择方法:提取式重事实,生成式重创新。实际应用中,常结合两者(如用提取式结果指导生成式)。如有更多数据集,可扩展对比实验!
更多推荐



所有评论(0)