本文目录导读:

我来详细讲解如何使用TextRank算法进行文本摘要提取,包括完整的Python实现案例。
TextRank算法原理
TextRank是一种基于图的排序算法,通过构建词或句子的图结构,计算节点的重要性来提取关键词或摘要。
完整实现案例
基础版:使用jieba实现
import jieba
import jieba.analyse
import numpy as np
from collections import defaultdict
import re
class TextRankSummarizer:
def __init__(self):
self.damping = 0.85 # 阻尼系数
self.max_iter = 200 # 最大迭代次数
self.min_diff = 0.001 # 收敛阈值
def preprocess(self, text):
"""文本预处理"""
# 分句
sentences = re.split('[。!?!?]', text)
sentences = [s.strip() for s in sentences if len(s.strip()) > 5]
return sentences
def sentence_similarity(self, sent1, sent2):
"""计算句子相似度"""
# 分词并去重
words1 = set(jieba.cut(sent1))
words2 = set(jieba.cut(sent2))
# 如果句子为空,返回0
if not words1 or not words2:
return 0
# 计算词交集
intersection = words1 & words2
# 使用Jaccard相似度
return len(intersection) / (len(words1) + len(words2) - len(intersection))
def build_similarity_matrix(self, sentences):
"""构建句子相似度矩阵"""
n = len(sentences)
similarity_matrix = np.zeros((n, n))
for i in range(n):
for j in range(n):
if i != j:
similarity_matrix[i][j] = self.sentence_similarity(
sentences[i], sentences[j]
)
# 归一化
for i in range(n):
row_sum = np.sum(similarity_matrix[i])
if row_sum > 0:
similarity_matrix[i] /= row_sum
return similarity_matrix
def textrank(self, similarity_matrix):
"""TextRank算法实现"""
n = len(similarity_matrix)
scores = np.ones(n) / n # 初始分数
for _ in range(self.max_iter):
prev_scores = np.copy(scores)
# 更新分数
scores = (1 - self.damping) + self.damping * \
similarity_matrix.T.dot(scores)
# 检查收敛
if np.sum(np.abs(scores - prev_scores)) < self.min_diff:
break
return scores
def summarize(self, text, num_sentences=3):
"""生成摘要"""
# 预处理
sentences = self.preprocess(text)
if len(sentences) <= num_sentences:
return text
# 构建相似度矩阵
similarity_matrix = self.build_similarity_matrix(sentences)
# 计算TextRank分数
scores = self.textrank(similarity_matrix)
# 获取最重要的句子
ranked_sentences = sorted(
[(score, sent) for score, sent in zip(scores, sentences)],
reverse=True
)
# 选取得分最高的句子
summary_sentences = [sent for _, sent in ranked_sentences[:num_sentences]]
# 按原顺序排序
summary_sentences.sort(key=lambda x: sentences.index(x))
return '。'.join(summary_sentences) + '。'
# 使用示例
if __name__ == "__main__":
text = """
人工智能(Artificial Intelligence,简称AI)是计算机科学的一个分支,
它试图理解智能的本质,并生产出一种新的能以人类智能相似的方式做出反应的智能机器。
人工智能的研究包括机器人、语言识别、图像识别、自然语言处理和专家系统等。
人工智能从诞生以来,理论和技术日益成熟,应用领域也不断扩大。
可以设想,未来人工智能带来的科技产品,将会是人类智慧的"容器"。
人工智能可以对人的意识、思维的信息过程的模拟。
人工智能不是人的智能,但能像人那样思考、也可能超过人的智能。
深度学习和机器学习是人工智能的重要分支,它们让计算机能够从数据中学习和改进。
人工智能的发展已经对各行各业产生了深远的影响,从医疗诊断到自动驾驶,
从语音助手到智能客服,AI正在改变我们的生活方式。
"""
summarizer = TextRankSummarizer()
summary = summarizer.summarize(text, num_sentences=3)
print("原文长度:", len(text))
print("摘要长度:", len(summary))
print("\n原文:")
print(text)
print("\n摘要:")
print(summary)
进阶版:使用NetworkX优化
import jieba
import networkx as nx
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
class AdvancedTextRankSummarizer:
def __init__(self):
self.damping = 0.85
def split_sentences(self, text):
"""智能分句"""
# 处理常见标点
text = re.sub('([。!?\?!])([^"\'》)])', r"\1\n\2", text)
text = re.sub('(\.{6})([^"\'》)])', r"\1\n\2", text)
text = re.sub('(\…{2})([^"\'》)])', r"\1\n\2", text)
text = re.sub('([。!?\?!\.{6}\…{2}]["\'》)])([^"\'》)])', r"\1\n\2", text)
sentences = text.split('\n')
sentences = [s.strip() for s in sentences if len(s.strip()) > 5]
return sentences
def get_sentence_vectors(self, sentences):
"""获取句子向量表示"""
vectorizer = TfidfVectorizer(tokenizer=jieba.lcut, max_features=5000)
vectors = vectorizer.fit_transform(sentences)
return vectors.toarray()
def build_graph(self, sentences):
"""构建句子图"""
# 获取句子向量
vectors = self.get_sentence_vectors(sentences)
# 计算相似度矩阵
similarity_matrix = cosine_similarity(vectors)
# 构建图
graph = nx.Graph()
# 添加节点
for i, sentence in enumerate(sentences):
graph.add_node(i, text=sentence)
# 添加边
for i in range(len(sentences)):
for j in range(i+1, len(sentences)):
if similarity_matrix[i][j] > 0.1: # 设置阈值
graph.add_edge(i, j, weight=similarity_matrix[i][j])
return graph
def summarize(self, text, num_sentences=3):
"""生成摘要"""
sentences = self.split_sentences(text)
if len(sentences) <= num_sentences:
return text
# 构建图
graph = self.build_graph(sentences)
# 使用PageRank算法计算句子重要性
scores = nx.pagerank(graph, alpha=self.damping)
# 排序并选择重要句子
ranked_sentences = sorted(
[(scores[i], i, sentences[i]) for i in range(len(sentences))],
reverse=True
)
# 选择最重要的句子
summary_indices = [item[1] for item in ranked_sentences[:num_sentences]]
summary_indices.sort()
summary = '。'.join([sentences[i] for i in summary_indices]) + '。'
return summary
# 使用示例
if __name__ == "__main__":
summarizer = AdvancedTextRankSummarizer()
text = """
自然语言处理是人工智能的一个重要分支,它研究如何让计算机理解和生成人类语言。
近年来,随着深度学习技术的发展,自然语言处理取得了突破性进展。
特别是Transformer架构的出现,极大地推动了机器翻译、文本生成等任务的发展。
BERT、GPT等预训练模型的出现,更是让自然语言处理进入了新的时代。
这些模型在大规模语料上进行预训练,然后通过微调适应各种下游任务。
自然语言处理技术已经广泛应用于智能客服、机器翻译、情感分析等领域。
随着技术的不断进步,自然语言处理将在更多领域发挥重要作用。
"""
summary = summarizer.summarize(text, num_sentences=2)
print("摘要生成结果:")
print(summary)
完整的工具类封装
import jieba
import jieba.analyse
import numpy as np
import networkx as nx
from sklearn.feature_extraction.text import TfidfVectorizer
import re
import logging
# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
class TextRankSummarizer:
"""
TextRank摘要提取器
支持关键词提取和摘要生成
"""
def __init__(self, use_networkx=True):
"""
初始化摘要提取器
Args:
use_networkx: 是否使用NetworkX库(更稳定)
"""
self.use_networkx = use_networkx
self.damping = 0.85
self.max_iter = 200
self.min_diff = 0.001
def clean_text(self, text):
"""清理文本"""
# 移除多余空格和换行
text = re.sub(r'\s+', ' ', text)
# 移除特殊字符
text = re.sub(r'[^\u4e00-\u9fa5a-zA-Z0-9,。!?、;:""''()\(\)\[\]]', '', text)
return text.strip()
def split_sentences(self, text):
"""分句"""
# 按标点分句
text = re.sub('([。!?\?!;;])', r'\1\n', text)
sentences = text.split('\n')
# 过滤空句子和太短的句子
sentences = [s.strip() for s in sentences if len(s.strip()) > 10]
return sentences
def calculate_similarity(self, sent1, sent2, method='jaccard'):
"""
计算句子相似度
Args:
sent1: 句子1
sent2: 句子2
method: 相似度计算方法 ('jaccard', 'cosine', 'tfidf')
"""
if method == 'jaccard':
words1 = set(jieba.lcut(sent1))
words2 = set(jieba.lcut(sent2))
if not words1 or not words2:
return 0
intersection = words1 & words2
return len(intersection) / (len(words1) + len(words2) - len(intersection))
elif method == 'cosine':
# 简单余弦相似度
words1 = list(jieba.lcut(sent1))
words2 = list(jieba.lcut(sent2))
# 构建词频向量
all_words = list(set(words1 + words2))
vec1 = np.array([words1.count(w) for w in all_words])
vec2 = np.array([words2.count(w) for w in all_words])
if np.linalg.norm(vec1) == 0 or np.linalg.norm(vec2) == 0:
return 0
return np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))
elif method == 'tfidf':
# 使用TF-IDF
vectorizer = TfidfVectorizer(tokenizer=jieba.lcut)
try:
vectors = vectorizer.fit_transform([sent1, sent2])
similarity = (vectors * vectors.T).toarray()[0][1]
return similarity
except:
return 0
else:
raise ValueError(f"Unknown similarity method: {method}")
def build_similarity_matrix(self, sentences, similarity_method='jaccard'):
"""构建相似度矩阵"""
n = len(sentences)
similarity_matrix = np.zeros((n, n))
print(f"构建相似度矩阵: {n} x {n}")
for i in range(n):
for j in range(i+1, n):
similarity = self.calculate_similarity(
sentences[i], sentences[j],
method=similarity_method
)
similarity_matrix[i][j] = similarity
similarity_matrix[j][i] = similarity
return similarity_matrix
def textrank_with_networkx(self, similarity_matrix):
"""使用NetworkX的PageRank算法"""
n = len(similarity_matrix)
# 构建图
graph = nx.Graph()
graph.add_nodes_from(range(n))
# 添加边
for i in range(n):
for j in range(i+1, n):
if similarity_matrix[i][j] > 0:
graph.add_edge(i, j, weight=similarity_matrix[i][j])
# 计算PageRank
scores = nx.pagerank(graph, alpha=self.damping)
return [scores[i] for i in range(n)]
def textrank_manual(self, similarity_matrix):
"""手动实现TextRank"""
n = len(similarity_matrix)
# 归一化相似度矩阵
normalized_matrix = np.copy(similarity_matrix)
for i in range(n):
row_sum = np.sum(normalized_matrix[i])
if row_sum > 0:
normalized_matrix[i] /= row_sum
# 初始化分数
scores = np.ones(n) / n
# 迭代计算
for iteration in range(self.max_iter):
prev_scores = np.copy(scores)
# 更新分数
scores = (1 - self.damping) + self.damping * \
normalized_matrix.T.dot(scores)
# 检查收敛
diff = np.sum(np.abs(scores - prev_scores))
if diff < self.min_diff:
print(f"收敛于第{iteration+1}次迭代")
break
return scores
def extract_keywords(self, text, topK=10):
"""提取关键词"""
keywords = jieba.analyse.textrank(text, topK=topK, withWeight=True)
return keywords
def summarize(self, text, num_sentences=3, similarity_method='jaccard'):
"""
生成摘要
Args:
text: 输入文本
num_sentences: 摘要句子数量
similarity_method: 相似度计算方法
Returns:
summary: 生成的摘要
sentences_with_scores: 每个句子的得分
"""
# 清理文本
text = self.clean_text(text)
# 分句
sentences = self.split_sentences(text)
print(f"共{len(sentences)}个句子")
if len(sentences) <= num_sentences:
return text, [(sentences[i], 1.0) for i in range(len(sentences))]
# 构建相似度矩阵
similarity_matrix = self.build_similarity_matrix(sentences, similarity_method)
# 计算TextRank分数
if self.use_networkx:
scores = self.textrank_with_networkx(similarity_matrix)
else:
scores = self.textrank_manual(similarity_matrix)
# 排序句子
sentences_with_scores = list(zip(sentences, scores))
sentences_with_scores.sort(key=lambda x: x[1], reverse=True)
# 选择重要句子
important_sentences = sentences_with_scores[:num_sentences]
# 按原顺序排序
selected_indices = [sentences.index(s[0]) for s in important_sentences]
selected_indices.sort()
# 生成摘要
summary = '。'.join([sentences[i] for i in selected_indices])
if summary and not summary.endswith('。'):
summary += '。'
# 返回所有句子的得分(已排序)
all_scores = sorted(sentences_with_scores, key=lambda x: sentences.index(x[0]))
return summary, all_scores
# 使用示例
def demo():
"""演示函数"""
# 创建摘要提取器
summarizer = TextRankSummarizer(use_networkx=True)
# 测试文本
text = """
人工智能(Artificial Intelligence)是计算机科学的一个重要分支。
它致力于研究如何让计算机模拟人类的智能行为,包括学习、推理、感知和理解自然语言等能力。
近年来,深度学习技术的突破让AI取得了前所未有的进展。
在图像识别领域,卷积神经网络(CNN)让计算机能够准确识别和理解图像内容。
在自然语言处理领域,循环神经网络(RNN)和Transformer架构让机器翻译和文本生成更加自然。
特别是BERT、GPT等预训练模型的提出,开创了自然语言处理的新范式。
这些模型通过在大规模语料上进行预训练,学习到了丰富的语言知识。
然后通过微调,可以适应各种特定的自然语言处理任务。
人工智能已经在医疗诊断、自动驾驶、智能客服等领域得到了广泛应用。
随着技术的不断进步,AI将会在更多领域发挥重要作用,推动社会进步。
"""
print("="*50)
print("原文:")
print(text)
print("="*50)
# 提取关键词
print("\n关键词提取结果:")
keywords = summarizer.extract_keywords(text, topK=5)
for word, weight in keywords:
print(f" {word}: {weight:.4f}")
# 生成摘要
print("\n摘要生成结果:")
summary, sentences_scores = summarizer.summarize(text, num_sentences=3)
print(summary)
print("\n句子得分详情:")
for sentence, score in sentences_scores:
print(f" {score:.4f}: {sentence[:50]}...")
if __name__ == "__main__":
demo()
优化建议
性能优化
# 使用缓存提高重复计算效率
from functools import lru_cache
@lru_cache(maxsize=1024)
def cached_similarity(sent1, sent2):
# 缓存相似度计算结果
pass
# 使用更高效的数据结构
from collections import Counter
def fast_similarity(sent1, sent2):
words1 = Counter(jieba.lcut(sent1))
words2 = Counter(jieba.lcut(sent2))
# 快速计算交集
intersection = sum(min(words1[w], words2[w]) for w in words1 if w in words2)
return intersection
质量优化
def enhanced_summarize(self, text, num_sentences=3):
"""
增强版摘要生成
考虑位置信息、长度惩罚等因素
"""
sentences = self.split_sentences(text)
# 计算基础得分
base_scores = self.calculate_textrank_scores(sentences)
# 位置权重(越靠前越重要)
position_weights = [1.0 / (i + 1) for i in range(len(sentences))]
# 长度惩罚(过长的句子适当降低权重)
length_weights = []
for sent in sentences:
length = len(sent)
if 20 <= length <= 100:
length_weights.append(1.0)
else:
length_weights.append(max(0.5, 1.0 - abs(length - 50) / 100))
# 综合得分
final_scores = [
base * pos * length
for base, pos, length in zip(base_scores, position_weights, length_weights)
]
# 选择最重要的句子
# ...
实际应用建议
- 文本预处理:根据具体领域进行针对性预处理
- 参数调优:根据文本特点调整相似度阈值和阻尼系数
- 多方法融合:结合TF-IDF、LDA等方法提高效果
- 并行计算:处理大量文本时使用多线程/多进程
这个实现涵盖了TextRank摘要提取的核心原理和完整代码,可以根据实际需求进行调整和优化。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播