您的位置:

Textrank算法原理详解

一、什么是Textrank算法

Textrank算法是一种用于文本关键词提取和摘要生成的算法。它是PageRank算法在文本领域的应用,基于图的排序算法。它通过建立文本关键词之间的相似度计算图,然后利用PageRank的思想对图中的节点进行排序,最终得到文本中最重要的关键词或句子。

它的优点在于不需要训练语料库,适用于各种语言和领域的文本,而且能够捕捉文本的核心信息,提取出最具有代表性的关键词或句子。

二、Textrank算法的原理

Textrank算法的原理可以分为以下几个步骤:

1. 文本预处理

对原始文本进行分词、去除停用词、词性标注和词干提取等预处理操作,得到文本单词集合。

import jieba
import jieba.analyse

# 分词
words = jieba.cut(text)

# 关键词提取
keywords = jieba.analyse.extract_tags(text, topK=10)

2. 构建关键词共现矩阵

统计文本中所有单词之间的共现次数,构建关键词共现矩阵。

import numpy as np

# 构建共现矩阵
matrix = np.zeros((len(words_dict), len(words_dict)))
for i in range(len(words_list)-window_size):
    for j in range(i+1, i+window_size):
        if words_list[i] in words_dict and words_list[j] in words_dict:
            matrix[words_dict[words_list[i]], words_dict[words_list[j]]] += 1
            matrix[words_dict[words_list[j]], words_dict[words_list[i]]] += 1

3. 计算节点之间的相似度

利用余弦相似度计算所有节点之间的相似度。

# 计算余弦相似度
def cosine_similarity(x, y):
    return np.dot(x, y) / (np.linalg.norm(x) * np.linalg.norm(y))

similarities = np.zeros((len(words_dict), len(words_dict)))
for i in range(len(words_dict)):
    for j in range(i+1, len(words_dict)):
        if matrix[i][j] > 0:
            similarities[i][j] = cosine_similarity(matrix[i], matrix[j])
            similarities[j][i] = similarities[i][j]

4. 利用PageRank思想对节点进行排序

利用PageRank的思想,将所有节点赋予初始权重,然后依次迭代更新节点的权重,直至收敛。

# 迭代计算节点权重
scores = np.ones(len(words_dict)) / len(words_dict)
for _ in range(max_iter):
    new_scores = np.zeros(len(words_dict))
    for i in range(len(words_dict)):
        for j in range(len(words_dict)):
            if similarities[i][j] > 0:
                new_scores[i] += similarities[i][j] * scores[j]
    scores = new_scores

三、Textrank算法的应用

Textrank算法可以应用于文本摘要、关键词提取、主题识别等场景。

1. 文本摘要

在文本摘要中,我们可以将每个句子看成一个节点,构建句子相似度图,然后利用Textrank算法抽取出最重要的句子,组成摘要。

# 构建句子相似度图
sentences = list(filter(lambda x: len(x)>5, re.split('[。!?]', text)))
graph = np.zeros((len(sentences), len(sentences)))
for i in range(len(sentences)):
    for j in range(i+1, len(sentences)):
        graph[i][j] = cosine_similarity(sentence_embedding[i], sentence_embedding[j])
        graph[j][i] = graph[i][j]

# 计算句子权重
scores = pagerank(graph)

# 抽取前k个句子组成摘要
summary_sentences = [sentences[i] for i in np.argsort(-scores)[:k]]
summary = ''.join(summary_sentences)

2. 关键词提取

在关键词提取中,我们可以利用Textrank算法抽取出文本中的重要关键词,作为文本的主题。

# 计算每个单词的权重
word_scores = np.sum(similarities, axis=0)

# 抽取前k个关键词
keywords = [words_list[i] for i in np.argsort(-word_scores)[:k]]

3. 主题识别

在主题识别中,我们可以将文本看成一个节点,根据与其他文本的相似度来衡量该文本的主题。

# 构建文本相似度图
corpus = [text1, text2, text3, ...]
embeddings = [get_embedding(corpus[i]) for i in range(len(corpus))]
graph = np.zeros((len(corpus), len(corpus)))
for i in range(len(corpus)):
    for j in range(i+1, len(corpus)):
        graph[i][j] = cosine_similarity(embeddings[i], embeddings[j])
        graph[j][i] = graph[i][j]

# 计算文本权重
scores = pagerank(graph)

# 选择得分最高的几个文本作为该主题的代表
topic_docs = [corpus[i] for i in np.argsort(-scores)[:k]]

四、Textrank算法的优化

Textrank算法存在一些缺点,比如对长度较短的文本表现不佳、对词频较高的词重视程度较低等。为了解决这些问题,可以采取以下优化措施:

1. 基于BM25算法的权重计算

对于不同的词汇,在计算权重的时候考虑它们在文档中出现的次数和文档集合中出现的频率,这样可以更好地反映词汇的重要性。

import math

k1 = 1.2
b = 0.75

# 计算TF-IDF
def tf(word, doc):
    return doc.count(word) / len(doc)

def idf(word, corpus):
    return math.log(len(corpus) / sum([1 for doc in corpus if word in doc]))

def tf_idf(word, doc, corpus):
    return tf(word, doc) * idf(word, corpus)

# 计算BM25
def bm25(word, doc, corpus):
    idf = idf(word, corpus)
    tf = tf(word, doc)
    return idf * (tf * (k1+1)) / (tf + k1 * (1-b+b*len(doc)/avg_doc_len))

# 基于BM25计算节点权重
scores = np.zeros(len(words_dict))
for i in range(len(words_dict)):
    for j in range(len(words_dict)):
        if matrix[i][j] > 0:
            scores[i] += bm25(words_list[i], doc, corpus) * cosine_similarity(matrix[i], matrix[j])

2. 根据词性过滤关键词

对于一些词性不太相关的词汇,可以通过词性过滤的方式来去除它们的影响。

# 构建词性字典
pos_dict = {
    'n': ['n', 'ng', 'nr', 'nr1', 'nr2', 'nrj', 'nrf', 'ns', 'nsf', 'nt', 'nz'],
    'v': ['v', 'vg', 'vd', 'vn', 'vshi', 'vyou', 'vf', 'vx', 'vi']
}

# 根据词性过滤
keywords = []
for w in words_list:
    pos = pseg.lcut(w)[0].flag[0]
    if len(w) > 1 and pos in pos_dict and pos_dict[pos]:
        if pos in ['n', 'ns', 'nz']:
            keywords.append(w)
        elif w in pos_dict[pos]:
            keywords.append(w)

五、总结

Textrank算法是一种基于图的排序算法,通过构建文本关键词相似度图,利用PageRank的思想对关键词节点进行排序,从而抽取出文本中最具有代表性的关键词或句子。在文本摘要、关键词提取、主题识别等场景中都有广泛的应用。